(git:374b731)
Loading...
Searching...
No Matches
pao_param_fock.F
Go to the documentation of this file.
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 Common framework for using eigenvectors of a Fock matrix as PAO basis.
10!> \author Ole Schuett
11! **************************************************************************************************
13 USE dbcsr_api, ONLY: dbcsr_get_block_p,&
14 dbcsr_get_info
15 USE kinds, ONLY: dp
16 USE mathlib, ONLY: diamat_all
17 USE pao_types, ONLY: pao_env_type
18#include "./base/base_uses.f90"
19
20 IMPLICIT NONE
21
22 PRIVATE
23
24 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pao_param_fock'
25
26 PUBLIC :: pao_calc_u_block_fock
27
28CONTAINS
29
30! **************************************************************************************************
31!> \brief Calculate new matrix U and optinally its gradient G
32!> \param pao ...
33!> \param iatom ...
34!> \param V ...
35!> \param U ...
36!> \param penalty ...
37!> \param gap ...
38!> \param evals ...
39!> \param M1 ...
40!> \param G ...
41! **************************************************************************************************
42 SUBROUTINE pao_calc_u_block_fock(pao, iatom, V, U, penalty, gap, evals, M1, G)
43 TYPE(pao_env_type), POINTER :: pao
44 INTEGER, INTENT(IN) :: iatom
45 REAL(dp), DIMENSION(:, :), POINTER :: v, u
46 REAL(dp), INTENT(INOUT), OPTIONAL :: penalty
47 REAL(dp), INTENT(OUT) :: gap
48 REAL(dp), DIMENSION(:), INTENT(OUT), OPTIONAL :: evals
49 REAL(dp), DIMENSION(:, :), OPTIONAL, POINTER :: m1, g
50
51 CHARACTER(len=*), PARAMETER :: routinen = 'pao_calc_U_block_fock'
52
53 INTEGER :: handle, i, j, m, n
54 INTEGER, DIMENSION(:), POINTER :: blk_sizes_pao, blk_sizes_pri
55 LOGICAL :: found
56 REAL(dp) :: alpha, beta, denom, diff
57 REAL(dp), DIMENSION(:), POINTER :: h_evals
58 REAL(dp), DIMENSION(:, :), POINTER :: block_n, d1, d2, h, h0, h_evecs, m2, m3, &
59 m4, m5
60
61 CALL timeset(routinen, handle)
62
63 CALL dbcsr_get_block_p(matrix=pao%matrix_H0, row=iatom, col=iatom, block=h0, found=found)
64 cpassert(ASSOCIATED(h0))
65 CALL dbcsr_get_block_p(matrix=pao%matrix_N_diag, row=iatom, col=iatom, block=block_n, found=found)
66 cpassert(ASSOCIATED(block_n))
67 IF (maxval(abs(v - transpose(v))) > 1e-14_dp) cpabort("Expect symmetric matrix")
68
69 ! figure out basis sizes
70 CALL dbcsr_get_info(pao%matrix_Y, row_blk_size=blk_sizes_pri, col_blk_size=blk_sizes_pao)
71 n = blk_sizes_pri(iatom) ! size of primary basis
72 m = blk_sizes_pao(iatom) ! size of pao basis
73
74 ! calculate H in the orthonormal basis
75 ALLOCATE (h(n, n))
76 h = matmul(matmul(block_n, h0 + v), block_n)
77
78 ! diagonalize H
79 ALLOCATE (h_evals(n), h_evecs(n, n))
80 h_evecs = h
81 CALL diamat_all(h_evecs, h_evals)
82
83 ! the eigenvectors of H become the rotation matrix U
84 u = h_evecs
85
86 ! copy eigenvectors around the gap from H_evals into evals array
87 IF (PRESENT(evals)) THEN
88 cpassert(mod(SIZE(evals), 2) == 0) ! gap will be exactely in the middle
89 i = SIZE(evals)/2
90 j = min(m, i)
91 evals(1 + i - j:i) = h_evals(1 + m - j:m) ! eigenvalues below gap
92 j = min(n - m, i)
93 evals(i:i + j) = h_evals(m:m + j) ! eigenvalues above gap
94 END IF
95
96 ! calculate homo-lumo gap (it's useful for detecting numerical issues)
97 gap = huge(dp)
98 IF (m < n) & ! catch special case n==m
99 gap = h_evals(m + 1) - h_evals(m)
100
101 IF (PRESENT(penalty)) THEN
102 ! penalty terms: occupied and virtual eigenvalues repel each other
103 alpha = pao%penalty_strength
104 beta = pao%penalty_dist
105 DO i = 1, m
106 DO j = m + 1, n
107 diff = h_evals(i) - h_evals(j)
108 penalty = penalty + alpha*exp(-(diff/beta)**2)
109 END DO
110 END DO
111
112 ! regularization energy
113 penalty = penalty + pao%regularization*sum(v**2)
114 END IF
115
116 IF (PRESENT(g)) THEN ! TURNING POINT (if calc grad) -------------------------
117
118 cpassert(PRESENT(m1))
119
120 ! calculate derivatives between eigenvectors of H
121 ALLOCATE (d1(n, n), m2(n, n), m3(n, n), m4(n, n))
122 DO i = 1, n
123 DO j = 1, n
124 ! ignore changes among occupied or virtual eigenvectors
125 ! They will get filtered out by M2*D1 anyways, however this early
126 ! intervention might stabilize numerics in the case of level-crossings.
127 IF (i <= m .EQV. j <= m) THEN
128 d1(i, j) = 0.0_dp
129 ELSE
130 denom = h_evals(i) - h_evals(j)
131 IF (abs(denom) > 1e-9_dp) THEN ! avoid division by zero
132 d1(i, j) = 1.0_dp/denom
133 ELSE
134 d1(i, j) = sign(1e+9_dp, denom)
135 END IF
136 END IF
137 END DO
138 END DO
139 IF (ASSOCIATED(m1)) THEN
140 m2 = matmul(transpose(m1), h_evecs)
141 ELSE
142 m2 = 0.0_dp
143 END IF
144 m3 = m2*d1 ! Hadamard product
145 m4 = matmul(matmul(h_evecs, m3), transpose(h_evecs))
146
147 ! gradient contribution from penalty terms
148 IF (PRESENT(penalty)) THEN
149 ALLOCATE (d2(n, n))
150 d2 = 0.0_dp
151 DO i = 1, n
152 DO j = 1, n
153 IF (i <= m .EQV. j <= m) cycle
154 diff = h_evals(i) - h_evals(j)
155 d2(i, i) = d2(i, i) - 2.0_dp*alpha*diff/beta**2*exp(-(diff/beta)**2)
156 END DO
157 END DO
158 m4 = m4 + matmul(matmul(h_evecs, d2), transpose(h_evecs))
159 DEALLOCATE (d2)
160 END IF
161
162 ! dH / dV, return to non-orthonormal basis
163 ALLOCATE (m5(n, n))
164 m5 = matmul(matmul(block_n, m4), block_n)
165
166 ! add regularization gradient
167 IF (PRESENT(penalty)) &
168 m5 = m5 + 2.0_dp*pao%regularization*v
169
170 ! symmetrize
171 g = 0.5_dp*(m5 + transpose(m5)) ! the final gradient
172
173 DEALLOCATE (d1, m2, m3, m4, m5)
174 END IF
175
176 DEALLOCATE (h, h_evals, h_evecs)
177
178 CALL timestop(handle)
179 END SUBROUTINE pao_calc_u_block_fock
180
181END MODULE pao_param_fock
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
Definition mathlib.F:372
Common framework for using eigenvectors of a Fock matrix as PAO basis.
subroutine, public pao_calc_u_block_fock(pao, iatom, v, u, penalty, gap, evals, m1, g)
Calculate new matrix U and optinally its gradient G.
Types used by the PAO machinery.
Definition pao_types.F:12