(git:ed6f26b)
Loading...
Searching...
No Matches
qs_condnum.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Calculation of overlap matrix condition numbers
10!> \par History
11!> \author JGH (14.11.2016)
12! **************************************************************************************************
17 USE cp_dbcsr_api, ONLY: &
21 dbcsr_release, dbcsr_type, dbcsr_type_no_symmetry, dbcsr_type_symmetric
26 USE cp_fm_diag, ONLY: cp_fm_power
30 USE cp_fm_types, ONLY: cp_fm_create,&
33 USE kinds, ONLY: dp
34 USE mathlib, ONLY: invmat
35#include "./base/base_uses.f90"
36
37 IMPLICIT NONE
38
39 PRIVATE
40
41! *** Global parameters ***
42
43 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_condnum'
44
45! *** Public subroutines ***
46
47 PUBLIC :: overlap_condnum
48
49CONTAINS
50
51! **************************************************************************************************
52!> \brief Calculation of the overlap matrix Condition Number
53!> \param matrixkp_s The overlap matrices to be calculated (kpoints, optional)
54!> \param condnum Condition numbers for 1 and 2 norm
55!> \param iunit output unit
56!> \param norml1 logical: calculate estimate to 1-norm
57!> \param norml2 logical: calculate estimate to 1-norm and 2-norm condition number
58!> \param use_arnoldi logical: use Arnoldi iteration to estimate 2-norm condition number
59!> \param blacs_env ...
60!> \date 07.11.2016
61!> \par History
62!> \author JHU
63!> \version 1.0
64! **************************************************************************************************
65 SUBROUTINE overlap_condnum(matrixkp_s, condnum, iunit, norml1, norml2, use_arnoldi, blacs_env)
66
67 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrixkp_s
68 REAL(kind=dp), DIMENSION(2), INTENT(INOUT) :: condnum
69 INTEGER, INTENT(IN) :: iunit
70 LOGICAL, INTENT(IN) :: norml1, norml2, use_arnoldi
71 TYPE(cp_blacs_env_type), POINTER :: blacs_env
72
73 CHARACTER(len=*), PARAMETER :: routinen = 'overlap_condnum'
74
75 INTEGER :: handle, ic, maxiter, nbas, ndep
76 LOGICAL :: converged
77 REAL(kind=dp) :: amnorm, anorm, eps_ev, max_ev, min_ev, &
78 threshold
79 REAL(kind=dp), DIMENSION(2) :: eigvals
80 TYPE(cp_fm_struct_type), POINTER :: matrix_struct
81 TYPE(cp_fm_type) :: fmsmat, fmwork
82 TYPE(dbcsr_type) :: tempmat
83 TYPE(dbcsr_type), POINTER :: smat
84
85 CALL timeset(routinen, handle)
86
87 condnum(1:2) = 0.0_dp
88 NULLIFY (smat)
89 IF (SIZE(matrixkp_s, 2) == 1) THEN
90 IF (iunit > 0) WRITE (iunit, '(/,T2,A)') "OVERLAP MATRIX CONDITION NUMBER"
91 smat => matrixkp_s(1, 1)%matrix
92 ELSE
93 IF (iunit > 0) WRITE (iunit, '(/,T2,A)') "OVERLAP MATRIX CONDITION NUMBER AT GAMMA POINT"
94 ALLOCATE (smat)
95 CALL dbcsr_create(smat, template=matrixkp_s(1, 1)%matrix)
96 CALL dbcsr_copy(smat, matrixkp_s(1, 1)%matrix)
97 DO ic = 2, SIZE(matrixkp_s, 2)
98 CALL dbcsr_add(smat, matrixkp_s(1, ic)%matrix, 1.0_dp, 1.0_dp)
99 END DO
100 END IF
101 !
102 IF (ASSOCIATED(smat)) THEN
103 cpassert(dbcsr_get_matrix_type(smat) .EQ. dbcsr_type_symmetric)
104 IF (norml1) THEN
105 ! norm of S
106 anorm = dbcsr_gershgorin_norm(smat)
107 CALL estimate_norm_invmat(smat, amnorm)
108 IF (iunit > 0) THEN
109 WRITE (iunit, '(T2,A)') "1-Norm Condition Number (Estimate)"
110 WRITE (iunit, '(T4,A,ES11.3E3,T32,A,ES11.3E3,A4,ES11.3E3,T63,A,F8.4)') &
111 "CN : |A|*|A^-1|: ", anorm, " * ", amnorm, "=", anorm*amnorm, "Log(1-CN):", log10(anorm*amnorm)
112 END IF
113 condnum(1) = anorm*amnorm
114 END IF
115 IF (norml2) THEN
116 eps_ev = 1.0e-14_dp
117 ! diagonalization
118 CALL dbcsr_get_info(smat, nfullrows_total=nbas)
119 CALL cp_fm_struct_create(fmstruct=matrix_struct, context=blacs_env, &
120 nrow_global=nbas, ncol_global=nbas)
121 CALL cp_fm_create(fmsmat, matrix_struct)
122 CALL cp_fm_create(fmwork, matrix_struct)
123 ! transfer to FM
124 CALL dbcsr_create(tempmat, template=smat, matrix_type=dbcsr_type_no_symmetry)
125 CALL dbcsr_desymmetrize(smat, tempmat)
126 CALL copy_dbcsr_to_fm(tempmat, fmsmat)
127
128 ! diagonalize
129 anorm = cp_fm_norm(fmsmat, "1")
130 CALL cp_fm_power(fmsmat, fmwork, -1.0_dp, eps_ev, ndep, eigvals=eigvals)
131 min_ev = eigvals(1)
132 max_ev = eigvals(2)
133 amnorm = cp_fm_norm(fmsmat, "1")
134
135 CALL dbcsr_release(tempmat)
136 CALL cp_fm_release(fmsmat)
137 CALL cp_fm_release(fmwork)
138 CALL cp_fm_struct_release(matrix_struct)
139
140 IF (iunit > 0) THEN
141 WRITE (iunit, '(T2,A)') "1-Norm and 2-Norm Condition Numbers using Diagonalization"
142 IF (min_ev > 0) THEN
143 WRITE (iunit, '(T4,A,ES11.3E3,T32,A,ES11.3E3,A4,ES11.3E3,T63,A,F8.4)') &
144 "CN : |A|*|A^-1|: ", anorm, " * ", amnorm, "=", anorm*amnorm, "Log(1-CN):", log10(anorm*amnorm)
145 WRITE (iunit, '(T4,A,ES11.3E3,T32,A,ES11.3E3,A4,ES11.3E3,T63,A,F8.4)') &
146 "CN : max/min ev: ", max_ev, " / ", min_ev, "=", max_ev/min_ev, "Log(2-CN):", log10(max_ev/min_ev)
147 ELSE
148 WRITE (iunit, '(T4,A,ES11.3E3,T32,A,ES11.3E3,T63,A)') &
149 "CN : max/min EV: ", max_ev, " / ", min_ev, "Log(CN): infinity"
150 END IF
151 END IF
152 IF (min_ev > 0) THEN
153 condnum(1) = anorm*amnorm
154 condnum(2) = max_ev/min_ev
155 ELSE
156 condnum(1:2) = 0.0_dp
157 END IF
158 END IF
159 IF (use_arnoldi) THEN
160 ! parameters for matrix condition test
161 threshold = 1.0e-6_dp
162 maxiter = 1000
163 eps_ev = 1.0e8_dp
164 CALL arnoldi_extremal(smat, max_ev, min_ev, &
165 threshold=threshold, max_iter=maxiter, converged=converged)
166 IF (iunit > 0) THEN
167 WRITE (iunit, '(T2,A)') "2-Norm Condition Number using Arnoldi iterations"
168 IF (min_ev > 0) THEN
169 WRITE (iunit, '(T4,A,ES11.3E3,T32,A,ES11.3E3,A4,ES11.3E3,T63,A,F8.4)') &
170 "CN : max/min ev: ", max_ev, " / ", min_ev, "=", max_ev/min_ev, "Log(2-CN):", log10(max_ev/min_ev)
171 ELSE
172 WRITE (iunit, '(T4,A,ES11.3E3,T32,A,ES11.3E3,T63,A)') &
173 "CN : max/min ev: ", max_ev, " / ", min_ev, "Log(CN): infinity"
174 END IF
175 END IF
176 IF (min_ev > 0) THEN
177 condnum(2) = max_ev/min_ev
178 ELSE
179 condnum(2) = 0.0_dp
180 END IF
181 IF (converged) THEN
182 IF (min_ev == 0) THEN
183 cpwarn("Ill-conditioned S matrix: basis set is overcomplete.")
184 ELSE IF ((max_ev/min_ev) > eps_ev) THEN
185 cpwarn("Ill-conditioned S matrix: basis set is overcomplete.")
186 END IF
187 ELSE
188 cpwarn("Condition number estimate of overlap matrix is not reliable (not converged).")
189 END IF
190 END IF
191 END IF
192 IF (SIZE(matrixkp_s, 2) == 1) THEN
193 NULLIFY (smat)
194 ELSE
195 CALL dbcsr_release(smat)
196 DEALLOCATE (smat)
197 END IF
198
199 CALL timestop(handle)
200
201 END SUBROUTINE overlap_condnum
202
203! **************************************************************************************************
204!> \brief Calculates an estimate of the 1-norm of the inverse of a matrix
205!> Uses LAPACK norm estimator algorithm
206!> NJ Higham, Function of Matrices, Algorithm 3.21, page 66
207!> \param amat Sparse, symmetric matrix
208!> \param anorm Estimate of ||INV(A)||
209!> \date 15.11.2016
210!> \par History
211!> \author JHU
212!> \version 1.0
213! **************************************************************************************************
214 SUBROUTINE estimate_norm_invmat(amat, anorm)
215 TYPE(dbcsr_type), POINTER :: amat
216 REAL(kind=dp), INTENT(OUT) :: anorm
217
218 INTEGER :: i, k, nbas
219 INTEGER, DIMENSION(1) :: r
220 REAL(kind=dp) :: g, gg
221 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: x, xsi
222 REAL(kind=dp), DIMENSION(2) :: work
223 REAL(kind=dp), EXTERNAL :: dlange
224 TYPE(dbcsr_type) :: pmat
225
226 ! generate a block diagonal preconditioner
227 CALL dbcsr_create(pmat, name="SMAT Preconditioner", template=amat)
228 ! replicate the diagonal blocks of the overlap matrix
229 CALL dbcsr_get_block_diag(amat, pmat)
230 ! invert preconditioner
231 CALL smat_precon_diag(pmat)
232
233 anorm = 1.0_dp
234 CALL dbcsr_get_info(amat, nfullrows_total=nbas)
235 ALLOCATE (x(nbas), xsi(nbas))
236 x(1:nbas) = 1._dp/real(nbas, kind=dp)
237 CALL dbcsr_solve(amat, x, pmat)
238 g = dlange("1", nbas, 1, x, nbas, work)
239 xsi(1:nbas) = sign(1._dp, x(1:nbas))
240 x(1:nbas) = xsi(1:nbas)
241 CALL dbcsr_solve(amat, x, pmat)
242 k = 2
243 DO
244 r = maxloc(abs(x))
245 x(1:nbas) = 0._dp
246 x(r) = 1._dp
247 CALL dbcsr_solve(amat, x, pmat)
248 gg = g
249 g = dlange("1", nbas, 1, x, nbas, work)
250 IF (g <= gg) EXIT
251 x(1:nbas) = sign(1._dp, x(1:nbas))
252 IF (sum(abs(x - xsi)) == 0 .OR. sum(abs(x + xsi)) == 0) EXIT
253 xsi(1:nbas) = x(1:nbas)
254 CALL dbcsr_solve(amat, x, pmat)
255 k = k + 1
256 IF (k > 5) EXIT
257 IF (sum(r) == sum(maxloc(abs(x)))) EXIT
258 END DO
259 !
260 IF (nbas > 1) THEN
261 DO i = 1, nbas
262 x(i) = -1._dp**(i + 1)*(1._dp + real(i - 1, dp)/real(nbas - 1, dp))
263 END DO
264 ELSE
265 x(1) = 1.0_dp
266 END IF
267 CALL dbcsr_solve(amat, x, pmat)
268 gg = dlange("1", nbas, 1, x, nbas, work)
269 gg = 2._dp*gg/real(3*nbas, dp)
270 anorm = max(g, gg)
271 DEALLOCATE (x, xsi)
272 CALL dbcsr_release(pmat)
273
274 END SUBROUTINE estimate_norm_invmat
275
276! **************************************************************************************************
277!> \brief ...
278!> \param amat ...
279!> \param x ...
280!> \param pmat ...
281! **************************************************************************************************
282 SUBROUTINE dbcsr_solve(amat, x, pmat)
283 TYPE(dbcsr_type), POINTER :: amat
284 REAL(kind=dp), DIMENSION(:), INTENT(INOUT) :: x
285 TYPE(dbcsr_type) :: pmat
286
287 INTEGER :: max_iter, nbas
288 LOGICAL :: converged
289 REAL(kind=dp) :: threshold
290
291 CALL dbcsr_get_info(amat, nfullrows_total=nbas)
292 max_iter = min(1000, nbas)
293 threshold = 1.e-6_dp
294 CALL arnoldi_conjugate_gradient(amat, x, pmat, converged=converged, threshold=threshold, max_iter=max_iter)
295
296 END SUBROUTINE dbcsr_solve
297
298! **************************************************************************************************
299!> \brief ...
300!> \param pmat ...
301! **************************************************************************************************
302 SUBROUTINE smat_precon_diag(pmat)
303 TYPE(dbcsr_type) :: pmat
304
305 INTEGER :: iatom, info, jatom, n
306 REAL(kind=dp), DIMENSION(:, :), POINTER :: sblock
307 TYPE(dbcsr_iterator_type) :: dbcsr_iter
308
309 CALL dbcsr_iterator_start(dbcsr_iter, pmat)
310 DO WHILE (dbcsr_iterator_blocks_left(dbcsr_iter))
311 CALL dbcsr_iterator_next_block(dbcsr_iter, iatom, jatom, sblock)
312 cpassert(iatom == jatom)
313 n = SIZE(sblock, 1)
314 CALL invmat(sblock(1:n, 1:n), info)
315 cpassert(info == 0)
316 END DO
317 CALL dbcsr_iterator_stop(dbcsr_iter)
318
319 END SUBROUTINE smat_precon_diag
320
321END MODULE qs_condnum
322
arnoldi iteration using dbcsr
Definition arnoldi_api.F:16
subroutine, public arnoldi_extremal(matrix_a, max_ev, min_ev, converged, threshold, max_iter)
simple wrapper to estimate extremal eigenvalues with arnoldi, using the old lanczos interface this hi...
subroutine, public arnoldi_conjugate_gradient(matrix_a, vec_x, matrix_p, converged, threshold, max_iter)
Wrapper for conjugated gradient algorithm for Ax=b.
methods related to the blacs parallel environment
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset)
...
character function, public dbcsr_get_matrix_type(matrix)
...
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_desymmetrize(matrix_a, matrix_b)
...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
real(dp) function, public dbcsr_gershgorin_norm(matrix)
Compute the gershgorin norm of a dbcsr matrix.
subroutine, public dbcsr_get_block_diag(matrix, diag)
Copies the diagonal blocks of matrix into diag.
DBCSR operations in CP2K.
subroutine, public copy_dbcsr_to_fm(matrix, fm)
Copy a DBCSR matrix to a BLACS matrix.
basic linear algebra operations for full matrices
real(kind=dp) function, public cp_fm_norm(matrix, mode)
norm of matrix using (p)dlange
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
Definition cp_fm_diag.F:17
subroutine, public cp_fm_power(matrix, work, exponent, threshold, n_dependent, verbose, eigvals)
...
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_create(matrix, matrix_struct, name, use_sp)
creates a new full matrix with the given structure
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 invmat(a, info)
returns inverse of matrix using the lapack routines DGETRF and DGETRI
Definition mathlib.F:543
Calculation of overlap matrix condition numbers.
Definition qs_condnum.F:13
subroutine, public overlap_condnum(matrixkp_s, condnum, iunit, norml1, norml2, use_arnoldi, blacs_env)
Calculation of the overlap matrix Condition Number.
Definition qs_condnum.F:66
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix
represent a full matrix