LCOV - code coverage report
Current view: top level - src - low_rank_preconditioner_model.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:591cf04) Lines: 100.0 % 22 22
Test Date: 2026-09-21 02:17:57 Functions: 100.0 % 3 3

            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 Small algebraic helpers for the rotationally covariant low-rank OT preconditioner.
      10              : ! **************************************************************************************************
      11              : MODULE low_rank_preconditioner_model
      12              :    USE kinds,                           ONLY: dp
      13              : 
      14              :    IMPLICIT NONE
      15              :    PRIVATE
      16              : 
      17              :    PUBLIC :: apply_low_rank_dense, low_rank_inverse_weight, low_rank_select_rank
      18              : 
      19              : CONTAINS
      20              : 
      21              : ! **************************************************************************************************
      22              : !> \brief Spectral inverse weight relative to a common occupied reference level.
      23              : !> \param eigenvalue complementary-state eigenvalue
      24              : !> \param reference common occupied reference level
      25              : !> \param energy_gap lower bound for the denominator
      26              : !> \return inverse spectral weight
      27              : ! **************************************************************************************************
      28        27428 :    PURE ELEMENTAL REAL(KIND=dp) FUNCTION low_rank_inverse_weight( &
      29              :       eigenvalue, reference, energy_gap) RESULT(weight)
      30              : 
      31              :       REAL(KIND=dp), INTENT(IN)                          :: eigenvalue, reference, energy_gap
      32              : 
      33              :       REAL(KIND=dp)                                      :: delta
      34              : 
      35        27428 :       delta = eigenvalue - reference
      36        27428 :       weight = 1.0_dp/MAX(energy_gap, delta)
      37              : 
      38        27428 :    END FUNCTION low_rank_inverse_weight
      39              : 
      40              : ! **************************************************************************************************
      41              : !> \brief Select a bounded spectral rank without cutting a degenerate boundary manifold.
      42              : !> \param eigenvalues ordered full-space eigenvalues
      43              : !> \param nocc number of occupied states at the start of eigenvalues
      44              : !> \param max_rank hard upper bound
      45              : !> \param degeneracy_tolerance relative degeneracy threshold
      46              : !> \return selected rank
      47              : ! **************************************************************************************************
      48           60 :    PURE INTEGER FUNCTION low_rank_select_rank(eigenvalues, nocc, max_rank, &
      49              :                                               degeneracy_tolerance) RESULT(rank_used)
      50              : 
      51              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: eigenvalues
      52              :       INTEGER, INTENT(IN)                                :: nocc, max_rank
      53              :       REAL(KIND=dp), INTENT(IN)                          :: degeneracy_tolerance
      54              : 
      55              :       INTEGER                                            :: ncomplement
      56              :       REAL(KIND=dp)                                      :: scale
      57              : 
      58           60 :       rank_used = 0
      59           60 :       ncomplement = SIZE(eigenvalues) - nocc
      60           60 :       IF (nocc < 0 .OR. ncomplement <= 0 .OR. max_rank <= 0) RETURN
      61              : 
      62           16 :       rank_used = MIN(max_rank, ncomplement)
      63              : 
      64              :       ! Exclude the complete boundary cluster if the hard rank cap would split it.
      65           18 :       DO WHILE (rank_used > 0 .AND. rank_used < ncomplement)
      66              :          scale = MAX(1.0_dp, ABS(eigenvalues(nocc + rank_used)), &
      67            8 :                      ABS(eigenvalues(nocc + rank_used + 1)))
      68            8 :          IF (ABS(eigenvalues(nocc + rank_used + 1) - eigenvalues(nocc + rank_used)) > &
      69              :              degeneracy_tolerance*scale) EXIT
      70            8 :          rank_used = rank_used - 1
      71              :       END DO
      72              : 
      73              :    END FUNCTION low_rank_select_rank
      74              : 
      75              : ! **************************************************************************************************
      76              : !> \brief Dense reference application used to verify right covariance under orbital rotations.
      77              : !> \param overlap_inverse inverse overlap matrix
      78              : !> \param vectors retained complementary-state vectors
      79              : !> \param eigenvalues retained complementary-state eigenvalues
      80              : !> \param reference common occupied reference level
      81              : !> \param energy_gap lower bound for spectral denominators
      82              : !> \param spectral_window overlap-inverse replacement window
      83              : !> \param matrix_in input orbital-gradient matrix
      84              : !> \param matrix_out preconditioned matrix
      85              : ! **************************************************************************************************
      86            4 :    PURE SUBROUTINE apply_low_rank_dense(overlap_inverse, vectors, eigenvalues, reference, &
      87            4 :                                         energy_gap, spectral_window, matrix_in, matrix_out)
      88              : 
      89              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: overlap_inverse, vectors
      90              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: eigenvalues
      91              :       REAL(KIND=dp), INTENT(IN)                          :: reference, energy_gap, spectral_window
      92              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: matrix_in
      93              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: matrix_out
      94              : 
      95              :       INTEGER                                            :: i
      96              :       REAL(KIND=dp)                                      :: correction
      97            8 :       REAL(KIND=dp), DIMENSION(SIZE(matrix_in, 2))       :: projections
      98              : 
      99          520 :       matrix_out = MATMUL(overlap_inverse, matrix_in)/spectral_window
     100           12 :       DO i = 1, SIZE(eigenvalues)
     101              :          correction = low_rank_inverse_weight(eigenvalues(i), reference, energy_gap) - &
     102            8 :                       1.0_dp/spectral_window
     103          176 :          projections(:) = MATMUL(vectors(:, i), matrix_in)
     104              :          matrix_out = matrix_out + correction*SPREAD(vectors(:, i), 2, SIZE(matrix_in, 2))* &
     105          156 :                       SPREAD(projections, 1, SIZE(matrix_in, 1))
     106              :       END DO
     107              : 
     108            4 :    END SUBROUTINE apply_low_rank_dense
     109              : 
     110              : END MODULE low_rank_preconditioner_model
        

Generated by: LCOV version 2.0-1