LCOV - code coverage report
Current view: top level - src - atom_xc.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:34ef472) Lines: 414 630 65.7 %
Date: 2024-04-26 08:30:29 Functions: 7 10 70.0 %

          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 routines that build the integrals of the Vxc potential calculated
      10             : !>      for the atomic code
      11             : ! **************************************************************************************************
      12             : MODULE atom_xc
      13             : 
      14             :    USE atom_types,                      ONLY: atom_basis_type,&
      15             :                                               atom_type,&
      16             :                                               gth_pseudo,&
      17             :                                               opmat_type,&
      18             :                                               sgp_pseudo,&
      19             :                                               upf_pseudo
      20             :    USE atom_utils,                      ONLY: atom_core_density,&
      21             :                                               atom_density,&
      22             :                                               coulomb_potential_numeric,&
      23             :                                               integrate_grid,&
      24             :                                               numpot_matrix
      25             :    USE cp_files,                        ONLY: close_file,&
      26             :                                               get_unit_number,&
      27             :                                               open_file
      28             :    USE input_constants,                 ONLY: xc_none
      29             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      30             :                                               section_vals_type,&
      31             :                                               section_vals_val_get
      32             :    USE kinds,                           ONLY: dp
      33             :    USE mathconstants,                   ONLY: fourpi,&
      34             :                                               pi
      35             :    USE xc_atom,                         ONLY: xc_rho_set_atom_update
      36             :    USE xc_derivative_desc,              ONLY: &
      37             :         deriv_norm_drho, deriv_norm_drhoa, deriv_norm_drhob, deriv_rho, deriv_rhoa, deriv_rhob, &
      38             :         deriv_tau, deriv_tau_a, deriv_tau_b
      39             :    USE xc_derivative_set_types,         ONLY: xc_derivative_set_type,&
      40             :                                               xc_dset_create,&
      41             :                                               xc_dset_get_derivative,&
      42             :                                               xc_dset_release,&
      43             :                                               xc_dset_zero_all
      44             :    USE xc_derivative_types,             ONLY: xc_derivative_get,&
      45             :                                               xc_derivative_type
      46             :    USE xc_derivatives,                  ONLY: xc_functionals_eval,&
      47             :                                               xc_functionals_get_needs
      48             :    USE xc_rho_cflags_types,             ONLY: xc_rho_cflags_type
      49             :    USE xc_rho_set_types,                ONLY: xc_rho_set_create,&
      50             :                                               xc_rho_set_release,&
      51             :                                               xc_rho_set_type
      52             : #include "./base/base_uses.f90"
      53             : 
      54             :    IMPLICIT NONE
      55             : 
      56             :    PRIVATE
      57             : 
      58             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'atom_xc'
      59             : 
      60             : ! ZMP added coulomb_potential_numeric
      61             : ! ZMP added public subroutines calculate_atom_zmp, calculate_atom_ext_vxc
      62             :    PUBLIC :: calculate_atom_vxc_lda, calculate_atom_vxc_lsd, &
      63             :              calculate_atom_zmp, calculate_atom_ext_vxc
      64             :    PUBLIC :: atom_vxc_lda, atom_vxc_lsd, atom_dpot_lda
      65             : 
      66             : CONTAINS
      67             : 
      68             : ! **************************************************************************************************
      69             : !> \brief ZMP subroutine for the calculation of the effective constraint
      70             : !>        potential in the atomic code.
      71             : !> \param ext_density  external electron density
      72             : !> \param atom         information about the atomic kind
      73             : !> \param lprint       save exchange-correlation potential to the file 'linear_potentials.dat'
      74             : !> \param xcmat        exchange-correlation potential matrix
      75             : !> \author D. Varsano [daniele.varsano@nano.cnr.it]
      76             : ! **************************************************************************************************
      77           0 :    SUBROUTINE calculate_atom_zmp(ext_density, atom, lprint, xcmat)
      78             :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: ext_density
      79             :       TYPE(atom_type), INTENT(INOUT)                     :: atom
      80             :       LOGICAL                                            :: lprint
      81             :       TYPE(opmat_type), OPTIONAL, POINTER                :: xcmat
      82             : 
      83             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_atom_zmp'
      84             : 
      85             :       INTEGER                                            :: extunit, handle, ir, nr, z
      86             :       REAL(KIND=dp)                                      :: int1, int2
      87           0 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: deltarho, rho_dum, vxc, vxc1, vxc2
      88           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rho
      89             : 
      90           0 :       CALL timeset(routineN, handle)
      91             : 
      92           0 :       nr = atom%basis%grid%nr
      93           0 :       z = atom%z
      94           0 :       ALLOCATE (rho(nr, 1), vxc(nr), vxc1(nr), vxc2(nr), rho_dum(nr), deltarho(nr))
      95           0 :       CALL atom_density(rho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="RHO")
      96             :       !Vxc1
      97           0 :       int1 = integrate_grid(ext_density, atom%basis%grid)
      98           0 :       int1 = fourpi*int1
      99           0 :       CALL coulomb_potential_numeric(vxc1, rho(:, 1), atom%basis%grid)
     100             : 
     101           0 :       vxc1 = -vxc1/z
     102             : 
     103             :       !Vxc2
     104           0 :       rho_dum = rho(:, 1)*int1/z
     105           0 :       deltarho = rho_dum - ext_density
     106           0 :       int2 = integrate_grid(deltarho, atom%basis%grid)
     107           0 :       CALL coulomb_potential_numeric(vxc2, deltarho, atom%basis%grid)
     108             : 
     109           0 :       vxc2 = vxc2*atom%lambda
     110             : 
     111             :       !Vxc
     112           0 :       vxc = vxc1 + vxc2
     113             : 
     114           0 :       atom%energy%exc = fourpi*integrate_grid(vxc, rho(:, 1), atom%basis%grid)
     115           0 :       atom%rho_diff_integral = fourpi*int2
     116             : 
     117           0 :       IF (lprint) THEN
     118           0 :          extunit = get_unit_number()
     119             :          CALL open_file(file_name="linear_potentials.dat", file_status="UNKNOWN", &
     120             :                         file_form="FORMATTED", file_action="WRITE", &
     121           0 :                         unit_number=extunit)
     122             : 
     123           0 :          WRITE (extunit, fmt='("#",T10,"R[bohr]",T36,"Rho[au]",T61,"DRho[au]",T86,"V_XC[au]",T111,"V_XC1[au]",T136,"V_XC2[au]")')
     124           0 :          DO ir = 1, nr
     125             :             WRITE (extunit, fmt='(T1,E24.15,T26,E24.15,T51,E24.15,T76,E24.15,T101,E24.15,T126,E24.15)') &
     126           0 :                atom%basis%grid%rad(ir), rho(ir, 1), deltarho(ir), vxc(ir), vxc1(ir), vxc2(ir)
     127             :          END DO
     128           0 :          CALL close_file(unit_number=extunit)
     129             :       END IF
     130             : 
     131           0 :       IF (PRESENT(xcmat)) CALL numpot_matrix(xcmat%op, vxc, atom%basis, 0)
     132             : 
     133           0 :       DEALLOCATE (rho, vxc, vxc1, vxc2, rho_dum, deltarho)
     134             : 
     135           0 :       CALL timestop(handle)
     136             : 
     137           0 :    END SUBROUTINE calculate_atom_zmp
     138             : 
     139             : ! **************************************************************************************************
     140             : !> \brief ZMP subroutine for the scf external density from the external v_xc.
     141             : !> \param vxc     exchange-correlation potential
     142             : !> \param atom    information about the atomic kind
     143             : !> \param lprint  save exchange-correlation potential to the file 'linear_potentials.dat'
     144             : !> \param xcmat   exchange-correlation potential matrix
     145             : !> \author D. Varsano [daniele.varsano@nano.cnr.it]
     146             : ! **************************************************************************************************
     147           0 :    SUBROUTINE calculate_atom_ext_vxc(vxc, atom, lprint, xcmat)
     148             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: vxc
     149             :       TYPE(atom_type), INTENT(INOUT)                     :: atom
     150             :       LOGICAL, INTENT(in)                                :: lprint
     151             :       TYPE(opmat_type), INTENT(inout), OPTIONAL, POINTER :: xcmat
     152             : 
     153             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_atom_ext_vxc'
     154             : 
     155             :       INTEGER                                            :: extunit, handle, ir, nr
     156           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: rho
     157             : 
     158           0 :       CALL timeset(routineN, handle)
     159           0 :       nr = atom%basis%grid%nr
     160             : 
     161           0 :       ALLOCATE (rho(nr, 1))
     162             : 
     163           0 :       CALL atom_density(rho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="RHO")
     164             : 
     165           0 :       IF (lprint) THEN
     166           0 :          extunit = get_unit_number()
     167             :          CALL open_file(file_name="linear_potentials.dat", file_status="UNKNOWN", &
     168             :                         file_form="FORMATTED", file_action="WRITE", &
     169           0 :                         unit_number=extunit)
     170             : 
     171           0 :          WRITE (extunit, fmt='("#",T10,"R[bohr]",T36,"Rho[au]",T61,"V_XC[au]")')
     172           0 :          DO ir = 1, nr
     173             :             WRITE (extunit, fmt='(T1,E24.15,T26,E24.15,T51,E24.15)') &
     174           0 :                atom%basis%grid%rad(ir), rho(ir, 1), vxc(ir)
     175             :          END DO
     176           0 :          CALL close_file(unit_number=extunit)
     177             :       END IF
     178             : 
     179           0 :       atom%energy%exc = fourpi*integrate_grid(vxc, rho(:, 1), atom%basis%grid)
     180           0 :       IF (PRESENT(xcmat)) CALL numpot_matrix(xcmat%op, vxc, atom%basis, 0)
     181             : 
     182           0 :       DEALLOCATE (rho)
     183             : 
     184           0 :       CALL timestop(handle)
     185             : 
     186           0 :    END SUBROUTINE calculate_atom_ext_vxc
     187             : 
     188             : ! **************************************************************************************************
     189             : !> \brief Calculate atomic exchange-correlation potential in spin-restricted case.
     190             : !> \param xcmat       exchange-correlation potential expressed in the atomic basis set
     191             : !> \param atom        information about the atomic kind
     192             : !> \param xc_section  XC input section
     193             : !> \par History
     194             : !>    * 03.2010 extension of GTH pseudo-potential definition [Juerg Hutter]
     195             : !>    * 02.2010 renamed to calculate_atom_vxc_lda() [Juerg Hutter]
     196             : !>    * 08.2008 created [Juerg Hutter]
     197             : ! **************************************************************************************************
     198      107782 :    SUBROUTINE calculate_atom_vxc_lda(xcmat, atom, xc_section)
     199             :       TYPE(opmat_type), POINTER                          :: xcmat
     200             :       TYPE(atom_type), INTENT(INOUT)                     :: atom
     201             :       TYPE(section_vals_type), POINTER                   :: xc_section
     202             : 
     203             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_atom_vxc_lda'
     204             : 
     205             :       INTEGER                                            :: deriv_order, handle, i, l, myfun, n1, &
     206             :                                                             n2, n3, nr, nspins, unit_nr
     207             :       INTEGER, DIMENSION(2, 3)                           :: bounds
     208             :       LOGICAL                                            :: lsd, nlcc
     209             :       REAL(KIND=dp)                                      :: density_cut, gradient_cut, tau_cut
     210      107782 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc, vxc
     211      107782 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: drho, lap, rho, tau
     212       53891 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: taumat, xcpot
     213             :       TYPE(section_vals_type), POINTER                   :: xc_fun_section
     214             :       TYPE(xc_derivative_set_type)                       :: deriv_set
     215             :       TYPE(xc_derivative_type), POINTER                  :: deriv
     216             :       TYPE(xc_rho_cflags_type)                           :: needs
     217             :       TYPE(xc_rho_set_type)                              :: rho_set
     218             : 
     219       53891 :       CALL timeset(routineN, handle)
     220             : 
     221       53891 :       nlcc = .FALSE.
     222       53891 :       IF (atom%potential%ppot_type == gth_pseudo) THEN
     223       47221 :          nlcc = atom%potential%gth_pot%nlcc
     224        6670 :       ELSE IF (atom%potential%ppot_type == upf_pseudo) THEN
     225          24 :          nlcc = atom%potential%upf_pot%core_correction
     226        6646 :       ELSE IF (atom%potential%ppot_type == sgp_pseudo) THEN
     227          84 :          nlcc = atom%potential%sgp_pot%has_nlcc
     228             :       END IF
     229             : 
     230       53891 :       IF (ASSOCIATED(xc_section)) THEN
     231       19483 :          xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
     232       19483 :          CALL section_vals_val_get(xc_fun_section, "_SECTION_PARAMETERS_", i_val=myfun)
     233             : 
     234       19483 :          IF (myfun == xc_none) THEN
     235          16 :             atom%energy%exc = 0._dp
     236             :          ELSE
     237       19467 :             CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", r_val=density_cut)
     238       19467 :             CALL section_vals_val_get(xc_section, "GRADIENT_CUTOFF", r_val=gradient_cut)
     239       19467 :             CALL section_vals_val_get(xc_section, "TAU_CUTOFF", r_val=tau_cut)
     240             : 
     241       19467 :             lsd = .FALSE.
     242       19467 :             nspins = 1
     243       19467 :             needs = xc_functionals_get_needs(xc_fun_section, lsd=lsd, calc_potential=.FALSE.)
     244             : 
     245             :             ! Prepare the structures needed to calculate and store the xc derivatives
     246             : 
     247             :             ! Array dimension: here anly one dimensional arrays are used,
     248             :             ! i.e. only the first column of deriv_data is read.
     249             :             ! The other to dimensions  are set to size equal 1
     250       19467 :             nr = atom%basis%grid%nr
     251      194670 :             bounds(1:2, 1:3) = 1
     252       19467 :             bounds(2, 1) = nr
     253             : 
     254             :             ! create a place where to put the derivatives
     255       19467 :             CALL xc_dset_create(deriv_set, local_bounds=bounds)
     256             :             ! create the place where to store the argument for the functionals
     257             :             CALL xc_rho_set_create(rho_set, bounds, rho_cutoff=density_cut, &
     258       19467 :                                    drho_cutoff=gradient_cut, tau_cutoff=tau_cut)
     259             :             ! allocate the required 3d arrays where to store rho and drho
     260       19467 :             CALL xc_rho_set_atom_update(rho_set, needs, nspins, bounds)
     261             : 
     262       19467 :             NULLIFY (rho, drho, tau)
     263       19467 :             IF (needs%rho) THEN
     264       58401 :                ALLOCATE (rho(nr, 1))
     265       19467 :                CALL atom_density(rho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="RHO")
     266       19467 :                IF (nlcc) THEN
     267         437 :                   CALL atom_core_density(rho(:, 1), atom%potential, typ="RHO", rr=atom%basis%grid%rad)
     268             :                END IF
     269             :             END IF
     270       19467 :             IF (needs%norm_drho) THEN
     271       56163 :                ALLOCATE (drho(nr, 1))
     272       18721 :                CALL atom_density(drho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="DER")
     273       18721 :                IF (nlcc) THEN
     274         437 :                   CALL atom_core_density(drho(:, 1), atom%potential, typ="DER", rr=atom%basis%grid%rad)
     275             :                END IF
     276             :             END IF
     277       19467 :             IF (needs%tau) THEN
     278         324 :                ALLOCATE (tau(nr, 1))
     279             :                CALL atom_density(tau(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, &
     280         108 :                                  typ="KIN", rr=atom%basis%grid%rad2)
     281             :             END IF
     282       19467 :             IF (needs%laplace_rho) THEN
     283           0 :                ALLOCATE (lap(nr, 1))
     284             :                CALL atom_density(lap(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, &
     285           0 :                                  typ="LAP", rr=atom%basis%grid%rad2)
     286           0 :                IF (nlcc) THEN
     287           0 :                   CALL atom_core_density(lap(:, 1), atom%potential, typ="LAP", rr=atom%basis%grid%rad)
     288             :                END IF
     289             :             END IF
     290             : 
     291       19467 :             CALL fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, nr)
     292             : 
     293       19467 :             CALL xc_dset_zero_all(deriv_set)
     294             : 
     295       19467 :             deriv_order = 1
     296             :             CALL xc_functionals_eval(xc_fun_section, lsd=lsd, rho_set=rho_set, deriv_set=deriv_set, &
     297       19467 :                                      deriv_order=deriv_order)
     298             : 
     299             :             ! Integration to get the matrix elements and energy
     300       19467 :             deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], allocate_deriv=.FALSE.)
     301       19467 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     302       19467 :             atom%energy%exc = fourpi*integrate_grid(xcpot(:, 1, 1), atom%basis%grid)
     303             : 
     304             :             ! dump grid density and xcpot (xc energy?)
     305             :             IF (.FALSE.) THEN
     306             :                CALL open_file(unit_number=unit_nr, file_status="UNKNOWN", file_action="WRITE", file_name="atom.dat")
     307             :                DO i = 1, SIZE(xcpot(:, 1, 1))
     308             :                   WRITE (unit_nr, *) atom%basis%grid%rad(i), rho(i, 1), xcpot(i, 1, 1)
     309             :                END DO
     310             :                CALL close_file(unit_nr)
     311             :             END IF
     312             : 
     313       19467 :             IF (needs%rho) THEN
     314       19467 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_rho], allocate_deriv=.FALSE.)
     315       19467 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     316       19467 :                CALL numpot_matrix(xcmat%op, xcpot(:, 1, 1), atom%basis, 0)
     317             :                IF (.FALSE.) THEN
     318             :                   CALL open_file(unit_number=unit_nr, file_status="UNKNOWN", file_action="WRITE", file_name="atompot.dat")
     319             :                   DO i = 1, SIZE(xcpot(:, 1, 1))
     320             :                      WRITE (unit_nr, *) atom%basis%grid%rad(i), rho(i, 1), xcpot(i, 1, 1)
     321             :                   END DO
     322             :                   CALL close_file(unit_nr)
     323             :                END IF
     324       19467 :                DEALLOCATE (rho)
     325             :             END IF
     326       19467 :             IF (needs%norm_drho) THEN
     327       18721 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho], allocate_deriv=.FALSE.)
     328       18721 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     329       18721 :                CALL numpot_matrix(xcmat%op, xcpot(:, 1, 1), atom%basis, 1)
     330             :                IF (.FALSE.) THEN
     331             :                   CALL open_file(unit_number=unit_nr, file_status="UNKNOWN", file_action="WRITE", file_name="atomdpot.dat")
     332             :                   DO i = 1, SIZE(xcpot(:, 1, 1))
     333             :                      WRITE (unit_nr, *) atom%basis%grid%rad(i), drho(i, 1), xcpot(i, 1, 1)
     334             :                   END DO
     335             :                   CALL close_file(unit_nr)
     336             :                END IF
     337       18721 :                DEALLOCATE (drho)
     338             :             END IF
     339       19467 :             IF (needs%tau) THEN
     340         108 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_tau], allocate_deriv=.FALSE.)
     341         108 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     342         108 :                n1 = SIZE(xcmat%op, 1)
     343         108 :                n2 = SIZE(xcmat%op, 2)
     344         108 :                n3 = SIZE(xcmat%op, 3)
     345         540 :                ALLOCATE (taumat(n1, n2, 0:n3 - 1))
     346      919980 :                taumat = 0._dp
     347             : 
     348       43308 :                xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
     349         108 :                CALL numpot_matrix(xcmat%op, xcpot(:, 1, 1), atom%basis, 2)
     350       43308 :                xcpot(:, 1, 1) = xcpot(:, 1, 1)/atom%basis%grid%rad2(:)
     351         108 :                CALL numpot_matrix(taumat, xcpot(:, 1, 1), atom%basis, 0)
     352         540 :                DO l = 0, 3
     353     1226172 :                   xcmat%op(:, :, l) = xcmat%op(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
     354             :                END DO
     355             : 
     356         108 :                DEALLOCATE (tau)
     357         108 :                DEALLOCATE (taumat)
     358             :             END IF
     359             : 
     360             :             ! assume lap is not really needed
     361       19467 :             IF (needs%laplace_rho) THEN
     362           0 :                DEALLOCATE (lap)
     363             :             END IF
     364             : 
     365             :             ! Release the xc structure used to store the xc derivatives
     366       19467 :             CALL xc_dset_release(deriv_set)
     367       19467 :             CALL xc_rho_set_release(rho_set)
     368             : 
     369             :          END IF !xc_none
     370             : 
     371             :       ELSE
     372             : 
     373             :          ! we don't have an xc_section, use a default setup
     374       34408 :          nr = atom%basis%grid%nr
     375      240856 :          ALLOCATE (rho(nr, 1), exc(nr), vxc(nr))
     376             : 
     377       34408 :          CALL atom_density(rho(:, 1), atom%orbitals%pmat, atom%basis, atom%state%maxl_occ, typ="RHO")
     378       34408 :          IF (nlcc) THEN
     379          64 :             CALL atom_core_density(rho(:, 1), atom%potential, typ="RHO", rr=atom%basis%grid%rad)
     380             :          END IF
     381       34408 :          CALL lda_pade(rho(:, 1), exc, vxc)
     382             : 
     383       34408 :          atom%energy%exc = fourpi*integrate_grid(exc, atom%basis%grid)
     384       34408 :          CALL numpot_matrix(xcmat%op, vxc, atom%basis, 0)
     385             : 
     386       34408 :          DEALLOCATE (rho, exc, vxc)
     387             : 
     388             :       END IF
     389             : 
     390       53891 :       CALL timestop(handle)
     391             : 
     392     1023929 :    END SUBROUTINE calculate_atom_vxc_lda
     393             : 
     394             : ! **************************************************************************************************
     395             : !> \brief Calculate atomic exchange-correlation potential in spin-polarized case.
     396             : !> \param xcmata      spin-alpha exchange-correlation potential matrix
     397             : !> \param xcmatb      spin-beta exchange-correlation potential matrix
     398             : !> \param atom        information about the atomic kind
     399             : !> \param xc_section  XC input section
     400             : !> \par History
     401             : !>    * 02.2010 created [Juerg Hutter]
     402             : ! **************************************************************************************************
     403        2670 :    SUBROUTINE calculate_atom_vxc_lsd(xcmata, xcmatb, atom, xc_section)
     404             :       TYPE(opmat_type), POINTER                          :: xcmata, xcmatb
     405             :       TYPE(atom_type), INTENT(INOUT)                     :: atom
     406             :       TYPE(section_vals_type), POINTER                   :: xc_section
     407             : 
     408             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_atom_vxc_lsd'
     409             : 
     410             :       INTEGER                                            :: deriv_order, handle, l, myfun, n1, n2, &
     411             :                                                             n3, nr, nspins
     412             :       INTEGER, DIMENSION(2, 3)                           :: bounds
     413             :       LOGICAL                                            :: lsd, nlcc
     414             :       REAL(KIND=dp)                                      :: density_cut, gradient_cut, tau_cut
     415        2670 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: exc, vxca, vxcb, xfun
     416        2670 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: drho, lap, rho, tau
     417        1335 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: taumat, xcpot
     418             :       TYPE(section_vals_type), POINTER                   :: xc_fun_section
     419             :       TYPE(xc_derivative_set_type)                       :: deriv_set
     420             :       TYPE(xc_derivative_type), POINTER                  :: deriv
     421             :       TYPE(xc_rho_cflags_type)                           :: needs
     422             :       TYPE(xc_rho_set_type)                              :: rho_set
     423             : 
     424        1335 :       CALL timeset(routineN, handle)
     425             : 
     426        1335 :       nlcc = .FALSE.
     427        1335 :       IF (atom%potential%ppot_type == gth_pseudo) THEN
     428        1203 :          nlcc = atom%potential%gth_pot%nlcc
     429         132 :       ELSE IF (atom%potential%ppot_type == upf_pseudo) THEN
     430           0 :          nlcc = atom%potential%upf_pot%core_correction
     431           0 :          CPASSERT(.NOT. nlcc)
     432         132 :       ELSE IF (atom%potential%ppot_type == sgp_pseudo) THEN
     433           0 :          nlcc = atom%potential%sgp_pot%has_nlcc
     434           0 :          CPASSERT(.NOT. nlcc)
     435             :       END IF
     436             : 
     437        1335 :       IF (ASSOCIATED(xc_section)) THEN
     438         921 :          IF (nlcc) THEN
     439         365 :             nr = atom%basis%grid%nr
     440        1095 :             ALLOCATE (xfun(nr))
     441             :          END IF
     442             : 
     443         921 :          xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
     444         921 :          CALL section_vals_val_get(xc_fun_section, "_SECTION_PARAMETERS_", i_val=myfun)
     445             : 
     446         921 :          IF (myfun == xc_none) THEN
     447           0 :             atom%energy%exc = 0._dp
     448             :          ELSE
     449         921 :             CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", r_val=density_cut)
     450         921 :             CALL section_vals_val_get(xc_section, "GRADIENT_CUTOFF", r_val=gradient_cut)
     451         921 :             CALL section_vals_val_get(xc_section, "TAU_CUTOFF", r_val=tau_cut)
     452             : 
     453         921 :             lsd = .TRUE.
     454         921 :             nspins = 2
     455         921 :             needs = xc_functionals_get_needs(xc_fun_section, lsd=lsd, calc_potential=.FALSE.)
     456             : 
     457             :             ! Prepare the structures needed to calculate and store the xc derivatives
     458             : 
     459             :             ! Array dimension: here anly one dimensional arrays are used,
     460             :             ! i.e. only the first column of deriv_data is read.
     461             :             ! The other to dimensions  are set to size equal 1
     462         921 :             nr = atom%basis%grid%nr
     463        9210 :             bounds(1:2, 1:3) = 1
     464         921 :             bounds(2, 1) = nr
     465             : 
     466             :             ! create a place where to put the derivatives
     467         921 :             CALL xc_dset_create(deriv_set, local_bounds=bounds)
     468             :             ! create the place where to store the argument for the functionals
     469             :             CALL xc_rho_set_create(rho_set, bounds, rho_cutoff=density_cut, &
     470         921 :                                    drho_cutoff=gradient_cut, tau_cutoff=tau_cut)
     471             :             ! allocate the required 3d arrays where to store rho and drho
     472         921 :             CALL xc_rho_set_atom_update(rho_set, needs, nspins, bounds)
     473             : 
     474         921 :             NULLIFY (rho, drho, tau)
     475         921 :             IF (needs%rho_spin) THEN
     476        2763 :                ALLOCATE (rho(nr, 2))
     477         921 :                CALL atom_density(rho(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, typ="RHO")
     478         921 :                CALL atom_density(rho(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, typ="RHO")
     479         921 :                IF (nlcc) THEN
     480      146365 :                   xfun = 0.0_dp
     481         365 :                   CALL atom_core_density(xfun(:), atom%potential, typ="RHO", rr=atom%basis%grid%rad)
     482      292365 :                   rho(:, 1) = rho(:, 1) + 0.5_dp*xfun(:)
     483      292365 :                   rho(:, 2) = rho(:, 2) + 0.5_dp*xfun(:)
     484             :                END IF
     485             :             END IF
     486         921 :             IF (needs%norm_drho_spin) THEN
     487        2757 :                ALLOCATE (drho(nr, 2))
     488         919 :                CALL atom_density(drho(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, typ="DER")
     489         919 :                CALL atom_density(drho(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, typ="DER")
     490         919 :                IF (nlcc) THEN
     491      146365 :                   xfun = 0.0_dp
     492         365 :                   CALL atom_core_density(xfun(:), atom%potential, typ="DER", rr=atom%basis%grid%rad)
     493      292365 :                   drho(:, 1) = drho(:, 1) + 0.5_dp*xfun(:)
     494      292365 :                   drho(:, 2) = drho(:, 2) + 0.5_dp*xfun(:)
     495             :                END IF
     496             :             END IF
     497         921 :             IF (needs%tau_spin) THEN
     498           6 :                ALLOCATE (tau(nr, 2))
     499             :                CALL atom_density(tau(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, &
     500           2 :                                  typ="KIN", rr=atom%basis%grid%rad2)
     501             :                CALL atom_density(tau(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, &
     502           2 :                                  typ="KIN", rr=atom%basis%grid%rad2)
     503             :             END IF
     504         921 :             IF (needs%laplace_rho_spin) THEN
     505           0 :                ALLOCATE (lap(nr, 2))
     506             :                CALL atom_density(lap(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, &
     507           0 :                                  typ="LAP", rr=atom%basis%grid%rad2)
     508             :                CALL atom_density(lap(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, &
     509           0 :                                  typ="LAP", rr=atom%basis%grid%rad2)
     510           0 :                IF (nlcc) THEN
     511           0 :                   xfun = 0.0_dp
     512           0 :                   CALL atom_core_density(xfun(:), atom%potential, typ="LAP", rr=atom%basis%grid%rad)
     513           0 :                   lap(:, 1) = lap(:, 1) + 0.5_dp*xfun(:)
     514           0 :                   lap(:, 2) = lap(:, 2) + 0.5_dp*xfun(:)
     515             :                END IF
     516             :             END IF
     517             : 
     518         921 :             CALL fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, nr)
     519             : 
     520         921 :             CALL xc_dset_zero_all(deriv_set)
     521             : 
     522         921 :             deriv_order = 1
     523             :             CALL xc_functionals_eval(xc_fun_section, lsd=lsd, rho_set=rho_set, deriv_set=deriv_set, &
     524         921 :                                      deriv_order=deriv_order)
     525             : 
     526             :             ! Integration to get the matrix elements and energy
     527         921 :             deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], allocate_deriv=.FALSE.)
     528         921 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     529         921 :             atom%energy%exc = fourpi*integrate_grid(xcpot(:, 1, 1), atom%basis%grid)
     530             : 
     531         921 :             IF (needs%rho_spin) THEN
     532         921 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa], allocate_deriv=.FALSE.)
     533         921 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     534         921 :                CALL numpot_matrix(xcmata%op, xcpot(:, 1, 1), atom%basis, 0)
     535         921 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_rhob], allocate_deriv=.FALSE.)
     536         921 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     537         921 :                CALL numpot_matrix(xcmatb%op, xcpot(:, 1, 1), atom%basis, 0)
     538         921 :                DEALLOCATE (rho)
     539             :             END IF
     540         921 :             IF (needs%norm_drho_spin) THEN
     541             :                ! drhoa
     542         919 :                NULLIFY (deriv)
     543         919 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa], allocate_deriv=.FALSE.)
     544         919 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     545         919 :                CALL numpot_matrix(xcmata%op, xcpot(:, 1, 1), atom%basis, 1)
     546             :                ! drhob
     547         919 :                NULLIFY (deriv)
     548         919 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob], allocate_deriv=.FALSE.)
     549         919 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     550         919 :                CALL numpot_matrix(xcmatb%op, xcpot(:, 1, 1), atom%basis, 1)
     551             :                ! Cross Terms
     552         919 :                NULLIFY (deriv)
     553         919 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
     554         919 :                IF (ASSOCIATED(deriv)) THEN
     555         919 :                   CALL xc_derivative_get(deriv, deriv_data=xcpot)
     556         919 :                   CALL numpot_matrix(xcmata%op, xcpot(:, 1, 1), atom%basis, 1)
     557         919 :                   CALL numpot_matrix(xcmatb%op, xcpot(:, 1, 1), atom%basis, 1)
     558             :                END IF
     559         919 :                DEALLOCATE (drho)
     560             :             END IF
     561         921 :             IF (needs%tau_spin) THEN
     562           2 :                n1 = SIZE(xcmata%op, 1)
     563           2 :                n2 = SIZE(xcmata%op, 2)
     564           2 :                n3 = SIZE(xcmata%op, 3)
     565          10 :                ALLOCATE (taumat(n1, n2, 0:n3 - 1))
     566             : 
     567           2 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_a], allocate_deriv=.FALSE.)
     568           2 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     569          86 :                taumat = 0._dp
     570         802 :                xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
     571           2 :                CALL numpot_matrix(xcmata%op, xcpot(:, 1, 1), atom%basis, 2)
     572         802 :                xcpot(:, 1, 1) = xcpot(:, 1, 1)/atom%basis%grid%rad2(:)
     573           2 :                CALL numpot_matrix(taumat, xcpot(:, 1, 1), atom%basis, 0)
     574          10 :                DO l = 0, 3
     575         106 :                   xcmata%op(:, :, l) = xcmata%op(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
     576             :                END DO
     577             : 
     578           2 :                deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_b], allocate_deriv=.FALSE.)
     579           2 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     580          86 :                taumat = 0._dp
     581         802 :                xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
     582           2 :                CALL numpot_matrix(xcmatb%op, xcpot(:, 1, 1), atom%basis, 2)
     583         802 :                xcpot(:, 1, 1) = xcpot(:, 1, 1)/atom%basis%grid%rad2(:)
     584           2 :                CALL numpot_matrix(taumat, xcpot(:, 1, 1), atom%basis, 0)
     585          10 :                DO l = 0, 3
     586         106 :                   xcmatb%op(:, :, l) = xcmatb%op(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
     587             :                END DO
     588             : 
     589           2 :                DEALLOCATE (tau)
     590           2 :                DEALLOCATE (taumat)
     591             :             END IF
     592             : 
     593             :             ! assume lap is not really needed
     594         921 :             IF (needs%laplace_rho_spin) THEN
     595           0 :                DEALLOCATE (lap)
     596             :             END IF
     597             : 
     598             :             ! Release the xc structure used to store the xc derivatives
     599         921 :             CALL xc_dset_release(deriv_set)
     600         921 :             CALL xc_rho_set_release(rho_set)
     601             : 
     602             :          END IF !xc_none
     603             : 
     604         921 :          IF (nlcc) DEALLOCATE (xfun)
     605             : 
     606             :       ELSE
     607             : 
     608             :          ! we don't have an xc_section, use a default setup
     609         414 :          nr = atom%basis%grid%nr
     610        3726 :          ALLOCATE (rho(nr, 2), exc(nr), vxca(nr), vxcb(nr))
     611         414 :          IF (nlcc) ALLOCATE (xfun(nr))
     612             : 
     613         414 :          CALL atom_density(rho(:, 1), atom%orbitals%pmata, atom%basis, atom%state%maxl_occ, typ="RHO")
     614         414 :          CALL atom_density(rho(:, 2), atom%orbitals%pmatb, atom%basis, atom%state%maxl_occ, typ="RHO")
     615         414 :          IF (nlcc) THEN
     616           0 :             xfun(:) = 0.0_dp
     617           0 :             CALL atom_core_density(xfun(:), atom%potential, typ="RHO", rr=atom%basis%grid%rad)
     618           0 :             rho(:, 1) = rho(:, 1) + 0.5_dp*xfun(:)
     619           0 :             rho(:, 2) = rho(:, 2) + 0.5_dp*xfun(:)
     620             :          END IF
     621         414 :          CALL lsd_pade(rho(:, 1), rho(:, 2), exc, vxca, vxcb)
     622             : 
     623         414 :          atom%energy%exc = fourpi*integrate_grid(exc, atom%basis%grid)
     624         414 :          CALL numpot_matrix(xcmata%op, vxca, atom%basis, 0)
     625         414 :          CALL numpot_matrix(xcmatb%op, vxcb, atom%basis, 0)
     626             : 
     627         414 :          DEALLOCATE (rho, exc, vxca, vxcb)
     628         414 :          IF (nlcc) DEALLOCATE (xfun)
     629             : 
     630             :       END IF
     631             : 
     632        1335 :       CALL timestop(handle)
     633             : 
     634       25365 :    END SUBROUTINE calculate_atom_vxc_lsd
     635             : 
     636             : ! **************************************************************************************************
     637             : !> \brief Alternative subroutine that calculates atomic exchange-correlation potential
     638             : !>        in spin-restricted case.
     639             : !> \param basis       atomic basis set
     640             : !> \param pmat        density matrix
     641             : !> \param maxl        maximum angular momentum
     642             : !> \param xc_section  XC input section
     643             : !> \param fexc        exchange-correlation energy
     644             : !> \param xcmat       exchange-correlation potential matrix
     645             : !> \par History
     646             : !>    * 07.2016 ADMM analysis [Juerg Hutter]
     647             : ! **************************************************************************************************
     648           8 :    SUBROUTINE atom_vxc_lda(basis, pmat, maxl, xc_section, fexc, xcmat)
     649             :       TYPE(atom_basis_type), POINTER                     :: basis
     650             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: pmat
     651             :       INTEGER, INTENT(IN)                                :: maxl
     652             :       TYPE(section_vals_type), POINTER                   :: xc_section
     653             :       REAL(KIND=dp), INTENT(OUT)                         :: fexc
     654             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: xcmat
     655             : 
     656             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'atom_vxc_lda'
     657             : 
     658             :       INTEGER                                            :: deriv_order, handle, l, myfun, n1, n2, &
     659             :                                                             n3, nr, nspins
     660             :       INTEGER, DIMENSION(2, 3)                           :: bounds
     661             :       LOGICAL                                            :: lsd
     662             :       REAL(KIND=dp)                                      :: density_cut, gradient_cut, tau_cut
     663          16 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: drho, lap, rho, tau
     664           8 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: taumat, xcpot
     665             :       TYPE(section_vals_type), POINTER                   :: xc_fun_section
     666             :       TYPE(xc_derivative_set_type)                       :: deriv_set
     667             :       TYPE(xc_derivative_type), POINTER                  :: deriv
     668             :       TYPE(xc_rho_cflags_type)                           :: needs
     669             :       TYPE(xc_rho_set_type)                              :: rho_set
     670             : 
     671           8 :       CALL timeset(routineN, handle)
     672             : 
     673           8 :       CPASSERT(ASSOCIATED(xc_section))
     674             : 
     675           8 :       xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
     676           8 :       CALL section_vals_val_get(xc_fun_section, "_SECTION_PARAMETERS_", i_val=myfun)
     677             : 
     678           8 :       IF (myfun == xc_none) THEN
     679           0 :          fexc = 0._dp
     680             :       ELSE
     681           8 :          CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", r_val=density_cut)
     682           8 :          CALL section_vals_val_get(xc_section, "GRADIENT_CUTOFF", r_val=gradient_cut)
     683           8 :          CALL section_vals_val_get(xc_section, "TAU_CUTOFF", r_val=tau_cut)
     684             : 
     685           8 :          lsd = .FALSE.
     686           8 :          nspins = 1
     687           8 :          needs = xc_functionals_get_needs(xc_fun_section, lsd=lsd, calc_potential=.FALSE.)
     688             : 
     689             :          ! Prepare the structures needed to calculate and store the xc derivatives
     690             : 
     691             :          ! Array dimension: here anly one dimensional arrays are used,
     692             :          ! i.e. only the first column of deriv_data is read.
     693             :          ! The other to dimensions  are set to size equal 1
     694           8 :          nr = basis%grid%nr
     695          80 :          bounds(1:2, 1:3) = 1
     696           8 :          bounds(2, 1) = nr
     697             : 
     698             :          ! create a place where to put the derivatives
     699           8 :          CALL xc_dset_create(deriv_set, local_bounds=bounds)
     700             :          ! create the place where to store the argument for the functionals
     701             :          CALL xc_rho_set_create(rho_set, bounds, rho_cutoff=density_cut, &
     702           8 :                                 drho_cutoff=gradient_cut, tau_cutoff=tau_cut)
     703             :          ! allocate the required 3d arrays where to store rho and drho
     704           8 :          CALL xc_rho_set_atom_update(rho_set, needs, nspins, bounds)
     705             : 
     706           8 :          NULLIFY (rho, drho, tau)
     707           8 :          IF (needs%rho) THEN
     708          24 :             ALLOCATE (rho(nr, 1))
     709           8 :             CALL atom_density(rho(:, 1), pmat, basis, maxl, typ="RHO")
     710             :          END IF
     711           8 :          IF (needs%norm_drho) THEN
     712          24 :             ALLOCATE (drho(nr, 1))
     713           8 :             CALL atom_density(drho(:, 1), pmat, basis, maxl, typ="DER")
     714             :          END IF
     715           8 :          IF (needs%tau) THEN
     716           0 :             ALLOCATE (tau(nr, 1))
     717           0 :             CALL atom_density(tau(:, 1), pmat, basis, maxl, typ="KIN", rr=basis%grid%rad2)
     718             :          END IF
     719           8 :          IF (needs%laplace_rho) THEN
     720           0 :             ALLOCATE (lap(nr, 1))
     721           0 :             CALL atom_density(lap(:, 1), pmat, basis, maxl, typ="LAP", rr=basis%grid%rad2)
     722             :          END IF
     723             : 
     724           8 :          CALL fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, nr)
     725             : 
     726           8 :          CALL xc_dset_zero_all(deriv_set)
     727             : 
     728           8 :          deriv_order = 1
     729             :          CALL xc_functionals_eval(xc_fun_section, lsd=lsd, rho_set=rho_set, deriv_set=deriv_set, &
     730           8 :                                   deriv_order=deriv_order)
     731             : 
     732             :          ! Integration to get the matrix elements and energy
     733           8 :          deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], allocate_deriv=.FALSE.)
     734           8 :          CALL xc_derivative_get(deriv, deriv_data=xcpot)
     735           8 :          fexc = fourpi*integrate_grid(xcpot(:, 1, 1), basis%grid)
     736             : 
     737           8 :          IF (needs%rho) THEN
     738           8 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_rho], allocate_deriv=.FALSE.)
     739           8 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     740           8 :             CALL numpot_matrix(xcmat, xcpot(:, 1, 1), basis, 0)
     741           8 :             DEALLOCATE (rho)
     742             :          END IF
     743           8 :          IF (needs%norm_drho) THEN
     744           8 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho], allocate_deriv=.FALSE.)
     745           8 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     746           8 :             CALL numpot_matrix(xcmat, xcpot(:, 1, 1), basis, 1)
     747           8 :             DEALLOCATE (drho)
     748             :          END IF
     749           8 :          IF (needs%tau) THEN
     750           0 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_tau], allocate_deriv=.FALSE.)
     751           0 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     752           0 :             n1 = SIZE(xcmat, 1)
     753           0 :             n2 = SIZE(xcmat, 2)
     754           0 :             n3 = SIZE(xcmat, 3)
     755           0 :             ALLOCATE (taumat(n1, n2, 0:n3 - 1))
     756           0 :             taumat = 0._dp
     757             : 
     758           0 :             xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
     759           0 :             CALL numpot_matrix(xcmat, xcpot(:, 1, 1), basis, 2)
     760           0 :             xcpot(:, 1, 1) = xcpot(:, 1, 1)/basis%grid%rad2(:)
     761           0 :             CALL numpot_matrix(taumat, xcpot(:, 1, 1), basis, 0)
     762           0 :             DO l = 0, 3
     763           0 :                xcmat(:, :, l) = xcmat(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
     764             :             END DO
     765             : 
     766           0 :             DEALLOCATE (tau)
     767           0 :             DEALLOCATE (taumat)
     768             :          END IF
     769             : 
     770             :          ! we assume lap is not really needed
     771           8 :          IF (needs%laplace_rho) THEN
     772           0 :             DEALLOCATE (lap)
     773             :          END IF
     774             : 
     775             :          ! Release the xc structure used to store the xc derivatives
     776           8 :          CALL xc_dset_release(deriv_set)
     777           8 :          CALL xc_rho_set_release(rho_set)
     778             : 
     779             :       END IF !xc_none
     780             : 
     781           8 :       CALL timestop(handle)
     782             : 
     783         152 :    END SUBROUTINE atom_vxc_lda
     784             : 
     785             : ! **************************************************************************************************
     786             : !> \brief Alternative subroutine that calculates atomic exchange-correlation potential
     787             : !>        in spin-polarized case.
     788             : !> \param basis       atomic basis set
     789             : !> \param pmata       spin-alpha density matrix
     790             : !> \param pmatb       spin-beta density matrix
     791             : !> \param maxl        maximum angular momentum
     792             : !> \param xc_section  XC input section
     793             : !> \param fexc        exchange-correlation energy
     794             : !> \param xcmata      spin-alpha exchange-correlation potential matrix
     795             : !> \param xcmatb      spin-beta exchange-correlation potential matrix
     796             : !> \par History
     797             : !>    * 07.2016 ADMM analysis [Juerg Hutter]
     798             : ! **************************************************************************************************
     799           0 :    SUBROUTINE atom_vxc_lsd(basis, pmata, pmatb, maxl, xc_section, fexc, xcmata, xcmatb)
     800             :       TYPE(atom_basis_type), POINTER                     :: basis
     801             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: pmata, pmatb
     802             :       INTEGER, INTENT(IN)                                :: maxl
     803             :       TYPE(section_vals_type), POINTER                   :: xc_section
     804             :       REAL(KIND=dp), INTENT(OUT)                         :: fexc
     805             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: xcmata, xcmatb
     806             : 
     807             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'atom_vxc_lsd'
     808             : 
     809             :       INTEGER                                            :: deriv_order, handle, l, myfun, n1, n2, &
     810             :                                                             n3, nr, nspins
     811             :       INTEGER, DIMENSION(2, 3)                           :: bounds
     812             :       LOGICAL                                            :: lsd
     813             :       REAL(KIND=dp)                                      :: density_cut, gradient_cut, tau_cut
     814           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: drho, lap, rho, tau
     815           0 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: taumat, xcpot
     816             :       TYPE(section_vals_type), POINTER                   :: xc_fun_section
     817             :       TYPE(xc_derivative_set_type)                       :: deriv_set
     818             :       TYPE(xc_derivative_type), POINTER                  :: deriv
     819             :       TYPE(xc_rho_cflags_type)                           :: needs
     820             :       TYPE(xc_rho_set_type)                              :: rho_set
     821             : 
     822           0 :       CALL timeset(routineN, handle)
     823             : 
     824           0 :       CPASSERT(ASSOCIATED(xc_section))
     825             : 
     826           0 :       xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
     827           0 :       CALL section_vals_val_get(xc_fun_section, "_SECTION_PARAMETERS_", i_val=myfun)
     828             : 
     829           0 :       IF (myfun == xc_none) THEN
     830           0 :          fexc = 0._dp
     831             :       ELSE
     832           0 :          CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", r_val=density_cut)
     833           0 :          CALL section_vals_val_get(xc_section, "GRADIENT_CUTOFF", r_val=gradient_cut)
     834           0 :          CALL section_vals_val_get(xc_section, "TAU_CUTOFF", r_val=tau_cut)
     835             : 
     836           0 :          lsd = .TRUE.
     837           0 :          nspins = 2
     838           0 :          needs = xc_functionals_get_needs(xc_fun_section, lsd=lsd, calc_potential=.FALSE.)
     839             : 
     840             :          ! Prepare the structures needed to calculate and store the xc derivatives
     841             : 
     842             :          ! Array dimension: here anly one dimensional arrays are used,
     843             :          ! i.e. only the first column of deriv_data is read.
     844             :          ! The other to dimensions  are set to size equal 1
     845           0 :          nr = basis%grid%nr
     846           0 :          bounds(1:2, 1:3) = 1
     847           0 :          bounds(2, 1) = nr
     848             : 
     849             :          ! create a place where to put the derivatives
     850           0 :          CALL xc_dset_create(deriv_set, local_bounds=bounds)
     851             :          ! create the place where to store the argument for the functionals
     852             :          CALL xc_rho_set_create(rho_set, bounds, rho_cutoff=density_cut, &
     853           0 :                                 drho_cutoff=gradient_cut, tau_cutoff=tau_cut)
     854             :          ! allocate the required 3d arrays where to store rho and drho
     855           0 :          CALL xc_rho_set_atom_update(rho_set, needs, nspins, bounds)
     856             : 
     857           0 :          NULLIFY (rho, drho, tau)
     858           0 :          IF (needs%rho_spin) THEN
     859           0 :             ALLOCATE (rho(nr, 2))
     860           0 :             CALL atom_density(rho(:, 1), pmata, basis, maxl, typ="RHO")
     861           0 :             CALL atom_density(rho(:, 2), pmatb, basis, maxl, typ="RHO")
     862             :          END IF
     863           0 :          IF (needs%norm_drho_spin) THEN
     864           0 :             ALLOCATE (drho(nr, 2))
     865           0 :             CALL atom_density(drho(:, 1), pmata, basis, maxl, typ="DER")
     866           0 :             CALL atom_density(drho(:, 2), pmatb, basis, maxl, typ="DER")
     867             :          END IF
     868           0 :          IF (needs%tau_spin) THEN
     869           0 :             ALLOCATE (tau(nr, 2))
     870           0 :             CALL atom_density(tau(:, 1), pmata, basis, maxl, typ="KIN", rr=basis%grid%rad2)
     871           0 :             CALL atom_density(tau(:, 2), pmatb, basis, maxl, typ="KIN", rr=basis%grid%rad2)
     872             :          END IF
     873           0 :          IF (needs%laplace_rho_spin) THEN
     874           0 :             ALLOCATE (lap(nr, 2))
     875           0 :             CALL atom_density(lap(:, 1), pmata, basis, maxl, typ="LAP", rr=basis%grid%rad2)
     876           0 :             CALL atom_density(lap(:, 2), pmatb, basis, maxl, typ="LAP", rr=basis%grid%rad2)
     877             :          END IF
     878             : 
     879           0 :          CALL fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, nr)
     880             : 
     881           0 :          CALL xc_dset_zero_all(deriv_set)
     882             : 
     883           0 :          deriv_order = 1
     884             :          CALL xc_functionals_eval(xc_fun_section, lsd=lsd, rho_set=rho_set, deriv_set=deriv_set, &
     885           0 :                                   deriv_order=deriv_order)
     886             : 
     887             :          ! Integration to get the matrix elements and energy
     888           0 :          deriv => xc_dset_get_derivative(deriv_set, [INTEGER::], allocate_deriv=.FALSE.)
     889           0 :          CALL xc_derivative_get(deriv, deriv_data=xcpot)
     890           0 :          fexc = fourpi*integrate_grid(xcpot(:, 1, 1), basis%grid)
     891             : 
     892           0 :          IF (needs%rho_spin) THEN
     893           0 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_rhoa], allocate_deriv=.FALSE.)
     894           0 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     895           0 :             CALL numpot_matrix(xcmata, xcpot(:, 1, 1), basis, 0)
     896           0 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_rhob], allocate_deriv=.FALSE.)
     897           0 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     898           0 :             CALL numpot_matrix(xcmatb, xcpot(:, 1, 1), basis, 0)
     899           0 :             DEALLOCATE (rho)
     900             :          END IF
     901           0 :          IF (needs%norm_drho_spin) THEN
     902             :             ! drhoa
     903           0 :             NULLIFY (deriv)
     904           0 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhoa], allocate_deriv=.FALSE.)
     905           0 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     906           0 :             CALL numpot_matrix(xcmata, xcpot(:, 1, 1), basis, 1)
     907             :             ! drhob
     908           0 :             NULLIFY (deriv)
     909           0 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drhob], allocate_deriv=.FALSE.)
     910           0 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     911           0 :             CALL numpot_matrix(xcmatb, xcpot(:, 1, 1), basis, 1)
     912             :             ! Cross Terms
     913           0 :             NULLIFY (deriv)
     914           0 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_norm_drho])
     915           0 :             IF (ASSOCIATED(deriv)) THEN
     916           0 :                CALL xc_derivative_get(deriv, deriv_data=xcpot)
     917           0 :                CALL numpot_matrix(xcmata, xcpot(:, 1, 1), basis, 1)
     918           0 :                CALL numpot_matrix(xcmatb, xcpot(:, 1, 1), basis, 1)
     919             :             END IF
     920           0 :             DEALLOCATE (drho)
     921             :          END IF
     922           0 :          IF (needs%tau_spin) THEN
     923           0 :             n1 = SIZE(xcmata, 1)
     924           0 :             n2 = SIZE(xcmata, 2)
     925           0 :             n3 = SIZE(xcmata, 3)
     926           0 :             ALLOCATE (taumat(n1, n2, 0:n3 - 1))
     927             : 
     928           0 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_a], allocate_deriv=.FALSE.)
     929           0 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     930           0 :             taumat = 0._dp
     931           0 :             xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
     932           0 :             CALL numpot_matrix(xcmata, xcpot(:, 1, 1), basis, 2)
     933           0 :             xcpot(:, 1, 1) = xcpot(:, 1, 1)/basis%grid%rad2(:)
     934           0 :             CALL numpot_matrix(taumat, xcpot(:, 1, 1), basis, 0)
     935           0 :             DO l = 0, 3
     936           0 :                xcmata(:, :, l) = xcmata(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
     937             :             END DO
     938             : 
     939           0 :             deriv => xc_dset_get_derivative(deriv_set, [deriv_tau_b], allocate_deriv=.FALSE.)
     940           0 :             CALL xc_derivative_get(deriv, deriv_data=xcpot)
     941           0 :             taumat = 0._dp
     942           0 :             xcpot(:, 1, 1) = 0.5_dp*xcpot(:, 1, 1)
     943           0 :             CALL numpot_matrix(xcmatb, xcpot(:, 1, 1), basis, 2)
     944           0 :             xcpot(:, 1, 1) = xcpot(:, 1, 1)/basis%grid%rad2(:)
     945           0 :             CALL numpot_matrix(taumat, xcpot(:, 1, 1), basis, 0)
     946           0 :             DO l = 0, 3
     947           0 :                xcmatb(:, :, l) = xcmatb(:, :, l) + REAL(l*(l + 1), dp)*taumat(:, :, l)
     948             :             END DO
     949             : 
     950           0 :             DEALLOCATE (tau)
     951           0 :             DEALLOCATE (taumat)
     952             :          END IF
     953             : 
     954             :          ! Release the xc structure used to store the xc derivatives
     955           0 :          CALL xc_dset_release(deriv_set)
     956           0 :          CALL xc_rho_set_release(rho_set)
     957             : 
     958             :       END IF !xc_none
     959             : 
     960           0 :       CALL timestop(handle)
     961             : 
     962           0 :    END SUBROUTINE atom_vxc_lsd
     963             : 
     964             : ! **************************************************************************************************
     965             : !> \brief Estimate the ADMM exchange energy correction term using a model exchange functional.
     966             : !> \param basis0      reference atomic basis set
     967             : !> \param pmat0       reference density matrix
     968             : !> \param basis1      ADMM basis set
     969             : !> \param pmat1       ADMM density matrix
     970             : !> \param maxl        maxumum angular momentum
     971             : !> \param functional  name of the model exchange functional:
     972             : !>                    "LINX" -- linear extrapolation of the Slater exchange potential [?]
     973             : !> \param dfexc       exchange-correlation energy difference
     974             : !> \param linxpar     LINX parameters
     975             : !> \par History
     976             : !>    * 07.2016 ADMM analysis [Juerg Hutter]
     977             : ! **************************************************************************************************
     978           3 :    SUBROUTINE atom_dpot_lda(basis0, pmat0, basis1, pmat1, maxl, functional, dfexc, linxpar)
     979             :       TYPE(atom_basis_type), POINTER                     :: basis0
     980             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: pmat0
     981             :       TYPE(atom_basis_type), POINTER                     :: basis1
     982             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: pmat1
     983             :       INTEGER, INTENT(IN)                                :: maxl
     984             :       CHARACTER(LEN=*), INTENT(IN)                       :: functional
     985             :       REAL(KIND=dp), INTENT(OUT)                         :: dfexc
     986             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: linxpar
     987             : 
     988             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'atom_dpot_lda'
     989             :       REAL(KIND=dp), PARAMETER :: alx = 0.20_dp, blx = -0.06_dp, &
     990             :          fs = -0.75_dp*(3._dp/pi)**(1._dp/3._dp)
     991             : 
     992             :       INTEGER                                            :: handle, ir, nr
     993             :       REAL(KIND=dp)                                      :: a, b, fx
     994           3 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: delta, drho0, drho1, pot0, pot1, rho0, &
     995             :                                                             rho1
     996             : 
     997           3 :       CALL timeset(routineN, handle)
     998             : 
     999           3 :       nr = basis0%grid%nr
    1000             : 
    1001          15 :       ALLOCATE (rho0(nr), drho0(nr))
    1002           3 :       CALL atom_density(rho0, pmat0, basis0, maxl, typ="RHO")
    1003           3 :       CALL atom_density(drho0, pmat0, basis0, maxl, typ="DER")
    1004             :       !
    1005          15 :       ALLOCATE (rho1(nr), drho1(nr))
    1006           3 :       CALL atom_density(rho1, pmat1, basis1, maxl, typ="RHO")
    1007             :       ! CONSIDER TO REMOVE [?]: drho1 is calculated but it is not used.
    1008           3 :       CALL atom_density(drho1, pmat1, basis1, maxl, typ="DER")
    1009             :       !
    1010           9 :       ALLOCATE (delta(nr))
    1011           3 :       fx = 4.0_dp/3.0_dp
    1012        1203 :       delta(1:nr) = fs*(rho0(1:nr)**fx - rho1(1:nr)**fx)
    1013             : 
    1014           6 :       SELECT CASE (TRIM(functional))
    1015             :       CASE ("LINX")
    1016           3 :          IF (PRESENT(linxpar)) THEN
    1017           0 :             a = linxpar(1)
    1018           0 :             b = linxpar(2)
    1019             :          ELSE
    1020             :             a = alx
    1021             :             b = blx
    1022             :          END IF
    1023          15 :          ALLOCATE (pot0(nr), pot1(nr))
    1024        1203 :          DO ir = 1, nr
    1025        1203 :             IF (rho0(ir) > 1.e-12_dp) THEN
    1026        1146 :                pot0(ir) = 0.5_dp*drho0(ir)/(3._dp*pi*pi*rho0(ir)**fx)
    1027             :             ELSE
    1028          54 :                pot0(ir) = 0._dp
    1029             :             END IF
    1030             :          END DO
    1031        1203 :          pot1(1:nr) = 1._dp + (a*pot0(1:nr)**2)/(1._dp + b*pot0(1:nr)**2)
    1032        1203 :          pot1(1:nr) = pot1(1:nr)*delta(1:nr)
    1033           3 :          dfexc = fourpi*integrate_grid(pot1(1:nr), basis0%grid)
    1034           3 :          DEALLOCATE (pot0, pot1)
    1035             :       CASE DEFAULT
    1036           3 :          CPABORT("Unknown functional in atom_dpot_lda")
    1037             :       END SELECT
    1038             : 
    1039           3 :       DEALLOCATE (rho0, rho1, drho0, drho1, delta)
    1040             : 
    1041           3 :       CALL timestop(handle)
    1042             : 
    1043           3 :    END SUBROUTINE atom_dpot_lda
    1044             : 
    1045             : ! **************************************************************************************************
    1046             : !> \brief Initialise object that holds components needed to compute the exchange-correlation
    1047             : !>        functional on the atomic radial grid.
    1048             : !> \param rho_set  electron density object to initialise
    1049             : !> \param nspins   number of spin components
    1050             : !> \param needs    components needed to compute the exchange-correlation functional
    1051             : !> \param rho      electron density on the grid
    1052             : !> \param drho     first derivative of the electron density on the grid
    1053             : !> \param tau      kinetic energy density on the grid
    1054             : !> \param lap      second derivative of the electron density on the grid
    1055             : !> \param na       number of points on the atomic radial grid
    1056             : !> \par History
    1057             : !>    * 02.2010 unrestricted KS and HF methods [Juerg Hutter]
    1058             : !>    * 08.2008 created as calculate_atom_vxc_lda() [Juerg Hutter]
    1059             : ! **************************************************************************************************
    1060       20396 :    SUBROUTINE fill_rho_set(rho_set, nspins, needs, rho, drho, tau, lap, na)
    1061             : 
    1062             :       TYPE(xc_rho_set_type), INTENT(INOUT)               :: rho_set
    1063             :       INTEGER, INTENT(IN)                                :: nspins
    1064             :       TYPE(xc_rho_cflags_type), INTENT(in)               :: needs
    1065             :       REAL(dp), DIMENSION(:, :), POINTER                 :: rho, drho, tau, lap
    1066             :       INTEGER, INTENT(IN)                                :: na
    1067             : 
    1068             :       REAL(KIND=dp), PARAMETER                           :: f13 = (1.0_dp/3.0_dp)
    1069             : 
    1070             :       INTEGER                                            :: ia
    1071             : 
    1072       39871 :       SELECT CASE (nspins)
    1073             :       CASE (1)
    1074       19475 :          CPASSERT(.NOT. needs%rho_spin)
    1075       19475 :          CPASSERT(.NOT. needs%drho_spin)
    1076       19475 :          CPASSERT(.NOT. needs%norm_drho_spin)
    1077       19475 :          CPASSERT(.NOT. needs%rho_spin_1_3)
    1078       19475 :          CPASSERT(.NOT. needs%tau_spin)
    1079       19475 :          CPASSERT(.NOT. needs%drho)
    1080             :          ! Give rho to 1/3
    1081       19475 :          IF (needs%rho_1_3) THEN
    1082      354095 :             DO ia = 1, na
    1083      354095 :                rho_set%rho_1_3(ia, 1, 1) = MAX(rho(ia, 1), 0.0_dp)**f13
    1084             :             END DO
    1085         895 :             rho_set%owns%rho_1_3 = .TRUE.
    1086         895 :             rho_set%has%rho_1_3 = .TRUE.
    1087             :          END IF
    1088             :          ! Give the density
    1089       19475 :          IF (needs%rho) THEN
    1090     8178307 :             DO ia = 1, na
    1091     8178307 :                rho_set%rho(ia, 1, 1) = rho(ia, 1)
    1092             :             END DO
    1093       19475 :             rho_set%owns%rho = .TRUE.
    1094       19475 :             rho_set%has%rho = .TRUE.
    1095             :          END IF
    1096             :          ! Give the norm of the gradient of the density
    1097       19475 :          IF (needs%norm_drho) THEN
    1098     7876529 :             DO ia = 1, na
    1099     7876529 :                rho_set%norm_drho(ia, 1, 1) = drho(ia, 1)
    1100             :             END DO
    1101       18729 :             rho_set%owns%norm_drho = .TRUE.
    1102       18729 :             rho_set%has%norm_drho = .TRUE.
    1103             :          END IF
    1104             :       CASE (2)
    1105         921 :          CPASSERT(.NOT. needs%drho)
    1106         921 :          CPASSERT(.NOT. needs%drho_spin)
    1107             :          ! Give the total density
    1108         921 :          IF (needs%rho) THEN
    1109           0 :             DO ia = 1, na
    1110           0 :                rho_set%rho(ia, 1, 1) = rho(ia, 1) + rho(ia, 2)
    1111             :             END DO
    1112           0 :             rho_set%owns%rho = .TRUE.
    1113           0 :             rho_set%has%rho = .TRUE.
    1114             :          END IF
    1115             :          ! Give the norm of the total gradient of the density
    1116         921 :          IF (needs%norm_drho) THEN
    1117      365719 :             DO ia = 1, na
    1118      365719 :                rho_set%norm_drho(ia, 1, 1) = drho(ia, 1) + drho(ia, 2)
    1119             :             END DO
    1120         919 :             rho_set%owns%norm_drho = .TRUE.
    1121         919 :             rho_set%has%norm_drho = .TRUE.
    1122             :          END IF
    1123             :          ! Give rho_spin
    1124         921 :          IF (needs%rho_spin) THEN
    1125      366521 :             DO ia = 1, na
    1126      365600 :                rho_set%rhoa(ia, 1, 1) = rho(ia, 1)
    1127      366521 :                rho_set%rhob(ia, 1, 1) = rho(ia, 2)
    1128             :             END DO
    1129         921 :             rho_set%owns%rho_spin = .TRUE.
    1130         921 :             rho_set%has%rho_spin = .TRUE.
    1131             :          END IF
    1132             :          ! Give rho_spin to 1/3
    1133         921 :          IF (needs%rho_spin_1_3) THEN
    1134      170024 :             DO ia = 1, na
    1135      169600 :                rho_set%rhoa_1_3(ia, 1, 1) = MAX(rho(ia, 1), 0.0_dp)**f13
    1136      170024 :                rho_set%rhob_1_3(ia, 1, 1) = MAX(rho(ia, 2), 0.0_dp)**f13
    1137             :             END DO
    1138         424 :             rho_set%owns%rho_1_3 = .TRUE.
    1139         424 :             rho_set%has%rho_1_3 = .TRUE.
    1140             :          END IF
    1141             :          ! Give the norm of the gradient of rhoa and of rhob separatedly
    1142       21317 :          IF (needs%norm_drho_spin) THEN
    1143      365719 :             DO ia = 1, na
    1144      364800 :                rho_set%norm_drhoa(ia, 1, 1) = drho(ia, 1)
    1145      365719 :                rho_set%norm_drhob(ia, 1, 1) = drho(ia, 2)
    1146             :             END DO
    1147         919 :             rho_set%owns%norm_drho_spin = .TRUE.
    1148         919 :             rho_set%has%norm_drho_spin = .TRUE.
    1149             :          END IF
    1150             :          !
    1151             :       END SELECT
    1152             : 
    1153             :       ! tau part
    1154       20396 :       IF (needs%tau) THEN
    1155         108 :          IF (nspins == 2) THEN
    1156           0 :             DO ia = 1, na
    1157           0 :                rho_set%tau(ia, 1, 1) = tau(ia, 1) + tau(ia, 2)
    1158             :             END DO
    1159           0 :             rho_set%owns%tau = .TRUE.
    1160           0 :             rho_set%has%tau = .TRUE.
    1161             :          ELSE
    1162       43308 :             DO ia = 1, na
    1163       43308 :                rho_set%tau(ia, 1, 1) = tau(ia, 1)
    1164             :             END DO
    1165         108 :             rho_set%owns%tau = .TRUE.
    1166         108 :             rho_set%has%tau = .TRUE.
    1167             :          END IF
    1168             :       END IF
    1169       20396 :       IF (needs%tau_spin) THEN
    1170           2 :          CPASSERT(nspins == 2)
    1171         802 :          DO ia = 1, na
    1172         800 :             rho_set%tau_a(ia, 1, 1) = tau(ia, 1)
    1173         802 :             rho_set%tau_b(ia, 1, 1) = tau(ia, 2)
    1174             :          END DO
    1175           2 :          rho_set%owns%tau_spin = .TRUE.
    1176           2 :          rho_set%has%tau_spin = .TRUE.
    1177             :       END IF
    1178             : 
    1179             :       ! Laplace
    1180       20396 :       IF (needs%laplace_rho) THEN
    1181           0 :          IF (nspins == 2) THEN
    1182           0 :             DO ia = 1, na
    1183           0 :                rho_set%laplace_rho(ia, 1, 1) = lap(ia, 1) + lap(ia, 2)
    1184             :             END DO
    1185           0 :             rho_set%owns%laplace_rho = .TRUE.
    1186           0 :             rho_set%has%laplace_rho = .TRUE.
    1187             :          ELSE
    1188           0 :             DO ia = 1, na
    1189           0 :                rho_set%laplace_rho(ia, 1, 1) = lap(ia, 1)
    1190             :             END DO
    1191           0 :             rho_set%owns%laplace_rho = .TRUE.
    1192           0 :             rho_set%has%laplace_rho = .TRUE.
    1193             :          END IF
    1194             :       END IF
    1195       20396 :       IF (needs%laplace_rho_spin) THEN
    1196           0 :          CPASSERT(nspins == 2)
    1197           0 :          DO ia = 1, na
    1198           0 :             rho_set%laplace_rhoa(ia, 1, 1) = lap(ia, 1)
    1199           0 :             rho_set%laplace_rhob(ia, 1, 1) = lap(ia, 2)
    1200             :          END DO
    1201           0 :          rho_set%owns%laplace_rho_spin = .TRUE.
    1202           0 :          rho_set%has%laplace_rho_spin = .TRUE.
    1203             :       END IF
    1204             : 
    1205       20396 :    END SUBROUTINE fill_rho_set
    1206             : 
    1207             : ! **************************************************************************************************
    1208             : !> \brief Calculate PADE exchange-correlation (xc) energy functional and potential
    1209             : !>        in spin-restricted case.
    1210             : !> \param rho  electron density
    1211             : !> \param exc  XC energy functional
    1212             : !> \param vxc  XC potential
    1213             : !> \par History
    1214             : !>    * 12.2008 created [Juerg Hutter]
    1215             : ! **************************************************************************************************
    1216       34408 :    PURE SUBROUTINE lda_pade(rho, exc, vxc)
    1217             : 
    1218             :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: rho
    1219             :       REAL(dp), DIMENSION(:), INTENT(OUT)                :: exc, vxc
    1220             : 
    1221             :       REAL(KIND=dp), PARAMETER :: a0 = 0.4581652932831429E+0_dp, a1 = 0.2217058676663745E+1_dp, &
    1222             :          a2 = 0.7405551735357053E+0_dp, a3 = 0.1968227878617998E-1_dp, &
    1223             :          b1 = 1.0000000000000000E+0_dp, b2 = 0.4504130959426697E+1_dp, &
    1224             :          b3 = 0.1110667363742916E+1_dp, b4 = 0.2359291751427506E-1_dp, f13 = (1.0_dp/3.0_dp), &
    1225             :          rsfac = 0.6203504908994000166680065_dp
    1226             : 
    1227             :       INTEGER                                            :: i, n
    1228             :       REAL(KIND=dp)                                      :: depade, dpv, dq, epade, p, q, rs
    1229             : 
    1230       34408 :       n = SIZE(rho)
    1231    13803956 :       exc(1:n) = 0._dp
    1232    13803956 :       vxc(1:n) = 0._dp
    1233             : 
    1234    13803956 :       DO i = 1, n
    1235    13803956 :          IF (rho(i) > 1.e-20_dp) THEN
    1236    12567538 :             rs = rsfac*rho(i)**(-f13)
    1237    12567538 :             p = a0 + (a1 + (a2 + a3*rs)*rs)*rs
    1238    12567538 :             q = (b1 + (b2 + (b3 + b4*rs)*rs)*rs)*rs
    1239    12567538 :             epade = -p/q
    1240             : 
    1241    12567538 :             dpv = a1 + (2.0_dp*a2 + 3.0_dp*a3*rs)*rs
    1242    12567538 :             dq = b1 + (2.0_dp*b2 + (3.0_dp*b3 + 4.0_dp*b4*rs)*rs)*rs
    1243    12567538 :             depade = f13*rs*(dpv*q - p*dq)/(q*q)
    1244             : 
    1245    12567538 :             exc(i) = epade*rho(i)
    1246    12567538 :             vxc(i) = epade + depade
    1247             :          END IF
    1248             :       END DO
    1249             : 
    1250       34408 :    END SUBROUTINE lda_pade
    1251             : 
    1252             : ! **************************************************************************************************
    1253             : !> \brief Calculate PADE exchange-correlation (xc) energy functional and potential
    1254             : !>        in spin-polarized case.
    1255             : !> \param rhoa  spin-alpha electron density
    1256             : !> \param rhob  spin-beta electron density
    1257             : !> \param exc   XC energy functional
    1258             : !> \param vxca  spin-alpha XC potential
    1259             : !> \param vxcb  spin-beta XC potential
    1260             : !> \par History
    1261             : !>    * 02.2010 created [Juerg Hutter]
    1262             : ! **************************************************************************************************
    1263         414 :    PURE SUBROUTINE lsd_pade(rhoa, rhob, exc, vxca, vxcb)
    1264             : 
    1265             :       REAL(dp), DIMENSION(:), INTENT(IN)                 :: rhoa, rhob
    1266             :       REAL(dp), DIMENSION(:), INTENT(OUT)                :: exc, vxca, vxcb
    1267             : 
    1268             :       REAL(KIND=dp), PARAMETER :: a0 = 0.4581652932831429E+0_dp, a1 = 0.2217058676663745E+1_dp, &
    1269             :          a2 = 0.7405551735357053E+0_dp, a3 = 0.1968227878617998E-1_dp, &
    1270             :          b1 = 1.0000000000000000E+0_dp, b2 = 0.4504130959426697E+1_dp, &
    1271             :          b3 = 0.1110667363742916E+1_dp, b4 = 0.2359291751427506E-1_dp, &
    1272             :          da0 = 0.119086804055547E+0_dp, da1 = 0.6157402568883345E+0_dp, &
    1273             :          da2 = 0.1574201515892867E+0_dp, da3 = 0.3532336663397157E-2_dp, &
    1274             :          db1 = 0.0000000000000000E+0_dp, db2 = 0.2673612973836267E+0_dp, &
    1275             :          db3 = 0.2052004607777787E+0_dp, db4 = 0.4200005045691381E-2_dp, f13 = (1.0_dp/3.0_dp), &
    1276             :          f43 = (4.0_dp/3.0_dp)
    1277             :       REAL(KIND=dp), PARAMETER :: fxfac = 1.923661050931536319759455_dp, &
    1278             :          rsfac = 0.6203504908994000166680065_dp
    1279             : 
    1280             :       INTEGER                                            :: i, n
    1281             :       REAL(KIND=dp)                                      :: dc, dpv, dq, dr, dx, fa0, fa1, fa2, fa3, &
    1282             :                                                             fb1, fb2, fb3, fb4, fx1, fx2, p, q, &
    1283             :                                                             rhoab, rs, x, xp, xq
    1284             : 
    1285             : ! 1/(2^(4/3) - 2)
    1286             : 
    1287         414 :       n = SIZE(rhoa)
    1288      166014 :       exc(1:n) = 0._dp
    1289      166014 :       vxca(1:n) = 0._dp
    1290      166014 :       vxcb(1:n) = 0._dp
    1291             : 
    1292      166014 :       DO i = 1, n
    1293      165600 :          rhoab = rhoa(i) + rhob(i)
    1294      166014 :          IF (rhoab > 1.e-20_dp) THEN
    1295      149382 :             rs = rsfac*rhoab**(-f13)
    1296             : 
    1297      149382 :             x = (rhoa(i) - rhob(i))/rhoab
    1298      149382 :             IF (x < -1.0_dp) THEN
    1299             :                fx1 = 1.0_dp
    1300             :                fx2 = -f43*fxfac*2.0_dp**f13
    1301      149382 :             ELSE IF (x > 1.0_dp) THEN
    1302             :                fx1 = 1.0_dp
    1303             :                fx2 = f43*fxfac*2.0_dp**f13
    1304             :             ELSE
    1305      149382 :                fx1 = ((1.0_dp + x)**f43 + (1.0_dp - x)**f43 - 2.0_dp)*fxfac
    1306      149382 :                fx2 = ((1.0_dp + x)**f13 - (1.0_dp - x)**f13)*fxfac*f43
    1307             :             END IF
    1308             : 
    1309      149382 :             fa0 = a0 + fx1*da0
    1310      149382 :             fa1 = a1 + fx1*da1
    1311      149382 :             fa2 = a2 + fx1*da2
    1312      149382 :             fa3 = a3 + fx1*da3
    1313      149382 :             fb1 = b1 + fx1*db1
    1314      149382 :             fb2 = b2 + fx1*db2
    1315      149382 :             fb3 = b3 + fx1*db3
    1316      149382 :             fb4 = b4 + fx1*db4
    1317             : 
    1318      149382 :             p = fa0 + (fa1 + (fa2 + fa3*rs)*rs)*rs
    1319      149382 :             q = (fb1 + (fb2 + (fb3 + fb4*rs)*rs)*rs)*rs
    1320      149382 :             dpv = fa1 + (2.0_dp*fa2 + 3.0_dp*fa3*rs)*rs
    1321             :             dq = fb1 + (2.0_dp*fb2 + (3.0_dp*fb3 + &
    1322      149382 :                                       4.0_dp*fb4*rs)*rs)*rs
    1323      149382 :             xp = da0 + (da1 + (da2 + da3*rs)*rs)*rs
    1324      149382 :             xq = (db1 + (db2 + (db3 + db4*rs)*rs)*rs)*rs
    1325             : 
    1326      149382 :             dr = (dpv*q - p*dq)/(q*q)
    1327      149382 :             dx = 2.0_dp*(xp*q - p*xq)/(q*q)*fx2/rhoab
    1328      149382 :             dc = f13*rs*dr - p/q
    1329             : 
    1330      149382 :             exc(i) = -p/q*rhoab
    1331      149382 :             vxca(i) = dc - dx*rhob(i)
    1332      149382 :             vxcb(i) = dc + dx*rhoa(i)
    1333             :          END IF
    1334             :       END DO
    1335             : 
    1336         414 :    END SUBROUTINE lsd_pade
    1337             : 
    1338             : END MODULE atom_xc

Generated by: LCOV version 1.15