LCOV - code coverage report
Current view: top level - src - low_rank_preconditioner_unittest.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 94.9 % 39 37
Test Date: 2026-10-15 00:55:44 Functions: 100.0 % 2 2

            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            2 : PROGRAM low_rank_preconditioner_unittest
       9            2 :    USE kinds,                           ONLY: dp
      10              :    USE low_rank_preconditioner_model,   ONLY: apply_low_rank_dense,&
      11              :                                               low_rank_inverse_weight,&
      12              :                                               low_rank_select_rank
      13              : 
      14              :    IMPLICIT NONE
      15              : 
      16              :    INTEGER, PARAMETER                                  :: nao = 5, nocc = 3, rank = 2
      17              :    REAL(KIND=dp), PARAMETER                            :: tolerance = 2.0E-14_dp
      18              :    INTEGER                                             :: i, selected_rank
      19              :    REAL(KIND=dp)                                       :: angle, energy_gap, mu, window
      20              :    REAL(KIND=dp), DIMENSION(7)                         :: full_eigenvalues
      21              :    REAL(KIND=dp), DIMENSION(rank)                      :: eigenvalues
      22              :    REAL(KIND=dp), DIMENSION(nao, nao)                  :: identity, overlap_inverse
      23              :    REAL(KIND=dp), DIMENSION(nao, rank)                 :: vectors
      24              :    REAL(KIND=dp), DIMENSION(nao, nocc)                 :: gradient, gradient_rotated, RESULT, &
      25              :                                                           result_rotated
      26              :    REAL(KIND=dp), DIMENSION(nocc, nocc)                :: rotation
      27              : 
      28            2 :    identity = 0.0_dp
      29           12 :    DO i = 1, nao
      30           12 :       identity(i, i) = 1.0_dp
      31              :    END DO
      32              : 
      33            2 :    overlap_inverse = identity
      34            2 :    overlap_inverse(1, 1) = 1.4_dp
      35            2 :    overlap_inverse(2, 2) = 0.8_dp
      36            2 :    overlap_inverse(1, 2) = 0.1_dp
      37            2 :    overlap_inverse(2, 1) = 0.1_dp
      38              : 
      39            2 :    vectors = 0.0_dp
      40            2 :    vectors(3, 1) = 1.0_dp
      41            2 :    vectors(4, 2) = 0.8_dp
      42            2 :    vectors(5, 2) = 0.6_dp
      43            2 :    eigenvalues = [0.35_dp, 0.8_dp]
      44            2 :    mu = -0.2_dp
      45            2 :    energy_gap = 0.08_dp
      46            2 :    window = 1.0_dp
      47              : 
      48              :    gradient = RESHAPE([0.2_dp, -0.1_dp, 0.4_dp, 0.3_dp, -0.2_dp, &
      49              :                        0.6_dp, 0.5_dp, -0.3_dp, 0.1_dp, 0.7_dp, &
      50            2 :                        -0.4_dp, 0.8_dp, 0.2_dp, -0.5_dp, 0.9_dp], [nao, nocc])
      51            2 :    angle = 0.37_dp
      52            2 :    rotation = 0.0_dp
      53            2 :    rotation(1, 1) = COS(angle)
      54            2 :    rotation(1, 2) = -SIN(angle)
      55            2 :    rotation(2, 1) = SIN(angle)
      56            2 :    rotation(2, 2) = COS(angle)
      57            2 :    rotation(3, 3) = 1.0_dp
      58          116 :    gradient_rotated = MATMUL(gradient, rotation)
      59              : 
      60              :    CALL apply_low_rank_dense(overlap_inverse, vectors, eigenvalues, mu, energy_gap, window, &
      61            2 :                              gradient, RESULT)
      62              :    CALL apply_low_rank_dense(overlap_inverse, vectors, eigenvalues, mu, energy_gap, window, &
      63            2 :                              gradient_rotated, result_rotated)
      64          152 :    IF (MAXVAL(ABS(result_rotated - MATMUL(RESULT, rotation))) > tolerance) THEN
      65            0 :       ERROR STOP "Low-rank preconditioner is not right-covariant under occupied rotations"
      66              :    END IF
      67              : 
      68            2 :    full_eigenvalues = [-0.8_dp, -0.2_dp, 0.2_dp, 0.4_dp, 0.7_dp, 0.7_dp, 1.4_dp]
      69            2 :    selected_rank = low_rank_select_rank(full_eigenvalues, 2, 3, 1.0E-8_dp)
      70            2 :    IF (selected_rank /= 2) ERROR STOP "Rank cap split a degenerate complementary manifold"
      71            2 :    selected_rank = low_rank_select_rank(full_eigenvalues, 2, 5, 1.0E-8_dp)
      72            2 :    IF (selected_rank /= 5) ERROR STOP "Full complementary space did not retain its rank"
      73            2 :    IF (ABS(low_rank_inverse_weight(1.5_dp, 0.0_dp, 0.08_dp) - 2.0_dp/3.0_dp) > tolerance) THEN
      74            0 :       ERROR STOP "Common-reference inverse weight differs from the spectral model"
      75              :    END IF
      76              : 
      77            2 : END PROGRAM low_rank_preconditioner_unittest
        

Generated by: LCOV version 2.0-1