LCOV - code coverage report
Current view: top level - src - smearing_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:3db43b4) Lines: 60.8 % 324 197
Test Date: 2026-04-03 06:55:30 Functions: 66.7 % 9 6

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Unified smearing module supporting four methods:
      10              : !>          smear_fermi_dirac  — Fermi-Dirac distribution
      11              : !>          smear_gaussian     — Gaussian broadening
      12              : !>          smear_mp           — Methfessel-Paxton first order
      13              : !>          smear_mv           — Marzari-Vanderbilt (cold smearing)
      14              : !>
      15              : !>        All methods share the bisection framework, LFOMO/HOMO logic, and the
      16              : !>        analytical rank-1 Jacobian.  Only the per-state math (f, kTS, g_i)
      17              : !>        differs, selected via a method integer from input_constants.
      18              : !>
      19              : !> \par History
      20              : !>      09.2008: Created (fermi_utils.F)
      21              : !>      02.2026: Extended to more smearing method and renamed
      22              : !> \author Joost VandeVondele
      23              : ! **************************************************************************************************
      24              : MODULE smearing_utils
      25              : 
      26              :    USE bibliography,                    ONLY: FuHo1983,&
      27              :                                               Marzari1999,&
      28              :                                               Mermin1965,&
      29              :                                               MethfesselPaxton1989,&
      30              :                                               cite_reference,&
      31              :                                               dosSantos2023
      32              :    USE input_constants,                 ONLY: smear_fermi_dirac,&
      33              :                                               smear_gaussian,&
      34              :                                               smear_mp,&
      35              :                                               smear_mv
      36              :    USE kahan_sum,                       ONLY: accurate_sum
      37              :    USE kinds,                           ONLY: dp
      38              :    USE mathconstants,                   ONLY: rootpi,&
      39              :                                               sqrt2,&
      40              :                                               sqrthalf
      41              : #include "base/base_uses.f90"
      42              : 
      43              :    IMPLICIT NONE
      44              : 
      45              :    PRIVATE
      46              : 
      47              :    ! Unified interface (method as parameter)
      48              :    PUBLIC :: SmearOcc, SmearFixed, SmearFixedDeriv, SmearFixedDerivMV
      49              :    PUBLIC :: Smearkp, Smearkp2
      50              :    PRIVATE :: cite_smearing
      51              : 
      52              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'smearing_utils'
      53              :    INTEGER, PARAMETER, PRIVATE                           :: BISECT_MAX_ITER = 400
      54              :    INTEGER, PARAMETER, PRIVATE                           :: NEWTON_MAX_ITER = 50
      55              : 
      56              : CONTAINS
      57              : ! **************************************************************************************************
      58              : !> \brief   Citation of Smearing methods
      59              : !> \param method ...
      60              : ! **************************************************************************************************
      61        25462 :    SUBROUTINE cite_smearing(method)
      62              :       INTEGER, INTENT(IN)                                :: method
      63              : 
      64        44440 :       SELECT CASE (method)
      65              :       CASE (smear_fermi_dirac)
      66        18978 :          CALL cite_reference(Mermin1965)
      67              :       CASE (smear_gaussian)
      68         6428 :          CALL cite_reference(FuHo1983)
      69              :       CASE (smear_mp)
      70           28 :          CALL cite_reference(FuHo1983)
      71           28 :          CALL cite_reference(MethfesselPaxton1989)
      72           28 :          CALL cite_reference(dosSantos2023)
      73              :       CASE (smear_mv)
      74           28 :          CALL cite_reference(FuHo1983)
      75           28 :          CALL cite_reference(Marzari1999)
      76        25490 :          CALL cite_reference(dosSantos2023)
      77              :       END SELECT
      78        25462 :    END SUBROUTINE cite_smearing
      79              : 
      80              : ! **************************************************************************************************
      81              : !> \brief   Returns occupations and smearing correction for a given set of
      82              : !>          energies and chemical potential, using one of four smearing methods.
      83              : !>
      84              : !>          Fermi-Dirac:  f_i = occ / [1 + exp((e_i - mu)/sigma)]
      85              : !>          Gaussian:     f_i = (occ/2) * erfc[(e_i - mu)/sigma]
      86              : !>          MP-1:         f_i = (occ/2) * erfc(x) - occ*x/(2*sqrt(pi)) * exp(-x^2)
      87              : !>          MV:           f_i = (occ/2) * erfc(u) + occ/(sqrt(2*pi)) * exp(-u^2),  u = x + 1/sqrt(2)
      88              : !>
      89              : !>          kTS is the smearing correction to the free energy (physically -TS
      90              : !>          for Fermi-Dirac; a variational correction term for the other methods).
      91              : !>          It enters the total energy and the Gillan extrapolation E(0) = E - kTS/2.
      92              : !>
      93              : !> \param f       occupations (output)
      94              : !> \param N       total number of electrons (output)
      95              : !> \param kTS     smearing correction to the free energy (output)
      96              : !> \param e       eigenvalues (input)
      97              : !> \param mu      chemical potential (input)
      98              : !> \param sigma   smearing width: kT for Fermi-Dirac, sigma for others (input)
      99              : !> \param maxocc  maximum occupation of an orbital (input)
     100              : !> \param method  smearing method selector from input_constants (input)
     101              : !> \param estate  excited state index for core-level spectroscopy (optional)
     102              : !> \param festate occupation of the excited state (optional)
     103              : ! **************************************************************************************************
     104      1112896 :    SUBROUTINE SmearOcc(f, N, kTS, e, mu, sigma, maxocc, method, estate, festate)
     105              : 
     106              :       REAL(KIND=dp), INTENT(OUT)                         :: f(:), N, kTS
     107              :       REAL(KIND=dp), INTENT(IN)                          :: e(:), mu, sigma, maxocc
     108              :       INTEGER, INTENT(IN)                                :: method
     109              :       INTEGER, INTENT(IN), OPTIONAL                      :: estate
     110              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: festate
     111              : 
     112              :       INTEGER                                            :: i, Nstate
     113              :       REAL(KIND=dp)                                      :: arg, expu2, expx2, occupation, term1, &
     114              :                                                             term2, tmp, tmp2, tmp3, tmp4, tmplog, &
     115              :                                                             u, x
     116              : 
     117      1112896 :       Nstate = SIZE(e)
     118      1112896 :       kTS = 0.0_dp
     119              : 
     120     22861324 :       DO i = 1, Nstate
     121     21748428 :          IF (PRESENT(estate) .AND. PRESENT(festate)) THEN
     122     21714364 :             IF (i == estate) THEN
     123         4012 :                occupation = festate
     124              :             ELSE
     125     21710352 :                occupation = maxocc
     126              :             END IF
     127              :          ELSE
     128        34064 :             occupation = maxocc
     129              :          END IF
     130              : 
     131      1112896 :          SELECT CASE (method)
     132              :          CASE (smear_fermi_dirac)
     133     19506100 :             IF (e(i) > mu) THEN
     134     11236829 :                arg = -(e(i) - mu)/sigma
     135     11236829 :                tmp = EXP(arg)
     136     11236829 :                tmp4 = tmp + 1.0_dp
     137     11236829 :                tmp2 = tmp/tmp4
     138     11236829 :                tmp3 = 1.0_dp/tmp4
     139     11236829 :                tmplog = -LOG(tmp4)
     140     11236829 :                term1 = tmp2*(arg + tmplog)
     141     11236829 :                term2 = tmp3*tmplog
     142              :             ELSE
     143      8269271 :                arg = (e(i) - mu)/sigma
     144      8269271 :                tmp = EXP(arg)
     145      8269271 :                tmp4 = tmp + 1.0_dp
     146      8269271 :                tmp2 = 1.0_dp/tmp4
     147      8269271 :                tmp3 = tmp/tmp4
     148      8269271 :                tmplog = -LOG(tmp4)
     149      8269271 :                term1 = tmp2*tmplog
     150      8269271 :                term2 = tmp3*(arg + tmplog)
     151              :             END IF
     152     19506100 :             f(i) = occupation*tmp2
     153     19506100 :             kTS = kTS + sigma*occupation*(term1 + term2)
     154              : 
     155              :          CASE (smear_gaussian)
     156      2242328 :             x = (e(i) - mu)/sigma
     157      2242328 :             expx2 = EXP(-x*x)
     158      2242328 :             f(i) = occupation*0.5_dp*ERFC(x)
     159      2242328 :             kTS = kTS - (sigma/(2.0_dp*rootpi))*occupation*expx2
     160              : 
     161              :          CASE (smear_mp)
     162            0 :             x = (e(i) - mu)/sigma
     163            0 :             expx2 = EXP(-x*x)
     164            0 :             f(i) = occupation*(0.5_dp*ERFC(x) - x/(2.0_dp*rootpi)*expx2)
     165            0 :             kTS = kTS + (sigma/(4.0_dp*rootpi))*occupation*(2.0_dp*x*x - 1.0_dp)*expx2
     166              : 
     167              :          CASE (smear_mv)
     168            0 :             x = (e(i) - mu)/sigma
     169            0 :             u = x + sqrthalf
     170            0 :             expu2 = EXP(-u*u)
     171            0 :             f(i) = occupation*(0.5_dp*ERFC(u) + expu2/(sqrt2*rootpi))
     172            0 :             kTS = kTS - (sigma/(sqrt2*rootpi))*occupation*u*expu2
     173              : 
     174              :          CASE DEFAULT
     175     21748428 :             CPABORT("SmearOcc: unknown smearing method")
     176              :          END SELECT
     177              :       END DO
     178              : 
     179      1112896 :       N = accurate_sum(f)
     180              : 
     181      1112896 :    END SUBROUTINE SmearOcc
     182              : 
     183              : ! **************************************************************************************************
     184              : !> \brief   k-point version of SmearOcc (module-private).
     185              : !>          Computes occupations and kTS for a 2D array of eigenvalues
     186              : !>          (nmo x nkp) weighted by k-point weights.
     187              : !>          Falls back to a step function when sigma < 1e-14.
     188              : !>
     189              : !> \param f       occupations (nmo x nkp, output)
     190              : !> \param nel     total number of electrons (output)
     191              : !> \param kTS     smearing correction (output)
     192              : !> \param e       eigenvalues (nmo x nkp, input)
     193              : !> \param mu      chemical potential (input)
     194              : !> \param wk      k-point weights (input)
     195              : !> \param sigma   smearing width (input)
     196              : !> \param maxocc  maximum occupation (input)
     197              : !> \param method  smearing method selector (input)
     198              : ! **************************************************************************************************
     199        44342 :    SUBROUTINE Smear2(f, nel, kTS, e, mu, wk, sigma, maxocc, method)
     200              : 
     201              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: f
     202              :       REAL(KIND=dp), INTENT(OUT)                         :: nel, kTS
     203              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: e
     204              :       REAL(KIND=dp), INTENT(IN)                          :: mu
     205              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: wk
     206              :       REAL(KIND=dp), INTENT(IN)                          :: sigma, maxocc
     207              :       INTEGER, INTENT(IN)                                :: method
     208              : 
     209              :       INTEGER                                            :: ik, is, nkp, nmo
     210              :       REAL(KIND=dp)                                      :: arg, expu2, expx2, term1, term2, tmp, &
     211              :                                                             tmp2, tmp3, tmp4, tmplog, u, x
     212              : 
     213        44342 :       nmo = SIZE(e, 1)
     214        44342 :       nkp = SIZE(e, 2)
     215        44342 :       kTS = 0.0_dp
     216              : 
     217        44342 :       IF (sigma > 1.0e-14_dp) THEN
     218       295888 :          DO ik = 1, nkp
     219     10189684 :             DO is = 1, nmo
     220       267112 :                SELECT CASE (method)
     221              :                CASE (smear_fermi_dirac)
     222      8939920 :                   IF (e(is, ik) > mu) THEN
     223      4912626 :                      arg = -(e(is, ik) - mu)/sigma
     224      4912626 :                      tmp = EXP(arg)
     225      4912626 :                      tmp4 = tmp + 1.0_dp
     226      4912626 :                      tmp2 = tmp/tmp4
     227      4912626 :                      tmp3 = 1.0_dp/tmp4
     228      4912626 :                      tmplog = -LOG(tmp4)
     229      4912626 :                      term1 = tmp2*(arg + tmplog)
     230      4912626 :                      term2 = tmp3*tmplog
     231              :                   ELSE
     232      4027294 :                      arg = (e(is, ik) - mu)/sigma
     233      4027294 :                      tmp = EXP(arg)
     234      4027294 :                      tmp4 = tmp + 1.0_dp
     235      4027294 :                      tmp2 = 1.0_dp/tmp4
     236      4027294 :                      tmp3 = tmp/tmp4
     237      4027294 :                      tmplog = -LOG(tmp4)
     238      4027294 :                      term1 = tmp2*tmplog
     239      4027294 :                      term2 = tmp3*(arg + tmplog)
     240              :                   END IF
     241      8939920 :                   f(is, ik) = maxocc*tmp2
     242      8939920 :                   kTS = kTS + sigma*maxocc*(term1 + term2)*wk(ik)
     243              : 
     244              :                CASE (smear_gaussian)
     245       855316 :                   x = (e(is, ik) - mu)/sigma
     246       855316 :                   expx2 = EXP(-x*x)
     247       855316 :                   f(is, ik) = maxocc*0.5_dp*ERFC(x)
     248       855316 :                   kTS = kTS - (sigma/(2.0_dp*rootpi))*maxocc*expx2*wk(ik)
     249              : 
     250              :                CASE (smear_mp)
     251        44800 :                   x = (e(is, ik) - mu)/sigma
     252        44800 :                   expx2 = EXP(-x*x)
     253        44800 :                   f(is, ik) = maxocc*(0.5_dp*ERFC(x) - x/(2.0_dp*rootpi)*expx2)
     254        44800 :                   kTS = kTS + (sigma/(4.0_dp*rootpi))*maxocc*(2.0_dp*x*x - 1.0_dp)*expx2*wk(ik)
     255              : 
     256              :                CASE (smear_mv)
     257        53760 :                   x = (e(is, ik) - mu)/sigma
     258        53760 :                   u = x + sqrthalf
     259        53760 :                   expu2 = EXP(-u*u)
     260        53760 :                   f(is, ik) = maxocc*(0.5_dp*ERFC(u) + expu2/(sqrt2*rootpi))
     261        53760 :                   kTS = kTS - (sigma/(sqrt2*rootpi))*maxocc*u*expu2*wk(ik)
     262              : 
     263              :                CASE DEFAULT
     264      9893796 :                   CPABORT("Smear2: unknown smearing method")
     265              :                END SELECT
     266              :             END DO
     267              :          END DO
     268              :       ELSE
     269              :          ! Zero-width limit: step function
     270        80530 :          DO ik = 1, nkp
     271       689150 :             DO is = 1, nmo
     272       673584 :                IF (e(is, ik) <= mu) THEN
     273       351784 :                   f(is, ik) = maxocc
     274              :                ELSE
     275       256836 :                   f(is, ik) = 0.0_dp
     276              :                END IF
     277              :             END DO
     278              :          END DO
     279              :       END IF
     280              : 
     281        44342 :       nel = 0.0_dp
     282       376418 :       DO ik = 1, nkp
     283       376418 :          nel = nel + accurate_sum(f(1:nmo, ik))*wk(ik)
     284              :       END DO
     285              : 
     286        44342 :    END SUBROUTINE Smear2
     287              : 
     288              : ! **************************************************************************************************
     289              : !> \brief   Bisection search for the chemical potential mu such that the total
     290              : !>          electron count equals N, for a given smearing method (Gamma point).
     291              : !>          Brackets mu by expanding outward from [min(e), max(e)] in steps
     292              : !>          of sigma, then bisects to machine precision.
     293              : !>
     294              : !>          For MP-1 and MV: the occupation function is non-monotonic, so it's
     295              : !>          possible that pure bisection find a spurious root.
     296              : !>          We first bisect with Gaussian smearing to get a reliable initial mu,
     297              : !>          then refine with Newton's method using the actual method's dN/dmu.
     298              : !>          (dos Santos & Marzari, PRB 2023)
     299              : !>
     300              : !> \param f       occupations (output)
     301              : !> \param mu      chemical potential found by bisection (output)
     302              : !> \param kTS     smearing correction (output)
     303              : !> \param e       eigenvalues (input)
     304              : !> \param N       target number of electrons (input)
     305              : !> \param sigma   smearing width (input)
     306              : !> \param maxocc  maximum occupation (input)
     307              : !> \param method  smearing method selector (input)
     308              : !> \param estate  excited state index for core-level spectroscopy (optional)
     309              : !> \param festate occupation of the excited state (optional)
     310              : ! **************************************************************************************************
     311        19808 :    SUBROUTINE SmearFixed(f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
     312              : 
     313              :       REAL(KIND=dp), INTENT(OUT)                         :: f(:), mu, kTS
     314              :       REAL(KIND=dp), INTENT(IN)                          :: e(:), N, sigma, maxocc
     315              :       INTEGER, INTENT(IN)                                :: method
     316              :       INTEGER, INTENT(IN), OPTIONAL                      :: estate
     317              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: festate
     318              : 
     319              :       INTEGER                                            :: iter, my_estate, Nstate
     320              :       REAL(KIND=dp)                                      :: Gsum, mu_max, mu_min, mu_now, &
     321              :                                                             my_festate, N_now, N_tmp
     322        19808 :       REAL(KIND=dp), ALLOCATABLE                         :: gvec(:)
     323              : 
     324        19808 :       IF (PRESENT(estate) .AND. PRESENT(festate)) THEN
     325        19768 :          my_estate = estate
     326        19768 :          my_festate = festate
     327              :       ELSE
     328           40 :          my_estate = NINT(maxocc)
     329           40 :          my_festate = my_estate
     330              :       END IF
     331              : 
     332        19808 :       Nstate = SIZE(e)
     333              : 
     334        19808 :       CALL cite_smearing(method)
     335              : 
     336        19808 :       SELECT CASE (method)
     337              : 
     338              :          ! Non-monotonic methods: Gaussian bisection + Newton refinement
     339              :       CASE (smear_mp, smear_mv)
     340              :          ! Step 1: Gaussian bisection for a reliable initial mu
     341            0 :          mu_min = MINVAL(e)
     342            0 :          iter = 0
     343            0 :          DO
     344            0 :             iter = iter + 1
     345            0 :             CALL SmearOcc(f, N_tmp, kTS, e, mu_min, sigma, maxocc, smear_gaussian, my_estate, my_festate)
     346            0 :             IF (N_tmp > N .OR. iter > 20) THEN
     347            0 :                mu_min = mu_min - sigma
     348              :             ELSE
     349              :                EXIT
     350              :             END IF
     351              :          END DO
     352              : 
     353            0 :          mu_max = MAXVAL(e)
     354            0 :          iter = 0
     355            0 :          DO
     356            0 :             iter = iter + 1
     357            0 :             CALL SmearOcc(f, N_tmp, kTS, e, mu_max, sigma, maxocc, smear_gaussian, my_estate, my_festate)
     358            0 :             IF (N_tmp < N .OR. iter > 20) THEN
     359            0 :                mu_max = mu_max + sigma
     360              :             ELSE
     361              :                EXIT
     362              :             END IF
     363              :          END DO
     364              : 
     365              :          iter = 0
     366            0 :          DO WHILE (mu_max - mu_min > EPSILON(mu)*MAX(1.0_dp, ABS(mu_max), ABS(mu_min)))
     367            0 :             iter = iter + 1
     368            0 :             mu_now = (mu_max + mu_min)/2.0_dp
     369            0 :             CALL SmearOcc(f, N_now, kTS, e, mu_now, sigma, maxocc, smear_gaussian, my_estate, my_festate)
     370            0 :             IF (N_now <= N) THEN
     371            0 :                mu_min = mu_now
     372              :             ELSE
     373            0 :                mu_max = mu_now
     374              :             END IF
     375            0 :             IF (iter > BISECT_MAX_ITER) EXIT
     376              :          END DO
     377            0 :          mu = (mu_max + mu_min)/2.0_dp
     378              : 
     379              :          ! Step 2: Newton refinement with the actual method
     380            0 :          ALLOCATE (gvec(Nstate))
     381            0 :          DO iter = 1, NEWTON_MAX_ITER
     382            0 :             CALL SmearOcc(f, N_now, kTS, e, mu, sigma, maxocc, method, my_estate, my_festate)
     383            0 :             IF (ABS(N_now - N) < N*1.0e-12_dp) EXIT
     384            0 :             CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, Nstate, method, my_estate, my_festate)
     385            0 :             Gsum = accurate_sum(gvec)
     386            0 :             IF (ABS(Gsum) < EPSILON(Gsum)) EXIT
     387            0 :             mu = mu + (N - N_now)/Gsum
     388              :          END DO
     389            0 :          DEALLOCATE (gvec)
     390              : 
     391              :          ! Final evaluation
     392            0 :          CALL SmearOcc(f, N_now, kTS, e, mu, sigma, maxocc, method, my_estate, my_festate)
     393              : 
     394              :          ! Monotonic methods (FD, Gaussian): pure bisection
     395              :       CASE DEFAULT
     396       424918 :          mu_min = MINVAL(e)
     397        19808 :          iter = 0
     398            0 :          DO
     399        19808 :             iter = iter + 1
     400        19808 :             CALL SmearOcc(f, N_tmp, kTS, e, mu_min, sigma, maxocc, method, my_estate, my_festate)
     401        19808 :             IF (N_tmp > N .OR. iter > 20) THEN
     402            0 :                mu_min = mu_min - sigma
     403              :             ELSE
     404              :                EXIT
     405              :             END IF
     406              :          END DO
     407              : 
     408       424918 :          mu_max = MAXVAL(e)
     409        19808 :          iter = 0
     410            0 :          DO
     411        19808 :             iter = iter + 1
     412        19808 :             CALL SmearOcc(f, N_tmp, kTS, e, mu_max, sigma, maxocc, method, my_estate, my_festate)
     413        19808 :             IF (N_tmp < N .OR. iter > 20) THEN
     414            0 :                mu_max = mu_max + sigma
     415              :             ELSE
     416              :                EXIT
     417              :             END IF
     418              :          END DO
     419              : 
     420              :          iter = 0
     421      1072904 :          DO WHILE (mu_max - mu_min > EPSILON(mu)*MAX(1.0_dp, ABS(mu_max), ABS(mu_min)))
     422      1053096 :             iter = iter + 1
     423      1053096 :             mu_now = (mu_max + mu_min)/2.0_dp
     424      1053096 :             CALL SmearOcc(f, N_now, kTS, e, mu_now, sigma, maxocc, method, my_estate, my_festate)
     425      1053096 :             IF (N_now <= N) THEN
     426       516751 :                mu_min = mu_now
     427              :             ELSE
     428       536345 :                mu_max = mu_now
     429              :             END IF
     430      1072904 :             IF (iter > BISECT_MAX_ITER) THEN
     431            0 :                CPWARN("SmearFixed: maximum bisection iterations reached")
     432            0 :                EXIT
     433              :             END IF
     434              :          END DO
     435              : 
     436        19808 :          mu = (mu_max + mu_min)/2.0_dp
     437        39616 :          CALL SmearOcc(f, N_now, kTS, e, mu, sigma, maxocc, method, my_estate, my_festate)
     438              : 
     439              :       END SELECT
     440              : 
     441        19808 :    END SUBROUTINE SmearFixed
     442              : 
     443              : ! **************************************************************************************************
     444              : !> \brief   Bisection search for mu given a target electron count (k-point case,
     445              : !>          single spin channel or spin-degenerate).
     446              : !>          Initial bracket width is max(10*sigma, 0.5) for Gaussian/MP/MV,
     447              : !>          or sigma*ln[(1-eps)/eps] for Fermi-Dirac, reflecting the different
     448              : !>          tail decay rates.
     449              : !>
     450              : !>          For MP-1 and MV: Gaussian bisection + Newton refinement
     451              : !>          (dos Santos & Marzari, PRB 2023).
     452              : !>
     453              : !> \param f       occupations (nmo x nkp, output)
     454              : !> \param mu      chemical potential (output)
     455              : !> \param kTS     smearing correction (output)
     456              : !> \param e       eigenvalues (nmo x nkp, input)
     457              : !> \param nel     target number of electrons (input)
     458              : !> \param wk      k-point weights (input)
     459              : !> \param sigma   smearing width (input)
     460              : !> \param maxocc  maximum occupation (input)
     461              : !> \param method  smearing method selector (input)
     462              : ! **************************************************************************************************
     463         5626 :    SUBROUTINE Smearkp(f, mu, kTS, e, nel, wk, sigma, maxocc, method)
     464              : 
     465              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: f
     466              :       REAL(KIND=dp), INTENT(OUT)                         :: mu, kTS
     467              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: e
     468              :       REAL(KIND=dp), INTENT(IN)                          :: nel
     469              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: wk
     470              :       REAL(KIND=dp), INTENT(IN)                          :: sigma, maxocc
     471              :       INTEGER, INTENT(IN)                                :: method
     472              : 
     473              :       REAL(KIND=dp), PARAMETER                           :: epsocc = 1.0e-12_dp
     474              : 
     475              :       INTEGER                                            :: bisect_method, ik, is, iter, nkp, nmo
     476              :       REAL(KIND=dp)                                      :: de, dNdmu, expu2, expx2, mu_max, mu_min, &
     477              :                                                             N_now, u, x
     478              : 
     479         5626 :       nmo = SIZE(e, 1)
     480         5626 :       nkp = SIZE(e, 2)
     481              : 
     482         5626 :       CALL cite_smearing(method)
     483              : 
     484              :       ! Choose bisection method: Gaussian for MP/MV, actual method for FD/Gaussian
     485         5682 :       SELECT CASE (method)
     486              :       CASE (smear_mp, smear_mv)
     487           56 :          bisect_method = smear_gaussian
     488              :       CASE DEFAULT
     489         5626 :          bisect_method = method
     490              :       END SELECT
     491              : 
     492              :       ! Initial bracket
     493          696 :       SELECT CASE (bisect_method)
     494              :       CASE (smear_fermi_dirac)
     495          696 :          de = sigma*LOG((1.0_dp - epsocc)/epsocc)
     496              :       CASE DEFAULT
     497         5626 :          de = 10.0_dp*sigma
     498              :       END SELECT
     499         5626 :       de = MAX(de, 0.5_dp)
     500              : 
     501              :       ! Bisection with bisect_method
     502       493066 :       mu_min = MINVAL(e) - de
     503       493066 :       mu_max = MAXVAL(e) + de
     504         5626 :       iter = 0
     505        36668 :       DO WHILE (mu_max - mu_min > EPSILON(mu)*MAX(1.0_dp, ABS(mu_max), ABS(mu_min)))
     506        36668 :          iter = iter + 1
     507        36668 :          mu = (mu_max + mu_min)/2.0_dp
     508        36668 :          CALL Smear2(f, N_now, kTS, e, mu, wk, sigma, maxocc, bisect_method)
     509              : 
     510        36668 :          IF (ABS(N_now - nel) < nel*epsocc) EXIT
     511              : 
     512        31042 :          IF (N_now <= nel) THEN
     513        16914 :             mu_min = mu
     514              :          ELSE
     515        14128 :             mu_max = mu
     516              :          END IF
     517              : 
     518        36668 :          IF (iter > BISECT_MAX_ITER) THEN
     519            0 :             CPWARN("Smearkp: maximum bisection iterations reached")
     520            0 :             EXIT
     521              :          END IF
     522              :       END DO
     523         5626 :       mu = (mu_max + mu_min)/2.0_dp
     524              : 
     525              :       ! Newton refinement for non-monotonic methods
     526              :       SELECT CASE (method)
     527              :       CASE (smear_mp, smear_mv)
     528         5822 :          DO iter = 1, NEWTON_MAX_ITER
     529          252 :             CALL Smear2(f, N_now, kTS, e, mu, wk, sigma, maxocc, method)
     530          252 :             IF (ABS(N_now - nel) < nel*epsocc) EXIT
     531              : 
     532              :             ! Compute dN/dmu = sum_{ik} wk * g_i(k)  inline
     533              :             dNdmu = 0.0_dp
     534         6468 :             DO ik = 1, nkp
     535        69188 :                DO is = 1, nmo
     536        62720 :                   x = (e(is, ik) - mu)/sigma
     537         6272 :                   SELECT CASE (method)
     538              :                   CASE (smear_mp)
     539        26880 :                      expx2 = EXP(-x*x)
     540        26880 :                      dNdmu = dNdmu + maxocc*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*rootpi)*expx2*wk(ik)
     541              :                   CASE (smear_mv)
     542        35840 :                      u = x + sqrthalf
     543        35840 :                      expu2 = EXP(-u*u)
     544        62720 :                      dNdmu = dNdmu + maxocc*(2.0_dp + sqrt2*x)/(sigma*rootpi)*expu2*wk(ik)
     545              :                   END SELECT
     546              :                END DO
     547              :             END DO
     548              : 
     549          196 :             IF (ABS(dNdmu) < EPSILON(dNdmu)) EXIT
     550          252 :             mu = mu + (nel - N_now)/dNdmu
     551              :          END DO
     552              :       END SELECT
     553              : 
     554              :       ! Final evaluation with the actual method
     555         5626 :       CALL Smear2(f, N_now, kTS, e, mu, wk, sigma, maxocc, method)
     556              : 
     557         5626 :    END SUBROUTINE Smearkp
     558              : 
     559              : ! **************************************************************************************************
     560              : !> \brief   Bisection search for mu (k-point, spin-polarised with a shared
     561              : !>          chemical potential across both spin channels).
     562              : !>          Asserts that the third dimension of f and e is exactly 2.
     563              : !>
     564              : !>          For MP-1 and MV: Gaussian bisection + Newton refinement.
     565              : !>
     566              : !> \param f       occupations (nmo x nkp x 2, output)
     567              : !> \param mu      chemical potential (output)
     568              : !> \param kTS     smearing correction (output)
     569              : !> \param e       eigenvalues (nmo x nkp x 2, input)
     570              : !> \param nel     target total number of electrons (input)
     571              : !> \param wk      k-point weights (input)
     572              : !> \param sigma   smearing width (input)
     573              : !> \param method  smearing method selector (input)
     574              : ! **************************************************************************************************
     575           28 :    SUBROUTINE Smearkp2(f, mu, kTS, e, nel, wk, sigma, method)
     576              : 
     577              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: f
     578              :       REAL(KIND=dp), INTENT(OUT)                         :: mu, kTS
     579              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: e
     580              :       REAL(KIND=dp), INTENT(IN)                          :: nel
     581              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: wk
     582              :       REAL(KIND=dp), INTENT(IN)                          :: sigma
     583              :       INTEGER, INTENT(IN)                                :: method
     584              : 
     585              :       REAL(KIND=dp), PARAMETER                           :: epsocc = 1.0e-12_dp
     586              : 
     587              :       INTEGER                                            :: bisect_method, ik, is, ispin, iter, nkp, &
     588              :                                                             nmo
     589              :       REAL(KIND=dp)                                      :: de, dNdmu, expu2, expx2, kTSa, kTSb, &
     590              :                                                             mu_max, mu_min, N_now, na, nb, u, x
     591              : 
     592           28 :       CPASSERT(SIZE(f, 3) == 2 .AND. SIZE(e, 3) == 2)
     593              : 
     594           28 :       nmo = SIZE(e, 1)
     595           28 :       nkp = SIZE(e, 2)
     596              : 
     597           28 :       CALL cite_smearing(method)
     598              : 
     599           28 :       SELECT CASE (method)
     600              :       CASE (smear_mp, smear_mv)
     601            0 :          bisect_method = smear_gaussian
     602              :       CASE DEFAULT
     603           28 :          bisect_method = method
     604              :       END SELECT
     605              : 
     606            0 :       SELECT CASE (bisect_method)
     607              :       CASE (smear_fermi_dirac)
     608            0 :          de = sigma*LOG((1.0_dp - epsocc)/epsocc)
     609              :       CASE DEFAULT
     610           28 :          de = 10.0_dp*sigma
     611              :       END SELECT
     612           28 :       de = MAX(de, 0.5_dp)
     613              : 
     614              :       ! Bisection with bisect_method
     615         1740 :       mu_min = MINVAL(e) - de
     616         1740 :       mu_max = MAXVAL(e) + de
     617           28 :       iter = 0
     618          870 :       DO WHILE (mu_max - mu_min > EPSILON(mu)*MAX(1.0_dp, ABS(mu_max), ABS(mu_min)))
     619          870 :          iter = iter + 1
     620          870 :          mu = (mu_max + mu_min)/2.0_dp
     621          870 :          CALL Smear2(f(:, :, 1), na, kTSa, e(:, :, 1), mu, wk, sigma, 1.0_dp, bisect_method)
     622          870 :          CALL Smear2(f(:, :, 2), nb, kTSb, e(:, :, 2), mu, wk, sigma, 1.0_dp, bisect_method)
     623          870 :          N_now = na + nb
     624              : 
     625          870 :          IF (ABS(N_now - nel) < nel*epsocc) EXIT
     626              : 
     627          842 :          IF (N_now <= nel) THEN
     628          380 :             mu_min = mu
     629              :          ELSE
     630          462 :             mu_max = mu
     631              :          END IF
     632              : 
     633          870 :          IF (iter > BISECT_MAX_ITER) THEN
     634            0 :             CPWARN("Smearkp2: maximum bisection iterations reached")
     635            0 :             EXIT
     636              :          END IF
     637              :       END DO
     638           28 :       mu = (mu_max + mu_min)/2.0_dp
     639              : 
     640              :       ! Newton refinement for non-monotonic methods
     641              :       SELECT CASE (method)
     642              :       CASE (smear_mp, smear_mv)
     643           28 :          DO iter = 1, NEWTON_MAX_ITER
     644            0 :             CALL Smear2(f(:, :, 1), na, kTSa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
     645            0 :             CALL Smear2(f(:, :, 2), nb, kTSb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
     646            0 :             N_now = na + nb
     647            0 :             IF (ABS(N_now - nel) < nel*epsocc) EXIT
     648              : 
     649              :             ! dN/dmu across both spin channels (maxocc=1 per spin)
     650              :             dNdmu = 0.0_dp
     651            0 :             DO ispin = 1, 2
     652            0 :                DO ik = 1, nkp
     653            0 :                   DO is = 1, nmo
     654            0 :                      x = (e(is, ik, ispin) - mu)/sigma
     655            0 :                      SELECT CASE (method)
     656              :                      CASE (smear_mp)
     657            0 :                         expx2 = EXP(-x*x)
     658            0 :                         dNdmu = dNdmu + (3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*rootpi)*expx2*wk(ik)
     659              :                      CASE (smear_mv)
     660            0 :                         u = x + sqrthalf
     661            0 :                         expu2 = EXP(-u*u)
     662            0 :                         dNdmu = dNdmu + (2.0_dp + sqrt2*x)/(sigma*rootpi)*expu2*wk(ik)
     663              :                      END SELECT
     664              :                   END DO
     665              :                END DO
     666              :             END DO
     667              : 
     668            0 :             IF (ABS(dNdmu) < EPSILON(dNdmu)) EXIT
     669            0 :             mu = mu + (nel - N_now)/dNdmu
     670              :          END DO
     671              :       END SELECT
     672              : 
     673              :       ! Final evaluation with the actual method
     674           28 :       CALL Smear2(f(:, :, 1), na, kTSa, e(:, :, 1), mu, wk, sigma, 1.0_dp, method)
     675           28 :       CALL Smear2(f(:, :, 2), nb, kTSb, e(:, :, 2), mu, wk, sigma, 1.0_dp, method)
     676           28 :       kTS = kTSa + kTSb
     677              : 
     678           28 :    END SUBROUTINE Smearkp2
     679              : 
     680              : ! **************************************************************************************************
     681              : !> \brief   Computes the smearing weight vector g_i = -df_i/de_i with mu held
     682              : !>          fixed (module-private helper for the analytical Jacobian routines).
     683              : !>
     684              : !>          Fermi-Dirac:  g_i = occ * f_norm * (1 - f_norm) / sigma
     685              : !>                        where f_norm = f_i/occ_i  (overflow-safe, uses
     686              : !>                        pre-computed f rather than re-evaluating exp)
     687              : !>          Gaussian:     g_i = occ / (sigma*sqrt(pi)) * exp(-x^2)
     688              : !>          MP-1:         g_i = occ * (3 - 2*x^2) / (2*sigma*sqrt(pi)) * exp(-x^2)
     689              : !>          MV:           g_i = occ * (2 + sqrt(2)*x) / (sigma*sqrt(pi)) * exp(-u^2)
     690              : !>
     691              : !>          Note: g_i can be negative for MP-1 (|x| > sqrt(3/2)) and MV
     692              : !>          (x < -sqrt(2)).  This does not break bisection (N(mu) is still
     693              : !>          monotone) but the Jacobian routines must guard against G = sum(g_i)
     694              : !>          being near zero.
     695              : !>
     696              : !> \param gvec    weight vector (Nstate, output)
     697              : !> \param f       occupations from a prior SmearOcc/SmearFixed call (input)
     698              : !> \param e       eigenvalues (input)
     699              : !> \param mu      chemical potential (input)
     700              : !> \param sigma   smearing width (input)
     701              : !> \param maxocc  maximum occupation (input)
     702              : !> \param Nstate  number of states (input)
     703              : !> \param method  smearing method selector (input)
     704              : !> \param estate  excited state index (optional)
     705              : !> \param festate occupation of the excited state (optional)
     706              : ! **************************************************************************************************
     707            0 :    SUBROUTINE compute_gvec(gvec, f, e, mu, sigma, maxocc, Nstate, method, estate, festate)
     708              : 
     709              :       REAL(KIND=dp), INTENT(OUT)                         :: gvec(:)
     710              :       REAL(KIND=dp), INTENT(IN)                          :: f(:), e(:), mu, sigma, maxocc
     711              :       INTEGER, INTENT(IN)                                :: Nstate, method
     712              :       INTEGER, INTENT(IN), OPTIONAL                      :: estate
     713              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: festate
     714              : 
     715              :       INTEGER                                            :: i
     716              :       REAL(KIND=dp)                                      :: expu2, expx2, fi_norm, occ_i, u, x
     717              : 
     718            0 :       DO i = 1, Nstate
     719            0 :          IF (PRESENT(estate) .AND. PRESENT(festate)) THEN
     720            0 :             IF (i == estate) THEN
     721            0 :                occ_i = festate
     722              :             ELSE
     723            0 :                occ_i = maxocc
     724              :             END IF
     725              :          ELSE
     726            0 :             occ_i = maxocc
     727              :          END IF
     728              : 
     729            0 :          IF (occ_i < EPSILON(occ_i)) THEN
     730            0 :             gvec(i) = 0.0_dp
     731            0 :             CYCLE
     732              :          END IF
     733              : 
     734            0 :          x = (e(i) - mu)/sigma
     735              : 
     736            0 :          SELECT CASE (method)
     737              :          CASE (smear_fermi_dirac)
     738            0 :             fi_norm = f(i)/occ_i
     739            0 :             gvec(i) = occ_i*fi_norm*(1.0_dp - fi_norm)/sigma
     740              : 
     741              :          CASE (smear_gaussian)
     742            0 :             expx2 = EXP(-x*x)
     743            0 :             gvec(i) = occ_i/(sigma*rootpi)*expx2
     744              : 
     745              :          CASE (smear_mp)
     746            0 :             expx2 = EXP(-x*x)
     747            0 :             gvec(i) = occ_i*(3.0_dp - 2.0_dp*x*x)/(2.0_dp*sigma*rootpi)*expx2
     748              : 
     749              :          CASE (smear_mv)
     750            0 :             u = x + sqrthalf
     751            0 :             expu2 = EXP(-u*u)
     752            0 :             gvec(i) = occ_i*(2.0_dp + sqrt2*x)/(sigma*rootpi)*expu2
     753              : 
     754              :          END SELECT
     755              :       END DO
     756              : 
     757            0 :    END SUBROUTINE compute_gvec
     758              : 
     759              : ! **************************************************************************************************
     760              : !> \brief   Analytical Jacobian df_i/de_j for any smearing method under the
     761              : !>          electron-number constraint sum(f) = N.
     762              : !>
     763              : !>          Differentiating f_i(e, mu(e)) where mu is implicitly defined by
     764              : !>          the constraint yields:
     765              : !>
     766              : !>            df_i/de_j  =  -delta_{ij} * g_i  +  g_i * g_j / G
     767              : !>
     768              : !>          where g_i = -df_i/de_i (mu fixed) and G = sum(g_i).
     769              : !>          This is a diagonal matrix plus a symmetric rank-1 update.
     770              : !>          Building it costs O(N) for g, plus O(N^2) for the outer product.
     771              : !>
     772              : !>          Replaces the original numerical finite-difference FermiFixedDeriv
     773              : !>          which required 2N bisection solves.  Exact to machine precision
     774              : !>          for all four methods.
     775              : !>
     776              : !> \param dfde    Jacobian matrix dfde(i,j) = df_i/de_j (Nstate x Nstate, output)
     777              : !> \param f       occupations (output)
     778              : !> \param mu      chemical potential (output)
     779              : !> \param kTS     smearing correction (output)
     780              : !> \param e       eigenvalues (input)
     781              : !> \param N       target number of electrons (input)
     782              : !> \param sigma   smearing width (input)
     783              : !> \param maxocc  maximum occupation (input)
     784              : !> \param method  smearing method selector (input)
     785              : !> \param estate  excited state index (optional)
     786              : !> \param festate occupation of the excited state (optional)
     787              : ! **************************************************************************************************
     788            0 :    SUBROUTINE SmearFixedDeriv(dfde, f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
     789              : 
     790              :       REAL(KIND=dp), INTENT(OUT)                         :: dfde(:, :), f(:), mu, kTS
     791              :       REAL(KIND=dp), INTENT(IN)                          :: e(:), N, sigma, maxocc
     792              :       INTEGER, INTENT(IN)                                :: method
     793              :       INTEGER, INTENT(IN), OPTIONAL                      :: estate
     794              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: festate
     795              : 
     796              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'SmearFixedDeriv'
     797              : 
     798              :       INTEGER                                            :: handle, i, j, Nstate
     799              :       REAL(KIND=dp)                                      :: Gsum
     800            0 :       REAL(KIND=dp), ALLOCATABLE                         :: gvec(:)
     801              : 
     802            0 :       CALL timeset(routineN, handle)
     803              : 
     804              :       ! Step 1: find mu and f
     805            0 :       CALL SmearFixed(f, mu, kTS, e, N, sigma, maxocc, method, estate, festate)
     806              : 
     807              :       ! Step 2: build g vector
     808            0 :       Nstate = SIZE(e)
     809            0 :       ALLOCATE (gvec(Nstate))
     810            0 :       CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, Nstate, method, estate, festate)
     811            0 :       Gsum = accurate_sum(gvec)
     812              : 
     813              :       ! Step 3: assemble dfde(i,j) = -delta_{ij}*g_i + g_i*g_j/G
     814            0 :       IF (ABS(Gsum) > EPSILON(Gsum)) THEN
     815            0 :          DO j = 1, Nstate
     816            0 :             DO i = 1, Nstate
     817            0 :                dfde(i, j) = gvec(i)*gvec(j)/Gsum
     818              :             END DO
     819            0 :             dfde(j, j) = dfde(j, j) - gvec(j)
     820              :          END DO
     821              :       ELSE
     822            0 :          dfde(:, :) = 0.0_dp
     823              :       END IF
     824              : 
     825            0 :       DEALLOCATE (gvec)
     826            0 :       CALL timestop(handle)
     827              : 
     828            0 :    END SUBROUTINE SmearFixedDeriv
     829              : 
     830              : ! **************************************************************************************************
     831              : !> \brief   Apply TRANSPOSE(df/de) to a vector WITHOUT forming the full N x N
     832              : !>          Jacobian.  O(N) time and O(N) memory for all four methods.
     833              : !>
     834              : !>          Exploiting the rank-1 structure of the constrained Jacobian:
     835              : !>
     836              : !>            [J^T v]_j  =  g_j * (g . v / G  -  v_j)
     837              : !>
     838              : !>          This replaces the pattern used in qs_mo_occupation:
     839              : !>            ALLOCATE(dfde(nmo,nmo))
     840              : !>            CALL SmearFixedDeriv(dfde, ...)
     841              : !>            RESULT = MATMUL(TRANSPOSE(dfde), v)
     842              : !>            DEALLOCATE(dfde)
     843              : !>          turning O(N^2) storage + O(N^2) MATMUL into O(N) throughout.
     844              : !>
     845              : !>          Currently the sole caller (qs_ot_scf do_ener) is dead code, but
     846              : !>          this routine is ready for when it is enabled.
     847              : !>
     848              : !> \param RESULT  output vector = TRANSPOSE(df/de) * v (Nstate, output)
     849              : !> \param f       occupations (output)
     850              : !> \param mu      chemical potential (output)
     851              : !> \param kTS     smearing correction (output)
     852              : !> \param e       eigenvalues (input)
     853              : !> \param N_el    target number of electrons (input)
     854              : !> \param sigma   smearing width (input)
     855              : !> \param maxocc  maximum occupation (input)
     856              : !> \param method  smearing method selector (input)
     857              : !> \param v       input vector to multiply (Nstate, input)
     858              : !> \param estate  excited state index (optional)
     859              : !> \param festate occupation of the excited state (optional)
     860              : ! **************************************************************************************************
     861            0 :    SUBROUTINE SmearFixedDerivMV(RESULT, f, mu, kTS, e, N_el, sigma, maxocc, method, v, estate, festate)
     862              : 
     863              :       REAL(KIND=dp), INTENT(OUT)                         :: RESULT(:), f(:), mu, kTS
     864              :       REAL(KIND=dp), INTENT(IN)                          :: e(:), N_el, sigma, maxocc
     865              :       INTEGER, INTENT(IN)                                :: method
     866              :       REAL(KIND=dp), INTENT(IN)                          :: v(:)
     867              :       INTEGER, INTENT(IN), OPTIONAL                      :: estate
     868              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: festate
     869              : 
     870              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'SmearFixedDerivMV'
     871              : 
     872              :       INTEGER                                            :: handle, i, Nstate
     873              :       REAL(KIND=dp)                                      :: gdotv, Gsum
     874            0 :       REAL(KIND=dp), ALLOCATABLE                         :: gvec(:)
     875              : 
     876            0 :       CALL timeset(routineN, handle)
     877              : 
     878              :       ! Step 1: find mu and f
     879            0 :       CALL SmearFixed(f, mu, kTS, e, N_el, sigma, maxocc, method, estate, festate)
     880              : 
     881              :       ! Step 2: build g vector
     882            0 :       Nstate = SIZE(e)
     883            0 :       ALLOCATE (gvec(Nstate))
     884            0 :       CALL compute_gvec(gvec, f, e, mu, sigma, maxocc, Nstate, method, estate, festate)
     885            0 :       Gsum = accurate_sum(gvec)
     886              : 
     887              :       ! Step 3: RESULT_j = g_j * (g.v / G - v_j)
     888            0 :       IF (ABS(Gsum) > EPSILON(Gsum)) THEN
     889              :          gdotv = 0.0_dp
     890            0 :          DO i = 1, Nstate
     891            0 :             gdotv = gdotv + gvec(i)*v(i)
     892              :          END DO
     893            0 :          DO i = 1, Nstate
     894            0 :             RESULT(i) = gvec(i)*(gdotv/Gsum - v(i))
     895              :          END DO
     896              :       ELSE
     897            0 :          RESULT(:) = 0.0_dp
     898              :       END IF
     899              : 
     900            0 :       DEALLOCATE (gvec)
     901            0 :       CALL timestop(handle)
     902              : 
     903            0 :    END SUBROUTINE SmearFixedDerivMV
     904              : 
     905              : END MODULE smearing_utils
        

Generated by: LCOV version 2.0-1