(git:374b731)
Loading...
Searching...
No Matches
dm_ls_scf_methods.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 lower level routines for linear scaling SCF
10!> \par History
11!> 2010.10 created [Joost VandeVondele]
12!> \author Joost VandeVondele
13! **************************************************************************************************
19 USE dbcsr_api, ONLY: &
20 dbcsr_add, dbcsr_add_on_diag, dbcsr_copy, dbcsr_create, dbcsr_desymmetrize, dbcsr_dot, &
21 dbcsr_filter, dbcsr_finalize, dbcsr_frobenius_norm, dbcsr_get_data_type, &
22 dbcsr_get_occupation, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
23 dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, &
24 dbcsr_put_block, dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_trace, dbcsr_type, &
25 dbcsr_type_no_symmetry
27 USE dm_ls_scf_types, ONLY: ls_cluster_atomic,&
30 USE input_constants, ONLY: &
42 USE kinds, ONLY: dp,&
43 int_8
44 USE machine, ONLY: m_flush,&
46 USE mathlib, ONLY: abnormal_value
47#include "./base/base_uses.f90"
48
49 IMPLICIT NONE
50
51 PRIVATE
52
53 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dm_ls_scf_methods'
54
55 PUBLIC :: ls_scf_init_matrix_s
59
60CONTAINS
61
62! **************************************************************************************************
63!> \brief initialize S matrix related properties (sqrt, inverse...)
64!> Might be factored-out since this seems common code with the other SCF.
65!> \param matrix_s ...
66!> \param ls_scf_env ...
67!> \par History
68!> 2010.10 created [Joost VandeVondele]
69!> \author Joost VandeVondele
70! **************************************************************************************************
71 SUBROUTINE ls_scf_init_matrix_s(matrix_s, ls_scf_env)
72 TYPE(dbcsr_type) :: matrix_s
73 TYPE(ls_scf_env_type) :: ls_scf_env
74
75 CHARACTER(len=*), PARAMETER :: routinen = 'ls_scf_init_matrix_S'
76
77 INTEGER :: handle, unit_nr
78 REAL(kind=dp) :: frob_matrix, frob_matrix_base
79 TYPE(cp_logger_type), POINTER :: logger
80 TYPE(dbcsr_type) :: matrix_tmp1, matrix_tmp2
81
82 CALL timeset(routinen, handle)
83
84 ! get a useful output_unit
85 logger => cp_get_default_logger()
86 IF (logger%para_env%is_source()) THEN
87 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
88 ELSE
89 unit_nr = -1
90 END IF
91
92 ! make our own copy of S
93 IF (ls_scf_env%has_unit_metric) THEN
94 CALL dbcsr_set(ls_scf_env%matrix_s, 0.0_dp)
95 CALL dbcsr_add_on_diag(ls_scf_env%matrix_s, 1.0_dp)
96 ELSE
97 CALL matrix_qs_to_ls(ls_scf_env%matrix_s, matrix_s, ls_scf_env%ls_mstruct, covariant=.true.)
98 END IF
99
100 CALL dbcsr_filter(ls_scf_env%matrix_s, ls_scf_env%eps_filter)
101
102 ! needs a preconditioner for S
103 IF (ls_scf_env%has_s_preconditioner) THEN
104 CALL dbcsr_create(ls_scf_env%matrix_bs_sqrt, template=ls_scf_env%matrix_s, &
105 matrix_type=dbcsr_type_no_symmetry)
106 CALL dbcsr_create(ls_scf_env%matrix_bs_sqrt_inv, template=ls_scf_env%matrix_s, &
107 matrix_type=dbcsr_type_no_symmetry)
108 CALL compute_matrix_preconditioner(ls_scf_env%matrix_s, &
109 ls_scf_env%s_preconditioner_type, ls_scf_env%ls_mstruct, &
110 ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv, &
111 ls_scf_env%eps_filter, ls_scf_env%s_sqrt_order, &
112 ls_scf_env%eps_lanczos, ls_scf_env%max_iter_lanczos)
113 END IF
114
115 ! precondition S
116 IF (ls_scf_env%has_s_preconditioner) THEN
117 CALL apply_matrix_preconditioner(ls_scf_env%matrix_s, "forward", &
118 ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
119 END IF
120
121 ! compute sqrt(S) and inv(sqrt(S))
122 IF (ls_scf_env%use_s_sqrt) THEN
123
124 CALL dbcsr_create(ls_scf_env%matrix_s_sqrt, template=ls_scf_env%matrix_s, &
125 matrix_type=dbcsr_type_no_symmetry)
126 CALL dbcsr_create(ls_scf_env%matrix_s_sqrt_inv, template=ls_scf_env%matrix_s, &
127 matrix_type=dbcsr_type_no_symmetry)
128
129 SELECT CASE (ls_scf_env%s_sqrt_method)
130 CASE (ls_s_sqrt_proot)
131 CALL matrix_sqrt_proot(ls_scf_env%matrix_s_sqrt, ls_scf_env%matrix_s_sqrt_inv, &
132 ls_scf_env%matrix_s, ls_scf_env%eps_filter, &
133 ls_scf_env%s_sqrt_order, &
134 ls_scf_env%eps_lanczos, ls_scf_env%max_iter_lanczos, &
135 symmetrize=.true.)
136 CASE (ls_s_sqrt_ns)
137 CALL matrix_sqrt_newton_schulz(ls_scf_env%matrix_s_sqrt, ls_scf_env%matrix_s_sqrt_inv, &
138 ls_scf_env%matrix_s, ls_scf_env%eps_filter, &
139 ls_scf_env%s_sqrt_order, &
140 ls_scf_env%eps_lanczos, ls_scf_env%max_iter_lanczos)
141 CASE DEFAULT
142 cpabort("Unknown sqrt method.")
143 END SELECT
144
145 IF (ls_scf_env%check_s_inv) THEN
146 CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, &
147 matrix_type=dbcsr_type_no_symmetry)
148 CALL dbcsr_create(matrix_tmp2, template=ls_scf_env%matrix_s, &
149 matrix_type=dbcsr_type_no_symmetry)
150
151 CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_s, &
152 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
153
154 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt_inv, &
155 0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
156
157 frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp2)
158 CALL dbcsr_add_on_diag(matrix_tmp2, -1.0_dp)
159 frob_matrix = dbcsr_frobenius_norm(matrix_tmp2)
160 IF (unit_nr > 0) THEN
161 WRITE (unit_nr, *) "Error for (inv(sqrt(S))*S*inv(sqrt(S))-I)", frob_matrix/frob_matrix_base
162 END IF
163
164 CALL dbcsr_release(matrix_tmp1)
165 CALL dbcsr_release(matrix_tmp2)
166 END IF
167 END IF
168
169 ! compute the inverse of S
170 IF (ls_scf_env%needs_s_inv) THEN
171 CALL dbcsr_create(ls_scf_env%matrix_s_inv, template=ls_scf_env%matrix_s, &
172 matrix_type=dbcsr_type_no_symmetry)
173 IF (.NOT. ls_scf_env%use_s_sqrt) THEN
174 CALL invert_hotelling(ls_scf_env%matrix_s_inv, ls_scf_env%matrix_s, ls_scf_env%eps_filter)
175 ELSE
176 CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_s_sqrt_inv, &
177 0.0_dp, ls_scf_env%matrix_s_inv, filter_eps=ls_scf_env%eps_filter)
178 END IF
179 IF (ls_scf_env%check_s_inv) THEN
180 CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, &
181 matrix_type=dbcsr_type_no_symmetry)
182 CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_inv, ls_scf_env%matrix_s, &
183 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
184 frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp1)
185 CALL dbcsr_add_on_diag(matrix_tmp1, -1.0_dp)
186 frob_matrix = dbcsr_frobenius_norm(matrix_tmp1)
187 IF (unit_nr > 0) THEN
188 WRITE (unit_nr, *) "Error for (inv(S)*S-I)", frob_matrix/frob_matrix_base
189 END IF
190 CALL dbcsr_release(matrix_tmp1)
191 END IF
192 END IF
193
194 CALL timestop(handle)
195 END SUBROUTINE ls_scf_init_matrix_s
196
197! **************************************************************************************************
198!> \brief compute for a block positive definite matrix s (bs)
199!> the sqrt(bs) and inv(sqrt(bs))
200!> \param matrix_s ...
201!> \param preconditioner_type ...
202!> \param ls_mstruct ...
203!> \param matrix_bs_sqrt ...
204!> \param matrix_bs_sqrt_inv ...
205!> \param threshold ...
206!> \param order ...
207!> \param eps_lanczos ...
208!> \param max_iter_lanczos ...
209!> \par History
210!> 2010.10 created [Joost VandeVondele]
211!> \author Joost VandeVondele
212! **************************************************************************************************
213 SUBROUTINE compute_matrix_preconditioner(matrix_s, preconditioner_type, ls_mstruct, &
214 matrix_bs_sqrt, matrix_bs_sqrt_inv, threshold, order, eps_lanczos, max_iter_lanczos)
215
216 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_s
217 INTEGER :: preconditioner_type
218 TYPE(ls_mstruct_type) :: ls_mstruct
219 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_bs_sqrt, matrix_bs_sqrt_inv
220 REAL(kind=dp) :: threshold
221 INTEGER :: order
222 REAL(kind=dp) :: eps_lanczos
223 INTEGER :: max_iter_lanczos
224
225 CHARACTER(LEN=*), PARAMETER :: routinen = 'compute_matrix_preconditioner'
226
227 INTEGER :: datatype, handle, iblock_col, iblock_row
228 LOGICAL :: block_needed
229 REAL(dp), DIMENSION(:, :), POINTER :: block_dp
230 TYPE(dbcsr_iterator_type) :: iter
231 TYPE(dbcsr_type) :: matrix_bs
232
233 CALL timeset(routinen, handle)
234
235 datatype = dbcsr_get_data_type(matrix_s) ! could be single or double precision
236
237 ! first generate a block diagonal copy of s
238 CALL dbcsr_create(matrix_bs, template=matrix_s)
239
240 SELECT CASE (preconditioner_type)
243 CALL dbcsr_iterator_start(iter, matrix_s)
244 DO WHILE (dbcsr_iterator_blocks_left(iter))
245 CALL dbcsr_iterator_next_block(iter, iblock_row, iblock_col, block_dp)
246
247 ! do we need the block ?
248 ! this depends on the preconditioner, but also the matrix clustering method employed
249 ! for a clustered matrix, right now, we assume that atomic and molecular preconditioners
250 ! are actually the same, and only require that the diagonal blocks (clustered) are present
251
252 block_needed = .false.
253
254 IF (iblock_row == iblock_col) THEN
255 block_needed = .true.
256 ELSE
257 IF (preconditioner_type == ls_s_preconditioner_molecular .AND. &
258 ls_mstruct%cluster_type == ls_cluster_atomic) THEN
259 IF (ls_mstruct%atom_to_molecule(iblock_row) == ls_mstruct%atom_to_molecule(iblock_col)) block_needed = .true.
260 END IF
261 END IF
262
263 ! add it
264 IF (block_needed) THEN
265 CALL dbcsr_put_block(matrix=matrix_bs, row=iblock_row, col=iblock_col, block=block_dp)
266 END IF
267
268 END DO
269 CALL dbcsr_iterator_stop(iter)
270 END SELECT
271
272 CALL dbcsr_finalize(matrix_bs)
273
274 SELECT CASE (preconditioner_type)
276 ! for now make it a simple identity matrix
277 CALL dbcsr_copy(matrix_bs_sqrt, matrix_bs)
278 CALL dbcsr_set(matrix_bs_sqrt, 0.0_dp)
279 CALL dbcsr_add_on_diag(matrix_bs_sqrt, 1.0_dp)
280
281 ! for now make it a simple identity matrix
282 CALL dbcsr_copy(matrix_bs_sqrt_inv, matrix_bs)
283 CALL dbcsr_set(matrix_bs_sqrt_inv, 0.0_dp)
284 CALL dbcsr_add_on_diag(matrix_bs_sqrt_inv, 1.0_dp)
286 CALL dbcsr_copy(matrix_bs_sqrt, matrix_bs)
287 CALL dbcsr_copy(matrix_bs_sqrt_inv, matrix_bs)
288 ! XXXXXXXXXXX
289 ! XXXXXXXXXXX the threshold here could be done differently,
290 ! XXXXXXXXXXX using eps_filter is reducing accuracy for no good reason, this is cheap
291 ! XXXXXXXXXXX
292 CALL matrix_sqrt_newton_schulz(matrix_bs_sqrt, matrix_bs_sqrt_inv, matrix_bs, &
293 threshold=min(threshold, 1.0e-10_dp), order=order, &
294 eps_lanczos=eps_lanczos, max_iter_lanczos=max_iter_lanczos)
295 END SELECT
296
297 CALL dbcsr_release(matrix_bs)
298
299 CALL timestop(handle)
300
301 END SUBROUTINE compute_matrix_preconditioner
302
303! **************************************************************************************************
304!> \brief apply a preconditioner either
305!> forward (precondition) inv(sqrt(bs)) * A * inv(sqrt(bs))
306!> backward (restore to old form) sqrt(bs) * A * sqrt(bs)
307!> \param matrix ...
308!> \param direction ...
309!> \param matrix_bs_sqrt ...
310!> \param matrix_bs_sqrt_inv ...
311!> \par History
312!> 2010.10 created [Joost VandeVondele]
313!> \author Joost VandeVondele
314! **************************************************************************************************
315 SUBROUTINE apply_matrix_preconditioner(matrix, direction, matrix_bs_sqrt, matrix_bs_sqrt_inv)
316
317 TYPE(dbcsr_type), INTENT(INOUT) :: matrix
318 CHARACTER(LEN=*) :: direction
319 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_bs_sqrt, matrix_bs_sqrt_inv
320
321 CHARACTER(LEN=*), PARAMETER :: routinen = 'apply_matrix_preconditioner'
322
323 INTEGER :: handle
324 TYPE(dbcsr_type) :: matrix_tmp
325
326 CALL timeset(routinen, handle)
327 CALL dbcsr_create(matrix_tmp, template=matrix, matrix_type=dbcsr_type_no_symmetry)
328
329 SELECT CASE (direction)
330 CASE ("forward")
331 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix, matrix_bs_sqrt_inv, &
332 0.0_dp, matrix_tmp)
333 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_bs_sqrt_inv, matrix_tmp, &
334 0.0_dp, matrix)
335 CASE ("backward")
336 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix, matrix_bs_sqrt, &
337 0.0_dp, matrix_tmp)
338 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_bs_sqrt, matrix_tmp, &
339 0.0_dp, matrix)
340 CASE DEFAULT
341 cpabort("")
342 END SELECT
343
344 CALL dbcsr_release(matrix_tmp)
345
346 CALL timestop(handle)
347
348 END SUBROUTINE apply_matrix_preconditioner
349
350! **************************************************************************************************
351!> \brief compute the density matrix with a trace that is close to nelectron.
352!> take a mu as input, and improve by bisection as needed.
353!> \param matrix_p ...
354!> \param mu ...
355!> \param fixed_mu ...
356!> \param sign_method ...
357!> \param sign_order ...
358!> \param matrix_ks ...
359!> \param matrix_s ...
360!> \param matrix_s_inv ...
361!> \param nelectron ...
362!> \param threshold ...
363!> \param sign_symmetric ...
364!> \param submatrix_sign_method ...
365!> \param matrix_s_sqrt_inv ...
366!> \par History
367!> 2010.10 created [Joost VandeVondele]
368!> 2020.07 support for methods with internal mu adjustment [Michael Lass]
369!> \author Joost VandeVondele
370! **************************************************************************************************
371 SUBROUTINE density_matrix_sign(matrix_p, mu, fixed_mu, sign_method, sign_order, matrix_ks, &
372 matrix_s, matrix_s_inv, nelectron, threshold, sign_symmetric, submatrix_sign_method, &
373 matrix_s_sqrt_inv)
374
375 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_p
376 REAL(kind=dp), INTENT(INOUT) :: mu
377 LOGICAL :: fixed_mu
378 INTEGER :: sign_method, sign_order
379 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_ks, matrix_s, matrix_s_inv
380 INTEGER, INTENT(IN) :: nelectron
381 REAL(kind=dp), INTENT(IN) :: threshold
382 LOGICAL, OPTIONAL :: sign_symmetric
383 INTEGER, OPTIONAL :: submatrix_sign_method
384 TYPE(dbcsr_type), INTENT(IN), OPTIONAL :: matrix_s_sqrt_inv
385
386 CHARACTER(LEN=*), PARAMETER :: routinen = 'density_matrix_sign'
387 REAL(kind=dp), PARAMETER :: initial_increment = 0.01_dp
388
389 INTEGER :: handle, iter, unit_nr, &
390 used_submatrix_sign_method
391 LOGICAL :: do_sign_symmetric, has_mu_high, &
392 has_mu_low, internal_mu_adjust
393 REAL(kind=dp) :: increment, mu_high, mu_low, trace
394 TYPE(cp_logger_type), POINTER :: logger
395
396 CALL timeset(routinen, handle)
397
398 logger => cp_get_default_logger()
399 IF (logger%para_env%is_source()) THEN
400 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
401 ELSE
402 unit_nr = -1
403 END IF
404
405 do_sign_symmetric = .false.
406 IF (PRESENT(sign_symmetric)) do_sign_symmetric = sign_symmetric
407
408 used_submatrix_sign_method = ls_scf_submatrix_sign_ns
409 IF (PRESENT(submatrix_sign_method)) used_submatrix_sign_method = submatrix_sign_method
410
411 internal_mu_adjust = ((sign_method .EQ. ls_scf_sign_submatrix) .AND. &
412 (used_submatrix_sign_method .EQ. ls_scf_submatrix_sign_direct_muadj .OR. &
413 used_submatrix_sign_method .EQ. ls_scf_submatrix_sign_direct_muadj_lowmem))
414
415 IF (internal_mu_adjust) THEN
416 CALL density_matrix_sign_internal_mu(matrix_p, trace, mu, sign_method, &
417 matrix_ks, matrix_s, threshold, &
418 used_submatrix_sign_method, &
419 nelectron, matrix_s_sqrt_inv)
420 ELSE
421 increment = initial_increment
422
423 has_mu_low = .false.
424 has_mu_high = .false.
425
426 ! bisect if both bounds are known, otherwise find the bounds with a linear search
427 DO iter = 1, 30
428 IF (has_mu_low .AND. has_mu_high) THEN
429 mu = (mu_low + mu_high)/2
430 IF (abs(mu_high - mu_low) < threshold) EXIT
431 END IF
432
433 CALL density_matrix_sign_fixed_mu(matrix_p, trace, mu, sign_method, sign_order, &
434 matrix_ks, matrix_s, matrix_s_inv, threshold, &
435 do_sign_symmetric, used_submatrix_sign_method, &
436 matrix_s_sqrt_inv)
437 IF (unit_nr > 0) WRITE (unit_nr, '(T2,A,I2,1X,F13.9,1X,F15.9)') &
438 "Density matrix: iter, mu, trace error: ", iter, mu, trace - nelectron
439
440 ! OK, we can skip early if we are as close as possible to the exact result
441 ! smaller differences should be considered 'noise'
442 IF (abs(trace - nelectron) < 0.5_dp .OR. fixed_mu) EXIT
443
444 IF (trace < nelectron) THEN
445 mu_low = mu
446 mu = mu + increment
447 has_mu_low = .true.
448 increment = increment*2
449 ELSE
450 mu_high = mu
451 mu = mu - increment
452 has_mu_high = .true.
453 increment = increment*2
454 END IF
455 END DO
456
457 END IF
458
459 CALL timestop(handle)
460
461 END SUBROUTINE density_matrix_sign
462
463! **************************************************************************************************
464!> \brief for a fixed mu, compute the corresponding density matrix and its trace
465!> \param matrix_p ...
466!> \param trace ...
467!> \param mu ...
468!> \param sign_method ...
469!> \param sign_order ...
470!> \param matrix_ks ...
471!> \param matrix_s ...
472!> \param matrix_s_inv ...
473!> \param threshold ...
474!> \param sign_symmetric ...
475!> \param submatrix_sign_method ...
476!> \param matrix_s_sqrt_inv ...
477!> \par History
478!> 2010.10 created [Joost VandeVondele]
479!> \author Joost VandeVondele
480! **************************************************************************************************
481 SUBROUTINE density_matrix_sign_fixed_mu(matrix_p, trace, mu, sign_method, sign_order, matrix_ks, &
482 matrix_s, matrix_s_inv, threshold, sign_symmetric, submatrix_sign_method, &
483 matrix_s_sqrt_inv)
484
485 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_p
486 REAL(kind=dp), INTENT(OUT) :: trace
487 REAL(kind=dp), INTENT(INOUT) :: mu
488 INTEGER :: sign_method, sign_order
489 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_ks, matrix_s, matrix_s_inv
490 REAL(kind=dp), INTENT(IN) :: threshold
491 LOGICAL :: sign_symmetric
492 INTEGER :: submatrix_sign_method
493 TYPE(dbcsr_type), INTENT(IN), OPTIONAL :: matrix_s_sqrt_inv
494
495 CHARACTER(LEN=*), PARAMETER :: routinen = 'density_matrix_sign_fixed_mu'
496
497 INTEGER :: handle, unit_nr
498 REAL(kind=dp) :: frob_matrix
499 TYPE(cp_logger_type), POINTER :: logger
500 TYPE(dbcsr_type) :: matrix_p_ud, matrix_sign, matrix_sinv_ks, matrix_ssqrtinv_ks_ssqrtinv, &
501 matrix_ssqrtinv_ks_ssqrtinv2, matrix_tmp
502
503 CALL timeset(routinen, handle)
504
505 logger => cp_get_default_logger()
506 IF (logger%para_env%is_source()) THEN
507 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
508 ELSE
509 unit_nr = -1
510 END IF
511
512 CALL dbcsr_create(matrix_sign, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
513
514 IF (sign_symmetric) THEN
515
516 IF (.NOT. PRESENT(matrix_s_sqrt_inv)) &
517 cpabort("Argument matrix_s_sqrt_inv required if sign_symmetric is set")
518
519 CALL dbcsr_create(matrix_ssqrtinv_ks_ssqrtinv, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
520 CALL dbcsr_create(matrix_ssqrtinv_ks_ssqrtinv2, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
521 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_sqrt_inv, matrix_ks, &
522 0.0_dp, matrix_ssqrtinv_ks_ssqrtinv2, filter_eps=threshold)
523 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_ssqrtinv_ks_ssqrtinv2, matrix_s_sqrt_inv, &
524 0.0_dp, matrix_ssqrtinv_ks_ssqrtinv, filter_eps=threshold)
525 CALL dbcsr_add_on_diag(matrix_ssqrtinv_ks_ssqrtinv, -mu)
526
527 SELECT CASE (sign_method)
528 CASE (ls_scf_sign_ns)
529 CALL matrix_sign_newton_schulz(matrix_sign, matrix_ssqrtinv_ks_ssqrtinv, threshold, sign_order)
530 CASE (ls_scf_sign_proot)
531 CALL matrix_sign_proot(matrix_sign, matrix_ssqrtinv_ks_ssqrtinv, threshold, sign_order)
533 CALL matrix_sign_submatrix(matrix_sign, matrix_ssqrtinv_ks_ssqrtinv, threshold, sign_order, submatrix_sign_method)
534 CASE DEFAULT
535 cpabort("Unkown sign method.")
536 END SELECT
537 CALL dbcsr_release(matrix_ssqrtinv_ks_ssqrtinv)
538 CALL dbcsr_release(matrix_ssqrtinv_ks_ssqrtinv2)
539
540 ELSE ! .NOT. sign_symmetric
541 ! get inv(S)*H-I*mu
542 CALL dbcsr_create(matrix_sinv_ks, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
543 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_inv, matrix_ks, &
544 0.0_dp, matrix_sinv_ks, filter_eps=threshold)
545 CALL dbcsr_add_on_diag(matrix_sinv_ks, -mu)
546
547 ! compute sign(inv(S)*H-I*mu)
548 SELECT CASE (sign_method)
549 CASE (ls_scf_sign_ns)
550 CALL matrix_sign_newton_schulz(matrix_sign, matrix_sinv_ks, threshold, sign_order)
551 CASE (ls_scf_sign_proot)
552 CALL matrix_sign_proot(matrix_sign, matrix_sinv_ks, threshold, sign_order)
554 CALL matrix_sign_submatrix(matrix_sign, matrix_sinv_ks, threshold, sign_order, submatrix_sign_method)
555 CASE DEFAULT
556 cpabort("Unkown sign method.")
557 END SELECT
558 CALL dbcsr_release(matrix_sinv_ks)
559 END IF
560
561 ! now construct the density matrix PS=0.5*(I-sign(inv(S)H-I*mu))
562 CALL dbcsr_create(matrix_p_ud, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
563 CALL dbcsr_copy(matrix_p_ud, matrix_sign)
564 CALL dbcsr_scale(matrix_p_ud, -0.5_dp)
565 CALL dbcsr_add_on_diag(matrix_p_ud, 0.5_dp)
566 CALL dbcsr_release(matrix_sign)
567
568 ! we now have PS, lets get its trace
569 CALL dbcsr_trace(matrix_p_ud, trace)
570
571 ! we can also check it is idempotent PS*PS=PS
572 CALL dbcsr_create(matrix_tmp, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
573 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_p_ud, matrix_p_ud, &
574 0.0_dp, matrix_tmp, filter_eps=threshold)
575 CALL dbcsr_add(matrix_tmp, matrix_p_ud, 1.0_dp, -1.0_dp)
576 frob_matrix = dbcsr_frobenius_norm(matrix_tmp)
577 IF (unit_nr > 0) WRITE (unit_nr, '(T2,A,F20.12)') "Deviation from idempotency: ", frob_matrix
578
579 IF (sign_symmetric) THEN
580 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_sqrt_inv, matrix_p_ud, &
581 0.0_dp, matrix_tmp, filter_eps=threshold)
582 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp, matrix_s_sqrt_inv, &
583 0.0_dp, matrix_p, filter_eps=threshold)
584 ELSE
585
586 ! get P=PS*inv(S)
587 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_p_ud, matrix_s_inv, &
588 0.0_dp, matrix_p, filter_eps=threshold)
589 END IF
590 CALL dbcsr_release(matrix_p_ud)
591 CALL dbcsr_release(matrix_tmp)
592
593 CALL timestop(handle)
594
595 END SUBROUTINE density_matrix_sign_fixed_mu
596
597! **************************************************************************************************
598!> \brief compute the corresponding density matrix and its trace, using methods with internal mu adjustment
599!> \param matrix_p ...
600!> \param trace ...
601!> \param mu ...
602!> \param sign_method ...
603!> \param matrix_ks ...
604!> \param matrix_s ...
605!> \param threshold ...
606!> \param submatrix_sign_method ...
607!> \param nelectron ...
608!> \param matrix_s_sqrt_inv ...
609!> \par History
610!> 2020.07 created, based on density_matrix_sign_fixed_mu [Michael Lass]
611!> \author Michael Lass
612! **************************************************************************************************
613 SUBROUTINE density_matrix_sign_internal_mu(matrix_p, trace, mu, sign_method, matrix_ks, &
614 matrix_s, threshold, submatrix_sign_method, &
615 nelectron, matrix_s_sqrt_inv)
616
617 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_p
618 REAL(kind=dp), INTENT(OUT) :: trace
619 REAL(kind=dp), INTENT(INOUT) :: mu
620 INTEGER :: sign_method
621 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_ks, matrix_s
622 REAL(kind=dp), INTENT(IN) :: threshold
623 INTEGER :: submatrix_sign_method
624 INTEGER, INTENT(IN) :: nelectron
625 TYPE(dbcsr_type), INTENT(IN) :: matrix_s_sqrt_inv
626
627 CHARACTER(LEN=*), PARAMETER :: routinen = 'density_matrix_sign_internal_mu'
628
629 INTEGER :: handle, unit_nr
630 REAL(kind=dp) :: frob_matrix
631 TYPE(cp_logger_type), POINTER :: logger
632 TYPE(dbcsr_type) :: matrix_p_ud, matrix_sign, &
633 matrix_ssqrtinv_ks_ssqrtinv, &
634 matrix_ssqrtinv_ks_ssqrtinv2, &
635 matrix_tmp
636
637 CALL timeset(routinen, handle)
638
639 logger => cp_get_default_logger()
640 IF (logger%para_env%is_source()) THEN
641 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
642 ELSE
643 unit_nr = -1
644 END IF
645
646 CALL dbcsr_create(matrix_sign, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
647
648 CALL dbcsr_create(matrix_ssqrtinv_ks_ssqrtinv, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
649 CALL dbcsr_create(matrix_ssqrtinv_ks_ssqrtinv2, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
650 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_sqrt_inv, matrix_ks, &
651 0.0_dp, matrix_ssqrtinv_ks_ssqrtinv2, filter_eps=threshold)
652 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_ssqrtinv_ks_ssqrtinv2, matrix_s_sqrt_inv, &
653 0.0_dp, matrix_ssqrtinv_ks_ssqrtinv, filter_eps=threshold)
654 CALL dbcsr_add_on_diag(matrix_ssqrtinv_ks_ssqrtinv, -mu)
655
656 SELECT CASE (sign_method)
658 SELECT CASE (submatrix_sign_method)
660 CALL matrix_sign_submatrix_mu_adjust(matrix_sign, matrix_ssqrtinv_ks_ssqrtinv, mu, nelectron, threshold, &
661 submatrix_sign_method)
662 CASE DEFAULT
663 cpabort("density_matrix_sign_internal_mu called with invalid submatrix sign method")
664 END SELECT
665 CASE DEFAULT
666 cpabort("density_matrix_sign_internal_mu called with invalid sign method.")
667 END SELECT
668 CALL dbcsr_release(matrix_ssqrtinv_ks_ssqrtinv)
669 CALL dbcsr_release(matrix_ssqrtinv_ks_ssqrtinv2)
670
671 ! now construct the density matrix PS=0.5*(I-sign(inv(S)H-I*mu))
672 CALL dbcsr_create(matrix_p_ud, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
673 CALL dbcsr_copy(matrix_p_ud, matrix_sign)
674 CALL dbcsr_scale(matrix_p_ud, -0.5_dp)
675 CALL dbcsr_add_on_diag(matrix_p_ud, 0.5_dp)
676 CALL dbcsr_release(matrix_sign)
677
678 ! we now have PS, lets get its trace
679 CALL dbcsr_trace(matrix_p_ud, trace)
680
681 ! we can also check it is idempotent PS*PS=PS
682 CALL dbcsr_create(matrix_tmp, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
683 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_p_ud, matrix_p_ud, &
684 0.0_dp, matrix_tmp, filter_eps=threshold)
685 CALL dbcsr_add(matrix_tmp, matrix_p_ud, 1.0_dp, -1.0_dp)
686 frob_matrix = dbcsr_frobenius_norm(matrix_tmp)
687 IF (unit_nr > 0) WRITE (unit_nr, '(T2,A,F20.12)') "Deviation from idempotency: ", frob_matrix
688
689 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_sqrt_inv, matrix_p_ud, &
690 0.0_dp, matrix_tmp, filter_eps=threshold)
691 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp, matrix_s_sqrt_inv, &
692 0.0_dp, matrix_p, filter_eps=threshold)
693 CALL dbcsr_release(matrix_p_ud)
694 CALL dbcsr_release(matrix_tmp)
695
696 CALL timestop(handle)
697
698 END SUBROUTINE density_matrix_sign_internal_mu
699
700! **************************************************************************************************
701!> \brief compute the density matrix using a trace-resetting algorithm
702!> \param matrix_p ...
703!> \param matrix_ks ...
704!> \param matrix_s_sqrt_inv ...
705!> \param nelectron ...
706!> \param threshold ...
707!> \param e_homo ...
708!> \param e_lumo ...
709!> \param e_mu ...
710!> \param dynamic_threshold ...
711!> \param matrix_ks_deviation ...
712!> \param max_iter_lanczos ...
713!> \param eps_lanczos ...
714!> \param converged ...
715!> \par History
716!> 2012.06 created [Florian Thoele]
717!> \author Florian Thoele
718! **************************************************************************************************
719 SUBROUTINE density_matrix_trs4(matrix_p, matrix_ks, matrix_s_sqrt_inv, &
720 nelectron, threshold, e_homo, e_lumo, e_mu, &
721 dynamic_threshold, matrix_ks_deviation, &
722 max_iter_lanczos, eps_lanczos, converged)
723
724 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_p
725 TYPE(dbcsr_type), INTENT(IN) :: matrix_ks, matrix_s_sqrt_inv
726 INTEGER, INTENT(IN) :: nelectron
727 REAL(kind=dp), INTENT(IN) :: threshold
728 REAL(kind=dp), INTENT(INOUT) :: e_homo, e_lumo, e_mu
729 LOGICAL, INTENT(IN), OPTIONAL :: dynamic_threshold
730 TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL :: matrix_ks_deviation
731 INTEGER, INTENT(IN) :: max_iter_lanczos
732 REAL(kind=dp), INTENT(IN) :: eps_lanczos
733 LOGICAL, INTENT(OUT), OPTIONAL :: converged
734
735 CHARACTER(LEN=*), PARAMETER :: routinen = 'density_matrix_trs4'
736 INTEGER, PARAMETER :: max_iter = 100
737 REAL(kind=dp), PARAMETER :: gamma_max = 6.0_dp, gamma_min = 0.0_dp
738
739 INTEGER :: branch, estimated_steps, handle, i, j, &
740 unit_nr
741 INTEGER(kind=int_8) :: flop1, flop2
742 LOGICAL :: arnoldi_converged, do_dyn_threshold
743 REAL(kind=dp) :: current_threshold, delta_n, eps_max, eps_min, est_threshold, frob_id, &
744 frob_x, gam, homo, lumo, max_eig, max_threshold, maxdev, maxev, min_eig, minev, mmin, mu, &
745 mu_a, mu_b, mu_c, mu_fa, mu_fc, occ_matrix, scaled_homo_bound, scaled_lumo_bound, t1, t2, &
746 trace_fx, trace_gx, xi
747 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: gamma_values
748 TYPE(cp_logger_type), POINTER :: logger
749 TYPE(dbcsr_type) :: matrix_k0, matrix_x, matrix_x_nosym, &
750 matrix_xidsq, matrix_xsq, tmp_gx
751
752 IF (nelectron == 0) THEN
753 CALL dbcsr_set(matrix_p, 0.0_dp)
754 RETURN
755 END IF
756
757 CALL timeset(routinen, handle)
758
759 logger => cp_get_default_logger()
760 IF (logger%para_env%is_source()) THEN
761 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
762 ELSE
763 unit_nr = -1
764 END IF
765
766 do_dyn_threshold = .false.
767 IF (PRESENT(dynamic_threshold)) do_dyn_threshold = dynamic_threshold
768
769 IF (PRESENT(converged)) converged = .false.
770
771 ! init X = (eps_n*I - H)/(eps_n - eps_0) ... H* = S^-1/2*H*S^-1/2
772 CALL dbcsr_create(matrix_x, template=matrix_ks, matrix_type="S")
773
774 ! at some points the non-symmetric version of x is required
775 CALL dbcsr_create(matrix_x_nosym, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
776
777 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_sqrt_inv, matrix_ks, &
778 0.0_dp, matrix_x_nosym, filter_eps=threshold)
779 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_x_nosym, matrix_s_sqrt_inv, &
780 0.0_dp, matrix_x, filter_eps=threshold)
781 CALL dbcsr_desymmetrize(matrix_x, matrix_x_nosym)
782
783 CALL dbcsr_create(matrix_k0, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
784 CALL dbcsr_copy(matrix_k0, matrix_x_nosym)
785
786 ! compute the deviation in the mixed matrix, as seen in the ortho basis
787 IF (do_dyn_threshold) THEN
788 cpassert(PRESENT(matrix_ks_deviation))
789 CALL dbcsr_add(matrix_ks_deviation, matrix_x_nosym, -1.0_dp, 1.0_dp)
790 CALL arnoldi_extremal(matrix_ks_deviation, maxev, minev, max_iter=max_iter_lanczos, threshold=eps_lanczos, &
791 converged=arnoldi_converged)
792 maxdev = max(abs(maxev), abs(minev))
793 IF (unit_nr > 0) THEN
794 WRITE (unit_nr, '(T6,A,1X,L12)') "Lanczos converged: ", arnoldi_converged
795 WRITE (unit_nr, '(T6,A,1X,F12.5)') "change in mixed matrix: ", maxdev
796 WRITE (unit_nr, '(T6,A,1X,F12.5)') "HOMO upper bound: ", e_homo + maxdev
797 WRITE (unit_nr, '(T6,A,1X,F12.5)') "LUMO lower bound: ", e_lumo - maxdev
798 WRITE (unit_nr, '(T6,A,1X,L12)') "Predicts a gap ? ", ((e_lumo - maxdev) - (e_homo + maxdev)) > 0
799 END IF
800 ! save the old mixed matrix
801 CALL dbcsr_copy(matrix_ks_deviation, matrix_x_nosym)
802
803 END IF
804
805 ! get largest/smallest eigenvalues for scaling
806 CALL arnoldi_extremal(matrix_x_nosym, max_eig, min_eig, max_iter=max_iter_lanczos, threshold=eps_lanczos, &
807 converged=arnoldi_converged)
808 IF (unit_nr > 0) WRITE (unit_nr, '(T6,A,1X,2F12.5,1X,A,1X,L1)') "Est. extremal eigenvalues", &
809 min_eig, max_eig, " converged: ", arnoldi_converged
810 eps_max = max_eig
811 eps_min = min_eig
812
813 ! scale KS matrix
814 IF (eps_max == eps_min) THEN
815 CALL dbcsr_scale(matrix_x, 1.0_dp/eps_max)
816 ELSE
817 CALL dbcsr_add_on_diag(matrix_x, -eps_max)
818 CALL dbcsr_scale(matrix_x, -1.0_dp/(eps_max - eps_min))
819 END IF
820
821 current_threshold = threshold
822 IF (do_dyn_threshold) THEN
823 ! scale bounds for HOMO/LUMO
824 scaled_homo_bound = (eps_max - (e_homo + maxdev))/(eps_max - eps_min)
825 scaled_lumo_bound = (eps_max - (e_lumo - maxdev))/(eps_max - eps_min)
826 END IF
827
828 CALL dbcsr_create(matrix_xsq, template=matrix_ks, matrix_type="S")
829
830 CALL dbcsr_create(matrix_xidsq, template=matrix_ks, matrix_type="S")
831
832 CALL dbcsr_create(tmp_gx, template=matrix_ks, matrix_type="S")
833
834 ALLOCATE (gamma_values(max_iter))
835
836 DO i = 1, max_iter
837 t1 = m_walltime()
838 flop1 = 0; flop2 = 0
839
840 ! get X*X
841 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_x, matrix_x, &
842 0.0_dp, matrix_xsq, &
843 filter_eps=current_threshold, flop=flop1)
844
845 ! intermediate use matrix_xidsq to compute = X*X-X
846 CALL dbcsr_copy(matrix_xidsq, matrix_x)
847 CALL dbcsr_add(matrix_xidsq, matrix_xsq, -1.0_dp, 1.0_dp)
848 frob_id = dbcsr_frobenius_norm(matrix_xidsq)
849 frob_x = dbcsr_frobenius_norm(matrix_x)
850
851 ! xidsq = (1-X)*(1-X)
852 ! use (1-x)*(1-x) = 1 + x*x - 2*x
853 CALL dbcsr_copy(matrix_xidsq, matrix_x)
854 CALL dbcsr_add(matrix_xidsq, matrix_xsq, -2.0_dp, 1.0_dp)
855 CALL dbcsr_add_on_diag(matrix_xidsq, 1.0_dp)
856
857 ! tmp_gx = 4X-3X*X
858 CALL dbcsr_copy(tmp_gx, matrix_x)
859 CALL dbcsr_add(tmp_gx, matrix_xsq, 4.0_dp, -3.0_dp)
860
861 ! get gamma
862 ! Tr(F) = Tr(XX*tmp_gx) Tr(G) is equivalent
863 CALL dbcsr_dot(matrix_xsq, matrix_xidsq, trace_gx)
864 CALL dbcsr_dot(matrix_xsq, tmp_gx, trace_fx)
865
866 ! if converged, and gam becomes noisy, fix it to 3, which results in a final McWeeny step.
867 ! do this only if the electron count is reasonable.
868 ! maybe tune if the current criterion is not good enough
869 delta_n = nelectron - trace_fx
870 ! condition: ABS(frob_id/frob_x) < SQRT(threshold) ...
871 IF (((frob_id*frob_id) < (threshold*frob_x*frob_x)) .AND. (abs(delta_n) < 0.5_dp)) THEN
872 gam = 3.0_dp
873 ELSE IF (abs(delta_n) < 1e-14_dp) THEN
874 gam = 0.0_dp ! rare case of perfect electron count
875 ELSE
876 ! make sure, we don't divide by zero, as soon as gam is outside the interval gam_min,gam_max, it doesn't matter
877 gam = delta_n/max(trace_gx, abs(delta_n)/100)
878 END IF
879 gamma_values(i) = gam
880
881 IF (unit_nr > 0 .AND. .false.) THEN
882 WRITE (unit_nr, *) "trace_fx", trace_fx, "trace_gx", trace_gx, "gam", gam, &
883 "frob_id", frob_id, "conv", abs(frob_id/frob_x)
884 END IF
885
886 IF (do_dyn_threshold) THEN
887 ! quantities used for dynamic thresholding, when the estimated gap is larger than zero
888 xi = (scaled_homo_bound - scaled_lumo_bound)
889 IF (xi > 0.0_dp) THEN
890 mmin = 0.5*(scaled_homo_bound + scaled_lumo_bound)
891 max_threshold = abs(1 - 2*mmin)*xi
892
893 scaled_homo_bound = evaluate_trs4_polynomial(scaled_homo_bound, gamma_values(i:), 1)
894 scaled_lumo_bound = evaluate_trs4_polynomial(scaled_lumo_bound, gamma_values(i:), 1)
895 estimated_steps = estimate_steps(scaled_homo_bound, scaled_lumo_bound, threshold)
896
897 est_threshold = (threshold/(estimated_steps + i + 1))*xi/(1 + threshold/(estimated_steps + i + 1))
898 est_threshold = min(max_threshold, est_threshold)
899 IF (i > 1) est_threshold = max(est_threshold, 0.1_dp*current_threshold)
900 current_threshold = est_threshold
901 ELSE
902 current_threshold = threshold
903 END IF
904 END IF
905
906 IF (gam > gamma_max) THEN
907 ! Xn+1 = 2X-X*X
908 CALL dbcsr_add(matrix_x, matrix_xsq, 2.0_dp, -1.0_dp)
909 CALL dbcsr_filter(matrix_x, current_threshold)
910 branch = 1
911 ELSE IF (gam < gamma_min) THEN
912 ! Xn+1 = X*X
913 CALL dbcsr_copy(matrix_x, matrix_xsq)
914 branch = 2
915 ELSE
916 ! Xn+1 = F(X) + gam*G(X)
917 CALL dbcsr_add(tmp_gx, matrix_xidsq, 1.0_dp, gam)
918 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_xsq, tmp_gx, &
919 0.0_dp, matrix_x, &
920 flop=flop2, filter_eps=current_threshold)
921 branch = 3
922 END IF
923
924 occ_matrix = dbcsr_get_occupation(matrix_x)
925 t2 = m_walltime()
926 IF (unit_nr > 0) THEN
927 WRITE (unit_nr, &
928 '(T6,A,I3,1X,F10.8,E12.3,F12.3,F13.3,E12.3)') "TRS4 it ", &
929 i, occ_matrix, abs(trace_gx), t2 - t1, &
930 (flop1 + flop2)/(1.0e6_dp*max(t2 - t1, 0.001_dp)), current_threshold
931 CALL m_flush(unit_nr)
932 END IF
933
934 IF (abnormal_value(trace_gx)) &
935 cpabort("trace_gx is an abnormal value (NaN/Inf).")
936
937 ! a branch of 1 or 2 appears to lead to a less accurate electron number count and premature exit
938 ! if it turns out this does not exit because we get stuck in branch 1/2 for a reason we need to refine further
939 ! condition: ABS(frob_id/frob_x) < SQRT(threshold) ...
940 IF ((frob_id*frob_id) < (threshold*frob_x*frob_x) .AND. branch == 3 .AND. (abs(delta_n) < 0.5_dp)) THEN
941 IF (PRESENT(converged)) converged = .true.
942 EXIT
943 END IF
944
945 END DO
946
947 occ_matrix = dbcsr_get_occupation(matrix_x)
948 IF (unit_nr > 0) WRITE (unit_nr, '(T6,A,I3,1X,F10.8,E12.3)') 'Final TRS4 iteration ', i, occ_matrix, abs(trace_gx)
949
950 ! free some memory
951 CALL dbcsr_release(tmp_gx)
952 CALL dbcsr_release(matrix_xsq)
953 CALL dbcsr_release(matrix_xidsq)
954
955 ! output to matrix_p, P = inv(S)^0.5 X inv(S)^0.5
956 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_x, matrix_s_sqrt_inv, &
957 0.0_dp, matrix_x_nosym, filter_eps=threshold)
958 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_sqrt_inv, matrix_x_nosym, &
959 0.0_dp, matrix_p, filter_eps=threshold)
960
961 ! calculate the chemical potential by doing a bisection of fk(x0)-0.5, where fk is evaluated using the stored values for gamma
962 ! E. Rubensson et al., Chem Phys Lett 432, 2006, 591-594
963 mu_a = 0.0_dp; mu_b = 1.0_dp;
964 mu_fa = evaluate_trs4_polynomial(mu_a, gamma_values, i - 1) - 0.5_dp
965 DO j = 1, 40
966 mu_c = 0.5*(mu_a + mu_b)
967 mu_fc = evaluate_trs4_polynomial(mu_c, gamma_values, i - 1) - 0.5_dp ! i-1 because in the last iteration, only convergence is checked
968 IF (abs(mu_fc) < 1.0e-6_dp .OR. (mu_b - mu_a)/2 < 1.0e-6_dp) EXIT !TODO: define threshold values
969
970 IF (mu_fc*mu_fa > 0) THEN
971 mu_a = mu_c
972 mu_fa = mu_fc
973 ELSE
974 mu_b = mu_c
975 END IF
976 END DO
977 mu = (eps_min - eps_max)*mu_c + eps_max
978 DEALLOCATE (gamma_values)
979 IF (unit_nr > 0) THEN
980 WRITE (unit_nr, '(T6,A,1X,F12.5)') 'Chemical potential (mu): ', mu
981 END IF
982 e_mu = mu
983
984 IF (do_dyn_threshold) THEN
985 CALL dbcsr_desymmetrize(matrix_x, matrix_x_nosym)
986 CALL compute_homo_lumo(matrix_k0, matrix_x_nosym, eps_min, eps_max, &
987 threshold, max_iter_lanczos, eps_lanczos, homo, lumo, unit_nr)
988 e_homo = homo
989 e_lumo = lumo
990 END IF
991
992 CALL dbcsr_release(matrix_x)
993 CALL dbcsr_release(matrix_x_nosym)
994 CALL dbcsr_release(matrix_k0)
995 CALL timestop(handle)
996
997 END SUBROUTINE density_matrix_trs4
998
999! **************************************************************************************************
1000!> \brief compute the density matrix using a non monotonic trace conserving
1001!> algorithm based on SIAM DOI. 10.1137/130911585.
1002!> 2014.04 created [Jonathan Mullin]
1003!> \param matrix_p ...
1004!> \param matrix_ks ...
1005!> \param matrix_s_sqrt_inv ...
1006!> \param nelectron ...
1007!> \param threshold ...
1008!> \param e_homo ...
1009!> \param e_lumo ...
1010!> \param non_monotonic ...
1011!> \param eps_lanczos ...
1012!> \param max_iter_lanczos ...
1013!> \author Jonathan Mullin
1014! **************************************************************************************************
1015 SUBROUTINE density_matrix_tc2(matrix_p, matrix_ks, matrix_s_sqrt_inv, &
1016 nelectron, threshold, e_homo, e_lumo, &
1017 non_monotonic, eps_lanczos, max_iter_lanczos)
1018
1019 TYPE(dbcsr_type), INTENT(INOUT) :: matrix_p
1020 TYPE(dbcsr_type), INTENT(IN) :: matrix_ks, matrix_s_sqrt_inv
1021 INTEGER, INTENT(IN) :: nelectron
1022 REAL(kind=dp), INTENT(IN) :: threshold
1023 REAL(kind=dp), INTENT(INOUT) :: e_homo, e_lumo
1024 LOGICAL, INTENT(IN), OPTIONAL :: non_monotonic
1025 REAL(kind=dp), INTENT(IN) :: eps_lanczos
1026 INTEGER, INTENT(IN) :: max_iter_lanczos
1027
1028 CHARACTER(LEN=*), PARAMETER :: routinen = 'density_matrix_tc2'
1029 INTEGER, PARAMETER :: max_iter = 100
1030
1031 INTEGER :: handle, i, j, k, unit_nr
1032 INTEGER(kind=int_8) :: flop1, flop2
1033 LOGICAL :: converged, do_non_monotonic
1034 REAL(kind=dp) :: beta, betab, eps_max, eps_min, gama, &
1035 max_eig, min_eig, occ_matrix, t1, t2, &
1036 trace_fx, trace_gx
1037 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: alpha, lambda, nu, poly, wu, x, y
1038 TYPE(cp_logger_type), POINTER :: logger
1039 TYPE(dbcsr_type) :: matrix_tmp, matrix_x, matrix_xsq
1040
1041 CALL timeset(routinen, handle)
1042
1043 logger => cp_get_default_logger()
1044 IF (logger%para_env%is_source()) THEN
1045 unit_nr = cp_logger_get_default_unit_nr(logger, local=.true.)
1046 ELSE
1047 unit_nr = -1
1048 END IF
1049
1050 do_non_monotonic = .false.
1051 IF (PRESENT(non_monotonic)) do_non_monotonic = non_monotonic
1052
1053 ! init X = (eps_n*I - H)/(eps_n - eps_0) ... H* = S^-1/2*H*S^-1/2
1054 CALL dbcsr_create(matrix_x, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
1055 CALL dbcsr_create(matrix_xsq, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
1056
1057 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_sqrt_inv, matrix_ks, &
1058 0.0_dp, matrix_xsq, filter_eps=threshold)
1059 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_xsq, matrix_s_sqrt_inv, &
1060 0.0_dp, matrix_x, filter_eps=threshold)
1061
1062 IF (unit_nr > 0) THEN
1063 WRITE (unit_nr, '(T6,A,1X,F12.5)') "HOMO upper bound: ", e_homo
1064 WRITE (unit_nr, '(T6,A,1X,F12.5)') "LUMO lower bound: ", e_lumo
1065 WRITE (unit_nr, '(T6,A,1X,L12)') "Predicts a gap ? ", ((e_lumo) - (e_homo)) > 0
1066 END IF
1067
1068 ! get largest/smallest eigenvalues for scaling
1069 CALL arnoldi_extremal(matrix_x, max_eig, min_eig, max_iter=max_iter_lanczos, threshold=eps_lanczos, &
1070 converged=converged)
1071 IF (unit_nr > 0) WRITE (unit_nr, '(T6,A,1X,2F12.5,1X,A,1X,L1)') "Est. extremal eigenvalues", &
1072 min_eig, max_eig, " converged: ", converged
1073
1074 eps_max = max_eig
1075 eps_min = min_eig
1076
1077 ! scale KS matrix
1078 CALL dbcsr_scale(matrix_x, -1.0_dp)
1079 CALL dbcsr_add_on_diag(matrix_x, eps_max)
1080 CALL dbcsr_scale(matrix_x, 1/(eps_max - eps_min))
1081
1082 CALL dbcsr_copy(matrix_xsq, matrix_x)
1083
1084 CALL dbcsr_create(matrix_tmp, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
1085
1086 ALLOCATE (poly(max_iter))
1087 ALLOCATE (nu(max_iter))
1088 ALLOCATE (wu(max_iter))
1089 ALLOCATE (alpha(max_iter))
1090 ALLOCATE (x(4))
1091 ALLOCATE (y(4))
1092 ALLOCATE (lambda(4))
1093
1094! Controls over the non_monotonic bounds, First if low gap, bias slightly
1095 beta = (eps_max - abs(e_lumo))/(eps_max - eps_min)
1096 betab = (eps_max + abs(e_homo))/(eps_max - eps_min)
1097
1098 IF ((beta - betab) < 0.005_dp) THEN
1099 beta = beta - 0.002_dp
1100 betab = betab + 0.002_dp
1101 END IF
1102! Check if input specifies to use monotonic bounds.
1103 IF (.NOT. do_non_monotonic) THEN
1104 beta = 0.0_dp
1105 betab = 1.0_dp
1106 END IF
1107! initial SCF cycle has no reliable estimate of homo/lumo, force monotinic bounds.
1108 IF (e_homo == 0.0_dp) THEN
1109 beta = 0.0_dp
1110 betab = 1.0_dp
1111 END IF
1112
1113 ! init to take true branch first
1114 trace_fx = nelectron
1115 trace_gx = 0
1116
1117 DO i = 1, max_iter
1118 t1 = m_walltime()
1119 flop1 = 0; flop2 = 0
1120
1121 IF (abs(trace_fx - nelectron) <= abs(trace_gx - nelectron)) THEN
1122! Xn+1 = (aX+ (1-a)I)^2
1123 poly(i) = 1.0_dp
1124 alpha(i) = 2.0_dp/(2.0_dp - beta)
1125
1126 CALL dbcsr_scale(matrix_x, alpha(i))
1127 CALL dbcsr_add_on_diag(matrix_x, 1.0_dp - alpha(i))
1128 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_x, matrix_x, &
1129 0.0_dp, matrix_xsq, &
1130 filter_eps=threshold, flop=flop1)
1131
1132!save X for control variables
1133 CALL dbcsr_copy(matrix_tmp, matrix_x)
1134
1135 CALL dbcsr_copy(matrix_x, matrix_xsq)
1136
1137 beta = (1.0_dp - alpha(i)) + alpha(i)*beta
1138 beta = beta*beta
1139 betab = (1.0_dp - alpha(i)) + alpha(i)*betab
1140 betab = betab*betab
1141 ELSE
1142! Xn+1 = 2aX-a^2*X^2
1143 poly(i) = 0.0_dp
1144 alpha(i) = 2.0_dp/(1.0_dp + betab)
1145
1146 CALL dbcsr_scale(matrix_x, alpha(i))
1147 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_x, matrix_x, &
1148 0.0_dp, matrix_xsq, &
1149 filter_eps=threshold, flop=flop1)
1150
1151!save X for control variables
1152 CALL dbcsr_copy(matrix_tmp, matrix_x)
1153!
1154 CALL dbcsr_add(matrix_x, matrix_xsq, 2.0_dp, -1.0_dp)
1155
1156 beta = alpha(i)*beta
1157 beta = 2.0_dp*beta - beta*beta
1158 betab = alpha(i)*betab
1159 betab = 2.0_dp*betab - betab*betab
1160
1161 END IF
1162 occ_matrix = dbcsr_get_occupation(matrix_x)
1163 t2 = m_walltime()
1164 IF (unit_nr > 0) THEN
1165 WRITE (unit_nr, &
1166 '(T6,A,I3,1X,F10.8,E12.3,F12.3,F13.3,E12.3)') "TC2 it ", &
1167 i, occ_matrix, t2 - t1, &
1168 (flop1 + flop2)/(1.0e6_dp*(t2 - t1)), threshold
1169 CALL m_flush(unit_nr)
1170 END IF
1171
1172! calculate control terms
1173 CALL dbcsr_trace(matrix_xsq, trace_fx)
1174
1175! intermediate use matrix_xsq compute X- X*X , temorarily use trace_gx
1176 CALL dbcsr_add(matrix_xsq, matrix_tmp, -1.0_dp, 1.0_dp)
1177 CALL dbcsr_trace(matrix_xsq, trace_gx)
1178 nu(i) = dbcsr_frobenius_norm(matrix_xsq)
1179 wu(i) = trace_gx
1180
1181! intermediate use matrix_xsq to compute = 2X - X*X
1182 CALL dbcsr_add(matrix_xsq, matrix_tmp, 1.0_dp, 1.0_dp)
1183 CALL dbcsr_trace(matrix_xsq, trace_gx)
1184! TC2 has quadratic convergence, using the frobeniums norm as an idempotency deviation test.
1185 IF (abs(nu(i)) < (threshold)) EXIT
1186 END DO
1187
1188 occ_matrix = dbcsr_get_occupation(matrix_x)
1189 IF (unit_nr > 0) WRITE (unit_nr, '(T6,A,I3,1X,1F10.8,1X,1F10.8)') 'Final TC2 iteration ', i, occ_matrix, abs(nu(i))
1190
1191 ! output to matrix_p, P = inv(S)^0.5 X inv(S)^0.5
1192 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_x, matrix_s_sqrt_inv, &
1193 0.0_dp, matrix_tmp, filter_eps=threshold)
1194 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_s_sqrt_inv, matrix_tmp, &
1195 0.0_dp, matrix_p, filter_eps=threshold)
1196
1197 CALL dbcsr_release(matrix_xsq)
1198 CALL dbcsr_release(matrix_tmp)
1199
1200 ! ALGO 3 from. SIAM DOI. 10.1137/130911585
1201 x(1) = 1.0_dp
1202 x(2) = 1.0_dp
1203 x(3) = 0.0_dp
1204 x(4) = 0.0_dp
1205 gama = 6.0_dp - 4.0_dp*(sqrt(2.0_dp))
1206 gama = gama - gama*gama
1207 DO WHILE (nu(i) < gama)
1208 ! safeguard against negative root, is skipping correct?
1209 IF (wu(i) < 1.0e-14_dp) THEN
1210 i = i - 1
1211 cycle
1212 END IF
1213 IF ((1.0_dp - 4.0_dp*nu(i)*nu(i)/wu(i)) < 0.0_dp) THEN
1214 i = i - 1
1215 cycle
1216 END IF
1217 y(1) = 0.5_dp*(1.0_dp - sqrt(1.0_dp - 4.0_dp*nu(i)*nu(i)/wu(i)))
1218 y(2) = 0.5_dp*(1.0_dp - sqrt(1.0_dp - 4.0_dp*nu(i)))
1219 y(3) = 0.5_dp*(1.0_dp + sqrt(1.0_dp - 4.0_dp*nu(i)))
1220 y(4) = 0.5_dp*(1.0_dp + sqrt(1.0_dp - 4.0_dp*nu(i)*nu(i)/wu(i)))
1221 y(:) = min(1.0_dp, max(0.0_dp, y(:)))
1222 DO j = i, 1, -1
1223 IF (poly(j) == 1.0_dp) THEN
1224 DO k = 1, 4
1225 y(k) = sqrt(y(k))
1226 y(k) = (y(k) - 1.0_dp + alpha(j))/alpha(j)
1227 END DO ! end K
1228 ELSE
1229 DO k = 1, 4
1230 y(k) = 1.0_dp - sqrt(1.0_dp - y(k))
1231 y(k) = y(k)/alpha(j)
1232 END DO ! end K
1233 END IF ! end poly
1234 END DO ! end j
1235 x(1) = min(x(1), y(1))
1236 x(2) = min(x(2), y(2))
1237 x(3) = max(x(3), y(3))
1238 x(4) = max(x(4), y(4))
1239 i = i - 1
1240 END DO ! end i
1241! lambda 1,2,3,4 are:: out lumo, in lumo, in homo, out homo
1242 DO k = 1, 4
1243 lambda(k) = eps_max - (eps_max - eps_min)*x(k)
1244 END DO ! end k
1245! END ALGO 3 from. SIAM DOI. 10.1137/130911585
1246 e_homo = lambda(4)
1247 e_lumo = lambda(1)
1248 IF (unit_nr > 0) WRITE (unit_nr, '(T6,A,3E12.4)') "outer homo/lumo/gap", e_homo, e_lumo, (e_lumo - e_homo)
1249 IF (unit_nr > 0) WRITE (unit_nr, '(T6,A,3E12.4)') "inner homo/lumo/gap", lambda(3), lambda(2), (lambda(2) - lambda(3))
1250
1251 DEALLOCATE (poly)
1252 DEALLOCATE (nu)
1253 DEALLOCATE (wu)
1254 DEALLOCATE (alpha)
1255 DEALLOCATE (x)
1256 DEALLOCATE (y)
1257 DEALLOCATE (lambda)
1258
1259 CALL dbcsr_release(matrix_x)
1260 CALL timestop(handle)
1261
1262 END SUBROUTINE density_matrix_tc2
1263
1264! **************************************************************************************************
1265!> \brief compute the homo and lumo given a KS matrix and a density matrix in the orthonormalized basis
1266!> and the eps_min and eps_max, min and max eigenvalue of the ks matrix
1267!> \param matrix_k ...
1268!> \param matrix_p ...
1269!> \param eps_min ...
1270!> \param eps_max ...
1271!> \param threshold ...
1272!> \param max_iter_lanczos ...
1273!> \param eps_lanczos ...
1274!> \param homo ...
1275!> \param lumo ...
1276!> \param unit_nr ...
1277!> \par History
1278!> 2012.06 created [Florian Thoele]
1279!> \author Florian Thoele
1280! **************************************************************************************************
1281 SUBROUTINE compute_homo_lumo(matrix_k, matrix_p, eps_min, eps_max, threshold, max_iter_lanczos, eps_lanczos, homo, lumo, unit_nr)
1282 TYPE(dbcsr_type) :: matrix_k, matrix_p
1283 REAL(kind=dp) :: eps_min, eps_max, threshold
1284 INTEGER, INTENT(IN) :: max_iter_lanczos
1285 REAL(kind=dp), INTENT(IN) :: eps_lanczos
1286 REAL(kind=dp) :: homo, lumo
1287 INTEGER :: unit_nr
1288
1289 LOGICAL :: converged
1290 REAL(kind=dp) :: max_eig, min_eig, shift1, shift2
1291 TYPE(dbcsr_type) :: tmp1, tmp2, tmp3
1292
1293! temporary matrices used for HOMO/LUMO calculation
1294
1295 CALL dbcsr_create(tmp1, template=matrix_k, matrix_type=dbcsr_type_no_symmetry)
1296
1297 CALL dbcsr_create(tmp2, template=matrix_k, matrix_type=dbcsr_type_no_symmetry)
1298
1299 CALL dbcsr_create(tmp3, template=matrix_k, matrix_type=dbcsr_type_no_symmetry)
1300
1301 shift1 = -eps_min
1302 shift2 = eps_max
1303
1304 ! find largest ev of P*(K+shift*1), where shift is the neg. val. of the smallest ev of K
1305 CALL dbcsr_copy(tmp2, matrix_k)
1306 CALL dbcsr_add_on_diag(tmp2, shift1)
1307 CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_p, tmp2, &
1308 0.0_dp, tmp1, filter_eps=threshold)
1309 CALL arnoldi_extremal(tmp1, max_eig, min_eig, converged=converged, &
1310 threshold=eps_lanczos, max_iter=max_iter_lanczos)
1311 homo = max_eig - shift1
1312 IF (unit_nr > 0) THEN
1313 WRITE (unit_nr, '(T6,A,1X,L12)') "Lanczos converged: ", converged
1314 END IF
1315
1316 ! -(1-P)*(K-shift*1) = (1-P)*(shift*1 - K), where shift is the largest ev of K
1317 CALL dbcsr_copy(tmp3, matrix_p)
1318 CALL dbcsr_scale(tmp3, -1.0_dp)
1319 CALL dbcsr_add_on_diag(tmp3, 1.0_dp) !tmp3 = 1-P
1320 CALL dbcsr_copy(tmp2, matrix_k)
1321 CALL dbcsr_add_on_diag(tmp2, -shift2)
1322 CALL dbcsr_multiply("N", "N", -1.0_dp, tmp3, tmp2, &
1323 0.0_dp, tmp1, filter_eps=threshold)
1324 CALL arnoldi_extremal(tmp1, max_eig, min_eig, converged=converged, &
1325 threshold=eps_lanczos, max_iter=max_iter_lanczos)
1326 lumo = -max_eig + shift2
1327
1328 IF (unit_nr > 0) THEN
1329 WRITE (unit_nr, '(T6,A,1X,L12)') "Lanczos converged: ", converged
1330 WRITE (unit_nr, '(T6,A,1X,3F12.5)') 'HOMO/LUMO/gap', homo, lumo, lumo - homo
1331 END IF
1332 CALL dbcsr_release(tmp1)
1333 CALL dbcsr_release(tmp2)
1334 CALL dbcsr_release(tmp3)
1335
1336 END SUBROUTINE compute_homo_lumo
1337
1338! **************************************************************************************************
1339!> \brief ...
1340!> \param x ...
1341!> \param gamma_values ...
1342!> \param i ...
1343!> \return ...
1344! **************************************************************************************************
1345 FUNCTION evaluate_trs4_polynomial(x, gamma_values, i) RESULT(xr)
1346 REAL(kind=dp) :: x
1347 REAL(kind=dp), DIMENSION(:) :: gamma_values
1348 INTEGER :: i
1349 REAL(kind=dp) :: xr
1350
1351 REAL(kind=dp), PARAMETER :: gam_max = 6.0_dp, gam_min = 0.0_dp
1352
1353 INTEGER :: k
1354
1355 xr = x
1356 DO k = 1, i
1357 IF (gamma_values(k) > gam_max) THEN
1358 xr = 2*xr - xr**2
1359 ELSE IF (gamma_values(k) < gam_min) THEN
1360 xr = xr**2
1361 ELSE
1362 xr = (xr*xr)*(4*xr - 3*xr*xr) + gamma_values(k)*xr*xr*((1 - xr)**2)
1363 END IF
1364 END DO
1365 END FUNCTION evaluate_trs4_polynomial
1366
1367! **************************************************************************************************
1368!> \brief ...
1369!> \param homo ...
1370!> \param lumo ...
1371!> \param threshold ...
1372!> \return ...
1373! **************************************************************************************************
1374 FUNCTION estimate_steps(homo, lumo, threshold) RESULT(steps)
1375 REAL(kind=dp) :: homo, lumo, threshold
1376 INTEGER :: steps
1377
1378 INTEGER :: i
1379 REAL(kind=dp) :: h, l, m
1380
1381 l = lumo
1382 h = homo
1383
1384 DO i = 1, 200
1385 IF (abs(l) < threshold .AND. abs(1 - h) < threshold) EXIT
1386 m = 0.5_dp*(h + l)
1387 IF (m > 0.5_dp) THEN
1388 h = h**2
1389 l = l**2
1390 ELSE
1391 h = 2*h - h**2
1392 l = 2*l - l**2
1393 END IF
1394 END DO
1395 steps = i - 1
1396 END FUNCTION estimate_steps
1397
1398END MODULE dm_ls_scf_methods
arnoldi iteration using dbcsr
Definition arnoldi_api.F:15
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...
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
lower level routines for linear scaling SCF
subroutine, public ls_scf_init_matrix_s(matrix_s, ls_scf_env)
initialize S matrix related properties (sqrt, inverse...) Might be factored-out since this seems comm...
subroutine, public density_matrix_sign_fixed_mu(matrix_p, trace, mu, sign_method, sign_order, matrix_ks, matrix_s, matrix_s_inv, threshold, sign_symmetric, submatrix_sign_method, matrix_s_sqrt_inv)
for a fixed mu, compute the corresponding density matrix and its trace
subroutine, public apply_matrix_preconditioner(matrix, direction, matrix_bs_sqrt, matrix_bs_sqrt_inv)
apply a preconditioner either forward (precondition) inv(sqrt(bs)) * A * inv(sqrt(bs)) backward (rest...
subroutine, public density_matrix_sign(matrix_p, mu, fixed_mu, sign_method, sign_order, matrix_ks, matrix_s, matrix_s_inv, nelectron, threshold, sign_symmetric, submatrix_sign_method, matrix_s_sqrt_inv)
compute the density matrix with a trace that is close to nelectron. take a mu as input,...
subroutine, public compute_matrix_preconditioner(matrix_s, preconditioner_type, ls_mstruct, matrix_bs_sqrt, matrix_bs_sqrt_inv, threshold, order, eps_lanczos, max_iter_lanczos)
compute for a block positive definite matrix s (bs) the sqrt(bs) and inv(sqrt(bs))
subroutine, public compute_homo_lumo(matrix_k, matrix_p, eps_min, eps_max, threshold, max_iter_lanczos, eps_lanczos, homo, lumo, unit_nr)
compute the homo and lumo given a KS matrix and a density matrix in the orthonormalized basis and the...
subroutine, public density_matrix_trs4(matrix_p, matrix_ks, matrix_s_sqrt_inv, nelectron, threshold, e_homo, e_lumo, e_mu, dynamic_threshold, matrix_ks_deviation, max_iter_lanczos, eps_lanczos, converged)
compute the density matrix using a trace-resetting algorithm
subroutine, public density_matrix_tc2(matrix_p, matrix_ks, matrix_s_sqrt_inv, nelectron, threshold, e_homo, e_lumo, non_monotonic, eps_lanczos, max_iter_lanczos)
compute the density matrix using a non monotonic trace conserving algorithm based on SIAM DOI....
Routines for a linear scaling quickstep SCF run based on the density matrix, with a focus on the inte...
subroutine, public matrix_qs_to_ls(matrix_ls, matrix_qs, ls_mstruct, covariant)
first link to QS, copy a QS matrix to LS matrix used to isolate QS style matrices from LS style will ...
Types needed for a linear scaling quickstep SCF run based on the density matrix.
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public ls_scf_submatrix_sign_direct_muadj
integer, parameter, public ls_s_preconditioner_molecular
integer, parameter, public ls_s_preconditioner_atomic
integer, parameter, public ls_scf_sign_submatrix
integer, parameter, public ls_s_sqrt_proot
integer, parameter, public ls_s_sqrt_ns
integer, parameter, public ls_s_preconditioner_none
integer, parameter, public ls_scf_sign_proot
integer, parameter, public ls_scf_submatrix_sign_ns
integer, parameter, public ls_scf_sign_ns
integer, parameter, public ls_scf_submatrix_sign_direct_muadj_lowmem
integer, parameter, public ls_cluster_atomic
Routines useful for iterative matrix calculations.
subroutine, public matrix_sqrt_newton_schulz(matrix_sqrt, matrix_sqrt_inv, matrix, threshold, order, eps_lanczos, max_iter_lanczos, symmetrize, converged)
compute the sqrt of a matrix via the sign function and the corresponding Newton-Schulz iterations the...
subroutine, public matrix_sign_submatrix(matrix_sign, matrix, threshold, sign_order, submatrix_sign_method)
Submatrix method.
subroutine, public matrix_sign_submatrix_mu_adjust(matrix_sign, matrix, mu, nelectron, threshold, variant)
Submatrix method with internal adjustment of chemical potential.
subroutine, public invert_hotelling(matrix_inverse, matrix, threshold, use_inv_as_guess, norm_convergence, filter_eps, accelerator_order, max_iter_lanczos, eps_lanczos, silent)
invert a symmetric positive definite matrix by Hotelling's method explicit symmetrization makes this ...
subroutine, public matrix_sign_proot(matrix_sign, matrix, threshold, sign_order)
compute the sign a matrix using the general algorithm for the p-th root of Richters et al....
subroutine, public matrix_sign_newton_schulz(matrix_sign, matrix, threshold, sign_order)
compute the sign a matrix using Newton-Schulz iterations
subroutine, public matrix_sqrt_proot(matrix_sqrt, matrix_sqrt_inv, matrix, threshold, order, eps_lanczos, max_iter_lanczos, symmetrize, converged)
compute the sqrt of a matrix via the general algorithm for the p-th root of Richters et al....
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public int_8
Definition kinds.F:54
integer, parameter, public dp
Definition kinds.F:34
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Definition machine.F:106
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Definition machine.F:123
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
logical function, public abnormal_value(a)
determines if a value is not normal (e.g. for Inf and Nan) based on IO to work also under optimizatio...
Definition mathlib.F:150
type of a logger, at the moment it contains just a print level starting at which level it should be l...