(git:5e7fe52)
Loading...
Searching...
No Matches
low_rank_preconditioner_model.F
Go to the documentation of this file.
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! **************************************************************************************************
12 USE kinds, ONLY: dp
13
14 IMPLICIT NONE
15 PRIVATE
16
18
19CONTAINS
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 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 delta = eigenvalue - reference
36 weight = 1.0_dp/max(energy_gap, delta)
37
38 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 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 rank_used = 0
59 ncomplement = SIZE(eigenvalues) - nocc
60 IF (nocc < 0 .OR. ncomplement <= 0 .OR. max_rank <= 0) RETURN
61
62 rank_used = min(max_rank, ncomplement)
63
64 ! Exclude the complete boundary cluster if the hard rank cap would split it.
65 DO WHILE (rank_used > 0 .AND. rank_used < ncomplement)
66 scale = max(1.0_dp, abs(eigenvalues(nocc + rank_used)), &
67 abs(eigenvalues(nocc + rank_used + 1)))
68 IF (abs(eigenvalues(nocc + rank_used + 1) - eigenvalues(nocc + rank_used)) > &
69 degeneracy_tolerance*scale) EXIT
70 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 PURE SUBROUTINE apply_low_rank_dense(overlap_inverse, vectors, eigenvalues, reference, &
87 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 REAL(kind=dp), DIMENSION(SIZE(matrix_in, 2)) :: projections
98
99 matrix_out = matmul(overlap_inverse, matrix_in)/spectral_window
100 DO i = 1, SIZE(eigenvalues)
101 correction = low_rank_inverse_weight(eigenvalues(i), reference, energy_gap) - &
102 1.0_dp/spectral_window
103 projections(:) = matmul(vectors(:, i), matrix_in)
104 matrix_out = matrix_out + correction*spread(vectors(:, i), 2, SIZE(matrix_in, 2))* &
105 spread(projections, 1, SIZE(matrix_in, 1))
106 END DO
107
108 END SUBROUTINE apply_low_rank_dense
109
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Small algebraic helpers for the rotationally covariant low-rank OT preconditioner.
pure elemental real(kind=dp) function, public low_rank_inverse_weight(eigenvalue, reference, energy_gap)
Spectral inverse weight relative to a common occupied reference level.
pure subroutine, public apply_low_rank_dense(overlap_inverse, vectors, eigenvalues, reference, energy_gap, spectral_window, matrix_in, matrix_out)
Dense reference application used to verify right covariance under orbital rotations.
pure integer function, public low_rank_select_rank(eigenvalues, nocc, max_rank, degeneracy_tolerance)
Select a bounded spectral rank without cutting a degenerate boundary manifold.