LCOV - code coverage report
Current view: top level - src/xc - xc.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b279b6b) Lines: 899 1283 70.1 %
Date: 2024-04-24 07:13:09 Functions: 28 30 93.3 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Exchange and Correlation functional calculations
      10             : !> \par History
      11             : !>      (13-Feb-2001) JGH, based on earlier version of apsi
      12             : !>      02.2003 Many many changes [fawzi]
      13             : !>      03.2004 new xc interface [fawzi]
      14             : !>      04.2004 kinetic functionals [fawzi]
      15             : !> \author fawzi
      16             : ! **************************************************************************************************
      17             : MODULE xc
      18             :    #:include 'xc.fypp'
      19             :    USE cp_array_utils, ONLY: cp_3d_r_cp_type
      20             :    USE cp_linked_list_xc_deriv, ONLY: cp_sll_xc_deriv_next, &
      21             :                                       cp_sll_xc_deriv_type
      22             :    USE cp_log_handling, ONLY: cp_get_default_logger, &
      23             :                               cp_logger_get_default_unit_nr, &
      24             :                               cp_logger_type, &
      25             :                               cp_to_string
      26             :    USE input_section_types, ONLY: section_get_ival, &
      27             :                                   section_get_lval, &
      28             :                                   section_get_rval, &
      29             :                                   section_vals_get_subs_vals, &
      30             :                                   section_vals_type, &
      31             :                                   section_vals_val_get
      32             :    USE kahan_sum, ONLY: accurate_dot_product, &
      33             :                         accurate_sum
      34             :    USE kinds, ONLY: default_path_length, &
      35             :                     dp
      36             :    USE pw_grid_types, ONLY: PW_MODE_DISTRIBUTED, &
      37             :                             pw_grid_type
      38             :    USE pw_methods, ONLY: pw_axpy, &
      39             :                          pw_copy, &
      40             :                          pw_derive, &
      41             :                          pw_scale, &
      42             :                          pw_transfer, &
      43             :                          pw_zero, pw_integrate_function
      44             :    USE pw_pool_types, ONLY: &
      45             :       pw_pool_type
      46             :    USE pw_types, ONLY: &
      47             :       pw_c1d_gs_type, pw_r3d_rs_type
      48             :    USE xc_derivative_desc, ONLY: &
      49             :       deriv_rho, deriv_rhoa, deriv_rhob, &
      50             :       deriv_norm_drhoa, deriv_norm_drhob, deriv_norm_drho, deriv_tau_a, deriv_tau_b, deriv_tau, &
      51             :       deriv_laplace_rho, deriv_laplace_rhoa, deriv_laplace_rhob, id_to_desc
      52             :    USE xc_derivative_set_types, ONLY: xc_derivative_set_type, &
      53             :                                       xc_dset_create, &
      54             :                                       xc_dset_get_derivative, &
      55             :                                       xc_dset_release, &
      56             :                                       xc_dset_zero_all, xc_dset_recover_pw
      57             :    USE xc_derivative_types, ONLY: xc_derivative_get, &
      58             :                                   xc_derivative_type
      59             :    USE xc_derivatives, ONLY: xc_functionals_eval, &
      60             :                              xc_functionals_get_needs
      61             :    USE xc_input_constants, ONLY: &
      62             :       xc_debug_new_routine, xc_default_f_routine, xc_test_lsd_f_routine
      63             :    USE xc_rho_cflags_types, ONLY: xc_rho_cflags_type
      64             :    USE xc_rho_set_types, ONLY: xc_rho_set_create, &
      65             :                                xc_rho_set_get, &
      66             :                                xc_rho_set_release, &
      67             :                                xc_rho_set_type, &
      68             :                                xc_rho_set_update, xc_rho_set_recover_pw
      69             :    USE xc_util, ONLY: xc_pw_smooth, xc_pw_laplace, xc_pw_divergence, xc_requires_tmp_g
      70             : #include "../base/base_uses.f90"
      71             : 
      72             :    IMPLICIT NONE
      73             :    PRIVATE
      74             :    PUBLIC :: xc_vxc_pw_create1, xc_vxc_pw_create, &
      75             :              xc_exc_calc, xc_calc_2nd_deriv_analytical, xc_calc_2nd_deriv_numerical, &
      76             :              xc_calc_2nd_deriv, xc_prep_2nd_deriv, divide_by_norm_drho, smooth_cutoff, &
      77             :              xc_uses_kinetic_energy_density, xc_uses_norm_drho
      78             :    PUBLIC :: calc_xc_density
      79             : 
      80             :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      81             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xc'
      82             : 
      83             : CONTAINS
      84             : 
      85             : ! **************************************************************************************************
      86             : !> \brief ...
      87             : !> \param xc_fun_section ...
      88             : !> \param lsd ...
      89             : !> \return ...
      90             : ! **************************************************************************************************
      91        6766 :    FUNCTION xc_uses_kinetic_energy_density(xc_fun_section, lsd) RESULT(res)
      92             :       TYPE(section_vals_type), POINTER, INTENT(IN) :: xc_fun_section
      93             :       LOGICAL, INTENT(IN) :: lsd
      94             :       LOGICAL :: res
      95             : 
      96             :       TYPE(xc_rho_cflags_type)                           :: needs
      97             : 
      98             :       needs = xc_functionals_get_needs(xc_fun_section, &
      99             :                                        lsd=lsd, &
     100       13532 :                                        calc_potential=.FALSE.)
     101        6766 :       res = (needs%tau_spin .OR. needs%tau)
     102             : 
     103        6766 :    END FUNCTION
     104             : 
     105             : ! **************************************************************************************************
     106             : !> \brief ...
     107             : !> \param xc_fun_section ...
     108             : !> \param lsd ...
     109             : !> \return ...
     110             : ! **************************************************************************************************
     111        6782 :    FUNCTION xc_uses_norm_drho(xc_fun_section, lsd) RESULT(res)
     112             :       TYPE(section_vals_type), POINTER, INTENT(IN) :: xc_fun_section
     113             :       LOGICAL, INTENT(IN) :: lsd
     114             :       LOGICAL :: res
     115             : 
     116             :       TYPE(xc_rho_cflags_type)                           :: needs
     117             : 
     118             :       needs = xc_functionals_get_needs(xc_fun_section, &
     119             :                                        lsd=lsd, &
     120       13564 :                                        calc_potential=.FALSE.)
     121        6782 :       res = (needs%norm_drho .OR. needs%norm_drho_spin)
     122             : 
     123        6782 :    END FUNCTION
     124             : 
     125             : ! **************************************************************************************************
     126             : !> \brief Exchange and Correlation functional calculations.
     127             : !>      depending on the selected functional_routine calls
     128             : !>      the correct routine
     129             : !> \param vxc_rho will contain the v_xc part that depend on rho
     130             : !>        (if one of the chosen xc functionals has it it is allocated and you
     131             : !>        are responsible for it)
     132             : !> \param vxc_tau will contain the kinetic tau part of v_xcthe functional
     133             : !>        (if one of the chosen xc functionals has it it is allocated and you
     134             : !>        are responsible for it)
     135             : !> \param rho_r the value of the density in the real space
     136             : !> \param rho_g value of the density in the g space (needs to be associated
     137             : !>        only for gradient corrections)
     138             : !> \param tau value of the kinetic density tau on the grid (can be null,
     139             : !>        used only with meta functionals)
     140             : !> \param exc the xc energy
     141             : !> \param xc_section parameters selecting the xc and the method used to
     142             : !>        calculate it
     143             : !> \param pw_pool the pool for the grids
     144             : !> \param compute_virial should the virial be computed... if so virial_xc must be present
     145             : !> \param virial_xc for calculating the GGA part of the stress
     146             : !> \param exc_r ...
     147             : !> \author fawzi
     148             : ! **************************************************************************************************
     149      207832 :    SUBROUTINE xc_vxc_pw_create1(vxc_rho, vxc_tau, rho_r, rho_g, tau, exc, xc_section, &
     150             :                                 pw_pool, compute_virial, virial_xc, exc_r)
     151             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER             :: vxc_rho, vxc_tau
     152             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r, tau
     153             :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
     154             :       REAL(KIND=dp), INTENT(out)                         :: exc
     155             :       TYPE(section_vals_type), POINTER                   :: xc_section
     156             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     157             :       LOGICAL, INTENT(IN)                                :: compute_virial
     158             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT)        :: virial_xc
     159             :       TYPE(pw_r3d_rs_type), INTENT(INOUT), OPTIONAL           :: exc_r
     160             : 
     161             :       INTEGER                                            :: f_routine
     162             : 
     163      103916 :       CPASSERT(ASSOCIATED(rho_r))
     164      103916 :       CPASSERT(ASSOCIATED(xc_section))
     165      103916 :       CPASSERT(.NOT. ASSOCIATED(vxc_rho))
     166      103916 :       CPASSERT(.NOT. ASSOCIATED(vxc_tau))
     167             : 
     168      103916 :       virial_xc = 0.0_dp
     169             : 
     170             :       CALL section_vals_val_get(xc_section, "FUNCTIONAL_ROUTINE", &
     171      103916 :                                 i_val=f_routine)
     172      103916 :       SELECT CASE (f_routine)
     173             :       CASE (xc_default_f_routine)
     174             :          CALL xc_vxc_pw_create(vxc_rho=vxc_rho, vxc_tau=vxc_tau, tau=tau, exc_r=exc_r, &
     175             :                                rho_r=rho_r, rho_g=rho_g, exc=exc, xc_section=xc_section, &
     176      103916 :                                pw_pool=pw_pool, compute_virial=compute_virial, virial_xc=virial_xc)
     177             :       CASE (xc_debug_new_routine)
     178           0 :          CPASSERT(.NOT. PRESENT(exc_r))
     179             :          CALL xc_vxc_pw_create_debug(vxc_rho=vxc_rho, vxc_tau=vxc_tau, tau=tau, &
     180             :                                      rho_r=rho_r, rho_g=rho_g, exc=exc, xc_section=xc_section, &
     181           0 :                                      pw_pool=pw_pool)
     182             :       CASE (xc_test_lsd_f_routine)
     183           0 :          CPASSERT(.NOT. PRESENT(exc_r))
     184             :          CALL xc_vxc_pw_create_test_lsd(vxc_rho=vxc_rho, vxc_tau=vxc_tau, &
     185             :                                         tau=tau, rho_r=rho_r, rho_g=rho_g, exc=exc, &
     186      103916 :                                         xc_section=xc_section, pw_pool=pw_pool)
     187             :       CASE default
     188             :       END SELECT
     189             : 
     190      103916 :    END SUBROUTINE xc_vxc_pw_create1
     191             : 
     192             : ! **************************************************************************************************
     193             : !> \brief calculates vxc using lsd with rhoa=rhob=0.5*rho and compares
     194             : !>      with the lda result
     195             : !> \param vxc_rho will contain the v_xc part that depend on rho
     196             : !>        (if one of the chosen xc functionals has it it is allocated and you
     197             : !>        are responsible for it)
     198             : !> \param vxc_tau will contain the kinetic tau part of v_xc
     199             : !>        (if one of the chosen xc functionals has it it is allocated and you
     200             : !>        are responsible for it)
     201             : !> \param rho_r the value of the density in the real space
     202             : !> \param rho_g value of the density in the g space (needs to be associated
     203             : !>        only for gradient corrections)
     204             : !> \param tau value of the kinetic density tau on the grid (can be null,
     205             : !>        used only with meta functionals)
     206             : !> \param exc the xc energy
     207             : !> \param xc_section which functional to calculate, and how
     208             : !> \param pw_pool the pool for the grids
     209             : !> \author Fawzi Mohamed
     210             : !> \note
     211             : !>      for debugging only: leaks, and non parallel
     212             : ! **************************************************************************************************
     213           0 :    SUBROUTINE xc_vxc_pw_create_test_lsd(vxc_rho, vxc_tau, rho_r, rho_g, tau, &
     214             :                                         exc, xc_section, pw_pool)
     215             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER             :: vxc_rho, vxc_tau
     216             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               :: rho_r, tau
     217             :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
     218             :       REAL(KIND=dp), INTENT(out)                         :: exc
     219             :       TYPE(section_vals_type), POINTER                   :: xc_section
     220             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     221             : 
     222             :       LOGICAL, PARAMETER                                 :: compute_virial = .FALSE.
     223             : 
     224             :       CHARACTER(len=default_path_length)                 :: filename
     225           0 :       INTEGER, DIMENSION(:), POINTER         :: split_desc
     226             :       INTEGER                                            :: i, ii, ispin, j, k, order
     227             :       INTEGER, DIMENSION(2, 3)                           :: bo
     228             :       REAL(kind=dp)                                      :: diff, exc2, maxdiff, tmp
     229             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: virial_xc
     230           0 :       REAL(kind=dp), DIMENSION(:, :, :), POINTER         :: pot, pot2, pot3
     231             :       TYPE(cp_sll_xc_deriv_type), POINTER                :: deriv_iter
     232           0 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER             :: vxc_rho2, vxc_tau2
     233           0 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho2_g
     234           0 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               ::  rho2_r, tau2
     235             :       TYPE(xc_derivative_set_type)                       :: dSet1, dSet2
     236             :       TYPE(xc_derivative_type), POINTER                  :: deriv, deriv2, deriv3
     237             :       TYPE(xc_rho_set_type)                              :: rho_set1, rho_set2
     238             : 
     239           0 :       NULLIFY (vxc_rho2, vxc_tau2, tau2, pot, pot3, pot3, &
     240           0 :                deriv, deriv2, deriv3, rho2_g)
     241             : 
     242           0 :       bo = rho_r(1)%pw_grid%bounds_local
     243             : 
     244           0 :       ALLOCATE (rho2_r(2))
     245           0 :       DO ispin = 1, 2
     246           0 :          CALL pw_pool%create_pw(rho2_r(ispin))
     247             :       END DO
     248           0 :       DO k = bo(1, 3), bo(2, 3)
     249           0 :          DO j = bo(1, 2), bo(2, 2)
     250           0 :             DO i = bo(1, 1), bo(2, 1)
     251           0 :                tmp = rho_r(1)%array(i, j, k)*0.5
     252           0 :                rho2_r(1)%array(i, j, k) = tmp
     253           0 :                rho2_r(2)%array(i, j, k) = tmp
     254             :             END DO
     255             :          END DO
     256             :       END DO
     257             : 
     258           0 :       IF (ASSOCIATED(tau)) THEN
     259           0 :          ALLOCATE (tau2(2))
     260           0 :          DO ispin = 1, 2
     261           0 :             CALL pw_pool%create_pw(tau2(ispin))
     262             :          END DO
     263             : 
     264           0 :          DO k = bo(1, 3), bo(2, 3)
     265           0 :             DO j = bo(1, 2), bo(2, 2)
     266           0 :                DO i = bo(1, 1), bo(2, 1)
     267           0 :                   tmp = tau(1)%array(i, j, k)*0.5
     268           0 :                   tau2(1)%array(i, j, k) = tmp
     269           0 :                   tau2(2)%array(i, j, k) = tmp
     270             :                END DO
     271             :             END DO
     272             :          END DO
     273             :       END IF
     274             : 
     275           0 :       PRINT *, "about to calculate xc (lda)"
     276             :       CALL xc_rho_set_and_dset_create(rho_r=rho_r, rho_g=rho_g, &
     277             :                                       tau=tau, xc_section=xc_section, &
     278             :                                       pw_pool=pw_pool, rho_set=rho_set1, &
     279             :                                       deriv_set=dSet1, deriv_order=1, &
     280           0 :                                       calc_potential=.FALSE.)
     281             :       CALL xc_vxc_pw_create(rho_r=rho_r, rho_g=rho_g, tau=tau, &
     282             :                             vxc_rho=vxc_rho, vxc_tau=vxc_tau, exc=exc, xc_section=xc_section, &
     283             :                             pw_pool=pw_pool, &
     284           0 :                             compute_virial=compute_virial, virial_xc=virial_xc)
     285           0 :       PRINT *, "did calculate xc (lda)"
     286           0 :       PRINT *, "about to calculate xc (lsd)"
     287             :       CALL xc_rho_set_and_dset_create(rho_set=rho_set2, deriv_set=dSet2, &
     288             :                                       rho_r=rho2_r, rho_g=rho2_g, tau=tau2, xc_section=xc_section, &
     289             :                                       pw_pool=pw_pool, deriv_order=1, &
     290           0 :                                       calc_potential=.FALSE.)
     291             :       CALL xc_vxc_pw_create(rho_r=rho2_r, rho_g=rho2_g, tau=tau2, &
     292             :                             vxc_rho=vxc_rho2, vxc_tau=vxc_tau2, exc=exc2, xc_section=xc_section, &
     293           0 :                             pw_pool=pw_pool, compute_virial=compute_virial, virial_xc=virial_xc)
     294           0 :       PRINT *, "did calculate xc (new)"
     295           0 :       PRINT *, "at (0,0,0) rho_r=", rho_r(1)%array(0, 0, 0), &
     296           0 :          "rho2_r(1)=", rho2_r(1)%array(0, 0, 0), &
     297           0 :          "rho2_r(2)=", rho2_r(2)%array(0, 0, 0), &
     298           0 :          "rho_r_sm=", rho_set1%rho(0, 0, 0), "rhoa2_r_sm=", rho_set2%rhoa(0, 0, 0), &
     299           0 :          "rhob2_r_sm=", rho_set2%rhob(0, 0, 0)
     300             :       OPEN (unit=120, file="rho.bindata", status="unknown", access='sequential', &
     301           0 :             form="unformatted", action="write")
     302           0 :       pot => rho_set1%rho
     303           0 :       WRITE (unit=120) pot(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(2, 3))
     304           0 :       CLOSE (unit=120)
     305             :       OPEN (unit=120, file="rhoa.bindata", status="unknown", access='sequential', &
     306           0 :             form="unformatted", action="write")
     307           0 :       pot => rho_set2%rhoa
     308           0 :       WRITE (unit=120) pot(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(2, 3))
     309           0 :       CLOSE (unit=120)
     310             :       OPEN (unit=120, file="rhob.bindata", status="unknown", access='sequential', &
     311           0 :             form="unformatted", action="write")
     312           0 :       pot => rho_set2%rhob
     313           0 :       WRITE (unit=120) pot(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(2, 3))
     314           0 :       CLOSE (unit=120)
     315             :       OPEN (unit=120, file="ndrho.bindata", status="unknown", access='sequential', &
     316           0 :             form="unformatted", action="write")
     317           0 :       pot => rho_set1%norm_drho
     318           0 :       WRITE (unit=120) pot(:, :, bo(2, 3))
     319           0 :       CLOSE (unit=120)
     320             :       OPEN (unit=120, file="ndrhoa.bindata", status="unknown", access='sequential', &
     321           0 :             form="unformatted", action="write")
     322           0 :       pot => rho_set2%norm_drhoa
     323           0 :       WRITE (unit=120) pot(:, :, bo(2, 3))
     324           0 :       CLOSE (unit=120)
     325             :       OPEN (unit=120, file="ndrhob.bindata", status="unknown", access='sequential', &
     326           0 :             form="unformatted", action="write")
     327           0 :       pot => rho_set2%norm_drhob
     328           0 :       WRITE (unit=120) pot(:, :, bo(2, 3))
     329           0 :       CLOSE (unit=120)
     330           0 :       IF (rho_set1%has%tau) THEN
     331             :          OPEN (unit=120, file="tau.bindata", status="unknown", access='sequential', &
     332           0 :                form="unformatted", action="write")
     333           0 :          pot => rho_set1%tau
     334           0 :          WRITE (unit=120) pot(:, :, bo(2, 3))
     335           0 :          CLOSE (unit=120)
     336             :       END IF
     337           0 :       IF (rho_set2%has%tau_spin) THEN
     338             :          OPEN (unit=120, file="tau_a.bindata", status="unknown", access='sequential', &
     339           0 :                form="unformatted", action="write")
     340           0 :          pot => rho_set2%tau_a
     341           0 :          WRITE (unit=120) pot(:, :, bo(2, 3))
     342           0 :          CLOSE (unit=120)
     343             :          OPEN (unit=120, file="tau_v.bindata", status="unknown", access='sequential', &
     344           0 :                form="unformatted", action="write")
     345           0 :          pot => rho_set2%tau_b
     346           0 :          WRITE (unit=120) pot(:, :, bo(2, 3))
     347           0 :          CLOSE (unit=120)
     348             :       END IF
     349             :       OPEN (unit=120, file="vxc.bindata", status="unknown", access='sequential', &
     350           0 :             form="unformatted", action="write")
     351           0 :       pot => vxc_rho(1)%array
     352           0 :       WRITE (unit=120) pot(:, :, bo(2, 3))
     353           0 :       CLOSE (unit=120)
     354             :       OPEN (unit=120, file="vxc2.bindata", status="unknown", access='sequential', &
     355           0 :             form="unformatted", action="write")
     356           0 :       pot => vxc_rho2(1)%array
     357           0 :       WRITE (unit=120) pot(:, :, bo(2, 3))
     358           0 :       CLOSE (unit=120)
     359           0 :       IF (ASSOCIATED(vxc_tau)) THEN
     360             :          OPEN (unit=120, file="vxc_tau.bindata", status="unknown", access='sequential', &
     361           0 :                form="unformatted", action="write")
     362           0 :          pot => vxc_tau(1)%array
     363           0 :          WRITE (unit=120) pot(:, :, bo(2, 3))
     364           0 :          CLOSE (unit=120)
     365             :       END IF
     366           0 :       IF (ASSOCIATED(vxc_tau2)) THEN
     367             :          OPEN (unit=120, file="vxc_tau2_a.bindata", status="unknown", access='sequential', &
     368           0 :                form="unformatted", action="write")
     369           0 :          pot => vxc_tau2(1)%array
     370           0 :          WRITE (unit=120) pot(:, :, bo(2, 3))
     371           0 :          CLOSE (unit=120)
     372             :          OPEN (unit=120, file="vxc_tau2_b.bindata", status="unknown", access='sequential', &
     373           0 :                form="unformatted", action="write")
     374           0 :          pot => vxc_tau2(2)%array
     375           0 :          WRITE (unit=120) pot(:, :, bo(2, 3))
     376           0 :          CLOSE (unit=120)
     377             :       END IF
     378             : 
     379           0 :       PRINT *, "calc diff on vxc"
     380           0 :       maxDiff = 0.0_dp
     381           0 :       DO ispin = 1, 1
     382           0 :          ii = 0
     383           0 :          DO k = bo(1, 3), bo(2, 3)
     384           0 :             DO j = bo(1, 2), bo(2, 2)
     385           0 :                DO i = bo(1, 1), bo(2, 1)
     386           0 :                   ii = ii + 1
     387             :                   diff = ABS(vxc_rho(ispin)%array(i, j, k) - &
     388           0 :                              vxc_rho2(ispin)%array(i, j, k))
     389           0 :                   IF (ii == 1) THEN
     390           0 :                      PRINT *, "vxc", ispin, "=", vxc_rho(ispin)%array(i, j, k), &
     391           0 :                         "vs", vxc_rho2(ispin)%array(i, j, k), "diff=", diff
     392             :                   END IF
     393           0 :                   IF (maxDiff < diff) THEN
     394           0 :                      maxDiff = diff
     395           0 :                      PRINT *, "diff=", diff, " at ", i, ",", j, ",", k, &
     396           0 :                         " spin=", ispin, "rho=", rho_set1%rho(i, j, k), &
     397           0 :                         " ndrho=", rho_set1%norm_drho(i, j, k)
     398             :                   END IF
     399             :                END DO
     400             :             END DO
     401             :          END DO
     402             :       END DO
     403           0 :       PRINT *, "diff exc=", ABS(exc - exc2), "diff vxc=", maxdiff
     404             :       ! CPASSERT(maxdiff<5.e-11)
     405             :       ! CPASSERT(ABS(exc-exc2)<1.e-14)
     406             : 
     407           0 :       IF (ASSOCIATED(vxc_tau)) THEN
     408           0 :          PRINT *, "calc diff on vxc_tau"
     409           0 :          maxDiff = 0.0_dp
     410           0 :          DO ispin = 1, 1
     411           0 :             ii = 0
     412           0 :             DO k = bo(1, 3), bo(2, 3)
     413           0 :                DO j = bo(1, 2), bo(2, 2)
     414           0 :                   DO i = bo(1, 1), bo(2, 1)
     415           0 :                      ii = ii + 1
     416             :                      diff = ABS(vxc_tau(ispin)%array(i, j, k) - &
     417           0 :                                 vxc_tau2(ispin)%array(i, j, k))
     418           0 :                      IF (ii == 1) THEN
     419           0 :                         PRINT *, "vxc_tau", ispin, "=", vxc_tau(ispin)%array(i, j, k), &
     420           0 :                            "vs", vxc_tau2(ispin)%array(i, j, k), "diff=", diff
     421             :                      END IF
     422           0 :                      IF (maxDiff < diff) THEN
     423           0 :                         maxDiff = diff
     424           0 :                         PRINT *, "diff=", diff, " at ", i, ",", j, ",", k, &
     425           0 :                            " spin=", ispin, "rho=", rho_set1%rho(i, j, k), &
     426           0 :                            " ndrho=", rho_set1%norm_drho(i, j, k)
     427             :                      END IF
     428             :                   END DO
     429             :                END DO
     430             :             END DO
     431             :          END DO
     432           0 :          PRINT *, "diff exc=", ABS(exc - exc2), "diff vxc_tau=", maxdiff
     433             :       END IF
     434           0 :       deriv_iter => dSet1%derivs
     435           0 :       DO WHILE (cp_sll_xc_deriv_next(deriv_iter, el_att=deriv))
     436             :          CALL xc_derivative_get(deriv, order=order, &
     437           0 :                                 split_desc=split_desc, deriv_data=pot)
     438           0 :          SELECT CASE (order)
     439             :          CASE (0)
     440           0 :             filename = "e_0.bindata"
     441           0 :             deriv2 => xc_dset_get_derivative(dSet2, [INTEGER::])
     442             :          CASE (1)
     443           0 :             filename = "e_"//TRIM(id_to_desc(split_desc(1)))//".bindata"
     444           0 :             IF (split_desc(1) == deriv_rho) THEN
     445           0 :                deriv2 => xc_dset_get_derivative(dSet2, [deriv_rhoa])
     446           0 :             ELSEIF (split_desc(1) == deriv_tau) THEN
     447           0 :                deriv2 => xc_dset_get_derivative(dSet2, [deriv_tau_a])
     448           0 :             ELSEIF (split_desc(1) == deriv_norm_drho) THEN
     449           0 :                deriv2 => xc_dset_get_derivative(dSet2, [deriv_norm_drhoa])
     450           0 :                deriv3 => xc_dset_get_derivative(dSet2, [deriv_norm_drho])
     451           0 :                IF (ASSOCIATED(deriv3)) THEN
     452           0 :                   IF (ASSOCIATED(deriv2)) THEN
     453             :                      CALL xc_derivative_get(deriv2, &
     454           0 :                                             deriv_data=pot2)
     455             :                      CALL xc_derivative_get(deriv3, &
     456           0 :                                             deriv_data=pot3)
     457           0 :                      pot2 = pot2 + pot3
     458             :                   ELSE
     459             :                      deriv2 => deriv3
     460             :                   END IF
     461           0 :                   NULLIFY (deriv3, pot2, pot3)
     462             :                END IF
     463             :             ELSE
     464           0 :                CPABORT("Unknown derivative variable")
     465             :             END IF
     466             :          CASE default
     467           0 :             CPABORT("Unsupported derivative order")
     468             :          END SELECT
     469             :          CALL xc_derivative_get(deriv2, &
     470           0 :                                 deriv_data=pot2)
     471           0 :          PRINT *, "checking ", filename
     472           0 :          maxDiff = 0.0_dp
     473           0 :          DO k = bo(1, 3), bo(2, 3)
     474           0 :             DO j = bo(1, 2), bo(2, 2)
     475           0 :                DO i = bo(1, 1), bo(2, 1)
     476           0 :                   diff = ABS(pot(i, j, k) - pot2(i, j, k))
     477           0 :                   IF (maxDiff < diff) THEN
     478           0 :                      maxDiff = diff
     479           0 :                      PRINT *, "ediff(", i, j, k, ")=", maxDiff, &
     480           0 :                         "rho=", rho_set1%rho(i, j, k), &
     481           0 :                         "ndrho=", rho_set1%norm_drho(i, j, k)
     482             :                   END IF
     483             :                END DO
     484             :             END DO
     485             :          END DO
     486           0 :          PRINT *, "maxdiff ", filename, "=", maxDiff
     487             :          OPEN (unit=120, file=TRIM(filename), status="unknown", &
     488             :                access='sequential', &
     489           0 :                form="unformatted")
     490           0 :          WRITE (unit=120) pot(:, :, bo(2, 3))
     491           0 :          CLOSE (unit=120)
     492             :       END DO
     493           0 :       deriv_iter => dSet2%derivs
     494           0 :       DO WHILE (cp_sll_xc_deriv_next(deriv_iter, el_att=deriv))
     495             :          CALL xc_derivative_get(deriv, order=order, &
     496           0 :                                 split_desc=split_desc, deriv_data=pot)
     497           0 :          SELECT CASE (order)
     498             :          CASE (0)
     499           0 :             filename = "e_0-2.bindata"
     500             :          CASE (1)
     501           0 :             filename = "e_"//TRIM(id_to_desc(split_desc(1)))//"-2.bindata"
     502             :          CASE default
     503           0 :             CPABORT("Unsupported derivative order")
     504             :          END SELECT
     505             :          OPEN (unit=120, file=TRIM(filename), status="unknown", &
     506             :                access='sequential', &
     507           0 :                form="unformatted")
     508           0 :          WRITE (unit=120) pot(:, :, bo(2, 3))
     509           0 :          CLOSE (unit=120)
     510             :       END DO
     511           0 :       CALL xc_rho_set_release(rho_set1)
     512           0 :       CALL xc_rho_set_release(rho_set2)
     513           0 :       CALL xc_dset_release(dSet2)
     514           0 :       CALL xc_dset_release(dSet1)
     515           0 :       DO ispin = 1, 2
     516           0 :          CALL pw_pool%give_back_pw(rho2_r(ispin))
     517           0 :          CALL pw_pool%give_back_pw(vxc_rho2(ispin))
     518           0 :          IF (ASSOCIATED(vxc_tau2)) THEN
     519           0 :             CALL pw_pool%give_back_pw(vxc_tau2(ispin))
     520             :          END IF
     521             :       END DO
     522           0 :       DEALLOCATE (vxc_rho2, rho2_r, rho2_g)
     523           0 :       IF (ASSOCIATED(vxc_tau2)) THEN
     524           0 :          DEALLOCATE (vxc_tau2)
     525             :       END IF
     526             : 
     527           0 :    END SUBROUTINE xc_vxc_pw_create_test_lsd
     528             : 
     529             : ! **************************************************************************************************
     530             : !> \brief calculates vxc outputting the yz plane of rho, and of the various components
     531             : !>      of the the derivatives and of vxc
     532             : !> \param vxc_rho will contain the v_xc part that depend on rho
     533             : !>        (if one of the chosen xc functionals has it it is allocated and you
     534             : !>        are responsible for it)
     535             : !> \param vxc_tau will contain the kinetic tau part of v_xc
     536             : !>        (if one of the chosen xc functionals has it it is allocated and you
     537             : !>        are responsible for it)
     538             : !> \param rho_r the value of the density in the real space
     539             : !> \param rho_g value of the density in the g space (needs to be associated
     540             : !>        only for gradient corrections)
     541             : !> \param tau value of the kinetic density tau on the grid (can be null,
     542             : !>        used only with meta functionals)
     543             : !> \param exc the xc energy
     544             : !> \param xc_section which functional should be used, and how to do it
     545             : !> \param pw_pool the pool for the grids
     546             : !> \author Fawzi Mohamed
     547             : !> \note
     548             : !>      for debugging only.
     549             : ! **************************************************************************************************
     550           0 :    SUBROUTINE xc_vxc_pw_create_debug(vxc_rho, vxc_tau, rho_r, rho_g, tau, exc, &
     551             :                                      xc_section, pw_pool)
     552             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER             :: vxc_rho, vxc_tau
     553             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               :: rho_r, tau
     554             :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
     555             :       REAL(KIND=dp), INTENT(out)                         :: exc
     556             :       TYPE(section_vals_type), POINTER                   :: xc_section
     557             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     558             : 
     559             :       LOGICAL, PARAMETER                                 :: compute_virial = .FALSE.
     560             : 
     561             :       CHARACTER(len=default_path_length)                 :: filename
     562           0 :       INTEGER, DIMENSION(:), POINTER         :: split_desc
     563             :       INTEGER                                            :: i, ispin, j, k, order
     564             :       INTEGER, DIMENSION(2, 3)                           :: bo
     565             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: virial_xc
     566           0 :       REAL(kind=dp), DIMENSION(:, :, :), POINTER         :: pot
     567             :       TYPE(cp_logger_type), POINTER                      :: logger
     568             :       TYPE(cp_sll_xc_deriv_type), POINTER                :: deriv_iter
     569             :       TYPE(xc_derivative_set_type)                       :: dSet1
     570             :       TYPE(xc_derivative_type), POINTER                  :: deriv
     571             :       TYPE(xc_rho_set_type)                              :: rho_set1
     572             : 
     573           0 :       NULLIFY (pot, deriv)
     574           0 :       logger => cp_get_default_logger()
     575             : 
     576           0 :       bo = rho_r(1)%pw_grid%bounds_local
     577             : 
     578             :       CALL xc_rho_set_and_dset_create(rho_r=rho_r, rho_g=rho_g, &
     579             :                                       tau=tau, xc_section=xc_section, &
     580             :                                       pw_pool=pw_pool, rho_set=rho_set1, &
     581             :                                       deriv_set=dSet1, deriv_order=1, &
     582           0 :                                       calc_potential=.FALSE.)
     583             : 
     584             :       ! outputs 0,:,: plane
     585           0 :       IF (bo(1, 1) <= 0 .AND. 0 <= bo(2, 1)) THEN
     586           0 :          IF (rho_set1%has%rho_spin) THEN
     587             :             OPEN (unit=120, file="rhoa.bindata", status="unknown", access='sequential', &
     588           0 :                   form="unformatted", action="write")
     589           0 :             pot => rho_set1%rhoa
     590           0 :             WRITE (unit=120) pot(0, :, :)
     591           0 :             CLOSE (unit=120)
     592             :             OPEN (unit=120, file="rhob.bindata", status="unknown", access='sequential', &
     593           0 :                   form="unformatted", action="write")
     594           0 :             pot => rho_set1%rhob
     595           0 :             WRITE (unit=120) pot(0, :, :)
     596           0 :             CLOSE (unit=120)
     597             :          END IF
     598           0 :          IF (rho_set1%has%norm_drho) THEN
     599             :             OPEN (unit=120, file="ndrho.bindata", status="unknown", access='sequential', &
     600           0 :                   form="unformatted", action="write")
     601           0 :             pot => rho_set1%norm_drho
     602           0 :             WRITE (unit=120) pot(0, :, :)
     603           0 :             CLOSE (unit=120)
     604             :          END IF
     605           0 :          IF (rho_set1%has%norm_drho_spin) THEN
     606             :             OPEN (unit=120, file="ndrhoa.bindata", status="unknown", access='sequential', &
     607           0 :                   form="unformatted", action="write")
     608           0 :             pot => rho_set1%norm_drhoa
     609           0 :             WRITE (unit=120) pot(0, :, :)
     610           0 :             CLOSE (unit=120)
     611             :             OPEN (unit=120, file="ndrhob.bindata", status="unknown", access='sequential', &
     612           0 :                   form="unformatted", action="write")
     613           0 :             pot => rho_set1%norm_drhob
     614           0 :             WRITE (unit=120) pot(0, :, :)
     615           0 :             CLOSE (unit=120)
     616             :          END IF
     617           0 :          IF (rho_set1%has%rho) THEN
     618             :             OPEN (unit=120, file="rho.bindata", status="unknown", access='sequential', &
     619           0 :                   form="unformatted", action="write")
     620           0 :             pot => rho_set1%rho
     621           0 :             WRITE (unit=120) pot(0, :, :)
     622           0 :             CLOSE (unit=120)
     623             :          END IF
     624           0 :          IF (rho_set1%has%tau) THEN
     625             :             OPEN (unit=120, file="tau.bindata", status="unknown", access='sequential', &
     626           0 :                   form="unformatted", action="write")
     627           0 :             pot => rho_set1%tau
     628           0 :             WRITE (unit=120) pot(0, :, :)
     629           0 :             CLOSE (unit=120)
     630             :          END IF
     631           0 :          IF (rho_set1%has%tau_spin) THEN
     632             :             OPEN (unit=120, file="tau_a.bindata", status="unknown", access='sequential', &
     633           0 :                   form="unformatted", action="write")
     634           0 :             pot => rho_set1%tau_a
     635           0 :             WRITE (unit=120) pot(0, :, :)
     636           0 :             CLOSE (unit=120)
     637             :             OPEN (unit=120, file="tau_b.bindata", status="unknown", access='sequential', &
     638           0 :                   form="unformatted", action="write")
     639           0 :             pot => rho_set1%tau_b
     640           0 :             WRITE (unit=120) pot(0, :, :)
     641           0 :             CLOSE (unit=120)
     642             :          END IF
     643             : 
     644           0 :          deriv_iter => dSet1%derivs
     645           0 :          DO WHILE (cp_sll_xc_deriv_next(deriv_iter, el_att=deriv))
     646             :             CALL xc_derivative_get(deriv, order=order, &
     647           0 :                                    split_desc=split_desc, deriv_data=pot)
     648           0 :             SELECT CASE (order)
     649             :             CASE (0)
     650           0 :                filename = "e_0.bindata"
     651             :             CASE (1)
     652           0 :                filename = "e_"//TRIM(id_to_desc(split_desc(1)))//".bindata"
     653             :             CASE default
     654           0 :                CPABORT("Unsupported derivative order")
     655             :             END SELECT
     656             :             OPEN (unit=120, file=TRIM(filename), status="unknown", &
     657             :                   access='sequential', &
     658           0 :                   form="unformatted")
     659           0 :             WRITE (unit=120) pot(0, :, :)
     660           0 :             CLOSE (unit=120)
     661             :          END DO
     662             :       END IF
     663             : 
     664             :       CALL xc_vxc_pw_create(vxc_rho=vxc_rho, vxc_tau=vxc_tau, &
     665             :                             rho_r=rho_r, rho_g=rho_g, tau=tau, &
     666             :                             exc=exc, xc_section=xc_section, &
     667             :                             pw_pool=pw_pool, &
     668           0 :                             compute_virial=compute_virial, virial_xc=virial_xc)
     669             : 
     670             :       ! outputs 0,:,: plane
     671           0 :       IF (bo(1, 1) <= 0 .AND. 0 <= bo(2, 1)) THEN
     672           0 :          IF (ASSOCIATED(vxc_rho)) THEN
     673           0 :             DO ispin = 1, SIZE(vxc_rho)
     674           0 :                WRITE (filename, "('vxc-',i1,'.bindata')") ispin
     675             :                OPEN (unit=120, file=filename, status="unknown", access='sequential', &
     676           0 :                      form="unformatted", action="write")
     677           0 :                pot => vxc_rho(ispin)%array
     678           0 :                WRITE (unit=120) pot(0, :, :)
     679           0 :                CLOSE (unit=120)
     680             : 
     681           0 :                pot => vxc_rho(ispin)%array
     682           0 :                DO k = bo(1, 3), bo(2, 3)
     683           0 :                   DO j = bo(1, 2), bo(2, 2)
     684           0 :                      DO i = bo(1, 1), bo(2, 1)
     685           0 :                         IF (ABS(pot(i, j, k)) > 10.0_dp) THEN
     686             :                            WRITE (cp_logger_get_default_unit_nr(logger), &
     687             :                                   "(' vxc_',i1,'(',i6,',',i6,',',i6,')=',e11.4)", &
     688           0 :                                   advance="no") ispin, i, j, k, pot(i, j, k)
     689           0 :                            IF (rho_set1%has%rho_spin) THEN
     690             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     691             :                                      "(' rho=(',e11.4,',',e11.4,')')", advance="no") &
     692           0 :                                  rho_set1%rhoa(i, j, k), rho_set1%rhob(i, j, k)
     693           0 :                            ELSE IF (rho_set1%has%rho) THEN
     694             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     695           0 :                                      "(' rho=',e11.4)", advance="no") rho_set1%rho(i, j, k)
     696             :                            END IF
     697           0 :                            IF (rho_set1%has%norm_drho_spin) THEN
     698             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     699             :                                      "(' ndrho=(',e11.4,',',e11.4,')')", advance="no") &
     700           0 :                                  rho_set1%norm_drhoa(i, j, k), &
     701           0 :                                  rho_set1%norm_drhob(i, j, k)
     702           0 :                            ELSE IF (rho_set1%has%norm_drho) THEN
     703             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     704           0 :                                      "(' ndrho=',e11.4)", advance="no") rho_set1%norm_drho(i, j, k)
     705             :                            END IF
     706           0 :                            IF (rho_set1%has%tau_spin) THEN
     707             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     708             :                                      "(' tau=(',e11.4,',',e11.4,')')", advance="no") &
     709           0 :                                  rho_set1%tau_a(i, j, k), &
     710           0 :                                  rho_set1%tau_b(i, j, k)
     711           0 :                            ELSE IF (rho_set1%has%tau) THEN
     712             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     713           0 :                                      "(' tau=',e11.4)", advance="no") rho_set1%tau(i, j, k)
     714             :                            END IF
     715             : 
     716           0 :                            deriv_iter => dSet1%derivs
     717           0 :                            DO WHILE (cp_sll_xc_deriv_next(deriv_iter, el_att=deriv))
     718             :                               CALL xc_derivative_get(deriv, order=order, &
     719           0 :                                                      split_desc=split_desc, deriv_data=pot)
     720           0 :                               SELECT CASE (order)
     721             :                               CASE (0)
     722           0 :                                  filename = " e_0"
     723             :                               CASE (1)
     724           0 :                                  filename = " e_"//TRIM(id_to_desc(split_desc(1)))
     725             :                               CASE default
     726           0 :                                  CPABORT("Unsupported derivative order")
     727             :                               END SELECT
     728             :                               WRITE (unit=cp_logger_get_default_unit_nr(logger), &
     729             :                                      fmt="(a,'=',e11.4)", advance="no") &
     730           0 :                                  TRIM(filename), pot(i, j, k)
     731             :                            END DO
     732             : 
     733             :                            WRITE (cp_logger_get_default_unit_nr(logger), &
     734           0 :                                   "()")
     735             :                         END IF
     736             :                      END DO
     737             :                   END DO
     738             :                END DO
     739             :             END DO
     740             :          END IF
     741           0 :          IF (ASSOCIATED(vxc_tau)) THEN
     742           0 :             DO ispin = 1, SIZE(vxc_tau)
     743           0 :                WRITE (filename, "('vxc_tau_',i1,'.bindata')") ispin
     744             :                OPEN (unit=120, file=filename, status="unknown", access='sequential', &
     745           0 :                      form="unformatted", action="write")
     746           0 :                pot => vxc_tau(ispin)%array
     747           0 :                WRITE (unit=120) pot(0, :, :)
     748           0 :                CLOSE (unit=120)
     749             : 
     750           0 :                pot => vxc_tau(ispin)%array
     751           0 :                DO k = bo(1, 3), bo(2, 3)
     752           0 :                   DO j = bo(1, 2), bo(2, 2)
     753           0 :                      DO i = bo(1, 1), bo(2, 1)
     754           0 :                         IF (ABS(pot(i, j, k)) > 10.0_dp) THEN
     755             :                            WRITE (cp_logger_get_default_unit_nr(logger), &
     756             :                                   "('vxc_tau_',i1,'(',i6,',',i6,',',i6,')=',e11.4)", &
     757           0 :                                   advance="no") ispin, i, j, k, pot(i, j, k)
     758           0 :                            IF (rho_set1%has%rho_spin) THEN
     759             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     760             :                                      "(' rho=(',e11.4,',',e11.4,')')", advance="no") &
     761           0 :                                  rho_set1%rhoa(i, j, k), rho_set1%rhob(i, j, k)
     762           0 :                            ELSE IF (rho_set1%has%rho) THEN
     763             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     764           0 :                                      "(' rho=',e11.4)", advance="no") rho_set1%rho(i, j, k)
     765             :                            END IF
     766           0 :                            IF (rho_set1%has%norm_drho_spin) THEN
     767             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     768             :                                      "(' ndrho=(',e11.4,',',e11.4,')')", advance="no") &
     769           0 :                                  rho_set1%norm_drhoa(i, j, k), &
     770           0 :                                  rho_set1%norm_drhob(i, j, k)
     771           0 :                            ELSE IF (rho_set1%has%norm_drho) THEN
     772             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     773           0 :                                      "(' ndrho=',e11.4)", advance="no") rho_set1%norm_drho(i, j, k)
     774             :                            END IF
     775           0 :                            IF (rho_set1%has%tau_spin) THEN
     776             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     777             :                                      "(' tau=(',e11.4,',',e11.4,')')", advance="no") &
     778           0 :                                  rho_set1%tau_a(i, j, k), &
     779           0 :                                  rho_set1%tau_b(i, j, k)
     780           0 :                            ELSE IF (rho_set1%has%tau) THEN
     781             :                               WRITE (cp_logger_get_default_unit_nr(logger), &
     782           0 :                                      "(' tau=',e11.4)", advance="no") rho_set1%tau(i, j, k)
     783             :                            END IF
     784             : 
     785           0 :                            deriv_iter => dSet1%derivs
     786           0 :                            DO WHILE (cp_sll_xc_deriv_next(deriv_iter, el_att=deriv))
     787             :                               CALL xc_derivative_get(deriv, order=order, &
     788           0 :                                                      split_desc=split_desc, deriv_data=pot)
     789           0 :                               SELECT CASE (order)
     790             :                               CASE (0)
     791           0 :                                  filename = " e_0"
     792             :                               CASE (1)
     793           0 :                                  filename = " e_"//TRIM(id_to_desc(split_desc(1)))
     794             :                               CASE default
     795           0 :                                  CPABORT("Unsupported derivative order")
     796             :                               END SELECT
     797             :                               WRITE (unit=cp_logger_get_default_unit_nr(logger), &
     798             :                                      fmt="(a,'=',e11.4)", advance="no") &
     799           0 :                                  TRIM(filename), pot(i, j, k)
     800             :                            END DO
     801             : 
     802           0 :                            WRITE (cp_logger_get_default_unit_nr(logger), "()")
     803             :                         END IF
     804             :                      END DO
     805             :                   END DO
     806             :                END DO
     807             :             END DO
     808             :          END IF
     809             :       END IF
     810             : 
     811           0 :       CALL xc_dset_release(dSet1)
     812           0 :       CALL xc_rho_set_release(rho_set1)
     813           0 :    END SUBROUTINE xc_vxc_pw_create_debug
     814             : 
     815             : ! **************************************************************************************************
     816             : !> \brief creates a xc_rho_set and a derivative set containing the derivatives
     817             : !>      of the functionals with the given deriv_order.
     818             : !> \param rho_set will contain the rho set
     819             : !> \param deriv_set will contain the derivatives
     820             : !> \param deriv_order the order of the requested derivatives. If positive
     821             : !>        0:deriv_order are calculated, if negative only -deriv_order is
     822             : !>        guaranteed to be valid. Orders not requested might be present,
     823             : !>        but might contain garbage.
     824             : !> \param rho_r the value of the density in the real space
     825             : !> \param rho_g value of the density in the g space (can be null, used only
     826             : !>        without smoothing of rho or deriv)
     827             : !> \param tau value of the kinetic density tau on the grid (can be null,
     828             : !>        used only with meta functionals)
     829             : !> \param xc_section the section describing the functional to use
     830             : !> \param pw_pool the pool for the grids
     831             : !> \param calc_potential if the basic components of the arguments
     832             : !>        should be kept in rho set (a basic component is for example drho
     833             : !>        when with lda a functional needs norm_drho)
     834             : !> \author fawzi
     835             : !> \note
     836             : !>      if any of the functionals is gradient corrected the full gradient is
     837             : !>      added to the rho set
     838             : ! **************************************************************************************************
     839      128281 :    SUBROUTINE xc_rho_set_and_dset_create(rho_set, deriv_set, deriv_order, &
     840             :                                          rho_r, rho_g, tau, xc_section, pw_pool, &
     841             :                                          calc_potential)
     842             : 
     843             :       TYPE(xc_rho_set_type)                              :: rho_set
     844             :       TYPE(xc_derivative_set_type)                       :: deriv_set
     845             :       INTEGER, INTENT(in)                                :: deriv_order
     846             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               :: rho_r, tau
     847             :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
     848             :       TYPE(section_vals_type), POINTER                   :: xc_section
     849             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     850             :       LOGICAL, INTENT(in)                                :: calc_potential
     851             : 
     852             :       CHARACTER(len=*), PARAMETER :: routineN = 'xc_rho_set_and_dset_create'
     853             : 
     854             :       INTEGER                                            :: handle, nspins
     855             :       LOGICAL                                            :: lsd
     856             :       TYPE(section_vals_type), POINTER                   :: xc_fun_sections
     857             : 
     858      128281 :       CALL timeset(routineN, handle)
     859             : 
     860      128281 :       CPASSERT(ASSOCIATED(pw_pool))
     861             : 
     862      128281 :       nspins = SIZE(rho_r)
     863      128281 :       lsd = (nspins /= 1)
     864             : 
     865      128281 :       xc_fun_sections => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
     866             : 
     867      128281 :       CALL xc_dset_create(deriv_set, pw_pool)
     868             : 
     869             :       CALL xc_rho_set_create(rho_set, &
     870             :                              rho_r(1)%pw_grid%bounds_local, &
     871             :                              rho_cutoff=section_get_rval(xc_section, "density_cutoff"), &
     872             :                              drho_cutoff=section_get_rval(xc_section, "gradient_cutoff"), &
     873      128281 :                              tau_cutoff=section_get_rval(xc_section, "tau_cutoff"))
     874             : 
     875             :       CALL xc_rho_set_update(rho_set, rho_r, rho_g, tau, &
     876             :                              xc_functionals_get_needs(xc_fun_sections, lsd, calc_potential), &
     877             :                              section_get_ival(xc_section, "XC_GRID%XC_DERIV"), &
     878             :                              section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO"), &
     879      128281 :                              pw_pool)
     880             : 
     881             :       CALL xc_functionals_eval(xc_fun_sections, &
     882             :                                lsd=lsd, &
     883             :                                rho_set=rho_set, &
     884             :                                deriv_set=deriv_set, &
     885      128281 :                                deriv_order=deriv_order)
     886             : 
     887      128281 :       CALL divide_by_norm_drho(deriv_set, rho_set, lsd)
     888             : 
     889      128281 :       CALL timestop(handle)
     890             : 
     891      128281 :    END SUBROUTINE xc_rho_set_and_dset_create
     892             : 
     893             : ! **************************************************************************************************
     894             : !> \brief smooths the cutoff on rho with a function smoothderiv_rho that is 0
     895             : !>      for rho<rho_cutoff and 1 for rho>rho_cutoff*rho_smooth_cutoff_range:
     896             : !>      E= integral e_0*smoothderiv_rho => dE/d...= de/d... * smooth,
     897             : !>      dE/drho = de/drho * smooth + e_0 * dsmooth/drho
     898             : !> \param pot the potential to smooth
     899             : !> \param rho , rhoa,rhob: the value of the density (used to apply the cutoff)
     900             : !> \param rhoa ...
     901             : !> \param rhob ...
     902             : !> \param rho_cutoff the value at whch the cutoff function must go to 0
     903             : !> \param rho_smooth_cutoff_range range of the smoothing
     904             : !> \param e_0 value of e_0, if given it is assumed that pot is the derivative
     905             : !>        wrt. to rho, and needs the dsmooth*e_0 contribution
     906             : !> \param e_0_scale_factor ...
     907             : !> \author Fawzi Mohamed
     908             : ! **************************************************************************************************
     909      247514 :    SUBROUTINE smooth_cutoff(pot, rho, rhoa, rhob, rho_cutoff, &
     910             :                             rho_smooth_cutoff_range, e_0, e_0_scale_factor)
     911             :       REAL(kind=dp), DIMENSION(:, :, :), INTENT(IN), &
     912             :          POINTER                                         :: pot, rho, rhoa, rhob
     913             :       REAL(kind=dp), INTENT(in)                          :: rho_cutoff, rho_smooth_cutoff_range
     914             :       REAL(kind=dp), DIMENSION(:, :, :), OPTIONAL, &
     915             :          POINTER                                         :: e_0
     916             :       REAL(kind=dp), INTENT(in), OPTIONAL                :: e_0_scale_factor
     917             : 
     918             :       INTEGER                                            :: i, j, k
     919             :       INTEGER, DIMENSION(2, 3)                           :: bo
     920             :       REAL(kind=dp) :: my_e_0_scale_factor, my_rho, my_rho_n, my_rho_n2, rho_smooth_cutoff, &
     921             :                        rho_smooth_cutoff_2, rho_smooth_cutoff_range_2
     922             : 
     923      247514 :       CPASSERT(ASSOCIATED(pot))
     924      990056 :       bo(1, :) = LBOUND(pot)
     925      990056 :       bo(2, :) = UBOUND(pot)
     926      247514 :       my_e_0_scale_factor = 1.0_dp
     927      247514 :       IF (PRESENT(e_0_scale_factor)) my_e_0_scale_factor = e_0_scale_factor
     928      247514 :       rho_smooth_cutoff = rho_cutoff*rho_smooth_cutoff_range
     929      247514 :       rho_smooth_cutoff_2 = (rho_cutoff + rho_smooth_cutoff)/2
     930      247514 :       rho_smooth_cutoff_range_2 = rho_smooth_cutoff_2 - rho_cutoff
     931             : 
     932      247514 :       IF (rho_smooth_cutoff_range > 0.0_dp) THEN
     933           2 :          IF (PRESENT(e_0)) THEN
     934           0 :             CPASSERT(ASSOCIATED(e_0))
     935           0 :             IF (ASSOCIATED(rho)) THEN
     936             : !$OMP              PARALLEL DO DEFAULT(NONE) SHARED(bo,e_0,pot,rho,&
     937             : !$OMP                          rho_cutoff,rho_smooth_cutoff,rho_smooth_cutoff_2,&
     938             : !$OMP                          rho_smooth_cutoff_range_2,my_e_0_scale_factor)&
     939           0 : !$OMP                    PRIVATE(k,j,i,my_rho,my_rho_n,my_rho_n2) COLLAPSE(3)
     940             :                DO k = bo(1, 3), bo(2, 3)
     941             :                   DO j = bo(1, 2), bo(2, 2)
     942             :                      DO i = bo(1, 1), bo(2, 1)
     943             :                         my_rho = rho(i, j, k)
     944             :                         IF (my_rho < rho_smooth_cutoff) THEN
     945             :                            IF (my_rho < rho_cutoff) THEN
     946             :                               pot(i, j, k) = 0.0_dp
     947             :                            ELSEIF (my_rho < rho_smooth_cutoff_2) THEN
     948             :                               my_rho_n = (my_rho - rho_cutoff)/rho_smooth_cutoff_range_2
     949             :                               my_rho_n2 = my_rho_n*my_rho_n
     950             :                               pot(i, j, k) = pot(i, j, k)* &
     951             :                                              my_rho_n2*(my_rho_n - 0.5_dp*my_rho_n2) + &
     952             :                                              my_e_0_scale_factor*e_0(i, j, k)* &
     953             :                                              my_rho_n2*(3.0_dp - 2.0_dp*my_rho_n) &
     954             :                                              /rho_smooth_cutoff_range_2
     955             :                            ELSE
     956             :                               my_rho_n = 2.0_dp - (my_rho - rho_cutoff)/rho_smooth_cutoff_range_2
     957             :                               my_rho_n2 = my_rho_n*my_rho_n
     958             :                               pot(i, j, k) = pot(i, j, k)* &
     959             :                                              (1.0_dp - my_rho_n2*(my_rho_n - 0.5_dp*my_rho_n2)) &
     960             :                                              + my_e_0_scale_factor*e_0(i, j, k)* &
     961             :                                              my_rho_n2*(3.0_dp - 2.0_dp*my_rho_n) &
     962             :                                              /rho_smooth_cutoff_range_2
     963             :                            END IF
     964             :                         END IF
     965             :                      END DO
     966             :                   END DO
     967             :                END DO
     968             :             ELSE
     969             : !$OMP              PARALLEL DO DEFAULT(NONE) SHARED(bo,pot,e_0,rhoa,rhob,&
     970             : !$OMP                          rho_cutoff,rho_smooth_cutoff,rho_smooth_cutoff_2,&
     971             : !$OMP                          rho_smooth_cutoff_range_2,my_e_0_scale_factor)&
     972           0 : !$OMP                    PRIVATE(k,j,i,my_rho,my_rho_n,my_rho_n2) COLLAPSE(3)
     973             :                DO k = bo(1, 3), bo(2, 3)
     974             :                   DO j = bo(1, 2), bo(2, 2)
     975             :                      DO i = bo(1, 1), bo(2, 1)
     976             :                         my_rho = rhoa(i, j, k) + rhob(i, j, k)
     977             :                         IF (my_rho < rho_smooth_cutoff) THEN
     978             :                            IF (my_rho < rho_cutoff) THEN
     979             :                               pot(i, j, k) = 0.0_dp
     980             :                            ELSEIF (my_rho < rho_smooth_cutoff_2) THEN
     981             :                               my_rho_n = (my_rho - rho_cutoff)/rho_smooth_cutoff_range_2
     982             :                               my_rho_n2 = my_rho_n*my_rho_n
     983             :                               pot(i, j, k) = pot(i, j, k)* &
     984             :                                              my_rho_n2*(my_rho_n - 0.5_dp*my_rho_n2) + &
     985             :                                              my_e_0_scale_factor*e_0(i, j, k)* &
     986             :                                              my_rho_n2*(3.0_dp - 2.0_dp*my_rho_n) &
     987             :                                              /rho_smooth_cutoff_range_2
     988             :                            ELSE
     989             :                               my_rho_n = 2.0_dp - (my_rho - rho_cutoff)/rho_smooth_cutoff_range_2
     990             :                               my_rho_n2 = my_rho_n*my_rho_n
     991             :                               pot(i, j, k) = pot(i, j, k)* &
     992             :                                              (1.0_dp - my_rho_n2*(my_rho_n - 0.5_dp*my_rho_n2)) &
     993             :                                              + my_e_0_scale_factor*e_0(i, j, k)* &
     994             :                                              my_rho_n2*(3.0_dp - 2.0_dp*my_rho_n) &
     995             :                                              /rho_smooth_cutoff_range_2
     996             :                            END IF
     997             :                         END IF
     998             :                      END DO
     999             :                   END DO
    1000             :                END DO
    1001             :             END IF
    1002             :          ELSE
    1003           2 :             IF (ASSOCIATED(rho)) THEN
    1004             : !$OMP              PARALLEL DO DEFAULT(NONE) SHARED(bo,pot,&
    1005             : !$OMP                          rho_cutoff,rho_smooth_cutoff,rho_smooth_cutoff_2,&
    1006             : !$OMP                          rho_smooth_cutoff_range_2,rho)&
    1007           2 : !$OMP                    PRIVATE(k,j,i,my_rho,my_rho_n,my_rho_n2) COLLAPSE(3)
    1008             :                DO k = bo(1, 3), bo(2, 3)
    1009             :                   DO j = bo(1, 2), bo(2, 2)
    1010             :                      DO i = bo(1, 1), bo(2, 1)
    1011             :                         my_rho = rho(i, j, k)
    1012             :                         IF (my_rho < rho_smooth_cutoff) THEN
    1013             :                            IF (my_rho < rho_cutoff) THEN
    1014             :                               pot(i, j, k) = 0.0_dp
    1015             :                            ELSEIF (my_rho < rho_smooth_cutoff_2) THEN
    1016             :                               my_rho_n = (my_rho - rho_cutoff)/rho_smooth_cutoff_range_2
    1017             :                               my_rho_n2 = my_rho_n*my_rho_n
    1018             :                               pot(i, j, k) = pot(i, j, k)* &
    1019             :                                              my_rho_n2*(my_rho_n - 0.5_dp*my_rho_n2)
    1020             :                            ELSE
    1021             :                               my_rho_n = 2.0_dp - (my_rho - rho_cutoff)/rho_smooth_cutoff_range_2
    1022             :                               my_rho_n2 = my_rho_n*my_rho_n
    1023             :                               pot(i, j, k) = pot(i, j, k)* &
    1024             :                                              (1.0_dp - my_rho_n2*(my_rho_n - 0.5_dp*my_rho_n2))
    1025             :                            END IF
    1026             :                         END IF
    1027             :                      END DO
    1028             :                   END DO
    1029             :                END DO
    1030             :             ELSE
    1031             : !$OMP              PARALLEL DO DEFAULT(NONE) SHARED(bo,pot,&
    1032             : !$OMP                          rho_cutoff,rho_smooth_cutoff,rho_smooth_cutoff_2,&
    1033             : !$OMP                          rho_smooth_cutoff_range_2,rhoa,rhob)&
    1034           0 : !$OMP                    PRIVATE(k,j,i,my_rho,my_rho_n,my_rho_n2) COLLAPSE(3)
    1035             :                DO k = bo(1, 3), bo(2, 3)
    1036             :                   DO j = bo(1, 2), bo(2, 2)
    1037             :                      DO i = bo(1, 1), bo(2, 1)
    1038             :                         my_rho = rhoa(i, j, k) + rhob(i, j, k)
    1039             :                         IF (my_rho < rho_smooth_cutoff) THEN
    1040             :                            IF (my_rho < rho_cutoff) THEN
    1041             :                               pot(i, j, k) = 0.0_dp
    1042             :                            ELSEIF (my_rho < rho_smooth_cutoff_2) THEN
    1043             :                               my_rho_n = (my_rho - rho_cutoff)/rho_smooth_cutoff_range_2
    1044             :                               my_rho_n2 = my_rho_n*my_rho_n
    1045             :                               pot(i, j, k) = pot(i, j, k)* &
    1046             :                                              my_rho_n2*(my_rho_n - 0.5_dp*my_rho_n2)
    1047             :                            ELSE
    1048             :                               my_rho_n = 2.0_dp - (my_rho - rho_cutoff)/rho_smooth_cutoff_range_2
    1049             :                               my_rho_n2 = my_rho_n*my_rho_n
    1050             :                               pot(i, j, k) = pot(i, j, k)* &
    1051             :                                              (1.0_dp - my_rho_n2*(my_rho_n - 0.5_dp*my_rho_n2))
    1052             :                            END IF
    1053             :                         END IF
    1054             :                      END DO
    1055             :                   END DO
    1056             :                END DO
    1057             :             END IF
    1058             :          END IF
    1059             :       END IF
    1060      247514 :    END SUBROUTINE smooth_cutoff
    1061             : 
    1062          64 :    SUBROUTINE calc_xc_density(pot, rho, rho_cutoff)
    1063             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                       :: pot
    1064             :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(INOUT)         :: rho
    1065             :       REAL(kind=dp), INTENT(in)                          :: rho_cutoff
    1066             : 
    1067             :       INTEGER                                            :: i, j, k, nspins
    1068             :       INTEGER, DIMENSION(2, 3)                           :: bo
    1069             :       REAL(kind=dp)                                      :: eps1, eps2, my_rho, my_pot
    1070             : 
    1071         256 :       bo(1, :) = LBOUND(pot%array)
    1072         256 :       bo(2, :) = UBOUND(pot%array)
    1073          64 :       nspins = SIZE(rho)
    1074             : 
    1075          64 :       eps1 = rho_cutoff*1.E-4_dp
    1076          64 :       eps2 = rho_cutoff
    1077             : 
    1078        3160 :       DO k = bo(1, 3), bo(2, 3)
    1079      161272 :          DO j = bo(1, 2), bo(2, 2)
    1080     4529376 :             DO i = bo(1, 1), bo(2, 1)
    1081     4368168 :                my_pot = pot%array(i, j, k)
    1082     4368168 :                IF (nspins == 2) THEN
    1083      339714 :                   my_rho = rho(1)%array(i, j, k) + rho(2)%array(i, j, k)
    1084             :                ELSE
    1085     4028454 :                   my_rho = rho(1)%array(i, j, k)
    1086             :                END IF
    1087     4526280 :                IF (my_rho > eps1) THEN
    1088     4139834 :                   pot%array(i, j, k) = my_pot/my_rho
    1089      228334 :                ELSE IF (my_rho < eps2) THEN
    1090      228334 :                   pot%array(i, j, k) = 0.0_dp
    1091             :                ELSE
    1092           0 :                   pot%array(i, j, k) = MIN(my_pot/my_rho, my_rho**(1._dp/3._dp))
    1093             :                END IF
    1094             :             END DO
    1095             :          END DO
    1096             :       END DO
    1097             : 
    1098          64 :    END SUBROUTINE calc_xc_density
    1099             : 
    1100             : ! **************************************************************************************************
    1101             : !> \brief Exchange and Correlation functional calculations
    1102             : !> \param vxc_rho will contain the v_xc part that depend on rho
    1103             : !>        (if one of the chosen xc functionals has it it is allocated and you
    1104             : !>        are responsible for it)
    1105             : !> \param vxc_tau will contain the kinetic tau part of v_xc
    1106             : !>        (if one of the chosen xc functionals has it it is allocated and you
    1107             : !>        are responsible for it)
    1108             : !> \param exc the xc energy
    1109             : !> \param rho_r the value of the density in the real space
    1110             : !> \param rho_g value of the density in the g space (needs to be associated
    1111             : !>        only for gradient corrections)
    1112             : !> \param tau value of the kinetic density tau on the grid (can be null,
    1113             : !>        used only with meta functionals)
    1114             : !> \param xc_section which functional to calculate, and how to do it
    1115             : !> \param pw_pool the pool for the grids
    1116             : !> \param compute_virial ...
    1117             : !> \param virial_xc ...
    1118             : !> \param exc_r the value of the xc functional in the real space
    1119             : !> \par History
    1120             : !>      JGH (13-Jun-2002): adaptation to new functionals
    1121             : !>      Fawzi (11.2002): drho_g(1:3)->drho_g
    1122             : !>      Fawzi (1.2003). lsd version
    1123             : !>      Fawzi (11.2003): version using the new xc interface
    1124             : !>      Fawzi (03.2004): fft free for smoothed density and derivs, gga lsd
    1125             : !>      Fawzi (04.2004): metafunctionals
    1126             : !>      mguidon (12.2008) : laplace functionals
    1127             : !> \author fawzi; based LDA version of JGH, based on earlier version of apsi
    1128             : !> \note
    1129             : !>      Beware: some really dirty pointer handling!
    1130             : !>      energy should be kept consistent with xc_exc_calc
    1131             : ! **************************************************************************************************
    1132      108860 :    SUBROUTINE xc_vxc_pw_create(vxc_rho, vxc_tau, exc, rho_r, rho_g, tau, xc_section, &
    1133             :                                pw_pool, compute_virial, virial_xc, exc_r)
    1134             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER             :: vxc_rho, vxc_tau
    1135             :       REAL(KIND=dp), INTENT(out)                         :: exc
    1136             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               :: rho_r, tau
    1137             :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
    1138             :       TYPE(section_vals_type), POINTER                   :: xc_section
    1139             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
    1140             :       LOGICAL                                            :: compute_virial
    1141             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(OUT)        :: virial_xc
    1142             :       TYPE(pw_r3d_rs_type), INTENT(INOUT), OPTIONAL            :: exc_r
    1143             : 
    1144             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xc_vxc_pw_create'
    1145             :       INTEGER, DIMENSION(2), PARAMETER :: norm_drho_spin_name = [deriv_norm_drhoa, deriv_norm_drhob]
    1146             : 
    1147             :       INTEGER                                            :: handle, idir, ispin, jdir, &
    1148             :                                                             npoints, nspins, &
    1149             :                                                             xc_deriv_method_id, xc_rho_smooth_id, deriv_id
    1150             :       INTEGER, DIMENSION(2, 3)                           :: bo
    1151             :       LOGICAL                                            :: dealloc_pw_to_deriv, has_laplace, &
    1152             :                                                             has_tau, lsd, use_virial, has_gradient, &
    1153             :                                                             has_derivs, has_rho, dealloc_pw_to_deriv_rho
    1154             :       REAL(KIND=dp)                                      :: density_smooth_cut_range, drho_cutoff, &
    1155             :                                                             rho_cutoff
    1156      108860 :       REAL(kind=dp), DIMENSION(:, :, :), POINTER         :: deriv_data, norm_drho, norm_drho_spin, &
    1157      217720 :                                                             rho, rhoa, rhob
    1158             :       TYPE(cp_sll_xc_deriv_type), POINTER                :: pos
    1159             :       TYPE(pw_grid_type), POINTER                        :: pw_grid
    1160      762020 :       TYPE(pw_r3d_rs_type), DIMENSION(3)                      :: pw_to_deriv, pw_to_deriv_rho
    1161             :       TYPE(pw_c1d_gs_type) :: tmp_g, vxc_g
    1162             :       TYPE(pw_r3d_rs_type)                                      ::  v_drho_r, virial_pw
    1163             :       TYPE(xc_derivative_set_type)                       :: deriv_set
    1164             :       TYPE(xc_derivative_type), POINTER                  :: deriv_att
    1165             :       TYPE(xc_rho_set_type)                              :: rho_set
    1166             : 
    1167      108860 :       CALL timeset(routineN, handle)
    1168      108860 :       NULLIFY (norm_drho_spin, norm_drho, pos)
    1169             : 
    1170      108860 :       pw_grid => rho_r(1)%pw_grid
    1171             : 
    1172      108860 :       CPASSERT(ASSOCIATED(xc_section))
    1173      108860 :       CPASSERT(ASSOCIATED(pw_pool))
    1174      108860 :       CPASSERT(.NOT. ASSOCIATED(vxc_rho))
    1175      108860 :       CPASSERT(.NOT. ASSOCIATED(vxc_tau))
    1176      108860 :       nspins = SIZE(rho_r)
    1177      108860 :       lsd = (nspins /= 1)
    1178      108860 :       IF (lsd) THEN
    1179       22337 :          CPASSERT(nspins == 2)
    1180             :       END IF
    1181             : 
    1182      108860 :       use_virial = compute_virial
    1183      108860 :       virial_xc = 0.0_dp
    1184             : 
    1185     1088600 :       bo = rho_r(1)%pw_grid%bounds_local
    1186      108860 :       npoints = (bo(2, 1) - bo(1, 1) + 1)*(bo(2, 2) - bo(1, 2) + 1)*(bo(2, 3) - bo(1, 3) + 1)
    1187             : 
    1188             :       ! calculate the potential derivatives
    1189             :       CALL xc_rho_set_and_dset_create(rho_set=rho_set, deriv_set=deriv_set, &
    1190             :                                       deriv_order=1, rho_r=rho_r, rho_g=rho_g, tau=tau, &
    1191             :                                       xc_section=xc_section, &
    1192             :                                       pw_pool=pw_pool, &
    1193      108860 :                                       calc_potential=.TRUE.)
    1194             : 
    1195             :       CALL section_vals_val_get(xc_section, "XC_GRID%XC_DERIV", &
    1196      108860 :                                 i_val=xc_deriv_method_id)
    1197             :       CALL section_vals_val_get(xc_section, "XC_GRID%XC_SMOOTH_RHO", &
    1198      108860 :                                 i_val=xc_rho_smooth_id)
    1199             :       CALL section_vals_val_get(xc_section, "DENSITY_SMOOTH_CUTOFF_RANGE", &
    1200      108860 :                                 r_val=density_smooth_cut_range)
    1201             : 
    1202             :       CALL xc_rho_set_get(rho_set, rho_cutoff=rho_cutoff, &
    1203      108860 :                           drho_cutoff=drho_cutoff)
    1204             : 
    1205      108860 :       CALL check_for_derivatives(deriv_set, lsd, has_rho, has_gradient, has_tau, has_laplace)
    1206             :       ! check for unknown derivatives
    1207      108860 :       has_derivs = has_rho .OR. has_gradient .OR. has_tau .OR. has_laplace
    1208             : 
    1209      457777 :       ALLOCATE (vxc_rho(nspins))
    1210             : 
    1211             :       CALL xc_rho_set_get(rho_set, rho=rho, rhoa=rhoa, rhob=rhob, &
    1212      108860 :                           can_return_null=.TRUE.)
    1213             : 
    1214             :       ! recover the vxc arrays
    1215      108860 :       IF (lsd) THEN
    1216       22337 :          CALL xc_dset_recover_pw(deriv_set, [deriv_rhoa], vxc_rho(1), pw_grid, pw_pool)
    1217       22337 :          CALL xc_dset_recover_pw(deriv_set, [deriv_rhob], vxc_rho(2), pw_grid, pw_pool)
    1218             : 
    1219             :       ELSE
    1220       86523 :          CALL xc_dset_recover_pw(deriv_set, [deriv_rho], vxc_rho(1), pw_grid, pw_pool)
    1221             :       END IF
    1222             : 
    1223      108860 :       deriv_att => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
    1224      108860 :       IF (ASSOCIATED(deriv_att)) THEN
    1225       57785 :          CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
    1226             : 
    1227             :          CALL xc_rho_set_get(rho_set, norm_drho=norm_drho, &
    1228             :                              rho_cutoff=rho_cutoff, &
    1229             :                              drho_cutoff=drho_cutoff, &
    1230       57785 :                              can_return_null=.TRUE.)
    1231       57785 :          CALL xc_rho_set_recover_pw(rho_set, pw_grid, pw_pool, dealloc_pw_to_deriv_rho, drho=pw_to_deriv_rho)
    1232             : 
    1233       57785 :          CPASSERT(ASSOCIATED(deriv_data))
    1234       57785 :          IF (use_virial) THEN
    1235        1522 :             CALL pw_pool%create_pw(virial_pw)
    1236        1522 :             CALL pw_zero(virial_pw)
    1237        6088 :             DO idir = 1, 3
    1238        4566 : !$OMP             PARALLEL WORKSHARE DEFAULT(NONE) SHARED(virial_pw,pw_to_deriv_rho,deriv_data,idir)
    1239             :                virial_pw%array(:, :, :) = pw_to_deriv_rho(idir)%array(:, :, :)*deriv_data(:, :, :)
    1240             : !$OMP             END PARALLEL WORKSHARE
    1241       15220 :                DO jdir = 1, idir
    1242             :                   virial_xc(idir, jdir) = -pw_grid%dvol* &
    1243             :                                           accurate_dot_product(virial_pw%array(:, :, :), &
    1244        9132 :                                                                pw_to_deriv_rho(jdir)%array(:, :, :))
    1245       13698 :                   virial_xc(jdir, idir) = virial_xc(idir, jdir)
    1246             :                END DO
    1247             :             END DO
    1248        1522 :             CALL pw_pool%give_back_pw(virial_pw)
    1249             :          END IF ! use_virial
    1250      231140 :          DO idir = 1, 3
    1251      173355 :             CPASSERT(ASSOCIATED(pw_to_deriv_rho(idir)%array))
    1252      231140 : !$OMP          PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_data,pw_to_deriv_rho,idir)
    1253             :             pw_to_deriv_rho(idir)%array(:, :, :) = pw_to_deriv_rho(idir)%array(:, :, :)*deriv_data(:, :, :)
    1254             : !$OMP          END PARALLEL WORKSHARE
    1255             :          END DO
    1256             : 
    1257             :          ! Deallocate pw to save memory
    1258       57785 :          CALL pw_pool%give_back_cr3d(deriv_att%deriv_data)
    1259             : 
    1260             :       END IF
    1261             : 
    1262      108860 :       IF ((has_gradient .AND. xc_requires_tmp_g(xc_deriv_method_id)) .OR. pw_grid%spherical) THEN
    1263       57059 :          CALL pw_pool%create_pw(vxc_g)
    1264       57059 :          IF (.NOT. pw_grid%spherical) THEN
    1265       57059 :             CALL pw_pool%create_pw(tmp_g)
    1266             :          END IF
    1267             :       END IF
    1268             : 
    1269      240057 :       DO ispin = 1, nspins
    1270             : 
    1271      131197 :          IF (lsd) THEN
    1272       44674 :             IF (ispin == 1) THEN
    1273             :                CALL xc_rho_set_get(rho_set, norm_drhoa=norm_drho_spin, &
    1274       22337 :                                    can_return_null=.TRUE.)
    1275       22337 :                IF (ASSOCIATED(norm_drho_spin)) CALL xc_rho_set_recover_pw( &
    1276       13848 :                   rho_set, pw_grid, pw_pool, dealloc_pw_to_deriv, drhoa=pw_to_deriv)
    1277             :             ELSE
    1278             :                CALL xc_rho_set_get(rho_set, norm_drhob=norm_drho_spin, &
    1279       22337 :                                    can_return_null=.TRUE.)
    1280       22337 :                IF (ASSOCIATED(norm_drho_spin)) CALL xc_rho_set_recover_pw( &
    1281       13848 :                   rho_set, pw_grid, pw_pool, dealloc_pw_to_deriv, drhob=pw_to_deriv)
    1282             :             END IF
    1283             : 
    1284       89348 :             deriv_att => xc_dset_get_derivative(deriv_set, [norm_drho_spin_name(ispin)])
    1285       44674 :             IF (ASSOCIATED(deriv_att)) THEN
    1286             :                CPASSERT(lsd)
    1287       27696 :                CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
    1288             : 
    1289       27696 :                IF (use_virial) THEN
    1290          96 :                   CALL pw_pool%create_pw(virial_pw)
    1291          96 :                   CALL pw_zero(virial_pw)
    1292         384 :                   DO idir = 1, 3
    1293         288 : !$OMP                PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_data,pw_to_deriv,virial_pw,idir)
    1294             :                      virial_pw%array(:, :, :) = pw_to_deriv(idir)%array(:, :, :)*deriv_data(:, :, :)
    1295             : !$OMP                END PARALLEL WORKSHARE
    1296         960 :                      DO jdir = 1, idir
    1297             :                         virial_xc(idir, jdir) = virial_xc(idir, jdir) - pw_grid%dvol* &
    1298             :                                                 accurate_dot_product(virial_pw%array(:, :, :), &
    1299         576 :                                                                      pw_to_deriv(jdir)%array(:, :, :))
    1300         864 :                         virial_xc(jdir, idir) = virial_xc(idir, jdir)
    1301             :                      END DO
    1302             :                   END DO
    1303          96 :                   CALL pw_pool%give_back_pw(virial_pw)
    1304             :                END IF ! use_virial
    1305             : 
    1306      110784 :                DO idir = 1, 3
    1307      110784 : !$OMP             PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_data,idir,pw_to_deriv)
    1308             :                   pw_to_deriv(idir)%array(:, :, :) = deriv_data(:, :, :)* &
    1309             :                                                      pw_to_deriv(idir)%array(:, :, :)
    1310             : !$OMP             END PARALLEL WORKSHARE
    1311             :                END DO
    1312             :             END IF ! deriv_att
    1313             : 
    1314             :          END IF ! LSD
    1315             : 
    1316      131197 :          IF (ASSOCIATED(pw_to_deriv_rho(1)%array)) THEN
    1317       70939 :             IF (.NOT. ASSOCIATED(pw_to_deriv(1)%array)) THEN
    1318       44631 :                pw_to_deriv = pw_to_deriv_rho
    1319       44631 :                dealloc_pw_to_deriv = ((.NOT. lsd) .OR. (ispin == 2))
    1320       44631 :                dealloc_pw_to_deriv = dealloc_pw_to_deriv .AND. dealloc_pw_to_deriv_rho
    1321             :             ELSE
    1322             :                ! This branch is called in case of open-shell systems
    1323             :                ! Add the contributions from norm_drho and norm_drho_spin
    1324      105232 :                DO idir = 1, 3
    1325       78924 :                   CALL pw_axpy(pw_to_deriv_rho(idir), pw_to_deriv(idir))
    1326      105232 :                   IF (ispin == 2) THEN
    1327       39462 :                      IF (dealloc_pw_to_deriv_rho) THEN
    1328       39462 :                         CALL pw_pool%give_back_pw(pw_to_deriv_rho(idir))
    1329             :                      END IF
    1330             :                   END IF
    1331             :                END DO
    1332             :             END IF
    1333             :          END IF
    1334             : 
    1335      131197 :          IF (ASSOCIATED(pw_to_deriv(1)%array)) THEN
    1336      289308 :             DO idir = 1, 3
    1337      289308 :                CALL pw_scale(pw_to_deriv(idir), -1.0_dp)
    1338             :             END DO
    1339             : 
    1340       72327 :             CALL xc_pw_divergence(xc_deriv_method_id, pw_to_deriv, tmp_g, vxc_g, vxc_rho(ispin))
    1341             : 
    1342       72327 :             IF (dealloc_pw_to_deriv) THEN
    1343      289308 :             DO idir = 1, 3
    1344      289308 :                CALL pw_pool%give_back_pw(pw_to_deriv(idir))
    1345             :             END DO
    1346             :             END IF
    1347             :          END IF
    1348             : 
    1349             :          ! ** Add laplace part to vxc_rho
    1350      131197 :          IF (has_laplace) THEN
    1351         896 :             IF (lsd) THEN
    1352         352 :                IF (ispin == 1) THEN
    1353             :                   deriv_id = deriv_laplace_rhoa
    1354             :                ELSE
    1355         176 :                   deriv_id = deriv_laplace_rhob
    1356             :                END IF
    1357             :             ELSE
    1358             :                deriv_id = deriv_laplace_rho
    1359             :             END IF
    1360             : 
    1361        1792 :             CALL xc_dset_recover_pw(deriv_set, [deriv_id], pw_to_deriv(1), pw_grid)
    1362             : 
    1363         896 :             IF (use_virial) CALL virial_laplace(rho_r(ispin), pw_pool, virial_xc, pw_to_deriv(1)%array)
    1364             : 
    1365         896 :             CALL xc_pw_laplace(pw_to_deriv(1), pw_pool, xc_deriv_method_id)
    1366             : 
    1367         896 :             CALL pw_axpy(pw_to_deriv(1), vxc_rho(ispin))
    1368             : 
    1369         896 :             CALL pw_pool%give_back_pw(pw_to_deriv(1))
    1370             :          END IF
    1371             : 
    1372      131197 :          IF (pw_grid%spherical) THEN
    1373             :             ! filter vxc
    1374           0 :             CALL pw_transfer(vxc_rho(ispin), vxc_g)
    1375           0 :             CALL pw_transfer(vxc_g, vxc_rho(ispin))
    1376             :          END IF
    1377             :          CALL smooth_cutoff(pot=vxc_rho(ispin)%array, rho=rho, rhoa=rhoa, rhob=rhob, &
    1378             :                             rho_cutoff=rho_cutoff*density_smooth_cut_range, &
    1379      131197 :                             rho_smooth_cutoff_range=density_smooth_cut_range)
    1380             : 
    1381      131197 :          v_drho_r = vxc_rho(ispin)
    1382      131197 :          CALL pw_pool%create_pw(vxc_rho(ispin))
    1383      131197 :          CALL xc_pw_smooth(v_drho_r, vxc_rho(ispin), xc_rho_smooth_id)
    1384      240057 :          CALL pw_pool%give_back_pw(v_drho_r)
    1385             :       END DO
    1386             : 
    1387      108860 :       CALL pw_pool%give_back_pw(vxc_g)
    1388      108860 :       CALL pw_pool%give_back_pw(tmp_g)
    1389             : 
    1390             :       ! 0-deriv -> value of exc
    1391             :       ! this has to be kept consistent with xc_exc_calc
    1392      108860 :       IF (has_derivs) THEN
    1393      108540 :          CALL xc_dset_recover_pw(deriv_set, [INTEGER::], v_drho_r, pw_grid)
    1394             : 
    1395             :          CALL smooth_cutoff(pot=v_drho_r%array, rho=rho, rhoa=rhoa, rhob=rhob, &
    1396             :                             rho_cutoff=rho_cutoff, &
    1397      108540 :                             rho_smooth_cutoff_range=density_smooth_cut_range)
    1398             : 
    1399      108540 :          exc = pw_integrate_function(v_drho_r)
    1400             :          !
    1401             :          ! return the xc functional value at the grid points
    1402             :          !
    1403      108540 :          IF (PRESENT(exc_r)) THEN
    1404          96 :             exc_r = v_drho_r
    1405             :          ELSE
    1406      108444 :             CALL v_drho_r%release()
    1407             :          END IF
    1408             :       ELSE
    1409         320 :          exc = 0.0_dp
    1410             :       END IF
    1411             : 
    1412      108860 :       CALL xc_rho_set_release(rho_set, pw_pool=pw_pool)
    1413             : 
    1414             :       ! tau part
    1415      108860 :       IF (has_tau) THEN
    1416       10158 :          ALLOCATE (vxc_tau(nspins))
    1417        2396 :          IF (lsd) THEN
    1418         574 :             CALL xc_dset_recover_pw(deriv_set, [deriv_tau_a], vxc_tau(1), pw_grid)
    1419         574 :             CALL xc_dset_recover_pw(deriv_set, [deriv_tau_b], vxc_tau(2), pw_grid)
    1420             :          ELSE
    1421        1822 :             CALL xc_dset_recover_pw(deriv_set, [deriv_tau], vxc_tau(1), pw_grid)
    1422             :          END IF
    1423        5366 :          DO ispin = 1, nspins
    1424        5366 :             CPASSERT(ASSOCIATED(vxc_tau(ispin)%array))
    1425             :          END DO
    1426             :       END IF
    1427      108860 :       CALL xc_dset_release(deriv_set)
    1428             : 
    1429      108860 :       CALL timestop(handle)
    1430             : 
    1431     2286060 :    END SUBROUTINE xc_vxc_pw_create
    1432             : 
    1433             : ! **************************************************************************************************
    1434             : !> \brief calculates just the exchange and correlation energy
    1435             : !>      (no vxc)
    1436             : !> \param rho_r      realspace density on the grid
    1437             : !> \param rho_g      g-space density on the grid
    1438             : !> \param tau        kinetic energy density on the grid
    1439             : !> \param xc_section XC parameters
    1440             : !> \param pw_pool    pool of plain-wave grids
    1441             : !> \return the XC energy
    1442             : !> \par History
    1443             : !>      11.2003 created [fawzi]
    1444             : !> \author fawzi
    1445             : !> \note
    1446             : !>      has to be kept consistent with xc_vxc_pw_create
    1447             : ! **************************************************************************************************
    1448       15550 :    FUNCTION xc_exc_calc(rho_r, rho_g, tau, xc_section, pw_pool) &
    1449             :       RESULT(exc)
    1450             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               :: rho_r, tau
    1451             :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
    1452             :       TYPE(section_vals_type), POINTER                   :: xc_section
    1453             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
    1454             :       REAL(kind=dp)                                      :: exc
    1455             : 
    1456             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xc_exc_calc'
    1457             : 
    1458             :       INTEGER                                            :: handle
    1459             :       REAL(dp)                                           :: density_smooth_cut_range, rho_cutoff
    1460        7775 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: e_0
    1461             :       TYPE(xc_derivative_set_type)                       :: deriv_set
    1462             :       TYPE(xc_derivative_type), POINTER                  :: deriv
    1463             :       TYPE(xc_rho_set_type)                              :: rho_set
    1464             : 
    1465        7775 :       CALL timeset(routineN, handle)
    1466        7775 :       NULLIFY (deriv, e_0)
    1467        7775 :       exc = 0.0_dp
    1468             : 
    1469             :       ! this has to be consistent with what is done in xc_vxc_pw_create
    1470             :       CALL xc_rho_set_and_dset_create(rho_set=rho_set, &
    1471             :                                       deriv_set=deriv_set, deriv_order=0, &
    1472             :                                       rho_r=rho_r, rho_g=rho_g, tau=tau, xc_section=xc_section, &
    1473             :                                       pw_pool=pw_pool, &
    1474        7775 :                                       calc_potential=.FALSE.)
    1475        7775 :       deriv => xc_dset_get_derivative(deriv_set, [INTEGER::])
    1476             : 
    1477        7775 :       IF (ASSOCIATED(deriv)) THEN
    1478        7775 :          CALL xc_derivative_get(deriv, deriv_data=e_0)
    1479             : 
    1480             :          CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", &
    1481        7775 :                                    r_val=rho_cutoff)
    1482             :          CALL section_vals_val_get(xc_section, "DENSITY_SMOOTH_CUTOFF_RANGE", &
    1483        7775 :                                    r_val=density_smooth_cut_range)
    1484             :          CALL smooth_cutoff(pot=e_0, rho=rho_set%rho, &
    1485             :                             rhoa=rho_set%rhoa, rhob=rho_set%rhob, &
    1486             :                             rho_cutoff=rho_cutoff, &
    1487        7775 :                             rho_smooth_cutoff_range=density_smooth_cut_range)
    1488             : 
    1489        7775 :          exc = accurate_sum(e_0)*rho_r(1)%pw_grid%dvol
    1490        7775 :          IF (rho_r(1)%pw_grid%para%mode == PW_MODE_DISTRIBUTED) THEN
    1491        7650 :             CALL rho_r(1)%pw_grid%para%group%sum(exc)
    1492             :          END IF
    1493             : 
    1494        7775 :          CALL xc_rho_set_release(rho_set, pw_pool=pw_pool)
    1495        7775 :          CALL xc_dset_release(deriv_set)
    1496             :       END IF
    1497        7775 :       CALL timestop(handle)
    1498      147725 :    END FUNCTION xc_exc_calc
    1499             : 
    1500             : ! **************************************************************************************************
    1501             : !> \brief Caller routine to calculate the second order potential in the direction of rho1_r
    1502             : !> \param v_xc XC potential, will be allocated, to be integrated with the KS density
    1503             : !> \param v_xc_tau ...
    1504             : !> \param deriv_set XC derivatives from xc_prep_2nd_deriv
    1505             : !> \param rho_set XC rho set from KS rho from xc_prep_2nd_deriv
    1506             : !> \param rho1_r first-order density in r space
    1507             : !> \param rho1_g first-order density in g space
    1508             : !> \param tau1_r ...
    1509             : !> \param pw_pool pw pool to create new grids
    1510             : !> \param xc_section XC section to calculate the derivatives from
    1511             : !> \param gapw whether to carry out GAPW (not possible with numerical derivatives)
    1512             : !> \param vxg GAPW potential
    1513             : !> \param lsd_singlets ...
    1514             : !> \param do_excitations ...
    1515             : !> \param do_triplet ...
    1516             : !> \param do_tddft ...
    1517             : !> \param compute_virial ...
    1518             : !> \param virial_xc virial terms will be collected here
    1519             : ! **************************************************************************************************
    1520       13844 :    SUBROUTINE xc_calc_2nd_deriv(v_xc, v_xc_tau, deriv_set, rho_set, rho1_r, rho1_g, tau1_r, &
    1521             :                                 pw_pool, xc_section, gapw, vxg, &
    1522             :                                 lsd_singlets, do_excitations, do_triplet, do_tddft, &
    1523             :                                 compute_virial, virial_xc)
    1524             : 
    1525             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER             :: v_xc, v_xc_tau
    1526             :       TYPE(xc_derivative_set_type)                       :: deriv_set
    1527             :       TYPE(xc_rho_set_type)                              :: rho_set
    1528             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               :: rho1_r, tau1_r
    1529             :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho1_g
    1530             :       TYPE(pw_pool_type), INTENT(IN), POINTER            :: pw_pool
    1531             :       TYPE(section_vals_type), INTENT(IN), POINTER       :: xc_section
    1532             :       LOGICAL, INTENT(IN)                                :: gapw
    1533             :       REAL(KIND=dp), DIMENSION(:, :, :, :), OPTIONAL, &
    1534             :          POINTER                                         :: vxg
    1535             :       LOGICAL, INTENT(IN), OPTIONAL                      :: lsd_singlets, do_excitations, &
    1536             :                                                             do_triplet, do_tddft, compute_virial
    1537             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT), &
    1538             :          OPTIONAL                                        :: virial_xc
    1539             : 
    1540             :       CHARACTER(len=*), PARAMETER :: routineN = 'xc_calc_2nd_deriv'
    1541             : 
    1542             :       INTEGER                                            :: handle, ispin, nspins
    1543             :       INTEGER, DIMENSION(2, 3)                           :: bo
    1544             :       LOGICAL                                            :: lsd, my_compute_virial, &
    1545             :                                                             my_do_excitations, my_do_tddft, &
    1546             :                                                             my_do_triplet, my_lsd_singlets
    1547             :       REAL(KIND=dp)                                      :: fac
    1548             :       TYPE(section_vals_type), POINTER                   :: xc_fun_section
    1549             :       TYPE(xc_rho_cflags_type)                           :: needs
    1550             :       TYPE(xc_rho_set_type)                              :: rho1_set
    1551             : 
    1552       13844 :       CALL timeset(routineN, handle)
    1553             : 
    1554       13844 :       my_compute_virial = .FALSE.
    1555       13844 :       IF (PRESENT(compute_virial)) my_compute_virial = compute_virial
    1556             : 
    1557       13844 :       my_do_tddft = .FALSE.
    1558       13844 :       IF (PRESENT(do_tddft)) my_do_tddft = do_tddft
    1559             : 
    1560       13844 :       my_do_excitations = .FALSE.
    1561       13844 :       IF (PRESENT(do_excitations)) my_do_excitations = do_excitations
    1562             : 
    1563       13844 :       my_lsd_singlets = .FALSE.
    1564       13844 :       IF (PRESENT(lsd_singlets)) my_lsd_singlets = lsd_singlets
    1565             : 
    1566       13844 :       my_do_triplet = .FALSE.
    1567       13844 :       IF (PRESENT(do_triplet)) my_do_triplet = do_triplet
    1568             : 
    1569       13844 :       nspins = SIZE(rho1_r)
    1570       13844 :       lsd = (nspins == 2)
    1571       13844 :       IF (nspins == 1 .AND. my_do_excitations .AND. (my_lsd_singlets .OR. my_do_triplet)) THEN
    1572           0 :          nspins = 2
    1573           0 :          lsd = .TRUE.
    1574             :       END IF
    1575             : 
    1576       13844 :       NULLIFY (v_xc, v_xc_tau)
    1577       57318 :       ALLOCATE (v_xc(nspins))
    1578       29630 :       DO ispin = 1, nspins
    1579       15786 :          CALL pw_pool%create_pw(v_xc(ispin))
    1580       29630 :          CALL pw_zero(v_xc(ispin))
    1581             :       END DO
    1582             : 
    1583       13844 :       xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
    1584       13844 :       needs = xc_functionals_get_needs(xc_fun_section, lsd, .TRUE.)
    1585             : 
    1586       13844 :       IF (needs%tau .OR. needs%tau_spin) THEN
    1587         514 :          IF (.NOT. ASSOCIATED(tau1_r)) &
    1588           0 :             CPABORT("Tau-dependent functionals requires allocated kinetic energy density grid")
    1589        2172 :          ALLOCATE (v_xc_tau(nspins))
    1590        1144 :          DO ispin = 1, nspins
    1591         630 :             CALL pw_pool%create_pw(v_xc_tau(ispin))
    1592       14474 :             CALL pw_zero(v_xc_tau(ispin))
    1593             :          END DO
    1594             :       END IF
    1595             : 
    1596       13844 :       IF (section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL") .AND. .NOT. my_do_tddft) THEN
    1597             :          !------!
    1598             :          ! rho1 !
    1599             :          !------!
    1600      130640 :          bo = rho1_r(1)%pw_grid%bounds_local
    1601             :          ! create the place where to store the argument for the functionals
    1602             :          CALL xc_rho_set_create(rho1_set, bo, &
    1603             :                                 rho_cutoff=section_get_rval(xc_section, "DENSITY_CUTOFF"), &
    1604             :                                 drho_cutoff=section_get_rval(xc_section, "GRADIENT_CUTOFF"), &
    1605       13064 :                                 tau_cutoff=section_get_rval(xc_section, "TAU_CUTOFF"))
    1606             : 
    1607             :          ! calculate the arguments needed by the functionals
    1608             :          CALL xc_rho_set_update(rho1_set, rho1_r, rho1_g, tau1_r, needs, &
    1609             :                                 section_get_ival(xc_section, "XC_GRID%XC_DERIV"), &
    1610             :                                 section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO"), &
    1611       13064 :                                 pw_pool)
    1612             : 
    1613       13064 :          fac = 0._dp
    1614       13064 :          IF (nspins == 1 .AND. my_do_excitations) THEN
    1615        1064 :             IF (my_lsd_singlets) fac = 1.0_dp
    1616        1064 :             IF (my_do_triplet) fac = -1.0_dp
    1617             :          END IF
    1618             : 
    1619             :          CALL xc_calc_2nd_deriv_analytical(v_xc, v_xc_tau, deriv_set, rho_set, &
    1620             :                                            rho1_set, pw_pool, xc_section, gapw, vxg=vxg, &
    1621       26128 :                                            tddfpt_fac=fac, compute_virial=compute_virial, virial_xc=virial_xc)
    1622             : 
    1623       13064 :          CALL xc_rho_set_release(rho1_set)
    1624             : 
    1625             :       ELSE
    1626         780 :          IF (gapw) CPABORT("Numerical 2nd derivatives not implemented with GAPW")
    1627             : 
    1628             :          CALL xc_calc_2nd_deriv_numerical(v_xc, v_xc_tau, rho_set, rho1_r, rho1_g, tau1_r, &
    1629             :                                           pw_pool, xc_section, &
    1630             :                                           my_do_excitations .AND. my_do_triplet, &
    1631         780 :                                           compute_virial, virial_xc, deriv_set)
    1632             :       END IF
    1633             : 
    1634       13844 :       CALL timestop(handle)
    1635             : 
    1636      304568 :    END SUBROUTINE xc_calc_2nd_deriv
    1637             : 
    1638             : ! **************************************************************************************************
    1639             : !> \brief calculates 2nd derivative numerically
    1640             : !> \param v_xc potential to be calculated (has to be allocated already)
    1641             : !> \param v_tau tau-part of the potential to be calculated (has to be allocated already)
    1642             : !> \param rho_set KS density from xc_prep_2nd_deriv
    1643             : !> \param rho1_r first-order density in r-space
    1644             : !> \param rho1_g first-order density in g-space
    1645             : !> \param tau1_r first-order kinetic-energy density in r-space
    1646             : !> \param pw_pool pw pool for new grids
    1647             : !> \param xc_section XC section to calculate the derivatives from
    1648             : !> \param do_triplet ...
    1649             : !> \param calc_virial whether to calculate virial terms
    1650             : !> \param virial_xc collects stress tensor components (no metaGGAs!)
    1651             : !> \param deriv_set deriv set from xc_prep_2nd_deriv (only for virials)
    1652             : ! **************************************************************************************************
    1653         832 :    SUBROUTINE xc_calc_2nd_deriv_numerical(v_xc, v_tau, rho_set, rho1_r, rho1_g, tau1_r, &
    1654             :                                           pw_pool, xc_section, &
    1655             :                                           do_triplet, calc_virial, virial_xc, deriv_set)
    1656             : 
    1657             :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN), POINTER :: v_xc, v_tau
    1658             :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set
    1659             :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN), POINTER   :: rho1_r, tau1_r
    1660             :       TYPE(pw_c1d_gs_type), DIMENSION(:), INTENT(IN), POINTER :: rho1_g
    1661             :       TYPE(pw_pool_type), INTENT(IN), POINTER            :: pw_pool
    1662             :       TYPE(section_vals_type), INTENT(IN), POINTER       :: xc_section
    1663             :       LOGICAL, INTENT(IN)                                :: do_triplet
    1664             :       LOGICAL, INTENT(IN), OPTIONAL                      :: calc_virial
    1665             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT), &
    1666             :          OPTIONAL                                        :: virial_xc
    1667             :       TYPE(xc_derivative_set_type), OPTIONAL             :: deriv_set
    1668             : 
    1669             :       CHARACTER(len=*), PARAMETER :: routineN = 'xc_calc_2nd_deriv_numerical'
    1670             :       REAL(KIND=dp), DIMENSION(-4:4, 4), PARAMETER :: &
    1671             :          weights = RESHAPE([0.0_dp, 0.0_dp, 0.0_dp, -0.5_dp, 0.0_dp, 0.5_dp, 0.0_dp, 0.0_dp, 0.0_dp, &
    1672             :                            0.0_dp, 0.0_dp, 1.0_dp/12.0_dp, -2.0_dp/3.0_dp, 0.0_dp, 2.0_dp/3.0_dp, -1.0_dp/12.0_dp, 0.0_dp, 0.0_dp, &
    1673             :                             0.0_dp, -1.0_dp/60.0_dp, 0.15_dp, -0.75_dp, 0.0_dp, 0.75_dp, -0.15_dp, 1.0_dp/60.0_dp, 0.0_dp, &
    1674             :             1.0_dp/280.0_dp, -4.0_dp/105.0_dp, 0.2_dp, -0.8_dp, 0.0_dp, 0.8_dp, -0.2_dp, 4.0_dp/105.0_dp, -1.0_dp/280.0_dp], [9, 4])
    1675             : 
    1676             :       INTEGER                                            :: handle, idir, ispin, nspins, istep, nsteps
    1677             :       INTEGER, DIMENSION(2, 3)                           :: bo
    1678             :       LOGICAL                                            :: gradient_f, lsd, my_calc_virial, tau_f, laplace_f, rho_f
    1679             :       REAL(KIND=dp)                                      :: exc, gradient_cut, h, weight, step, rho_cutoff
    1680         832 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: dr1dr, dra1dra, drb1drb
    1681             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: virial_dummy
    1682         832 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: norm_drho, norm_drho2, norm_drho2a, &
    1683         832 :                                                             norm_drho2b, norm_drhoa, norm_drhob, &
    1684        2496 :                                                             rho, rho1, rho1a, rho1b, rhoa, rhob, &
    1685        1664 :                                                             tau_a, tau_b, tau, tau1, tau1a, tau1b, laplace, laplace1, &
    1686         832 :                                                             laplacea, laplaceb, laplace1a, laplace1b, &
    1687        1664 :                                                             laplace2, laplace2a, laplace2b, deriv_data
    1688       19968 :       TYPE(cp_3d_r_cp_type), DIMENSION(3)                :: drho, drho1, drho1a, drho1b, drhoa, drhob
    1689             :       TYPE(pw_r3d_rs_type)                                      :: v_drho, v_drhoa, v_drhob
    1690         832 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER             :: vxc_rho, vxc_tau
    1691         832 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
    1692         832 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               ::  rho_r, tau_r
    1693             :       TYPE(pw_r3d_rs_type)                                      :: virial_pw, v_laplace, v_laplacea, v_laplaceb
    1694             :       TYPE(section_vals_type), POINTER                   :: xc_fun_section
    1695             :       TYPE(xc_derivative_set_type)                       :: deriv_set1
    1696             :       TYPE(xc_rho_cflags_type)                           :: needs
    1697             :       TYPE(xc_rho_set_type)                              :: rho1_set, rho2_set
    1698             : 
    1699         832 :       CALL timeset(routineN, handle)
    1700             : 
    1701         832 :       my_calc_virial = .FALSE.
    1702         832 :       IF (PRESENT(calc_virial) .AND. PRESENT(virial_xc)) my_calc_virial = calc_virial
    1703             : 
    1704         832 :       nspins = SIZE(v_xc)
    1705             : 
    1706         832 :       NULLIFY (tau, tau_r, tau_a, tau_b)
    1707             : 
    1708         832 :       h = section_get_rval(xc_section, "STEP_SIZE")
    1709         832 :       nsteps = section_get_ival(xc_section, "NSTEPS")
    1710         832 :       IF (nsteps < LBOUND(weights, 2) .OR. nspins > UBOUND(weights, 2)) THEN
    1711           0 :          CPABORT("The number of steps must be a value from 1 to 4.")
    1712             :       END IF
    1713             : 
    1714         832 :       IF (nspins == 2) THEN
    1715         324 :          NULLIFY (vxc_rho, rho_g, vxc_tau)
    1716         972 :          ALLOCATE (rho_r(2))
    1717         972 :          DO ispin = 1, nspins
    1718         972 :             CALL pw_pool%create_pw(rho_r(ispin))
    1719             :          END DO
    1720         324 :          IF (ASSOCIATED(tau1_r) .AND. ASSOCIATED(v_tau)) THEN
    1721         162 :             ALLOCATE (tau_r(2))
    1722         162 :             DO ispin = 1, nspins
    1723         162 :                CALL pw_pool%create_pw(tau_r(ispin))
    1724             :             END DO
    1725             :          END IF
    1726         324 :          CALL xc_rho_set_get(rho_set, can_return_null=.TRUE., rhoa=rhoa, rhob=rhob, tau_a=tau_a, tau_b=tau_b)
    1727        2496 :          DO istep = -nsteps, nsteps
    1728        2172 :             IF (istep == 0) CYCLE
    1729        1848 :             weight = weights(istep, nsteps)/h
    1730        1848 :             step = REAL(istep, dp)*h
    1731             :             CALL calc_resp_potential_numer_ab(rho_r, rho_g, rho1_r, rhoa, rhob, vxc_rho, &
    1732        1848 :                                               tau_r, tau1_r, tau_a, tau_b, vxc_tau, xc_section, pw_pool, step)
    1733        5544 :             DO ispin = 1, nspins
    1734        3696 :                CALL pw_axpy(vxc_rho(ispin), v_xc(ispin), weight)
    1735        5544 :                IF (ASSOCIATED(vxc_tau) .AND. ASSOCIATED(v_tau)) THEN
    1736         456 :                   CALL pw_axpy(vxc_tau(ispin), v_tau(ispin), weight)
    1737             :                END IF
    1738             :             END DO
    1739        5544 :             DO ispin = 1, nspins
    1740        5544 :                CALL vxc_rho(ispin)%release()
    1741             :             END DO
    1742        1848 :             DEALLOCATE (vxc_rho)
    1743        2172 :             IF (ASSOCIATED(vxc_tau)) THEN
    1744         684 :                DO ispin = 1, nspins
    1745         684 :                   CALL vxc_tau(ispin)%release()
    1746             :                END DO
    1747         228 :                DEALLOCATE (vxc_tau)
    1748             :             END IF
    1749             :          END DO
    1750         508 :       ELSE IF (nspins == 1 .AND. do_triplet) THEN
    1751          24 :          NULLIFY (vxc_rho, vxc_tau, rho_g)
    1752          72 :          ALLOCATE (rho_r(2))
    1753          72 :          DO ispin = 1, 2
    1754          72 :             CALL pw_pool%create_pw(rho_r(ispin))
    1755             :          END DO
    1756          24 :          IF (ASSOCIATED(tau1_r) .AND. ASSOCIATED(v_tau)) THEN
    1757           0 :             ALLOCATE (tau_r(2))
    1758           0 :             DO ispin = 1, nspins
    1759           0 :                CALL pw_pool%create_pw(tau_r(ispin))
    1760             :             END DO
    1761             :          END IF
    1762          24 :          CALL xc_rho_set_get(rho_set, can_return_null=.TRUE., rhoa=rhoa, rhob=rhob, tau_a=tau_a, tau_b=tau_b)
    1763         192 :          DO istep = -nsteps, nsteps
    1764         168 :             IF (istep == 0) CYCLE
    1765         144 :             weight = weights(istep, nsteps)/h
    1766         144 :             step = REAL(istep, dp)*h
    1767             :             ! K(alpha,alpha)
    1768         144 : !$OMP PARALLEL DEFAULT(NONE) SHARED(rho_r,rhoa,rhob,step,rho1_r,tau_r,tau_a,tau_b,tau1_r)
    1769             : !$OMP WORKSHARE
    1770             :             rho_r(1)%array(:, :, :) = rhoa(:, :, :) + step*rho1_r(1)%array(:, :, :)
    1771             : !$OMP END WORKSHARE NOWAIT
    1772             : !$OMP WORKSHARE
    1773             :             rho_r(2)%array(:, :, :) = rhob(:, :, :)
    1774             : !$OMP END WORKSHARE NOWAIT
    1775             :             IF (ASSOCIATED(tau1_r)) THEN
    1776             : !$OMP WORKSHARE
    1777             :                tau_r(1)%array(:, :, :) = tau_a(:, :, :) + step*tau1_r(1)%array(:, :, :)
    1778             : !$OMP END WORKSHARE NOWAIT
    1779             : !$OMP WORKSHARE
    1780             :                tau_r(2)%array(:, :, :) = tau_b(:, :, :)
    1781             : !$OMP END WORKSHARE NOWAIT
    1782             :             END IF
    1783             : !$OMP END PARALLEL
    1784             :             CALL xc_vxc_pw_create(vxc_rho, vxc_tau, exc, rho_r, rho_g, tau_r, xc_section, &
    1785         144 :                                   pw_pool, .FALSE., virial_dummy)
    1786         144 :             CALL pw_axpy(vxc_rho(1), v_xc(1), weight)
    1787         144 :             IF (ASSOCIATED(vxc_tau) .AND. ASSOCIATED(v_tau)) THEN
    1788           0 :                CALL pw_axpy(vxc_tau(1), v_tau(1), weight)
    1789             :             END IF
    1790         432 :             DO ispin = 1, 2
    1791         432 :                CALL vxc_rho(ispin)%release()
    1792             :             END DO
    1793         144 :             DEALLOCATE (vxc_rho)
    1794         144 :             IF (ASSOCIATED(vxc_tau)) THEN
    1795           0 :             DO ispin = 1, 2
    1796           0 :                CALL vxc_tau(ispin)%release()
    1797             :             END DO
    1798           0 :             DEALLOCATE (vxc_tau)
    1799             :             END IF
    1800         144 : !$OMP PARALLEL DEFAULT(NONE) SHARED(rho_r,rhoa,rhob,step,rho1_r,tau_r,tau_a,tau_b,tau1_r)
    1801             : !$OMP WORKSHARE
    1802             :             ! K(alpha,beta)
    1803             :             rho_r(1)%array(:, :, :) = rhoa(:, :, :)
    1804             : !$OMP END WORKSHARE NOWAIT
    1805             : !$OMP WORKSHARE
    1806             :             rho_r(2)%array(:, :, :) = rhob(:, :, :) + step*rho1_r(1)%array(:, :, :)
    1807             : !$OMP END WORKSHARE NOWAIT
    1808             :             IF (ASSOCIATED(tau1_r)) THEN
    1809             : !$OMP WORKSHARE
    1810             :                tau_r(1)%array(:, :, :) = tau_a(:, :, :)
    1811             : !$OMP END WORKSHARE NOWAIT
    1812             : !$OMP WORKSHARE
    1813             :                tau_r(2)%array(:, :, :) = tau_b(:, :, :) + step*tau1_r(1)%array(:, :, :)
    1814             : !$OMP END WORKSHARE NOWAIT
    1815             :             END IF
    1816             : !$OMP END PARALLEL
    1817             :             CALL xc_vxc_pw_create(vxc_rho, vxc_tau, exc, rho_r, rho_g, tau_r, xc_section, &
    1818         144 :                                   pw_pool, .FALSE., virial_dummy)
    1819         144 :             CALL pw_axpy(vxc_rho(1), v_xc(1), weight)
    1820         144 :             IF (ASSOCIATED(vxc_tau) .AND. ASSOCIATED(v_tau)) THEN
    1821           0 :                CALL pw_axpy(vxc_tau(1), v_tau(1), weight)
    1822             :             END IF
    1823         432 :             DO ispin = 1, 2
    1824         432 :                CALL vxc_rho(ispin)%release()
    1825             :             END DO
    1826         144 :             DEALLOCATE (vxc_rho)
    1827         168 :             IF (ASSOCIATED(vxc_tau)) THEN
    1828           0 :             DO ispin = 1, 2
    1829           0 :                CALL vxc_tau(ispin)%release()
    1830             :             END DO
    1831           0 :             DEALLOCATE (vxc_tau)
    1832             :             END IF
    1833             :          END DO
    1834             :       ELSE
    1835         484 :          NULLIFY (vxc_rho, rho_r, rho_g, vxc_tau, tau_r, tau)
    1836         968 :          ALLOCATE (rho_r(1))
    1837         484 :          CALL pw_pool%create_pw(rho_r(1))
    1838         484 :          IF (ASSOCIATED(tau1_r) .AND. ASSOCIATED(v_tau)) THEN
    1839          92 :             ALLOCATE (tau_r(1))
    1840          46 :             CALL pw_pool%create_pw(tau_r(1))
    1841             :          END IF
    1842         484 :          CALL xc_rho_set_get(rho_set, can_return_null=.TRUE., rho=rho, tau=tau)
    1843        3776 :          DO istep = -nsteps, nsteps
    1844        3292 :             IF (istep == 0) CYCLE
    1845        2808 :             weight = weights(istep, nsteps)/h
    1846        2808 :             step = REAL(istep, dp)*h
    1847        2808 : !$OMP PARALLEL DEFAULT(NONE) SHARED(rho_r,rho,step,rho1_r,tau1_r,tau,tau_r)
    1848             : !$OMP WORKSHARE
    1849             :             rho_r(1)%array(:, :, :) = rho(:, :, :) + step*rho1_r(1)%array(:, :, :)
    1850             : !$OMP END WORKSHARE NOWAIT
    1851             :             IF (ASSOCIATED(tau1_r) .AND. ASSOCIATED(tau) .AND. ASSOCIATED(tau1_r)) THEN
    1852             : !$OMP WORKSHARE
    1853             :                tau_r(1)%array(:, :, :) = tau(:, :, :) + step*tau1_r(1)%array(:, :, :)
    1854             : !$OMP END WORKSHARE NOWAIT
    1855             :             END IF
    1856             : !$OMP END PARALLEL
    1857             :             CALL xc_vxc_pw_create(vxc_rho, vxc_tau, exc, rho_r, rho_g, tau_r, xc_section, &
    1858        2808 :                                   pw_pool, .FALSE., virial_dummy)
    1859        2808 :             CALL pw_axpy(vxc_rho(1), v_xc(1), weight)
    1860        2808 :             IF (ASSOCIATED(vxc_tau) .AND. ASSOCIATED(v_tau)) THEN
    1861         276 :                CALL pw_axpy(vxc_tau(1), v_tau(1), weight)
    1862             :             END IF
    1863        2808 :             CALL vxc_rho(1)%release()
    1864        2808 :             DEALLOCATE (vxc_rho)
    1865        3292 :             IF (ASSOCIATED(vxc_tau)) THEN
    1866         276 :                CALL vxc_tau(1)%release()
    1867         276 :                DEALLOCATE (vxc_tau)
    1868             :             END IF
    1869             :          END DO
    1870             :       END IF
    1871             : 
    1872         832 :       IF (my_calc_virial) THEN
    1873          36 :          lsd = (nspins == 2)
    1874          36 :          IF (nspins == 1 .AND. do_triplet) THEN
    1875           0 :             lsd = .TRUE.
    1876             :          END IF
    1877             : 
    1878          36 :          CALL check_for_derivatives(deriv_set, (nspins == 2), rho_f, gradient_f, tau_f, laplace_f)
    1879             : 
    1880             :          ! Calculate the virial terms
    1881             :          ! Those arising from the first derivatives are treated like in xc_calc_2nd_deriv_analytical
    1882             :          ! Those arising from the second derivatives are calculated numerically
    1883             :          ! We assume that all metaGGA functionals require the gradient
    1884          36 :          IF (gradient_f) THEN
    1885         360 :             bo = rho_set%local_bounds
    1886             : 
    1887             :             ! Create the work grid for the virial terms
    1888          36 :             CALL allocate_pw(virial_pw, pw_pool, bo)
    1889             : 
    1890          36 :             gradient_cut = section_get_rval(xc_section, "GRADIENT_CUTOFF")
    1891             : 
    1892             :             ! create the container to store the argument of the functionals
    1893             :             CALL xc_rho_set_create(rho1_set, bo, &
    1894             :                                    rho_cutoff=section_get_rval(xc_section, "DENSITY_CUTOFF"), &
    1895             :                                    drho_cutoff=gradient_cut, &
    1896          36 :                                    tau_cutoff=section_get_rval(xc_section, "TAU_CUTOFF"))
    1897             : 
    1898          36 :             xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
    1899          36 :             needs = xc_functionals_get_needs(xc_fun_section, lsd, .TRUE.)
    1900             : 
    1901             :             ! calculate the arguments needed by the functionals
    1902             :             CALL xc_rho_set_update(rho1_set, rho1_r, rho1_g, tau1_r, needs, &
    1903             :                                    section_get_ival(xc_section, "XC_GRID%XC_DERIV"), &
    1904             :                                    section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO"), &
    1905          36 :                                    pw_pool)
    1906             : 
    1907          36 :             IF (lsd) THEN
    1908             :                CALL xc_rho_set_get(rho_set, drhoa=drhoa, drhob=drhob, norm_drho=norm_drho, &
    1909             :                                    norm_drhoa=norm_drhoa, norm_drhob=norm_drhob, tau_a=tau_a, tau_b=tau_b, &
    1910          10 :                                    laplace_rhoa=laplacea, laplace_rhob=laplaceb, can_return_null=.TRUE.)
    1911             :                CALL xc_rho_set_get(rho1_set, rhoa=rho1a, rhob=rho1b, drhoa=drho1a, drhob=drho1b, laplace_rhoa=laplace1a, &
    1912          10 :                                    laplace_rhob=laplace1b, can_return_null=.TRUE.)
    1913             : 
    1914          10 :                CALL calc_drho_from_ab(drho, drhoa, drhob)
    1915          10 :                CALL calc_drho_from_ab(drho1, drho1a, drho1b)
    1916             :             ELSE
    1917          26 :                CALL xc_rho_set_get(rho_set, drho=drho, norm_drho=norm_drho, tau=tau, laplace_rho=laplace, can_return_null=.TRUE.)
    1918          26 :                CALL xc_rho_set_get(rho1_set, rho=rho1, drho=drho1, laplace_rho=laplace1, can_return_null=.TRUE.)
    1919             :             END IF
    1920             : 
    1921          36 :             CALL prepare_dr1dr(dr1dr, drho, drho1)
    1922             : 
    1923          36 :             IF (lsd) THEN
    1924          10 :                CALL prepare_dr1dr(dra1dra, drhoa, drho1a)
    1925          10 :                CALL prepare_dr1dr(drb1drb, drhob, drho1b)
    1926             : 
    1927          10 :                CALL allocate_pw(v_drho, pw_pool, bo)
    1928          10 :                CALL allocate_pw(v_drhoa, pw_pool, bo)
    1929          10 :                CALL allocate_pw(v_drhob, pw_pool, bo)
    1930             : 
    1931          10 :                IF (ASSOCIATED(norm_drhoa)) CALL apply_drho(deriv_set, [deriv_norm_drhoa], virial_pw, drhoa, drho1a, virial_xc, &
    1932          10 :                                                            norm_drhoa, gradient_cut, dra1dra, v_drhoa%array)
    1933          10 :                IF (ASSOCIATED(norm_drhob)) CALL apply_drho(deriv_set, [deriv_norm_drhob], virial_pw, drhob, drho1b, virial_xc, &
    1934          10 :                                                            norm_drhob, gradient_cut, drb1drb, v_drhob%array)
    1935          10 :                IF (ASSOCIATED(norm_drho)) CALL apply_drho(deriv_set, [deriv_norm_drho], virial_pw, drho, drho1, virial_xc, &
    1936           6 :                                                           norm_drho, gradient_cut, dr1dr, v_drho%array)
    1937          10 :                IF (laplace_f) THEN
    1938           2 :                   CALL xc_derivative_get(xc_dset_get_derivative(deriv_set, [deriv_laplace_rhoa]), deriv_data=deriv_data)
    1939           2 :                   CPASSERT(ASSOCIATED(deriv_data))
    1940       15026 :                   virial_pw%array(:, :, :) = -rho1a(:, :, :)
    1941           2 :                   CALL virial_laplace(virial_pw, pw_pool, virial_xc, deriv_data)
    1942             : 
    1943           2 :                   CALL allocate_pw(v_laplacea, pw_pool, bo)
    1944             : 
    1945           2 :                   CALL xc_derivative_get(xc_dset_get_derivative(deriv_set, [deriv_laplace_rhob]), deriv_data=deriv_data)
    1946           2 :                   CPASSERT(ASSOCIATED(deriv_data))
    1947       15026 :                   virial_pw%array(:, :, :) = -rho1b(:, :, :)
    1948           2 :                   CALL virial_laplace(virial_pw, pw_pool, virial_xc, deriv_data)
    1949             : 
    1950           2 :                   CALL allocate_pw(v_laplaceb, pw_pool, bo)
    1951             :                END IF
    1952             : 
    1953             :             ELSE
    1954             : 
    1955             :                ! Create the work grid for the potential of the gradient part
    1956          26 :                CALL allocate_pw(v_drho, pw_pool, bo)
    1957             : 
    1958             :                CALL apply_drho(deriv_set, [deriv_norm_drho], virial_pw, drho, drho1, virial_xc, &
    1959          26 :                                norm_drho, gradient_cut, dr1dr, v_drho%array)
    1960          26 :                IF (laplace_f) THEN
    1961           2 :                   CALL xc_derivative_get(xc_dset_get_derivative(deriv_set, [deriv_laplace_rho]), deriv_data=deriv_data)
    1962           2 :                   CPASSERT(ASSOCIATED(deriv_data))
    1963       28862 :                   virial_pw%array(:, :, :) = -rho1(:, :, :)
    1964           2 :                   CALL virial_laplace(virial_pw, pw_pool, virial_xc, deriv_data)
    1965             : 
    1966           2 :                   CALL allocate_pw(v_laplace, pw_pool, bo)
    1967             :                END IF
    1968             : 
    1969             :             END IF
    1970             : 
    1971          36 :             IF (lsd) THEN
    1972      150260 :                rho_r(1)%array = rhoa
    1973      150260 :                rho_r(2)%array = rhob
    1974             :             ELSE
    1975      701552 :                rho_r(1)%array = rho
    1976             :             END IF
    1977          36 :             IF (ASSOCIATED(tau1_r)) THEN
    1978           8 :             IF (lsd) THEN
    1979       60104 :                tau_r(1)%array = tau_a
    1980       60104 :                tau_r(2)%array = tau_b
    1981             :             ELSE
    1982      115448 :                tau_r(1)%array = tau
    1983             :             END IF
    1984             :             END IF
    1985             : 
    1986             :             ! Create deriv sets with same densities but different gradients
    1987          36 :             CALL xc_dset_create(deriv_set1, pw_pool)
    1988             : 
    1989          36 :             rho_cutoff = section_get_rval(xc_section, "DENSITY_CUTOFF")
    1990             : 
    1991             :             ! create the place where to store the argument for the functionals
    1992             :             CALL xc_rho_set_create(rho2_set, bo, &
    1993             :                                    rho_cutoff=rho_cutoff, &
    1994             :                                    drho_cutoff=section_get_rval(xc_section, "GRADIENT_CUTOFF"), &
    1995          36 :                                    tau_cutoff=section_get_rval(xc_section, "TAU_CUTOFF"))
    1996             : 
    1997             :             ! calculate the arguments needed by the functionals
    1998             :             CALL xc_rho_set_update(rho2_set, rho_r, rho_g, tau_r, needs, &
    1999             :                                    section_get_ival(xc_section, "XC_GRID%XC_DERIV"), &
    2000             :                                    section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO"), &
    2001          36 :                                    pw_pool)
    2002             : 
    2003          36 :             IF (lsd) THEN
    2004             :                CALL xc_rho_set_get(rho1_set, rhoa=rho1a, rhob=rho1b, tau_a=tau1a, tau_b=tau1b, &
    2005          10 :                                    laplace_rhoa=laplace1a, laplace_rhob=laplace1b, can_return_null=.TRUE.)
    2006             :                CALL xc_rho_set_get(rho2_set, norm_drhoa=norm_drho2a, norm_drhob=norm_drho2b, &
    2007          10 :                                    norm_drho=norm_drho2, laplace_rhoa=laplace2a, laplace_rhob=laplace2b, can_return_null=.TRUE.)
    2008             : 
    2009          64 :                DO istep = -nsteps, nsteps
    2010          54 :                   IF (istep == 0) CYCLE
    2011          44 :                   weight = weights(istep, nsteps)/h
    2012          44 :                   step = REAL(istep, dp)*h
    2013          44 :                   IF (ASSOCIATED(norm_drhoa)) THEN
    2014          44 :                      CALL get_derivs_rho(norm_drho2a, norm_drhoa, step, xc_fun_section, lsd, rho2_set, deriv_set1)
    2015             :                      CALL update_deriv_rho(deriv_set1, [deriv_rhoa], bo, &
    2016          44 :                                            norm_drhoa, gradient_cut, weight, rho1a, v_drhoa%array)
    2017             :                      CALL update_deriv_rho(deriv_set1, [deriv_rhob], bo, &
    2018          44 :                                            norm_drhoa, gradient_cut, weight, rho1b, v_drhoa%array)
    2019             :                      CALL update_deriv_rho(deriv_set1, [deriv_norm_drhoa], bo, &
    2020          44 :                                            norm_drhoa, gradient_cut, weight, dra1dra, v_drhoa%array)
    2021             :                      CALL update_deriv_drho_ab(deriv_set1, [deriv_norm_drhob], bo, &
    2022          44 :                                                norm_drhoa, gradient_cut, weight, dra1dra, drb1drb, v_drhoa%array, v_drhob%array)
    2023             :                      CALL update_deriv_drho_ab(deriv_set1, [deriv_norm_drho], bo, &
    2024          44 :                                                norm_drhoa, gradient_cut, weight, dra1dra, dr1dr, v_drhoa%array, v_drho%array)
    2025          44 :                      IF (tau_f) THEN
    2026             :                         CALL update_deriv_rho(deriv_set1, [deriv_tau_a], bo, &
    2027           8 :                                               norm_drhoa, gradient_cut, weight, tau1a, v_drhoa%array)
    2028             :                         CALL update_deriv_rho(deriv_set1, [deriv_tau_b], bo, &
    2029           8 :                                               norm_drhoa, gradient_cut, weight, tau1b, v_drhoa%array)
    2030             :                      END IF
    2031          44 :                      IF (laplace_f) THEN
    2032             :                         CALL update_deriv_rho(deriv_set1, [deriv_laplace_rhoa], bo, &
    2033           4 :                                               norm_drhoa, gradient_cut, weight, laplace1a, v_drhoa%array)
    2034             :                         CALL update_deriv_rho(deriv_set1, [deriv_laplace_rhob], bo, &
    2035           4 :                                               norm_drhoa, gradient_cut, weight, laplace1b, v_drhoa%array)
    2036             :                      END IF
    2037             :                   END IF
    2038             : 
    2039          44 :                   IF (ASSOCIATED(norm_drhob)) THEN
    2040          44 :                      CALL get_derivs_rho(norm_drho2b, norm_drhob, step, xc_fun_section, lsd, rho2_set, deriv_set1)
    2041             :                      CALL update_deriv_rho(deriv_set1, [deriv_rhoa], bo, &
    2042          44 :                                            norm_drhob, gradient_cut, weight, rho1a, v_drhob%array)
    2043             :                      CALL update_deriv_rho(deriv_set1, [deriv_rhob], bo, &
    2044          44 :                                            norm_drhob, gradient_cut, weight, rho1b, v_drhob%array)
    2045             :                      CALL update_deriv_rho(deriv_set1, [deriv_norm_drhob], bo, &
    2046          44 :                                            norm_drhob, gradient_cut, weight, drb1drb, v_drhob%array)
    2047             :                      CALL update_deriv_drho_ab(deriv_set1, [deriv_norm_drhoa], bo, &
    2048          44 :                                                norm_drhob, gradient_cut, weight, drb1drb, dra1dra, v_drhob%array, v_drhoa%array)
    2049             :                      CALL update_deriv_drho_ab(deriv_set1, [deriv_norm_drho], bo, &
    2050          44 :                                                norm_drhob, gradient_cut, weight, drb1drb, dr1dr, v_drhob%array, v_drho%array)
    2051          44 :                      IF (tau_f) THEN
    2052             :                         CALL update_deriv_rho(deriv_set1, [deriv_tau_a], bo, &
    2053           8 :                                               norm_drhob, gradient_cut, weight, tau1a, v_drhob%array)
    2054             :                         CALL update_deriv_rho(deriv_set1, [deriv_tau_b], bo, &
    2055           8 :                                               norm_drhob, gradient_cut, weight, tau1b, v_drhob%array)
    2056             :                      END IF
    2057          44 :                      IF (laplace_f) THEN
    2058             :                         CALL update_deriv_rho(deriv_set1, [deriv_laplace_rhoa], bo, &
    2059           4 :                                               norm_drhob, gradient_cut, weight, laplace1a, v_drhob%array)
    2060             :                         CALL update_deriv_rho(deriv_set1, [deriv_laplace_rhob], bo, &
    2061           4 :                                               norm_drhob, gradient_cut, weight, laplace1b, v_drhob%array)
    2062             :                      END IF
    2063             :                   END IF
    2064             : 
    2065          44 :                   IF (ASSOCIATED(norm_drho)) THEN
    2066          20 :                      CALL get_derivs_rho(norm_drho2, norm_drho, step, xc_fun_section, lsd, rho2_set, deriv_set1)
    2067             :                      CALL update_deriv_rho(deriv_set1, [deriv_rhoa], bo, &
    2068          20 :                                            norm_drho, gradient_cut, weight, rho1a, v_drho%array)
    2069             :                      CALL update_deriv_rho(deriv_set1, [deriv_rhob], bo, &
    2070          20 :                                            norm_drho, gradient_cut, weight, rho1b, v_drho%array)
    2071             :                      CALL update_deriv_rho(deriv_set1, [deriv_norm_drho], bo, &
    2072          20 :                                            norm_drho, gradient_cut, weight, dr1dr, v_drho%array)
    2073             :                      CALL update_deriv_drho_ab(deriv_set1, [deriv_norm_drhoa], bo, &
    2074          20 :                                                norm_drho, gradient_cut, weight, dr1dr, dra1dra, v_drho%array, v_drhoa%array)
    2075             :                      CALL update_deriv_drho_ab(deriv_set1, [deriv_norm_drhob], bo, &
    2076          20 :                                                norm_drho, gradient_cut, weight, dr1dr, drb1drb, v_drho%array, v_drhob%array)
    2077          20 :                      IF (tau_f) THEN
    2078             :                         CALL update_deriv_rho(deriv_set1, [deriv_tau_a], bo, &
    2079           8 :                                               norm_drho, gradient_cut, weight, tau1a, v_drho%array)
    2080             :                         CALL update_deriv_rho(deriv_set1, [deriv_tau_b], bo, &
    2081           8 :                                               norm_drho, gradient_cut, weight, tau1b, v_drho%array)
    2082             :                      END IF
    2083          20 :                      IF (laplace_f) THEN
    2084             :                         CALL update_deriv_rho(deriv_set1, [deriv_laplace_rhoa], bo, &
    2085           4 :                                               norm_drho, gradient_cut, weight, laplace1a, v_drho%array)
    2086             :                         CALL update_deriv_rho(deriv_set1, [deriv_laplace_rhob], bo, &
    2087           4 :                                               norm_drho, gradient_cut, weight, laplace1b, v_drho%array)
    2088             :                      END IF
    2089             :                   END IF
    2090             : 
    2091          54 :                   IF (laplace_f) THEN
    2092             : 
    2093           4 :                      CALL get_derivs_rho(laplace2a, laplacea, step, xc_fun_section, lsd, rho2_set, deriv_set1)
    2094             : 
    2095             :                      ! Obtain the numerical 2nd derivatives w.r.t. to drho and collect the potential
    2096             :                      CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_rhoa], bo, &
    2097           4 :                                        weight, rho1a, v_laplacea%array)
    2098             :                      CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_rhob], bo, &
    2099           4 :                                        weight, rho1b, v_laplacea%array)
    2100           4 :                      IF (ASSOCIATED(norm_drho)) THEN
    2101             :                         CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_norm_drho], bo, &
    2102           4 :                                           weight, dr1dr, v_laplacea%array)
    2103             :                      END IF
    2104           4 :                      IF (ASSOCIATED(norm_drhoa)) THEN
    2105             :                         CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_norm_drhoa], bo, &
    2106           4 :                                           weight, dra1dra, v_laplacea%array)
    2107             :                      END IF
    2108           4 :                      IF (ASSOCIATED(norm_drhob)) THEN
    2109             :                         CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_norm_drhob], bo, &
    2110           4 :                                           weight, drb1drb, v_laplacea%array)
    2111             :                      END IF
    2112             : 
    2113           4 :                      IF (ASSOCIATED(tau1a)) THEN
    2114             :                         CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_tau_a], bo, &
    2115           4 :                                           weight, tau1a, v_laplacea%array)
    2116             :                      END IF
    2117           4 :                      IF (ASSOCIATED(tau1b)) THEN
    2118             :                         CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_tau_b], bo, &
    2119           4 :                                           weight, tau1b, v_laplacea%array)
    2120             :                      END IF
    2121             : 
    2122             :                      CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_laplace_rhoa], bo, &
    2123           4 :                                        weight, laplace1a, v_laplacea%array)
    2124             : 
    2125             :                      CALL update_deriv(deriv_set1, laplacea, rho_cutoff, [deriv_laplace_rhob], bo, &
    2126           4 :                                        weight, laplace1b, v_laplacea%array)
    2127             : 
    2128             :                      ! The same for the beta spin
    2129           4 :                      CALL get_derivs_rho(laplace2b, laplaceb, step, xc_fun_section, lsd, rho2_set, deriv_set1)
    2130             : 
    2131             :                      ! Obtain the numerical 2nd derivatives w.r.t. to drho and collect the potential
    2132             :                      CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_rhoa], bo, &
    2133           4 :                                        weight, rho1a, v_laplaceb%array)
    2134             :                      CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_rhob], bo, &
    2135           4 :                                        weight, rho1b, v_laplaceb%array)
    2136           4 :                      IF (ASSOCIATED(norm_drho)) THEN
    2137             :                         CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_norm_drho], bo, &
    2138           4 :                                           weight, dr1dr, v_laplaceb%array)
    2139             :                      END IF
    2140           4 :                      IF (ASSOCIATED(norm_drhoa)) THEN
    2141             :                         CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_norm_drhoa], bo, &
    2142           4 :                                           weight, dra1dra, v_laplaceb%array)
    2143             :                      END IF
    2144           4 :                      IF (ASSOCIATED(norm_drhob)) THEN
    2145             :                         CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_norm_drhob], bo, &
    2146           4 :                                           weight, drb1drb, v_laplaceb%array)
    2147             :                      END IF
    2148             : 
    2149           4 :                      IF (tau_f) THEN
    2150             :                         CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_tau_a], bo, &
    2151           4 :                                           weight, tau1a, v_laplaceb%array)
    2152             :                         CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_tau_b], bo, &
    2153           4 :                                           weight, tau1b, v_laplaceb%array)
    2154             :                      END IF
    2155             : 
    2156             :                      CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_laplace_rhoa], bo, &
    2157           4 :                                        weight, laplace1a, v_laplaceb%array)
    2158             : 
    2159             :                      CALL update_deriv(deriv_set1, laplaceb, rho_cutoff, [deriv_laplace_rhob], bo, &
    2160           4 :                                        weight, laplace1b, v_laplaceb%array)
    2161             :                   END IF
    2162             :                END DO
    2163             : 
    2164          10 :                CALL virial_drho_drho(virial_pw, drhoa, v_drhoa, virial_xc)
    2165          10 :                CALL virial_drho_drho(virial_pw, drhob, v_drhob, virial_xc)
    2166          10 :                CALL virial_drho_drho(virial_pw, drho, v_drho, virial_xc)
    2167             : 
    2168          10 :                CALL deallocate_pw(v_drho, pw_pool)
    2169          10 :                CALL deallocate_pw(v_drhoa, pw_pool)
    2170          10 :                CALL deallocate_pw(v_drhob, pw_pool)
    2171             : 
    2172          10 :                IF (laplace_f) THEN
    2173       15026 :                   virial_pw%array(:, :, :) = -rhoa(:, :, :)
    2174           2 :                   CALL virial_laplace(virial_pw, pw_pool, virial_xc, v_laplacea%array)
    2175           2 :                   CALL deallocate_pw(v_laplacea, pw_pool)
    2176             : 
    2177       15026 :                   virial_pw%array(:, :, :) = -rhob(:, :, :)
    2178           2 :                   CALL virial_laplace(virial_pw, pw_pool, virial_xc, v_laplaceb%array)
    2179           2 :                   CALL deallocate_pw(v_laplaceb, pw_pool)
    2180             :                END IF
    2181             : 
    2182          10 :                CALL deallocate_pw(virial_pw, pw_pool)
    2183             : 
    2184          40 :                DO idir = 1, 3
    2185          30 :                   DEALLOCATE (drho(idir)%array)
    2186          40 :                   DEALLOCATE (drho1(idir)%array)
    2187             :                END DO
    2188          10 :                DEALLOCATE (dra1dra, drb1drb)
    2189             : 
    2190             :             ELSE
    2191          26 :                CALL xc_rho_set_get(rho1_set, rho=rho1, tau=tau1, laplace_rho=laplace1, can_return_null=.TRUE.)
    2192          26 :                CALL xc_rho_set_get(rho2_set, norm_drho=norm_drho2, laplace_rho=laplace2, can_return_null=.TRUE.)
    2193             : 
    2194         200 :                DO istep = -nsteps, nsteps
    2195         174 :                   IF (istep == 0) CYCLE
    2196         148 :                   weight = weights(istep, nsteps)/h
    2197         148 :                   step = REAL(istep, dp)*h
    2198         148 :                   CALL get_derivs_rho(norm_drho2, norm_drho, step, xc_fun_section, lsd, rho2_set, deriv_set1)
    2199             : 
    2200             :                   ! Obtain the numerical 2nd derivatives w.r.t. to drho and collect the potential
    2201             :                   CALL update_deriv_rho(deriv_set1, [deriv_rho], bo, &
    2202         148 :                                         norm_drho, gradient_cut, weight, rho1, v_drho%array)
    2203             :                   CALL update_deriv_rho(deriv_set1, [deriv_norm_drho], bo, &
    2204         148 :                                         norm_drho, gradient_cut, weight, dr1dr, v_drho%array)
    2205             : 
    2206         148 :                   IF (tau_f) THEN
    2207             :                      CALL update_deriv_rho(deriv_set1, [deriv_tau], bo, &
    2208          24 :                                            norm_drho, gradient_cut, weight, tau1, v_drho%array)
    2209             :                   END IF
    2210         174 :                   IF (laplace_f) THEN
    2211             :                      CALL update_deriv_rho(deriv_set1, [deriv_laplace_rho], bo, &
    2212          12 :                                            norm_drho, gradient_cut, weight, laplace1, v_drho%array)
    2213             : 
    2214          12 :                      CALL get_derivs_rho(laplace2, laplace, step, xc_fun_section, lsd, rho2_set, deriv_set1)
    2215             : 
    2216             :                      ! Obtain the numerical 2nd derivatives w.r.t. to drho and collect the potential
    2217             :                      CALL update_deriv(deriv_set1, laplace, rho_cutoff, [deriv_rho], bo, &
    2218          12 :                                        weight, rho1, v_laplace%array)
    2219             :                      CALL update_deriv(deriv_set1, laplace, rho_cutoff, [deriv_norm_drho], bo, &
    2220          12 :                                        weight, dr1dr, v_laplace%array)
    2221             : 
    2222          12 :                      IF (tau_f) THEN
    2223             :                         CALL update_deriv(deriv_set1, laplace, rho_cutoff, [deriv_tau], bo, &
    2224          12 :                                           weight, tau1, v_laplace%array)
    2225             :                      END IF
    2226             : 
    2227             :                      CALL update_deriv(deriv_set1, laplace, rho_cutoff, [deriv_laplace_rho], bo, &
    2228          12 :                                        weight, laplace1, v_laplace%array)
    2229             :                   END IF
    2230             :                END DO
    2231             : 
    2232             :                ! Calculate the virial contribution from the potential
    2233          26 :                CALL virial_drho_drho(virial_pw, drho, v_drho, virial_xc)
    2234             : 
    2235          26 :                CALL deallocate_pw(v_drho, pw_pool)
    2236             : 
    2237          26 :                IF (laplace_f) THEN
    2238       28862 :                   virial_pw%array(:, :, :) = -rho(:, :, :)
    2239           2 :                   CALL virial_laplace(virial_pw, pw_pool, virial_xc, v_laplace%array)
    2240           2 :                   CALL deallocate_pw(v_laplace, pw_pool)
    2241             :                END IF
    2242             : 
    2243          26 :                CALL deallocate_pw(virial_pw, pw_pool)
    2244             :             END IF
    2245             : 
    2246             :          END IF
    2247             : 
    2248          36 :          CALL xc_dset_release(deriv_set1)
    2249             : 
    2250          36 :          DEALLOCATE (dr1dr)
    2251             : 
    2252          36 :          CALL xc_rho_set_release(rho1_set)
    2253          36 :          CALL xc_rho_set_release(rho2_set)
    2254             :       END IF
    2255             : 
    2256        2012 :       DO ispin = 1, SIZE(rho_r)
    2257        2012 :          CALL pw_pool%give_back_pw(rho_r(ispin))
    2258             :       END DO
    2259         832 :       DEALLOCATE (rho_r)
    2260             : 
    2261         832 :       IF (ASSOCIATED(tau_r)) THEN
    2262         254 :       DO ispin = 1, SIZE(tau_r)
    2263         254 :          CALL pw_pool%give_back_pw(tau_r(ispin))
    2264             :       END DO
    2265         100 :       DEALLOCATE (tau_r)
    2266             :       END IF
    2267             : 
    2268         832 :       CALL timestop(handle)
    2269             : 
    2270       37440 :    END SUBROUTINE xc_calc_2nd_deriv_numerical
    2271             : 
    2272             : ! **************************************************************************************************
    2273             : !> \brief ...
    2274             : !> \param rho_r ...
    2275             : !> \param rho_g ...
    2276             : !> \param rho1_r ...
    2277             : !> \param rhoa ...
    2278             : !> \param rhob ...
    2279             : !> \param vxc_rho ...
    2280             : !> \param tau_r ...
    2281             : !> \param tau1_r ...
    2282             : !> \param tau_a ...
    2283             : !> \param tau_b ...
    2284             : !> \param vxc_tau ...
    2285             : !> \param xc_section ...
    2286             : !> \param pw_pool ...
    2287             : !> \param step ...
    2288             : ! **************************************************************************************************
    2289        1848 :    SUBROUTINE calc_resp_potential_numer_ab(rho_r, rho_g, rho1_r, rhoa, rhob, vxc_rho, &
    2290             :                                            tau_r, tau1_r, tau_a, tau_b, vxc_tau, &
    2291             :                                            xc_section, pw_pool, step)
    2292             : 
    2293             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER, INTENT(IN) :: vxc_rho, vxc_tau
    2294             :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN)            :: rho1_r
    2295             :       TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN), POINTER   :: tau1_r
    2296             :       TYPE(pw_pool_type), INTENT(IN), POINTER            :: pw_pool
    2297             :       TYPE(section_vals_type), INTENT(IN), POINTER       :: xc_section
    2298             :       REAL(KIND=dp), INTENT(IN)                          :: step
    2299             :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER, INTENT(IN) :: rhoa, rhob, tau_a, tau_b
    2300             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER, INTENT(IN)   :: rho_r
    2301             :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
    2302             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               ::  tau_r
    2303             : 
    2304             :       CHARACTER(len=*), PARAMETER :: routineN = 'calc_resp_potential_numer_ab'
    2305             : 
    2306             :       INTEGER                                            :: handle
    2307             :       REAL(KIND=dp)                                      :: exc
    2308             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: virial_dummy
    2309             : 
    2310        1848 :       CALL timeset(routineN, handle)
    2311             : 
    2312        1848 : !$OMP PARALLEL DEFAULT(NONE) SHARED(rho_r,rhoa,rhob,step,rho1_r,tau_r,tau_a,tau_b,tau1_r)
    2313             : !$OMP WORKSHARE
    2314             :       rho_r(1)%array(:, :, :) = rhoa(:, :, :) + step*rho1_r(1)%array(:, :, :)
    2315             : !$OMP END WORKSHARE NOWAIT
    2316             : !$OMP WORKSHARE
    2317             :       rho_r(2)%array(:, :, :) = rhob(:, :, :) + step*rho1_r(2)%array(:, :, :)
    2318             : !$OMP END WORKSHARE NOWAIT
    2319             :       IF (ASSOCIATED(tau1_r) .AND. ASSOCIATED(tau_r) .AND. ASSOCIATED(tau_a) .AND. ASSOCIATED(tau_b)) THEN
    2320             : !$OMP WORKSHARE
    2321             :          tau_r(1)%array(:, :, :) = tau_a(:, :, :) + step*tau1_r(1)%array(:, :, :)
    2322             : !$OMP END WORKSHARE NOWAIT
    2323             : !$OMP WORKSHARE
    2324             :          tau_r(2)%array(:, :, :) = tau_b(:, :, :) + step*tau1_r(2)%array(:, :, :)
    2325             : !$OMP END WORKSHARE NOWAIT
    2326             :       END IF
    2327             : !$OMP END PARALLEL
    2328             :       CALL xc_vxc_pw_create(vxc_rho, vxc_tau, exc, rho_r, rho_g, tau_r, xc_section, &
    2329        1848 :                             pw_pool, .FALSE., virial_dummy)
    2330             : 
    2331        1848 :       CALL timestop(handle)
    2332             : 
    2333        1848 :    END SUBROUTINE calc_resp_potential_numer_ab
    2334             : 
    2335             : ! **************************************************************************************************
    2336             : !> \brief calculates stress tensor and potential contributions from the first derivative
    2337             : !> \param deriv_set ...
    2338             : !> \param description ...
    2339             : !> \param virial_pw ...
    2340             : !> \param drho ...
    2341             : !> \param drho1 ...
    2342             : !> \param virial_xc ...
    2343             : !> \param norm_drho ...
    2344             : !> \param gradient_cut ...
    2345             : !> \param dr1dr ...
    2346             : !> \param v_drho ...
    2347             : ! **************************************************************************************************
    2348          52 :    SUBROUTINE apply_drho(deriv_set, description, virial_pw, drho, drho1, virial_xc, norm_drho, gradient_cut, dr1dr, v_drho)
    2349             : 
    2350             :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set
    2351             :       INTEGER, DIMENSION(:), INTENT(in)                  :: description
    2352             :       TYPE(pw_r3d_rs_type), INTENT(IN)                          :: virial_pw
    2353             :       TYPE(cp_3d_r_cp_type), DIMENSION(3), INTENT(IN)     :: drho, drho1
    2354             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT)      :: virial_xc
    2355             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: norm_drho
    2356             :       REAL(KIND=dp), INTENT(IN)                          :: gradient_cut
    2357             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: dr1dr
    2358             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: v_drho
    2359             : 
    2360             :       CHARACTER(len=*), PARAMETER :: routineN = 'apply_drho'
    2361             : 
    2362             :       INTEGER                                            :: handle
    2363          52 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: deriv_data
    2364             :       TYPE(xc_derivative_type), POINTER                  :: deriv_att
    2365             : 
    2366          52 :       CALL timeset(routineN, handle)
    2367             : 
    2368          52 :       deriv_att => xc_dset_get_derivative(deriv_set, description)
    2369          52 :       IF (ASSOCIATED(deriv_att)) THEN
    2370          52 :          CALL xc_derivative_get(deriv_att, deriv_data=deriv_data)
    2371          52 :          CALL virial_drho_drho1(virial_pw, drho, drho1, deriv_data, virial_xc)
    2372             : 
    2373          52 : !$OMP    PARALLEL WORKSHARE DEFAULT(NONE) SHARED(dr1dr,gradient_cut,norm_drho,v_drho,deriv_data)
    2374             :          v_drho(:, :, :) = v_drho(:, :, :) + &
    2375             :                            deriv_data(:, :, :)*dr1dr(:, :, :)/MAX(gradient_cut, norm_drho(:, :, :))**2
    2376             : !$OMP    END PARALLEL WORKSHARE
    2377             :       END IF
    2378             : 
    2379          52 :       CALL timestop(handle)
    2380             : 
    2381          52 :    END SUBROUTINE apply_drho
    2382             : 
    2383             : ! **************************************************************************************************
    2384             : !> \brief adds potential contributions from derivatives of rho or diagonal terms of norm_drho
    2385             : !> \param deriv_set1 ...
    2386             : !> \param description ...
    2387             : !> \param bo ...
    2388             : !> \param norm_drho norm_drho of which derivative is calculated
    2389             : !> \param gradient_cut ...
    2390             : !> \param h ...
    2391             : !> \param rho1 function to contract the derivative with (rho1 for rho, dr1dr for norm_drho)
    2392             : !> \param v_drho ...
    2393             : ! **************************************************************************************************
    2394         728 :    SUBROUTINE update_deriv_rho(deriv_set1, description, bo, norm_drho, gradient_cut, weight, rho1, v_drho)
    2395             : 
    2396             :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set1
    2397             :       INTEGER, DIMENSION(:), INTENT(in)                  :: description
    2398             :       INTEGER, DIMENSION(2, 3), INTENT(IN)               :: bo
    2399             :       REAL(KIND=dp), DIMENSION(bo(1, 1):bo(2, 1), bo(1, &
    2400             :                                                      2):bo(2, 2), bo(1, 3):bo(2, 3)), INTENT(IN)     :: norm_drho
    2401             :       REAL(KIND=dp), INTENT(IN)                          :: gradient_cut, weight
    2402             :       REAL(KIND=dp), DIMENSION(bo(1, 1):bo(2, 1), bo(1, &
    2403             :                                                      2):bo(2, 2), bo(1, 3):bo(2, 3)), INTENT(IN)     :: rho1
    2404             :       REAL(KIND=dp), DIMENSION(bo(1, 1):bo(2, 1), bo(1, &
    2405             :                                                      2):bo(2, 2), bo(1, 3):bo(2, 3)), INTENT(INOUT)  :: v_drho
    2406             : 
    2407             :       CHARACTER(len=*), PARAMETER :: routineN = 'update_deriv_rho'
    2408             : 
    2409             :       INTEGER                                            :: handle, i, j, k
    2410             :       REAL(KIND=dp)                                      :: de
    2411         728 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: deriv_data1
    2412             :       TYPE(xc_derivative_type), POINTER                  :: deriv_att1
    2413             : 
    2414         728 :       CALL timeset(routineN, handle)
    2415             : 
    2416             :       ! Obtain the numerical 2nd derivatives w.r.t. to drho and collect the potential
    2417         728 :       deriv_att1 => xc_dset_get_derivative(deriv_set1, description)
    2418         728 :       IF (ASSOCIATED(deriv_att1)) THEN
    2419         728 :          CALL xc_derivative_get(deriv_att1, deriv_data=deriv_data1)
    2420             : !$OMP PARALLEL DO DEFAULT(NONE) SHARED(bo,deriv_data1,weight,norm_drho,v_drho,rho1,gradient_cut) &
    2421         728 : !$OMP PRIVATE(i,j,k,de) COLLAPSE(3)
    2422             :          DO k = bo(1, 3), bo(2, 3)
    2423             :             DO j = bo(1, 2), bo(2, 2)
    2424             :                DO i = bo(1, 1), bo(2, 1)
    2425             :                   de = weight*deriv_data1(i, j, k)/MAX(gradient_cut, norm_drho(i, j, k))**2
    2426             :                   v_drho(i, j, k) = v_drho(i, j, k) - de*rho1(i, j, k)
    2427             :                END DO
    2428             :             END DO
    2429             :          END DO
    2430             : !$OMP END PARALLEL DO
    2431             :       END IF
    2432             : 
    2433         728 :       CALL timestop(handle)
    2434             : 
    2435         728 :    END SUBROUTINE update_deriv_rho
    2436             : 
    2437             : ! **************************************************************************************************
    2438             : !> \brief adds potential contributions from derivatives of a component with positive and negative values
    2439             : !> \param deriv_set1 ...
    2440             : !> \param description ...
    2441             : !> \param bo ...
    2442             : !> \param h ...
    2443             : !> \param rho1 function to contract the derivative with (rho1 for rho, dr1dr for norm_drho)
    2444             : !> \param v ...
    2445             : ! **************************************************************************************************
    2446         120 :    SUBROUTINE update_deriv(deriv_set1, rho, rho_cutoff, description, bo, weight, rho1, v)
    2447             : 
    2448             :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set1
    2449             :       INTEGER, DIMENSION(:), INTENT(in)                  :: description
    2450             :       INTEGER, DIMENSION(2, 3), INTENT(IN)               :: bo
    2451             :       REAL(KIND=dp), INTENT(IN)                          :: weight, rho_cutoff
    2452             :       REAL(KIND=dp), DIMENSION(bo(1, 1):bo(2, 1), bo(1, &
    2453             :                                                      2):bo(2, 2), bo(1, 3):bo(2, 3)), INTENT(IN)     :: rho, rho1
    2454             :       REAL(KIND=dp), DIMENSION(bo(1, 1):bo(2, 1), bo(1, &
    2455             :                                                      2):bo(2, 2), bo(1, 3):bo(2, 3)), INTENT(INOUT)  :: v
    2456             : 
    2457             :       CHARACTER(len=*), PARAMETER :: routineN = 'update_deriv'
    2458             : 
    2459             :       INTEGER                                            :: handle, i, j, k
    2460             :       REAL(KIND=dp)                                      :: de
    2461         120 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: deriv_data1
    2462             :       TYPE(xc_derivative_type), POINTER                  :: deriv_att1
    2463             : 
    2464         120 :       CALL timeset(routineN, handle)
    2465             : 
    2466             :       ! Obtain the numerical 2nd derivatives w.r.t. to drho and collect the potential
    2467         120 :       deriv_att1 => xc_dset_get_derivative(deriv_set1, description)
    2468         120 :       IF (ASSOCIATED(deriv_att1)) THEN
    2469         120 :          CALL xc_derivative_get(deriv_att1, deriv_data=deriv_data1)
    2470             : !$OMP PARALLEL DO DEFAULT(NONE) SHARED(bo,deriv_data1,weight,v,rho1,rho, rho_cutoff) &
    2471         120 : !$OMP PRIVATE(i,j,k,de) COLLAPSE(3)
    2472             :          DO k = bo(1, 3), bo(2, 3)
    2473             :             DO j = bo(1, 2), bo(2, 2)
    2474             :                DO i = bo(1, 1), bo(2, 1)
    2475             :                   ! We have to consider that the given density (mostly the Laplacian) may have positive and negative values
    2476             :                   de = weight*deriv_data1(i, j, k)/SIGN(MAX(ABS(rho(i, j, k)), rho_cutoff), rho(i, j, k))
    2477             :                   v(i, j, k) = v(i, j, k) + de*rho1(i, j, k)
    2478             :                END DO
    2479             :             END DO
    2480             :          END DO
    2481             : !$OMP END PARALLEL DO
    2482             :       END IF
    2483             : 
    2484         120 :       CALL timestop(handle)
    2485             : 
    2486         120 :    END SUBROUTINE update_deriv
    2487             : 
    2488             : ! **************************************************************************************************
    2489             : !> \brief adds mixed derivatives of norm_drho
    2490             : !> \param deriv_set1 ...
    2491             : !> \param description ...
    2492             : !> \param bo ...
    2493             : !> \param norm_drhoa norm_drho of which derivatives is calculated
    2494             : !> \param gradient_cut ...
    2495             : !> \param h ...
    2496             : !> \param dra1dra dr1dr corresponding to norm_drho
    2497             : !> \param drb1drb ...
    2498             : !> \param v_drhoa potential corresponding to norm_drho
    2499             : !> \param v_drhob ...
    2500             : ! **************************************************************************************************
    2501         216 :    SUBROUTINE update_deriv_drho_ab(deriv_set1, description, bo, &
    2502         216 :                                    norm_drhoa, gradient_cut, weight, dra1dra, drb1drb, v_drhoa, v_drhob)
    2503             : 
    2504             :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set1
    2505             :       INTEGER, DIMENSION(:), INTENT(in)                  :: description
    2506             :       INTEGER, DIMENSION(2, 3), INTENT(IN)               :: bo
    2507             :       REAL(KIND=dp), DIMENSION(bo(1, 1):bo(2, 1), bo(1, &
    2508             :                                                      2):bo(2, 2), bo(1, 3):bo(2, 3)), INTENT(IN)     :: norm_drhoa
    2509             :       REAL(KIND=dp), INTENT(IN)                          :: gradient_cut, weight
    2510             :       REAL(KIND=dp), DIMENSION(bo(1, 1):bo(2, 1), bo(1, &
    2511             :                                                      2):bo(2, 2), bo(1, 3):bo(2, 3)), INTENT(IN)     :: dra1dra, drb1drb
    2512             :       REAL(KIND=dp), DIMENSION(bo(1, 1):bo(2, 1), bo(1, &
    2513             :                                                      2):bo(2, 2), bo(1, 3):bo(2, 3)), INTENT(INOUT)  :: v_drhoa, v_drhob
    2514             : 
    2515             :       CHARACTER(len=*), PARAMETER :: routineN = 'update_deriv_drho_ab'
    2516             : 
    2517             :       INTEGER                                            :: handle, i, j, k
    2518             :       REAL(KIND=dp)                                      :: de
    2519         216 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: deriv_data1
    2520             :       TYPE(xc_derivative_type), POINTER                  :: deriv_att1
    2521             : 
    2522         216 :       CALL timeset(routineN, handle)
    2523             : 
    2524         216 :       deriv_att1 => xc_dset_get_derivative(deriv_set1, description)
    2525         216 :       IF (ASSOCIATED(deriv_att1)) THEN
    2526         168 :          CALL xc_derivative_get(deriv_att1, deriv_data=deriv_data1)
    2527             : !$OMP    PARALLEL DO PRIVATE(k,j,i,de)  DEFAULT(NONE) &
    2528         168 : !$OMP    SHARED(bo,drb1drb,dra1dra,deriv_data1,weight,gradient_cut,norm_drhoa,v_drhoa,v_drhob) COLLAPSE(3)
    2529             :          DO k = bo(1, 3), bo(2, 3)
    2530             :             DO j = bo(1, 2), bo(2, 2)
    2531             :                DO i = bo(1, 1), bo(2, 1)
    2532             :                   ! We introduce a factor of two because we will average between both numerical derivatives
    2533             :                   de = 0.5_dp*weight*deriv_data1(i, j, k)/MAX(gradient_cut, norm_drhoa(i, j, k))**2
    2534             :                   v_drhoa(i, j, k) = v_drhoa(i, j, k) - de*drb1drb(i, j, k)
    2535             :                   v_drhob(i, j, k) = v_drhob(i, j, k) - de*dra1dra(i, j, k)
    2536             :                END DO
    2537             :             END DO
    2538             :          END DO
    2539             :       END IF
    2540             : 
    2541         216 :       CALL timestop(handle)
    2542             : 
    2543         216 :    END SUBROUTINE update_deriv_drho_ab
    2544             : 
    2545             : ! **************************************************************************************************
    2546             : !> \brief calculate derivative sets for helper points
    2547             : !> \param norm_drho2 norm_drho of new points
    2548             : !> \param norm_drho norm_drho of KS density
    2549             : !> \param h ...
    2550             : !> \param xc_fun_section ...
    2551             : !> \param lsd ...
    2552             : !> \param rho2_set rho_set for new points
    2553             : !> \param deriv_set1 will contain derivatives of the perturbed density
    2554             : ! **************************************************************************************************
    2555         276 :    SUBROUTINE get_derivs_rho(norm_drho2, norm_drho, step, xc_fun_section, lsd, rho2_set, deriv_set1)
    2556             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: norm_drho2
    2557             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: norm_drho
    2558             :       REAL(KIND=dp), INTENT(IN)                          :: step
    2559             :       TYPE(section_vals_type), INTENT(IN), POINTER       :: xc_fun_section
    2560             :       LOGICAL, INTENT(IN)                                :: lsd
    2561             :       TYPE(xc_rho_set_type), INTENT(INOUT)               :: rho2_set
    2562             :       TYPE(xc_derivative_set_type)                       :: deriv_set1
    2563             : 
    2564             :       CHARACTER(len=*), PARAMETER :: routineN = 'get_derivs_rho'
    2565             : 
    2566             :       INTEGER                                            :: handle
    2567             : 
    2568         276 :       CALL timeset(routineN, handle)
    2569             : 
    2570             :       ! Copy the densities, do one step into the direction of drho
    2571         276 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(norm_drho,norm_drho2,step)
    2572             :       norm_drho2 = norm_drho*(1.0_dp + step)
    2573             : !$OMP END PARALLEL WORKSHARE
    2574             : 
    2575         276 :       CALL xc_dset_zero_all(deriv_set1)
    2576             : 
    2577             :       ! Calculate the derivatives of the functional
    2578             :       CALL xc_functionals_eval(xc_fun_section, &
    2579             :                                lsd=lsd, &
    2580             :                                rho_set=rho2_set, &
    2581             :                                deriv_set=deriv_set1, &
    2582         276 :                                deriv_order=1)
    2583             : 
    2584             :       ! Return to the original values
    2585         276 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(norm_drho,norm_drho2)
    2586             :       norm_drho2 = norm_drho
    2587             : !$OMP END PARALLEL WORKSHARE
    2588             : 
    2589         276 :       CALL divide_by_norm_drho(deriv_set1, rho2_set, lsd)
    2590             : 
    2591         276 :       CALL timestop(handle)
    2592             : 
    2593         276 :    END SUBROUTINE get_derivs_rho
    2594             : 
    2595             : ! **************************************************************************************************
    2596             : !> \brief Calculates the second derivative of E_xc at rho in the direction
    2597             : !>      rho1  (if you see the second derivative as bilinear form)
    2598             : !>      partial_rho|_(rho=rho) partial_rho|_(rho=rho) E_xc drho(rho1)drho
    2599             : !>      The other direction is still undetermined, thus it returns
    2600             : !>      a potential (partial integration is performed to reduce it to
    2601             : !>      function of rho, removing the dependence from its partial derivs)
    2602             : !>      Has to be called after the setup by xc_prep_2nd_deriv.
    2603             : !> \param v_xc       exchange-correlation potential
    2604             : !> \param v_xc_tau ...
    2605             : !> \param deriv_set  derivatives of the exchange-correlation potential
    2606             : !> \param rho_set    object containing the density at which the derivatives were calculated
    2607             : !> \param rho1_set   object containing the density with which to fold
    2608             : !> \param pw_pool    the pool for the grids
    2609             : !> \param xc_section XC parameters
    2610             : !> \param gapw       Gaussian and augmented plane waves calculation
    2611             : !> \param vxg ...
    2612             : !> \param tddfpt_fac factor that multiplies the crossterms (tddfpt triplets
    2613             : !>        on a closed shell system it should be -1, defaults to 1)
    2614             : !> \param compute_virial ...
    2615             : !> \param virial_xc ...
    2616             : !> \note
    2617             : !>      The old version of this routine was smarter: it handled split_desc(1)
    2618             : !>      and split_desc(2) separately, thus the code automatically handled all
    2619             : !>      possible cross terms (you only had to check if it was diagonal to avoid
    2620             : !>      double counting). I think that is the way to go if you want to add more
    2621             : !>      terms (tau,rho in LSD,...). The problem with the old code was that it
    2622             : !>      because of the old functional structure it sometime guessed wrongly
    2623             : !>      which derivative was where. There were probably still bugs with gradient
    2624             : !>      corrected functionals (never tested), and it didn't contain first
    2625             : !>      derivatives with respect to drho (that contribute also to the second
    2626             : !>      derivative wrt. rho).
    2627             : !>      The code was a little complex because it really tried to handle any
    2628             : !>      functional derivative in the most efficient way with the given contents of
    2629             : !>      rho_set.
    2630             : !>      Anyway I strongly encourage whoever wants to modify this code to give a
    2631             : !>      look to the old version. [fawzi]
    2632             : ! **************************************************************************************************
    2633       31304 :    SUBROUTINE xc_calc_2nd_deriv_analytical(v_xc, v_xc_tau, deriv_set, rho_set, rho1_set, &
    2634             :                                            pw_pool, xc_section, gapw, vxg, tddfpt_fac, &
    2635             :                                            compute_virial, virial_xc)
    2636             : 
    2637             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER             :: v_xc, v_xc_tau
    2638             :       TYPE(xc_derivative_set_type)                       :: deriv_set
    2639             :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set, rho1_set
    2640             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
    2641             :       TYPE(section_vals_type), POINTER                   :: xc_section
    2642             :       LOGICAL, INTENT(IN), OPTIONAL                      :: gapw
    2643             :       REAL(kind=dp), DIMENSION(:, :, :, :), OPTIONAL, &
    2644             :          POINTER                                         :: vxg
    2645             :       REAL(kind=dp), INTENT(in), OPTIONAL                :: tddfpt_fac
    2646             :       LOGICAL, INTENT(IN), OPTIONAL                      :: compute_virial
    2647             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT), &
    2648             :          OPTIONAL                                        :: virial_xc
    2649             : 
    2650             :       CHARACTER(len=*), PARAMETER :: routineN = 'xc_calc_2nd_deriv_analytical'
    2651             : 
    2652             :       INTEGER                                            :: handle, i, ia, idir, ir, ispin, j, jdir, &
    2653             :                                                             k, nspins, xc_deriv_method_id
    2654             :       INTEGER, DIMENSION(2, 3)                           :: bo
    2655             :       LOGICAL                                            :: gradient_f, lsd, my_compute_virial, &
    2656             :                                                             my_gapw, tau_f, laplace_f, rho_f
    2657             :       REAL(KIND=dp)                                      :: fac, gradient_cut, tmp, factor2
    2658       31304 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: dr1dr, dra1dra, drb1drb
    2659       62608 :       REAL(kind=dp), DIMENSION(:, :, :), POINTER         :: deriv_data, e_drhoa, e_drhob, &
    2660       31304 :                                                             e_drho, norm_drho, norm_drhoa, &
    2661       31304 :                                                             norm_drhob, rho1, rho1a, rho1b, &
    2662       31304 :                                                             tau1, tau1a, tau1b, laplace1, laplace1a, laplace1b, &
    2663       31304 :                                                             rho, rhoa, rhob
    2664      594776 :       TYPE(cp_3d_r_cp_type), DIMENSION(3)                :: drho, drho1, drho1a, drho1b, drhoa, drhob
    2665       31304 :       TYPE(pw_r3d_rs_type), DIMENSION(:), ALLOCATABLE         :: v_drhoa, v_drhob, v_drho, v_laplace
    2666       31304 :       TYPE(pw_r3d_rs_type), DIMENSION(:, :), ALLOCATABLE      :: v_drho_r
    2667             :       TYPE(pw_r3d_rs_type)                                      ::  virial_pw
    2668             :       TYPE(pw_c1d_gs_type) :: tmp_g, vxc_g
    2669             :       TYPE(xc_derivative_type), POINTER                  :: deriv_att
    2670             : 
    2671       31304 :       CALL timeset(routineN, handle)
    2672             : 
    2673       31304 :       NULLIFY (e_drhoa, e_drhob, e_drho)
    2674             : 
    2675       31304 :       my_gapw = .FALSE.
    2676       31304 :       IF (PRESENT(gapw)) my_gapw = gapw
    2677             : 
    2678       31304 :       my_compute_virial = .FALSE.
    2679       31304 :       IF (PRESENT(compute_virial)) my_compute_virial = compute_virial
    2680             : 
    2681       31304 :       CPASSERT(ASSOCIATED(v_xc))
    2682       31304 :       CPASSERT(ASSOCIATED(xc_section))
    2683       31304 :       IF (my_gapw) THEN
    2684       10060 :          CPASSERT(PRESENT(vxg))
    2685             :       END IF
    2686       31304 :       IF (my_compute_virial) THEN
    2687         354 :          CPASSERT(PRESENT(virial_xc))
    2688             :       END IF
    2689             : 
    2690             :       CALL section_vals_val_get(xc_section, "XC_GRID%XC_DERIV", &
    2691       31304 :                                 i_val=xc_deriv_method_id)
    2692       31304 :       CALL xc_rho_set_get(rho_set, drho_cutoff=gradient_cut)
    2693       31304 :       nspins = SIZE(v_xc)
    2694       31304 :       lsd = ASSOCIATED(rho_set%rhoa)
    2695       31304 :       fac = 0.0_dp
    2696       31304 :       factor2 = 1.0_dp
    2697       31304 :       IF (PRESENT(tddfpt_fac)) fac = tddfpt_fac
    2698       31304 :       IF (PRESENT(tddfpt_fac)) factor2 = tddfpt_fac
    2699             : 
    2700      313040 :       bo = rho_set%local_bounds
    2701             : 
    2702       31304 :       CALL check_for_derivatives(deriv_set, lsd, rho_f, gradient_f, tau_f, laplace_f)
    2703             : 
    2704       31304 :       IF (tau_f) THEN
    2705         614 :          CPASSERT(ASSOCIATED(v_xc_tau))
    2706             :       END IF
    2707             : 
    2708       31304 :       IF (gradient_f) THEN
    2709      203810 :          ALLOCATE (v_drho_r(3, nspins), v_drho(nspins))
    2710       40762 :          DO ispin = 1, nspins
    2711       84136 :             DO idir = 1, 3
    2712       84136 :                CALL allocate_pw(v_drho_r(idir, ispin), pw_pool, bo)
    2713             :             END DO
    2714       40762 :             CALL allocate_pw(v_drho(ispin), pw_pool, bo)
    2715             :          END DO
    2716             : 
    2717       19728 :          IF (xc_requires_tmp_g(xc_deriv_method_id) .AND. .NOT. my_gapw) THEN
    2718       12034 :             IF (ASSOCIATED(pw_pool)) THEN
    2719       12034 :                CALL pw_pool%create_pw(tmp_g)
    2720       12034 :                CALL pw_pool%create_pw(vxc_g)
    2721             :             ELSE
    2722             :                ! remember to refix for gapw
    2723           0 :                CPABORT("XC_DERIV method is not implemented in GAPW")
    2724             :             END IF
    2725             :          END IF
    2726             :       END IF
    2727             : 
    2728       65826 :       DO ispin = 1, nspins
    2729   965751470 :          v_xc(ispin)%array = 0.0_dp
    2730             :       END DO
    2731             : 
    2732       31304 :       IF (tau_f) THEN
    2733        1290 :          DO ispin = 1, nspins
    2734    14079874 :             v_xc_tau(ispin)%array = 0.0_dp
    2735             :          END DO
    2736             :       END IF
    2737             : 
    2738       31304 :       IF (laplace_f .AND. my_gapw) &
    2739           0 :          CPABORT("Laplace-dependent functional not implemented with GAPW!")
    2740             : 
    2741       31304 :       IF (my_compute_virial .AND. (gradient_f .OR. laplace_f)) CALL allocate_pw(virial_pw, pw_pool, bo)
    2742             : 
    2743       31304 :       IF (lsd) THEN
    2744             : 
    2745             :          !-------------------!
    2746             :          ! UNrestricted case !
    2747             :          !-------------------!
    2748             : 
    2749        4512 :          CALL xc_rho_set_get(rho1_set, rhoa=rho1a, rhob=rho1b)
    2750             : 
    2751        4512 :          IF (gradient_f) THEN
    2752             :             CALL xc_rho_set_get(rho_set, drhoa=drhoa, drhob=drhob, &
    2753        2176 :                                 norm_drho=norm_drho, norm_drhoa=norm_drhoa, norm_drhob=norm_drhob)
    2754        2176 :             CALL xc_rho_set_get(rho1_set, drhoa=drho1a, drhob=drho1b)
    2755             : 
    2756        2176 :             CALL calc_drho_from_ab(drho, drhoa, drhob)
    2757        2176 :             CALL calc_drho_from_ab(drho1, drho1a, drho1b)
    2758             : 
    2759        2176 :             CALL prepare_dr1dr(dra1dra, drhoa, drho1a)
    2760        2176 :             IF (nspins /= 1) THEN
    2761        1306 :                CALL prepare_dr1dr(drb1drb, drhob, drho1b)
    2762        1306 :                CALL prepare_dr1dr(dr1dr, drho, drho1)
    2763             :             ELSE
    2764         870 :                CALL prepare_dr1dr(drb1drb, drhob, drho1b)
    2765         870 :                CALL prepare_dr1dr_ab(dr1dr, drhoa, drhob, drho1a, drho1b, fac)
    2766             :             END IF
    2767             : 
    2768       17844 :             ALLOCATE (v_drhoa(nspins), v_drhob(nspins))
    2769        5658 :             DO ispin = 1, nspins
    2770        3482 :                CALL allocate_pw(v_drhoa(ispin), pw_pool, bo)
    2771        5658 :                CALL allocate_pw(v_drhob(ispin), pw_pool, bo)
    2772             :             END DO
    2773             : 
    2774             :          END IF
    2775             : 
    2776        4512 :          IF (laplace_f) THEN
    2777          26 :             CALL xc_rho_set_get(rho1_set, laplace_rhoa=laplace1a, laplace_rhob=laplace1b)
    2778             : 
    2779         130 :             ALLOCATE (v_laplace(nspins))
    2780          78 :             DO ispin = 1, nspins
    2781          78 :                CALL allocate_pw(v_laplace(ispin), pw_pool, bo)
    2782             :             END DO
    2783             : 
    2784          26 :             IF (my_compute_virial) CALL xc_rho_set_get(rho_set, rhoa=rhoa, rhob=rhob)
    2785             :          END IF
    2786             : 
    2787        4512 :          IF (tau_f) THEN
    2788          62 :             CALL xc_rho_set_get(rho1_set, tau_a=tau1a, tau_b=tau1b)
    2789             :          END IF
    2790             : 
    2791        4512 :          IF (nspins /= 1) THEN
    2792             : 
    2793        3218 :             $:add_2nd_derivative_terms(arguments_openshell)
    2794             : 
    2795             :          ELSE
    2796             : 
    2797        1294 :             $:add_2nd_derivative_terms(arguments_triplet_outer, arguments_triplet_inner)
    2798             : 
    2799             :          END IF
    2800             : 
    2801        4512 :          IF (gradient_f) THEN
    2802             : 
    2803        2176 :             IF (my_compute_virial) THEN
    2804           8 :                CALL virial_drho_drho(virial_pw, drhoa, v_drhoa(1), virial_xc)
    2805           8 :                CALL virial_drho_drho(virial_pw, drhob, v_drhob(2), virial_xc)
    2806          32 :                DO idir = 1, 3
    2807          24 : !$OMP          PARALLEL WORKSHARE DEFAULT(NONE) SHARED(drho,idir,v_drho,virial_pw)
    2808             :                   virial_pw%array(:, :, :) = drho(idir)%array(:, :, :)*(v_drho(1)%array(:, :, :) + v_drho(2)%array(:, :, :))
    2809             : !$OMP          END PARALLEL WORKSHARE
    2810          80 :                   DO jdir = 1, idir
    2811             :                      tmp = -0.5_dp*virial_pw%pw_grid%dvol*accurate_dot_product(virial_pw%array(:, :, :), &
    2812          48 :                                                                                drho(jdir)%array(:, :, :))
    2813          48 :                      virial_xc(jdir, idir) = virial_xc(jdir, idir) + tmp
    2814          72 :                      virial_xc(idir, jdir) = virial_xc(jdir, idir)
    2815             :                   END DO
    2816             :                END DO
    2817             :             END IF ! my_compute_virial
    2818             : 
    2819        2176 :             IF (my_gapw) THEN
    2820             : !$OMP            PARALLEL DO PRIVATE(ia,idir,ispin,ir) DEFAULT(NONE) &
    2821             : !$OMP            SHARED(bo,nspins,vxg,drhoa,drhob,v_drhoa,v_drhob,v_drho, &
    2822         602 : !$OMP                   e_drhoa,e_drhob,e_drho,drho1a,drho1b,fac,drho,drho1) COLLAPSE(3)
    2823             :                DO ir = bo(1, 2), bo(2, 2)
    2824             :                   DO ia = bo(1, 1), bo(2, 1)
    2825             :                      DO idir = 1, 3
    2826             :                         DO ispin = 1, nspins
    2827             :                            vxg(idir, ia, ir, ispin) = &
    2828             :                               -(v_drhoa(ispin)%array(ia, ir, 1)*drhoa(idir)%array(ia, ir, 1) + &
    2829             :                                 v_drhob(ispin)%array(ia, ir, 1)*drhob(idir)%array(ia, ir, 1) + &
    2830             :                                 v_drho(ispin)%array(ia, ir, 1)*drho(idir)%array(ia, ir, 1))
    2831             :                         END DO
    2832             :                         IF (ASSOCIATED(e_drhoa)) THEN
    2833             :                            vxg(idir, ia, ir, 1) = vxg(idir, ia, ir, 1) + &
    2834             :                                                   e_drhoa(ia, ir, 1)*drho1a(idir)%array(ia, ir, 1)
    2835             :                         END IF
    2836             :                         IF (nspins /= 1 .AND. ASSOCIATED(e_drhob)) THEN
    2837             :                            vxg(idir, ia, ir, 2) = vxg(idir, ia, ir, 2) + &
    2838             :                                                   e_drhob(ia, ir, 1)*drho1b(idir)%array(ia, ir, 1)
    2839             :                         END IF
    2840             :                         IF (ASSOCIATED(e_drho)) THEN
    2841             :                            IF (nspins /= 1) THEN
    2842             :                               vxg(idir, ia, ir, 1) = vxg(idir, ia, ir, 1) + &
    2843             :                                                      e_drho(ia, ir, 1)*drho1(idir)%array(ia, ir, 1)
    2844             :                               vxg(idir, ia, ir, 2) = vxg(idir, ia, ir, 2) + &
    2845             :                                                      e_drho(ia, ir, 1)*drho1(idir)%array(ia, ir, 1)
    2846             :                            ELSE
    2847             :                               vxg(idir, ia, ir, 1) = vxg(idir, ia, ir, 1) + &
    2848             :                                                      e_drho(ia, ir, 1)*(drho1a(idir)%array(ia, ir, 1) + &
    2849             :                                                                         fac*drho1b(idir)%array(ia, ir, 1))
    2850             :                            END IF
    2851             :                         END IF
    2852             :                      END DO
    2853             :                   END DO
    2854             :                END DO
    2855             :             ELSE
    2856             : 
    2857             :                ! partial integration
    2858        6296 :                DO idir = 1, 3
    2859             : 
    2860       12978 :                   DO ispin = 1, nspins
    2861             : !$OMP                PARALLEL WORKSHARE DEFAULT(NONE) &
    2862       12978 : !$OMP                SHARED(v_drho_r,v_drhoa,v_drhob,v_drho,drhoa,drhob,drho,ispin,idir)
    2863             :                      v_drho_r(idir, ispin)%array(:, :, :) = &
    2864             :                         v_drhoa(ispin)%array(:, :, :)*drhoa(idir)%array(:, :, :) + &
    2865             :                         v_drhob(ispin)%array(:, :, :)*drhob(idir)%array(:, :, :) + &
    2866             :                         v_drho(ispin)%array(:, :, :)*drho(idir)%array(:, :, :)
    2867             : !$OMP                END PARALLEL WORKSHARE
    2868             :                   END DO
    2869        4722 :                   IF (ASSOCIATED(e_drhoa)) THEN
    2870             : !$OMP                PARALLEL WORKSHARE DEFAULT(NONE) &
    2871        4722 : !$OMP                SHARED(v_drho_r,e_drhoa,drho1a,idir)
    2872             :                      v_drho_r(idir, 1)%array(:, :, :) = v_drho_r(idir, 1)%array(:, :, :) - &
    2873             :                                                         e_drhoa(:, :, :)*drho1a(idir)%array(:, :, :)
    2874             : !$OMP                END PARALLEL WORKSHARE
    2875             :                   END IF
    2876        4722 :                   IF (nspins /= 1 .AND. ASSOCIATED(e_drhob)) THEN
    2877             : !$OMP                PARALLEL WORKSHARE DEFAULT(NONE)&
    2878        3534 : !$OMP                SHARED(v_drho_r,e_drhob,drho1b,idir)
    2879             :                      v_drho_r(idir, 2)%array(:, :, :) = v_drho_r(idir, 2)%array(:, :, :) - &
    2880             :                                                         e_drhob(:, :, :)*drho1b(idir)%array(:, :, :)
    2881             : !$OMP                END PARALLEL WORKSHARE
    2882             :                   END IF
    2883        6296 :                   IF (ASSOCIATED(e_drho)) THEN
    2884             : !$OMP                  PARALLEL DO PRIVATE(k,j,i) DEFAULT(NONE)&
    2885        4722 : !$OMP                  SHARED(bo,v_drho_r,e_drho,drho1a,drho1b,drho1,fac,idir,nspins) COLLAPSE(3)
    2886             :                      DO k = bo(1, 3), bo(2, 3)
    2887             :                         DO j = bo(1, 2), bo(2, 2)
    2888             :                            DO i = bo(1, 1), bo(2, 1)
    2889             :                               IF (nspins /= 1) THEN
    2890             :                                  v_drho_r(idir, 1)%array(i, j, k) = v_drho_r(idir, 1)%array(i, j, k) - &
    2891             :                                                                     e_drho(i, j, k)*drho1(idir)%array(i, j, k)
    2892             :                                  v_drho_r(idir, 2)%array(i, j, k) = v_drho_r(idir, 2)%array(i, j, k) - &
    2893             :                                                                     e_drho(i, j, k)*drho1(idir)%array(i, j, k)
    2894             :                               ELSE
    2895             :                                  v_drho_r(idir, 1)%array(i, j, k) = v_drho_r(idir, 1)%array(i, j, k) - &
    2896             :                                                                     e_drho(i, j, k)*(drho1a(idir)%array(i, j, k) + &
    2897             :                                                                                      fac*drho1b(idir)%array(i, j, k))
    2898             :                               END IF
    2899             :                            END DO
    2900             :                         END DO
    2901             :                      END DO
    2902             :                   END IF
    2903             :                END DO
    2904             : 
    2905        4326 :                DO ispin = 1, nspins
    2906             :                   ! partial integration
    2907        4326 :                   CALL xc_pw_divergence(xc_deriv_method_id, v_drho_r(:, ispin), tmp_g, vxc_g, v_xc(ispin))
    2908             :                END DO ! ispin
    2909             : 
    2910             :             END IF
    2911             : 
    2912        8704 :             DO idir = 1, 3
    2913        6528 :                DEALLOCATE (drho(idir)%array)
    2914        8704 :                DEALLOCATE (drho1(idir)%array)
    2915             :             END DO
    2916             : 
    2917        5658 :             DO ispin = 1, nspins
    2918        3482 :                CALL deallocate_pw(v_drhoa(ispin), pw_pool)
    2919        5658 :                CALL deallocate_pw(v_drhob(ispin), pw_pool)
    2920             :             END DO
    2921             : 
    2922        2176 :             DEALLOCATE (v_drhoa, v_drhob)
    2923             : 
    2924             :          END IF ! gradient_f
    2925             : 
    2926        4512 :          IF (laplace_f .AND. my_compute_virial) THEN
    2927           0 :             virial_pw%array(:, :, :) = -rhoa(:, :, :)
    2928           0 :             CALL virial_laplace(virial_pw, pw_pool, virial_xc, v_laplace(1)%array)
    2929           0 :             virial_pw%array(:, :, :) = -rhob(:, :, :)
    2930           0 :             CALL virial_laplace(virial_pw, pw_pool, virial_xc, v_laplace(2)%array)
    2931             :          END IF
    2932             : 
    2933             :       ELSE
    2934             : 
    2935             :          !-----------------!
    2936             :          ! restricted case !
    2937             :          !-----------------!
    2938             : 
    2939       26792 :          CALL xc_rho_set_get(rho1_set, rho=rho1)
    2940             : 
    2941       26792 :          IF (gradient_f) THEN
    2942       17552 :             CALL xc_rho_set_get(rho_set, drho=drho, norm_drho=norm_drho)
    2943       17552 :             CALL xc_rho_set_get(rho1_set, drho=drho1)
    2944       17552 :             CALL prepare_dr1dr(dr1dr, drho, drho1)
    2945             :          END IF
    2946             : 
    2947       26792 :          IF (laplace_f) THEN
    2948         126 :             CALL xc_rho_set_get(rho1_set, laplace_rho=laplace1)
    2949             : 
    2950         504 :             ALLOCATE (v_laplace(nspins))
    2951         252 :             DO ispin = 1, nspins
    2952         252 :                CALL allocate_pw(v_laplace(ispin), pw_pool, bo)
    2953             :             END DO
    2954             : 
    2955         126 :             IF (my_compute_virial) CALL xc_rho_set_get(rho_set, rho=rho)
    2956             :          END IF
    2957             : 
    2958       26792 :          IF (tau_f) THEN
    2959         552 :             CALL xc_rho_set_get(rho1_set, tau=tau1)
    2960             :          END IF
    2961             : 
    2962      292448 :          $:add_2nd_derivative_terms(arguments_closedshell)
    2963             : 
    2964       26792 :          IF (gradient_f) THEN
    2965             : 
    2966       17552 :             IF (my_compute_virial) THEN
    2967         220 :                CALL virial_drho_drho(virial_pw, drho, v_drho(1), virial_xc)
    2968             :             END IF ! my_compute_virial
    2969             : 
    2970       17552 :             IF (my_gapw) THEN
    2971             : 
    2972       26640 :                DO idir = 1, 3
    2973             : !$OMP               PARALLEL DO PRIVATE(ia,ir) DEFAULT(NONE) &
    2974       26640 : !$OMP               SHARED(bo,vxg,drho,v_drho,e_drho,drho1,idir,factor2) COLLAPSE(2)
    2975             :                   DO ia = bo(1, 1), bo(2, 1)
    2976             :                      DO ir = bo(1, 2), bo(2, 2)
    2977             :                         vxg(idir, ia, ir, 1) = -drho(idir)%array(ia, ir, 1)*v_drho(1)%array(ia, ir, 1)
    2978             :                         IF (ASSOCIATED(e_drho)) THEN
    2979             :                            vxg(idir, ia, ir, 1) = vxg(idir, ia, ir, 1) + factor2*drho1(idir)%array(ia, ir, 1)*e_drho(ia, ir, 1)
    2980             :                         END IF
    2981             :                      END DO
    2982             :                   END DO
    2983             :                END DO
    2984             : 
    2985             :             ELSE
    2986             :                ! partial integration
    2987       43568 :                DO idir = 1, 3
    2988             : !$OMP             PARALLEL WORKSHARE DEFAULT(NONE)&
    2989       43568 : !$OMP             SHARED(v_drho_r,drho,v_drho,drho1,e_drho,idir)
    2990             :                   v_drho_r(idir, 1)%array(:, :, :) = drho(idir)%array(:, :, :)*v_drho(1)%array(:, :, :) - &
    2991             :                                                      drho1(idir)%array(:, :, :)*e_drho(:, :, :)
    2992             : !$OMP             END PARALLEL WORKSHARE
    2993             :                END DO
    2994             : 
    2995       10892 :                CALL xc_pw_divergence(xc_deriv_method_id, v_drho_r(:, 1), tmp_g, vxc_g, v_xc(1))
    2996             :             END IF
    2997             : 
    2998             :          END IF
    2999             : 
    3000       26792 :          IF (laplace_f .AND. my_compute_virial) THEN
    3001      265668 :             virial_pw%array(:, :, :) = -rho(:, :, :)
    3002          12 :             CALL virial_laplace(virial_pw, pw_pool, virial_xc, v_laplace(1)%array)
    3003             :          END IF
    3004             : 
    3005             :       END IF
    3006             : 
    3007       31304 :       IF (laplace_f) THEN
    3008         330 :          DO ispin = 1, nspins
    3009         178 :             CALL xc_pw_laplace(v_laplace(ispin), pw_pool, xc_deriv_method_id)
    3010         330 :             CALL pw_axpy(v_laplace(ispin), v_xc(ispin))
    3011             :          END DO
    3012             :       END IF
    3013             : 
    3014       31304 :       IF (gradient_f) THEN
    3015             : 
    3016       40762 :          DO ispin = 1, nspins
    3017       21034 :             CALL deallocate_pw(v_drho(ispin), pw_pool)
    3018      103864 :             DO idir = 1, 3
    3019       84136 :                CALL deallocate_pw(v_drho_r(idir, ispin), pw_pool)
    3020             :             END DO
    3021             :          END DO
    3022       19728 :          DEALLOCATE (v_drho, v_drho_r)
    3023             : 
    3024             :       END IF
    3025             : 
    3026       31304 :       IF (laplace_f) THEN
    3027         330 :       DO ispin = 1, nspins
    3028         330 :          CALL deallocate_pw(v_laplace(ispin), pw_pool)
    3029             :       END DO
    3030         152 :       DEALLOCATE (v_laplace)
    3031             :       END IF
    3032             : 
    3033       31304 :       IF (ASSOCIATED(tmp_g%pw_grid) .AND. ASSOCIATED(pw_pool)) THEN
    3034       12034 :          CALL pw_pool%give_back_pw(tmp_g)
    3035             :       END IF
    3036             : 
    3037       31304 :       IF (ASSOCIATED(vxc_g%pw_grid) .AND. ASSOCIATED(pw_pool)) THEN
    3038       12034 :          CALL pw_pool%give_back_pw(vxc_g)
    3039             :       END IF
    3040             : 
    3041       31304 :       IF (my_compute_virial .AND. (gradient_f .OR. laplace_f)) THEN
    3042         228 :          CALL deallocate_pw(virial_pw, pw_pool)
    3043             :       END IF
    3044             : 
    3045       31304 :       CALL timestop(handle)
    3046       93912 :    END SUBROUTINE xc_calc_2nd_deriv_analytical
    3047             : 
    3048             : ! **************************************************************************************************
    3049             : !> \brief allocates grids using pw_pool (if associated) or with bounds
    3050             : !> \param pw ...
    3051             : !> \param pw_pool ...
    3052             : !> \param bo ...
    3053             : ! **************************************************************************************************
    3054       91604 :    SUBROUTINE allocate_pw(pw, pw_pool, bo)
    3055             :       TYPE(pw_r3d_rs_type), INTENT(OUT)                         :: pw
    3056             :       TYPE(pw_pool_type), INTENT(IN), POINTER            :: pw_pool
    3057             :       INTEGER, DIMENSION(2, 3), INTENT(IN)               :: bo
    3058             : 
    3059       91604 :       IF (ASSOCIATED(pw_pool)) THEN
    3060       60584 :          CALL pw_pool%create_pw(pw)
    3061       60584 :          CALL pw_zero(pw)
    3062             :       ELSE
    3063      155100 :          ALLOCATE (pw%array(bo(1, 1):bo(2, 1), bo(1, 2):bo(2, 2), bo(1, 3):bo(2, 3)))
    3064    79163040 :          pw%array = 0.0_dp
    3065             :       END IF
    3066             : 
    3067       91604 :    END SUBROUTINE allocate_pw
    3068             : 
    3069             : ! **************************************************************************************************
    3070             : !> \brief deallocates grid allocated with allocate_pw
    3071             : !> \param pw ...
    3072             : !> \param pw_pool ...
    3073             : ! **************************************************************************************************
    3074       91604 :    SUBROUTINE deallocate_pw(pw, pw_pool)
    3075             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                       :: pw
    3076             :       TYPE(pw_pool_type), INTENT(IN), POINTER            :: pw_pool
    3077             : 
    3078       91604 :       IF (ASSOCIATED(pw_pool)) THEN
    3079       60584 :          CALL pw_pool%give_back_pw(pw)
    3080             :       ELSE
    3081       31020 :          CALL pw%release()
    3082             :       END IF
    3083             : 
    3084       91604 :    END SUBROUTINE deallocate_pw
    3085             : 
    3086             : ! **************************************************************************************************
    3087             : !> \brief updates virial from first derivative w.r.t. norm_drho
    3088             : !> \param virial_pw ...
    3089             : !> \param drho ...
    3090             : !> \param drho1 ...
    3091             : !> \param deriv_data ...
    3092             : !> \param virial_xc ...
    3093             : ! **************************************************************************************************
    3094         296 :    SUBROUTINE virial_drho_drho1(virial_pw, drho, drho1, deriv_data, virial_xc)
    3095             :       TYPE(pw_r3d_rs_type), INTENT(IN)                          :: virial_pw
    3096             :       TYPE(cp_3d_r_cp_type), DIMENSION(3), INTENT(IN)     :: drho, drho1
    3097             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: deriv_data
    3098             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT)      :: virial_xc
    3099             : 
    3100             :       INTEGER                                            :: idir, jdir
    3101             :       REAL(KIND=dp)                                      :: tmp
    3102             : 
    3103        1184 :       DO idir = 1, 3
    3104             : !$OMP    PARALLEL WORKSHARE DEFAULT(NONE)&
    3105         888 : !$OMP    SHARED(drho,idir,virial_pw,deriv_data)
    3106             :          virial_pw%array(:, :, :) = drho(idir)%array(:, :, :)*deriv_data(:, :, :)
    3107             : !$OMP    END PARALLEL WORKSHARE
    3108        3848 :          DO jdir = 1, 3
    3109             :             tmp = virial_pw%pw_grid%dvol*accurate_dot_product(virial_pw%array(:, :, :), &
    3110        2664 :                                                               drho1(jdir)%array(:, :, :))
    3111        2664 :             virial_xc(jdir, idir) = virial_xc(jdir, idir) + tmp
    3112        3552 :             virial_xc(idir, jdir) = virial_xc(idir, jdir) + tmp
    3113             :          END DO
    3114             :       END DO
    3115             : 
    3116         296 :    END SUBROUTINE virial_drho_drho1
    3117             : 
    3118             : ! **************************************************************************************************
    3119             : !> \brief Adds virial contribution from second order potential parts
    3120             : !> \param virial_pw ...
    3121             : !> \param drho ...
    3122             : !> \param v_drho ...
    3123             : !> \param virial_xc ...
    3124             : ! **************************************************************************************************
    3125         292 :    SUBROUTINE virial_drho_drho(virial_pw, drho, v_drho, virial_xc)
    3126             :       TYPE(pw_r3d_rs_type), INTENT(IN)                          :: virial_pw
    3127             :       TYPE(cp_3d_r_cp_type), DIMENSION(3), INTENT(IN)     :: drho
    3128             :       TYPE(pw_r3d_rs_type), INTENT(IN)                        :: v_drho
    3129             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT)      :: virial_xc
    3130             : 
    3131             :       INTEGER                                            :: idir, jdir
    3132             :       REAL(KIND=dp)                                      :: tmp
    3133             : 
    3134        1168 :       DO idir = 1, 3
    3135             : !$OMP PARALLEL WORKSHARE DEFAULT(NONE)&
    3136         876 : !$OMP SHARED(drho,idir,v_drho,virial_pw)
    3137             :          virial_pw%array(:, :, :) = drho(idir)%array(:, :, :)*v_drho%array(:, :, :)
    3138             : !$OMP END PARALLEL WORKSHARE
    3139        2920 :          DO jdir = 1, idir
    3140             :             tmp = -virial_pw%pw_grid%dvol*accurate_dot_product(virial_pw%array(:, :, :), &
    3141        1752 :                                                                drho(jdir)%array(:, :, :))
    3142        1752 :             virial_xc(jdir, idir) = virial_xc(jdir, idir) + tmp
    3143        2628 :             virial_xc(idir, jdir) = virial_xc(jdir, idir)
    3144             :          END DO
    3145             :       END DO
    3146             : 
    3147         292 :    END SUBROUTINE virial_drho_drho
    3148             : 
    3149             : ! **************************************************************************************************
    3150             : !> \brief ...
    3151             : !> \param rho_r ...
    3152             : !> \param pw_pool ...
    3153             : !> \param virial_xc ...
    3154             : !> \param deriv_data ...
    3155             : ! **************************************************************************************************
    3156         132 :    SUBROUTINE virial_laplace(rho_r, pw_pool, virial_xc, deriv_data)
    3157             :       TYPE(pw_r3d_rs_type), TARGET :: rho_r
    3158             :       TYPE(pw_pool_type), POINTER, INTENT(IN) :: pw_pool
    3159             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT) :: virial_xc
    3160             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: deriv_data
    3161             : 
    3162             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'virial_laplace'
    3163             : 
    3164             :       INTEGER :: handle, idir, jdir
    3165             :       TYPE(pw_r3d_rs_type), POINTER :: virial_pw
    3166             :       TYPE(pw_c1d_gs_type), POINTER :: tmp_g, rho_g
    3167             :       INTEGER, DIMENSION(3) :: my_deriv
    3168             : 
    3169         132 :       CALL timeset(routineN, handle)
    3170             : 
    3171         132 :       NULLIFY (virial_pw, tmp_g, rho_g)
    3172         132 :       ALLOCATE (virial_pw, tmp_g, rho_g)
    3173         132 :       CALL pw_pool%create_pw(virial_pw)
    3174         132 :       CALL pw_pool%create_pw(tmp_g)
    3175         132 :       CALL pw_pool%create_pw(rho_g)
    3176         132 :       CALL pw_zero(virial_pw)
    3177         132 :       CALL pw_transfer(rho_r, rho_g)
    3178         528 :       DO idir = 1, 3
    3179        1320 :          DO jdir = idir, 3
    3180         792 :             CALL pw_copy(rho_g, tmp_g)
    3181             : 
    3182         792 :             my_deriv = 0
    3183         792 :             my_deriv(idir) = 1
    3184         792 :             my_deriv(jdir) = my_deriv(jdir) + 1
    3185             : 
    3186         792 :             CALL pw_derive(tmp_g, my_deriv)
    3187         792 :             CALL pw_transfer(tmp_g, virial_pw)
    3188             :             virial_xc(idir, jdir) = virial_xc(idir, jdir) - 2.0_dp*virial_pw%pw_grid%dvol* &
    3189             :                                     accurate_dot_product(virial_pw%array(:, :, :), &
    3190         792 :                                                          deriv_data(:, :, :))
    3191        1188 :             virial_xc(jdir, idir) = virial_xc(idir, jdir)
    3192             :          END DO
    3193             :       END DO
    3194         132 :       CALL pw_pool%give_back_pw(virial_pw)
    3195         132 :       CALL pw_pool%give_back_pw(tmp_g)
    3196         132 :       CALL pw_pool%give_back_pw(rho_g)
    3197         132 :       DEALLOCATE (virial_pw, tmp_g, rho_g)
    3198             : 
    3199         132 :       CALL timestop(handle)
    3200             : 
    3201         132 :    END SUBROUTINE virial_laplace
    3202             : 
    3203             : ! **************************************************************************************************
    3204             : !> \brief Prepare objects for the calculation of the 2nd derivatives of the density functional.
    3205             : !>      The calculation must then be performed with xc_calc_2nd_deriv.
    3206             : !> \param deriv_set object containing the XC derivatives (out)
    3207             : !> \param rho_set object that will contain the density at which the
    3208             : !>        derivatives were calculated
    3209             : !> \param rho_r the place where you evaluate the derivative
    3210             : !> \param pw_pool the pool for the grids
    3211             : !> \param xc_section which functional should be used and how to calculate it
    3212             : !> \param tau_r kinetic energy density in real space
    3213             : ! **************************************************************************************************
    3214       11646 :    SUBROUTINE xc_prep_2nd_deriv(deriv_set, &
    3215             :                                 rho_set, rho_r, pw_pool, xc_section, tau_r)
    3216             : 
    3217             :       TYPE(xc_derivative_set_type)                       :: deriv_set
    3218             :       TYPE(xc_rho_set_type)                              :: rho_set
    3219             :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER               :: rho_r
    3220             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
    3221             :       TYPE(section_vals_type), POINTER                   :: xc_section
    3222             :       TYPE(pw_r3d_rs_type), DIMENSION(:), OPTIONAL, POINTER     :: tau_r
    3223             : 
    3224             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xc_prep_2nd_deriv'
    3225             : 
    3226             :       INTEGER                                            :: handle, nspins
    3227             :       LOGICAL                                            :: lsd
    3228       11646 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER               :: rho_g
    3229       11646 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: tau
    3230             : 
    3231       11646 :       CALL timeset(routineN, handle)
    3232             : 
    3233       11646 :       CPASSERT(ASSOCIATED(xc_section))
    3234       11646 :       CPASSERT(ASSOCIATED(pw_pool))
    3235             : 
    3236       11646 :       nspins = SIZE(rho_r)
    3237       11646 :       lsd = (nspins /= 1)
    3238             : 
    3239       11646 :       NULLIFY (rho_g, tau)
    3240       11646 :       IF (PRESENT(tau_r)) &
    3241       11218 :          tau => tau_r
    3242             : 
    3243       11646 :       IF (section_get_lval(xc_section, "2ND_DERIV_ANALYTICAL")) THEN
    3244             :          CALL xc_rho_set_and_dset_create(rho_set, deriv_set, 2, &
    3245             :                                          rho_r, rho_g, tau, xc_section, pw_pool, &
    3246       11562 :                                          calc_potential=.TRUE.)
    3247             :       ELSE
    3248             :          CALL xc_rho_set_and_dset_create(rho_set, deriv_set, 1, &
    3249             :                                          rho_r, rho_g, tau, xc_section, pw_pool, &
    3250          84 :                                          calc_potential=.TRUE.)
    3251             :       END IF
    3252             : 
    3253       11646 :       CALL timestop(handle)
    3254             : 
    3255       11646 :    END SUBROUTINE xc_prep_2nd_deriv
    3256             : 
    3257             : ! **************************************************************************************************
    3258             : !> \brief divides derivatives from deriv_set by norm_drho
    3259             : !> \param deriv_set ...
    3260             : !> \param rho_set ...
    3261             : !> \param lsd ...
    3262             : ! **************************************************************************************************
    3263      138635 :    SUBROUTINE divide_by_norm_drho(deriv_set, rho_set, lsd)
    3264             : 
    3265             :       TYPE(xc_derivative_set_type), INTENT(INOUT)        :: deriv_set
    3266             :       TYPE(xc_rho_set_type), INTENT(IN)                  :: rho_set
    3267             :       LOGICAL, INTENT(IN)                                :: lsd
    3268             : 
    3269      138635 :       INTEGER, DIMENSION(:), POINTER                     :: split_desc
    3270             :       INTEGER                                            :: idesc
    3271             :       INTEGER, DIMENSION(2, 3)                           :: bo
    3272             :       REAL(KIND=dp)                                      :: drho_cutoff
    3273      138635 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: norm_drho, norm_drhoa, norm_drhob
    3274     1663620 :       TYPE(cp_3d_r_cp_type), DIMENSION(3)                 :: drho, drhoa, drhob
    3275             :       TYPE(cp_sll_xc_deriv_type), POINTER                :: pos
    3276             :       TYPE(xc_derivative_type), POINTER                  :: deriv_att
    3277             : 
    3278             : ! check for unknown derivatives and divide by norm_drho where necessary
    3279             : 
    3280     1386350 :       bo = rho_set%local_bounds
    3281             :       CALL xc_rho_set_get(rho_set, drho_cutoff=drho_cutoff, norm_drho=norm_drho, &
    3282             :                           norm_drhoa=norm_drhoa, norm_drhob=norm_drhob, &
    3283      138635 :                           drho=drho, drhoa=drhoa, drhob=drhob, can_return_null=.TRUE.)
    3284             : 
    3285      138635 :       pos => deriv_set%derivs
    3286      594946 :       DO WHILE (cp_sll_xc_deriv_next(pos, el_att=deriv_att))
    3287      456311 :          CALL xc_derivative_get(deriv_att, split_desc=split_desc)
    3288      973622 :          DO idesc = 1, SIZE(split_desc)
    3289      456311 :             SELECT CASE (split_desc(idesc))
    3290             :             CASE (deriv_norm_drho)
    3291      114495 :                IF (ASSOCIATED(norm_drho)) THEN
    3292      114495 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_att,norm_drho,drho_cutoff)
    3293             :                   deriv_att%deriv_data(:, :, :) = deriv_att%deriv_data(:, :, :)/ &
    3294             :                                                   MAX(norm_drho(:, :, :), drho_cutoff)
    3295             : !$OMP END PARALLEL WORKSHARE
    3296           0 :                ELSE IF (ASSOCIATED(drho(1)%array)) THEN
    3297           0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_att,drho,drho_cutoff)
    3298             :                   deriv_att%deriv_data(:, :, :) = deriv_att%deriv_data(:, :, :)/ &
    3299             :                                                   MAX(SQRT(drho(1)%array(:, :, :)**2 + &
    3300             :                                                            drho(2)%array(:, :, :)**2 + &
    3301             :                                                            drho(3)%array(:, :, :)**2), drho_cutoff)
    3302             : !$OMP END PARALLEL WORKSHARE
    3303           0 :                ELSE IF (ASSOCIATED(drhoa(1)%array) .AND. ASSOCIATED(drhob(1)%array)) THEN
    3304           0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_att,drhoa,drhob,drho_cutoff)
    3305             :                   deriv_att%deriv_data(:, :, :) = deriv_att%deriv_data(:, :, :)/ &
    3306             :                                                   MAX(SQRT((drhoa(1)%array(:, :, :) + drhob(1)%array(:, :, :))**2 + &
    3307             :                                                            (drhoa(2)%array(:, :, :) + drhob(2)%array(:, :, :))**2 + &
    3308             :                                                            (drhoa(3)%array(:, :, :) + drhob(3)%array(:, :, :))**2), drho_cutoff)
    3309             : !$OMP END PARALLEL WORKSHARE
    3310             :                ELSE
    3311           0 :                   CPABORT("Normalization of derivative requires any of norm_drho, drho or drhoa+drhob!")
    3312             :                END IF
    3313             :             CASE (deriv_norm_drhoa)
    3314       19298 :                IF (ASSOCIATED(norm_drhoa)) THEN
    3315       19298 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_att,norm_drhoa,drho_cutoff)
    3316             :                   deriv_att%deriv_data(:, :, :) = deriv_att%deriv_data(:, :, :)/ &
    3317             :                                                   MAX(norm_drhoa(:, :, :), drho_cutoff)
    3318             : !$OMP END PARALLEL WORKSHARE
    3319           0 :                ELSE IF (ASSOCIATED(drhoa(1)%array)) THEN
    3320           0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_att,drhoa,drho_cutoff)
    3321             :                   deriv_att%deriv_data(:, :, :) = deriv_att%deriv_data(:, :, :)/ &
    3322             :                                                   MAX(SQRT(drhoa(1)%array(:, :, :)**2 + &
    3323             :                                                            drhoa(2)%array(:, :, :)**2 + &
    3324             :                                                            drhoa(3)%array(:, :, :)**2), drho_cutoff)
    3325             : !$OMP END PARALLEL WORKSHARE
    3326             :                ELSE
    3327           0 :                   CPABORT("Normalization of derivative requires any of norm_drhoa or drhoa!")
    3328             :                END IF
    3329             :             CASE (deriv_norm_drhob)
    3330       19294 :                IF (ASSOCIATED(norm_drhob)) THEN
    3331       19294 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_att,norm_drhob,drho_cutoff)
    3332             :                   deriv_att%deriv_data(:, :, :) = deriv_att%deriv_data(:, :, :)/ &
    3333             :                                                   MAX(norm_drhob(:, :, :), drho_cutoff)
    3334             : !$OMP END PARALLEL WORKSHARE
    3335           0 :                ELSE IF (ASSOCIATED(drhob(1)%array)) THEN
    3336           0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(deriv_att,drhob,drho_cutoff)
    3337             :                   deriv_att%deriv_data(:, :, :) = deriv_att%deriv_data(:, :, :)/ &
    3338             :                                                   MAX(SQRT(drhob(1)%array(:, :, :)**2 + &
    3339             :                                                            drhob(2)%array(:, :, :)**2 + &
    3340             :                                                            drhob(3)%array(:, :, :)**2), drho_cutoff)
    3341             : !$OMP END PARALLEL WORKSHARE
    3342             :                ELSE
    3343           0 :                   CPABORT("Normalization of derivative requires any of norm_drhob or drhob!")
    3344             :                END IF
    3345             :             CASE (deriv_rho, deriv_tau, deriv_laplace_rho)
    3346      158321 :                IF (lsd) &
    3347           0 :                   CPABORT(TRIM(id_to_desc(split_desc(idesc)))//" not handled in lsd!'")
    3348             :             CASE (deriv_rhoa, deriv_rhob, deriv_tau_a, deriv_tau_b, deriv_laplace_rhoa, deriv_laplace_rhob)
    3349             :             CASE default
    3350      378676 :                CPABORT("Unknown derivative id")
    3351             :             END SELECT
    3352             :          END DO
    3353             :       END DO
    3354             : 
    3355      138635 :    END SUBROUTINE divide_by_norm_drho
    3356             : 
    3357             : ! **************************************************************************************************
    3358             : !> \brief allocates and calculates drho from given spin densities drhoa, drhob
    3359             : !> \param drho ...
    3360             : !> \param drhoa ...
    3361             : !> \param drhob ...
    3362             : ! **************************************************************************************************
    3363       17488 :    SUBROUTINE calc_drho_from_ab(drho, drhoa, drhob)
    3364             :       TYPE(cp_3d_r_cp_type), DIMENSION(3), INTENT(OUT)    :: drho
    3365             :       TYPE(cp_3d_r_cp_type), DIMENSION(3), INTENT(IN)     :: drhoa, drhob
    3366             : 
    3367             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'calc_drho_from_ab'
    3368             : 
    3369             :       INTEGER                                            :: handle, idir
    3370             : 
    3371        4372 :       CALL timeset(routineN, handle)
    3372             : 
    3373       17488 :       DO idir = 1, 3
    3374       13116 :          NULLIFY (drho(idir)%array)
    3375             :          ALLOCATE (drho(idir)%array(LBOUND(drhoa(1)%array, 1):UBOUND(drhoa(1)%array, 1), &
    3376             :                                     LBOUND(drhoa(1)%array, 2):UBOUND(drhoa(1)%array, 2), &
    3377       65580 :                                     LBOUND(drhoa(1)%array, 3):UBOUND(drhoa(1)%array, 3)))
    3378       17488 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(drho,drhoa,drhob,idir)
    3379             :          drho(idir)%array(:, :, :) = drhoa(idir)%array(:, :, :) + drhob(idir)%array(:, :, :)
    3380             : !$OMP END PARALLEL WORKSHARE
    3381             :       END DO
    3382             : 
    3383        4372 :       CALL timestop(handle)
    3384             : 
    3385        4372 :    END SUBROUTINE
    3386             : 
    3387             : ! **************************************************************************************************
    3388             : !> \brief allocates and calculates dot products of two density gradients
    3389             : !> \param dr1dr ...
    3390             : !> \param drho ...
    3391             : !> \param drho1 ...
    3392             : ! **************************************************************************************************
    3393       23266 :    SUBROUTINE prepare_dr1dr(dr1dr, drho, drho1)
    3394             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    3395             :          INTENT(OUT)                                     :: dr1dr
    3396             :       TYPE(cp_3d_r_cp_type), DIMENSION(3), INTENT(IN)     :: drho, drho1
    3397             : 
    3398             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'prepare_dr1dr'
    3399             : 
    3400             :       INTEGER                                            :: handle, idir
    3401             : 
    3402       23266 :       CALL timeset(routineN, handle)
    3403             : 
    3404           0 :       ALLOCATE (dr1dr(LBOUND(drho(1)%array, 1):UBOUND(drho(1)%array, 1), &
    3405             :                       LBOUND(drho(1)%array, 2):UBOUND(drho(1)%array, 2), &
    3406      116330 :                       LBOUND(drho(1)%array, 3):UBOUND(drho(1)%array, 3)))
    3407             : 
    3408       23266 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(dr1dr,drho,drho1)
    3409             :       dr1dr(:, :, :) = drho(1)%array(:, :, :)*drho1(1)%array(:, :, :)
    3410             : !$OMP END PARALLEL WORKSHARE
    3411       69798 :       DO idir = 2, 3
    3412       69798 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(dr1dr,drho,drho1,idir)
    3413             :          dr1dr(:, :, :) = dr1dr(:, :, :) + drho(idir)%array(:, :, :)*drho1(idir)%array(:, :, :)
    3414             : !$OMP END PARALLEL WORKSHARE
    3415             :       END DO
    3416             : 
    3417       23266 :       CALL timestop(handle)
    3418             : 
    3419       23266 :    END SUBROUTINE prepare_dr1dr
    3420             : 
    3421             : ! **************************************************************************************************
    3422             : !> \brief allocates and calculates dot product of two densities for triplets
    3423             : !> \param dr1dr ...
    3424             : !> \param drhoa ...
    3425             : !> \param drhob ...
    3426             : !> \param drho1a ...
    3427             : !> \param drho1b ...
    3428             : !> \param fac ...
    3429             : ! **************************************************************************************************
    3430         870 :    SUBROUTINE prepare_dr1dr_ab(dr1dr, drhoa, drhob, drho1a, drho1b, fac)
    3431             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    3432             :          INTENT(OUT)                                     :: dr1dr
    3433             :       TYPE(cp_3d_r_cp_type), DIMENSION(3), INTENT(IN)    :: drhoa, drhob, drho1a, drho1b
    3434             :       REAL(KIND=dp), INTENT(IN)                          :: fac
    3435             : 
    3436             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'prepare_dr1dr_ab'
    3437             : 
    3438             :       INTEGER                                            :: handle, idir
    3439             : 
    3440         870 :       CALL timeset(routineN, handle)
    3441             : 
    3442           0 :       ALLOCATE (dr1dr(LBOUND(drhoa(1)%array, 1):UBOUND(drhoa(1)%array, 1), &
    3443             :                       LBOUND(drhoa(1)%array, 2):UBOUND(drhoa(1)%array, 2), &
    3444        4350 :                       LBOUND(drhoa(1)%array, 3):UBOUND(drhoa(1)%array, 3)))
    3445             : 
    3446         870 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(fac,dr1dr,drho1a,drho1b,drhoa,drhob)
    3447             :       dr1dr(:, :, :) = drhoa(1)%array(:, :, :)*(drho1a(1)%array(:, :, :) + &
    3448             :                                                 fac*drho1b(1)%array(:, :, :)) + &
    3449             :                        drhob(1)%array(:, :, :)*(fac*drho1a(1)%array(:, :, :) + &
    3450             :                                                 drho1b(1)%array(:, :, :))
    3451             : !$OMP END PARALLEL WORKSHARE
    3452        2610 :       DO idir = 2, 3
    3453        2610 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(fac,dr1dr,drho1a,drho1b,drhoa,drhob,idir)
    3454             :          dr1dr(:, :, :) = dr1dr(:, :, :) + &
    3455             :                           drhoa(idir)%array(:, :, :)*(drho1a(idir)%array(:, :, :) + &
    3456             :                                                       fac*drho1b(idir)%array(:, :, :)) + &
    3457             :                           drhob(idir)%array(:, :, :)*(fac*drho1a(idir)%array(:, :, :) + &
    3458             :                                                       drho1b(idir)%array(:, :, :))
    3459             : !$OMP END PARALLEL WORKSHARE
    3460             :       END DO
    3461             : 
    3462         870 :       CALL timestop(handle)
    3463             : 
    3464         870 :    END SUBROUTINE prepare_dr1dr_ab
    3465             : 
    3466             : ! **************************************************************************************************
    3467             : !> \brief checks for gradients
    3468             : !> \param deriv_set ...
    3469             : !> \param lsd ...
    3470             : !> \param gradient_f ...
    3471             : !> \param tau_f ...
    3472             : !> \param laplace_f ...
    3473             : ! **************************************************************************************************
    3474      140200 :    SUBROUTINE check_for_derivatives(deriv_set, lsd, rho_f, gradient_f, tau_f, laplace_f)
    3475             :       TYPE(xc_derivative_set_type), INTENT(IN)           :: deriv_set
    3476             :       LOGICAL, INTENT(IN)                                :: lsd
    3477             :       LOGICAL, INTENT(OUT)                               :: rho_f, gradient_f, tau_f, laplace_f
    3478             : 
    3479             :       CHARACTER(len=*), PARAMETER :: routineN = 'check_for_derivatives'
    3480             : 
    3481             :       INTEGER                                            :: handle, iorder, order
    3482      140200 :       INTEGER, DIMENSION(:), POINTER                     :: split_desc
    3483             :       TYPE(cp_sll_xc_deriv_type), POINTER                :: pos
    3484             :       TYPE(xc_derivative_type), POINTER                  :: deriv_att
    3485             : 
    3486      140200 :       CALL timeset(routineN, handle)
    3487             : 
    3488      140200 :       rho_f = .FALSE.
    3489      140200 :       gradient_f = .FALSE.
    3490      140200 :       tau_f = .FALSE.
    3491      140200 :       laplace_f = .FALSE.
    3492             :       ! check for unknown derivatives
    3493      140200 :       pos => deriv_set%derivs
    3494      639140 :       DO WHILE (cp_sll_xc_deriv_next(pos, el_att=deriv_att))
    3495             :          CALL xc_derivative_get(deriv_att, order=order, &
    3496      498940 :                                 split_desc=split_desc)
    3497      639140 :          IF (lsd) THEN
    3498      305685 :             DO iorder = 1, size(split_desc)
    3499      152117 :                SELECT CASE (split_desc(iorder))
    3500             :                CASE (deriv_rhoa, deriv_rhob)
    3501       80026 :                   rho_f = .TRUE.
    3502             :                CASE (deriv_norm_drho, deriv_norm_drhoa, deriv_norm_drhob)
    3503       70238 :                   gradient_f = .TRUE.
    3504             :                CASE (deriv_tau_a, deriv_tau_b)
    3505        2376 :                   tau_f = .TRUE.
    3506             :                CASE (deriv_laplace_rhoa, deriv_laplace_rhob)
    3507         928 :                   laplace_f = .TRUE.
    3508             :                CASE (deriv_rho, deriv_tau, deriv_laplace_rho)
    3509           0 :                   CPABORT("Derivative not handled in lsd!")
    3510             :                CASE default
    3511      153568 :                   CPABORT("Unknown derivative id")
    3512             :                END SELECT
    3513             :             END DO
    3514             :          ELSE
    3515      644385 :             DO iorder = 1, size(split_desc)
    3516      346823 :                SELECT CASE (split_desc(iorder))
    3517             :                CASE (deriv_rho)
    3518      176005 :                   rho_f = .TRUE.
    3519             :                CASE (deriv_tau)
    3520        4712 :                   tau_f = .TRUE.
    3521             :                CASE (deriv_norm_drho)
    3522      115543 :                   gradient_f = .TRUE.
    3523             :                CASE (deriv_laplace_rho)
    3524        1302 :                   laplace_f = .TRUE.
    3525             :                CASE default
    3526      297562 :                   CPABORT("Unknown derivative id")
    3527             :                END SELECT
    3528             :             END DO
    3529             :          END IF
    3530             :       END DO
    3531             : 
    3532      140200 :       CALL timestop(handle)
    3533             : 
    3534      140200 :    END SUBROUTINE check_for_derivatives
    3535             : 
    3536             : END MODULE xc
    3537             : 

Generated by: LCOV version 1.15