49#include "./base/base_uses.f90"
55 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'dm_ls_scf_methods'
77 CHARACTER(len=*),
PARAMETER :: routinen =
'ls_scf_init_matrix_S'
79 INTEGER :: handle, unit_nr
80 REAL(kind=
dp) :: frob_matrix, frob_matrix_base
84 CALL timeset(routinen, handle)
88 IF (logger%para_env%is_source())
THEN
95 IF (ls_scf_env%has_unit_metric)
THEN
96 CALL dbcsr_set(ls_scf_env%matrix_s, 0.0_dp)
99 CALL matrix_qs_to_ls(ls_scf_env%matrix_s, matrix_s, ls_scf_env%ls_mstruct, covariant=.true.)
102 CALL dbcsr_filter(ls_scf_env%matrix_s, ls_scf_env%eps_filter)
105 IF (ls_scf_env%has_s_preconditioner)
THEN
106 CALL dbcsr_create(ls_scf_env%matrix_bs_sqrt, template=ls_scf_env%matrix_s, &
107 matrix_type=dbcsr_type_no_symmetry)
108 CALL dbcsr_create(ls_scf_env%matrix_bs_sqrt_inv, template=ls_scf_env%matrix_s, &
109 matrix_type=dbcsr_type_no_symmetry)
111 ls_scf_env%s_preconditioner_type, ls_scf_env%ls_mstruct, &
112 ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv, &
113 ls_scf_env%eps_filter, ls_scf_env%s_sqrt_order, &
114 ls_scf_env%eps_lanczos, ls_scf_env%max_iter_lanczos)
118 IF (ls_scf_env%has_s_preconditioner)
THEN
120 ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
124 IF (ls_scf_env%use_s_sqrt)
THEN
126 CALL dbcsr_create(ls_scf_env%matrix_s_sqrt, template=ls_scf_env%matrix_s, &
127 matrix_type=dbcsr_type_no_symmetry)
128 CALL dbcsr_create(ls_scf_env%matrix_s_sqrt_inv, template=ls_scf_env%matrix_s, &
129 matrix_type=dbcsr_type_no_symmetry)
131 SELECT CASE (ls_scf_env%s_sqrt_method)
134 ls_scf_env%matrix_s, ls_scf_env%eps_filter, &
135 ls_scf_env%s_sqrt_order, &
136 ls_scf_env%eps_lanczos, ls_scf_env%max_iter_lanczos, &
140 ls_scf_env%matrix_s, ls_scf_env%eps_filter, &
141 ls_scf_env%s_sqrt_order, &
142 ls_scf_env%eps_lanczos, ls_scf_env%max_iter_lanczos, &
145 cpabort(
"Unknown sqrt method.")
148 IF (ls_scf_env%check_s_inv)
THEN
149 CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, &
150 matrix_type=dbcsr_type_no_symmetry)
151 CALL dbcsr_create(matrix_tmp2, template=ls_scf_env%matrix_s, &
152 matrix_type=dbcsr_type_no_symmetry)
154 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_s, &
155 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
157 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt_inv, &
158 0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
163 IF (unit_nr > 0)
THEN
164 WRITE (unit_nr, *)
"Error for (inv(sqrt(S))*S*inv(sqrt(S))-I)", frob_matrix/frob_matrix_base
173 IF (ls_scf_env%needs_s_inv)
THEN
174 CALL dbcsr_create(ls_scf_env%matrix_s_inv, template=ls_scf_env%matrix_s, &
175 matrix_type=dbcsr_type_no_symmetry)
176 IF (.NOT. ls_scf_env%use_s_sqrt)
THEN
177 CALL invert_hotelling(ls_scf_env%matrix_s_inv, ls_scf_env%matrix_s, ls_scf_env%eps_filter)
179 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_s_sqrt_inv, &
180 0.0_dp, ls_scf_env%matrix_s_inv, filter_eps=ls_scf_env%eps_filter)
182 IF (ls_scf_env%check_s_inv)
THEN
183 CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, &
184 matrix_type=dbcsr_type_no_symmetry)
185 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, ls_scf_env%matrix_s_inv, ls_scf_env%matrix_s, &
186 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
190 IF (unit_nr > 0)
THEN
191 WRITE (unit_nr, *)
"Error for (inv(S)*S-I)", frob_matrix/frob_matrix_base
197 CALL timestop(handle)
217 matrix_bs_sqrt, matrix_bs_sqrt_inv, threshold, order, &
218 eps_lanczos, max_iter_lanczos)
221 INTEGER :: preconditioner_type
223 TYPE(
dbcsr_type),
INTENT(INOUT) :: matrix_bs_sqrt, matrix_bs_sqrt_inv
224 REAL(kind=
dp) :: threshold
226 REAL(kind=
dp) :: eps_lanczos
227 INTEGER :: max_iter_lanczos
229 CHARACTER(LEN=*),
PARAMETER :: routinen =
'compute_matrix_preconditioner'
231 INTEGER :: handle, iblock_col, iblock_row
232 LOGICAL :: block_needed
233 REAL(
dp),
DIMENSION(:, :),
POINTER :: block_dp
237 CALL timeset(routinen, handle)
242 SELECT CASE (preconditioner_type)
254 block_needed = .false.
256 IF (iblock_row == iblock_col)
THEN
257 block_needed = .true.
261 IF (ls_mstruct%atom_to_molecule(iblock_row) == ls_mstruct%atom_to_molecule(iblock_col)) block_needed = .true.
266 IF (block_needed)
THEN
267 CALL dbcsr_put_block(matrix=matrix_bs, row=iblock_row, col=iblock_col, block=block_dp)
276 SELECT CASE (preconditioner_type)
284 CALL dbcsr_copy(matrix_bs_sqrt_inv, matrix_bs)
285 CALL dbcsr_set(matrix_bs_sqrt_inv, 0.0_dp)
289 CALL dbcsr_copy(matrix_bs_sqrt_inv, matrix_bs)
295 threshold=min(threshold, 1.0e-10_dp), order=order, &
296 eps_lanczos=eps_lanczos, max_iter_lanczos=max_iter_lanczos, &
302 CALL timestop(handle)
321 CHARACTER(LEN=*) :: direction
322 TYPE(
dbcsr_type),
INTENT(INOUT) :: matrix_bs_sqrt, matrix_bs_sqrt_inv
324 CHARACTER(LEN=*),
PARAMETER :: routinen =
'apply_matrix_preconditioner'
329 CALL timeset(routinen, handle)
330 CALL dbcsr_create(matrix_tmp, template=matrix, matrix_type=dbcsr_type_no_symmetry)
332 SELECT CASE (direction)
334 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix, matrix_bs_sqrt_inv, &
336 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_bs_sqrt_inv, matrix_tmp, &
341 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_bs_sqrt, matrix_tmp, &
344 cpabort(
"Direction should be forward or backward when applying preconditioner")
349 CALL timestop(handle)
375 matrix_s, matrix_s_inv, nelectron, threshold, sign_symmetric, submatrix_sign_method, &
379 REAL(kind=
dp),
INTENT(INOUT) :: mu
381 INTEGER :: sign_method, sign_order
382 TYPE(
dbcsr_type),
INTENT(INOUT) :: matrix_ks, matrix_s, matrix_s_inv
383 INTEGER,
INTENT(IN) :: nelectron
384 REAL(kind=
dp),
INTENT(IN) :: threshold
385 LOGICAL,
OPTIONAL :: sign_symmetric
386 INTEGER,
OPTIONAL :: submatrix_sign_method
387 TYPE(
dbcsr_type),
INTENT(IN),
OPTIONAL :: matrix_s_sqrt_inv
389 CHARACTER(LEN=*),
PARAMETER :: routinen =
'density_matrix_sign'
390 REAL(kind=
dp),
PARAMETER :: initial_increment = 0.01_dp
392 INTEGER :: handle, iter, unit_nr, &
393 used_submatrix_sign_method
394 LOGICAL :: do_sign_symmetric, has_mu_high, &
395 has_mu_low, internal_mu_adjust
396 REAL(kind=
dp) :: increment, mu_high, mu_low, trace
399 CALL timeset(routinen, handle)
402 IF (logger%para_env%is_source())
THEN
408 do_sign_symmetric = .false.
409 IF (
PRESENT(sign_symmetric)) do_sign_symmetric = sign_symmetric
412 IF (
PRESENT(submatrix_sign_method)) used_submatrix_sign_method = submatrix_sign_method
418 IF (internal_mu_adjust)
THEN
419 CALL density_matrix_sign_internal_mu(matrix_p, trace, mu, sign_method, &
420 matrix_ks, matrix_s, threshold, &
421 used_submatrix_sign_method, &
422 nelectron, matrix_s_sqrt_inv)
424 increment = initial_increment
427 has_mu_high = .false.
431 IF (has_mu_low .AND. has_mu_high)
THEN
432 mu = (mu_low + mu_high)/2
433 IF (abs(mu_high - mu_low) < threshold)
EXIT
437 matrix_ks, matrix_s, matrix_s_inv, threshold, &
438 do_sign_symmetric, used_submatrix_sign_method, &
440 IF (unit_nr > 0)
WRITE (unit_nr,
'(T2,A,I2,1X,F13.9,1X,F15.9)') &
441 "Density matrix: iter, mu, trace error: ", iter, mu, trace - nelectron
445 IF (abs(trace - nelectron) < 0.5_dp .OR. fixed_mu)
EXIT
447 IF (trace < nelectron)
THEN
451 increment = increment*2
456 increment = increment*2
462 CALL timestop(handle)
485 matrix_s, matrix_s_inv, threshold, sign_symmetric, submatrix_sign_method, &
489 REAL(kind=
dp),
INTENT(OUT) :: trace
490 REAL(kind=
dp),
INTENT(INOUT) :: mu
491 INTEGER :: sign_method, sign_order
492 TYPE(
dbcsr_type),
INTENT(INOUT) :: matrix_ks, matrix_s, matrix_s_inv
493 REAL(kind=
dp),
INTENT(IN) :: threshold
494 LOGICAL :: sign_symmetric
495 INTEGER :: submatrix_sign_method
496 TYPE(
dbcsr_type),
INTENT(IN),
OPTIONAL :: matrix_s_sqrt_inv
498 CHARACTER(LEN=*),
PARAMETER :: routinen =
'density_matrix_sign_fixed_mu'
500 INTEGER :: handle, unit_nr
501 REAL(kind=
dp) :: frob_matrix
503 TYPE(
dbcsr_type) :: matrix_p_ud, matrix_sign, matrix_sinv_ks, matrix_ssqrtinv_ks_ssqrtinv, &
504 matrix_ssqrtinv_ks_ssqrtinv2, matrix_tmp
506 CALL timeset(routinen, handle)
509 IF (logger%para_env%is_source())
THEN
515 CALL dbcsr_create(matrix_sign, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
517 IF (sign_symmetric)
THEN
519 IF (.NOT.
PRESENT(matrix_s_sqrt_inv))
THEN
520 cpabort(
"Argument matrix_s_sqrt_inv required if sign_symmetric is set")
523 CALL dbcsr_create(matrix_ssqrtinv_ks_ssqrtinv, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
524 CALL dbcsr_create(matrix_ssqrtinv_ks_ssqrtinv2, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
525 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_s_sqrt_inv, matrix_ks, &
526 0.0_dp, matrix_ssqrtinv_ks_ssqrtinv2, filter_eps=threshold)
527 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_ssqrtinv_ks_ssqrtinv2, matrix_s_sqrt_inv, &
528 0.0_dp, matrix_ssqrtinv_ks_ssqrtinv, filter_eps=threshold)
531 SELECT CASE (sign_method)
535 CALL matrix_sign_proot(matrix_sign, matrix_ssqrtinv_ks_ssqrtinv, threshold, sign_order)
537 CALL matrix_sign_submatrix(matrix_sign, matrix_ssqrtinv_ks_ssqrtinv, threshold, sign_order, submatrix_sign_method)
539 cpabort(
"Unkown sign method.")
546 CALL dbcsr_create(matrix_sinv_ks, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
548 0.0_dp, matrix_sinv_ks, filter_eps=threshold)
552 SELECT CASE (sign_method)
558 CALL matrix_sign_submatrix(matrix_sign, matrix_sinv_ks, threshold, sign_order, submatrix_sign_method)
560 cpabort(
"Unkown sign method.")
566 CALL dbcsr_create(matrix_p_ud, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
576 CALL dbcsr_create(matrix_tmp, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
578 0.0_dp, matrix_tmp, filter_eps=threshold)
579 CALL dbcsr_add(matrix_tmp, matrix_p_ud, 1.0_dp, -1.0_dp)
581 IF (unit_nr > 0 .AND. frob_matrix > 0.001_dp)
THEN
582 WRITE (unit_nr,
'(T2,A,F20.12)')
"Deviation from idempotency: ", frob_matrix
585 IF (sign_symmetric)
THEN
586 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_s_sqrt_inv, matrix_p_ud, &
587 0.0_dp, matrix_tmp, filter_eps=threshold)
588 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_tmp, matrix_s_sqrt_inv, &
589 0.0_dp, matrix_p, filter_eps=threshold)
593 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_p_ud, matrix_s_inv, &
594 0.0_dp, matrix_p, filter_eps=threshold)
599 CALL timestop(handle)
619 SUBROUTINE density_matrix_sign_internal_mu(matrix_p, trace, mu, sign_method, matrix_ks, &
620 matrix_s, threshold, submatrix_sign_method, &
621 nelectron, matrix_s_sqrt_inv)
624 REAL(kind=
dp),
INTENT(OUT) :: trace
625 REAL(kind=
dp),
INTENT(INOUT) :: mu
626 INTEGER :: sign_method
627 TYPE(
dbcsr_type),
INTENT(INOUT) :: matrix_ks, matrix_s
628 REAL(kind=
dp),
INTENT(IN) :: threshold
629 INTEGER :: submatrix_sign_method
630 INTEGER,
INTENT(IN) :: nelectron
631 TYPE(
dbcsr_type),
INTENT(IN) :: matrix_s_sqrt_inv
633 CHARACTER(LEN=*),
PARAMETER :: routinen =
'density_matrix_sign_internal_mu'
635 INTEGER :: handle, unit_nr
636 REAL(kind=
dp) :: frob_matrix
638 TYPE(
dbcsr_type) :: matrix_p_ud, matrix_sign, &
639 matrix_ssqrtinv_ks_ssqrtinv, &
640 matrix_ssqrtinv_ks_ssqrtinv2, &
643 CALL timeset(routinen, handle)
646 IF (logger%para_env%is_source())
THEN
652 CALL dbcsr_create(matrix_sign, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
654 CALL dbcsr_create(matrix_ssqrtinv_ks_ssqrtinv, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
655 CALL dbcsr_create(matrix_ssqrtinv_ks_ssqrtinv2, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
656 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_s_sqrt_inv, matrix_ks, &
657 0.0_dp, matrix_ssqrtinv_ks_ssqrtinv2, filter_eps=threshold)
658 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_ssqrtinv_ks_ssqrtinv2, matrix_s_sqrt_inv, &
659 0.0_dp, matrix_ssqrtinv_ks_ssqrtinv, filter_eps=threshold)
662 SELECT CASE (sign_method)
664 SELECT CASE (submatrix_sign_method)
667 submatrix_sign_method)
669 cpabort(
"density_matrix_sign_internal_mu called with invalid submatrix sign method")
672 cpabort(
"density_matrix_sign_internal_mu called with invalid sign method.")
678 CALL dbcsr_create(matrix_p_ud, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
688 CALL dbcsr_create(matrix_tmp, template=matrix_s, matrix_type=dbcsr_type_no_symmetry)
690 0.0_dp, matrix_tmp, filter_eps=threshold)
691 CALL dbcsr_add(matrix_tmp, matrix_p_ud, 1.0_dp, -1.0_dp)
693 IF (unit_nr > 0 .AND. frob_matrix > 0.001_dp)
THEN
694 WRITE (unit_nr,
'(T2,A,F20.12)')
"Deviation from idempotency: ", frob_matrix
697 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_s_sqrt_inv, matrix_p_ud, &
698 0.0_dp, matrix_tmp, filter_eps=threshold)
699 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_tmp, matrix_s_sqrt_inv, &
700 0.0_dp, matrix_p, filter_eps=threshold)
704 CALL timestop(handle)
706 END SUBROUTINE density_matrix_sign_internal_mu
729 nelectron, threshold, e_homo, e_lumo, e_mu, &
730 dynamic_threshold, matrix_ks_deviation, &
731 max_iter_lanczos, eps_lanczos, converged, iounit)
734 TYPE(
dbcsr_type),
INTENT(IN) :: matrix_ks, matrix_s_sqrt_inv
735 INTEGER,
INTENT(IN) :: nelectron
736 REAL(kind=
dp),
INTENT(IN) :: threshold
737 REAL(kind=
dp),
INTENT(INOUT) :: e_homo, e_lumo, e_mu
738 LOGICAL,
INTENT(IN),
OPTIONAL :: dynamic_threshold
739 TYPE(
dbcsr_type),
INTENT(INOUT),
OPTIONAL :: matrix_ks_deviation
740 INTEGER,
INTENT(IN) :: max_iter_lanczos
741 REAL(kind=
dp),
INTENT(IN) :: eps_lanczos
742 LOGICAL,
INTENT(OUT),
OPTIONAL :: converged
743 INTEGER,
INTENT(IN),
OPTIONAL :: iounit
745 CHARACTER(LEN=*),
PARAMETER :: routinen =
'density_matrix_trs4'
746 INTEGER,
PARAMETER :: max_iter = 100
747 REAL(kind=
dp),
PARAMETER :: gamma_max = 6.0_dp, gamma_min = 0.0_dp
749 INTEGER :: branch, estimated_steps, handle, i, j, &
751 INTEGER(kind=int_8) :: flop1, flop2
752 LOGICAL :: arnoldi_converged, do_dyn_threshold
753 REAL(kind=
dp) :: current_threshold, delta_n, eps_max, eps_min, est_threshold, frob_id, &
754 frob_x, gam, homo, lumo, max_eig, max_threshold, maxdev, maxev, min_eig, minev, mmin, mu, &
755 mu_a, mu_b, mu_c, mu_fa, mu_fc, occ_matrix, scaled_homo_bound, scaled_lumo_bound, t1, t2, &
756 trace_fx, trace_gx, xi
757 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: gamma_values
759 TYPE(
dbcsr_type) :: matrix_k0, matrix_x, matrix_x_nosym, &
760 matrix_xidsq, matrix_xsq, tmp_gx
762 IF (nelectron == 0)
THEN
767 CALL timeset(routinen, handle)
769 IF (
PRESENT(iounit))
THEN
773 IF (logger%para_env%is_source())
THEN
780 do_dyn_threshold = .false.
781 IF (
PRESENT(dynamic_threshold)) do_dyn_threshold = dynamic_threshold
783 IF (
PRESENT(converged)) converged = .false.
786 CALL dbcsr_create(matrix_x, template=matrix_ks, matrix_type=
"S")
789 CALL dbcsr_create(matrix_x_nosym, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
791 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_s_sqrt_inv, matrix_ks, &
792 0.0_dp, matrix_x_nosym, filter_eps=threshold)
793 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_x_nosym, matrix_s_sqrt_inv, &
794 0.0_dp, matrix_x, filter_eps=threshold)
797 CALL dbcsr_create(matrix_k0, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
801 IF (do_dyn_threshold)
THEN
802 cpassert(
PRESENT(matrix_ks_deviation))
803 CALL dbcsr_add(matrix_ks_deviation, matrix_x_nosym, -1.0_dp, 1.0_dp)
804 CALL arnoldi_extremal(matrix_ks_deviation, maxev, minev, max_iter=max_iter_lanczos, threshold=eps_lanczos, &
805 converged=arnoldi_converged)
806 maxdev = max(abs(maxev), abs(minev))
807 IF (unit_nr > 0)
THEN
808 WRITE (unit_nr,
'(T6,A,1X,L12)')
"Lanczos converged: ", arnoldi_converged
809 WRITE (unit_nr,
'(T6,A,1X,F12.5)')
"change in mixed matrix: ", maxdev
810 WRITE (unit_nr,
'(T6,A,1X,F12.5)')
"HOMO upper bound: ", e_homo + maxdev
811 WRITE (unit_nr,
'(T6,A,1X,F12.5)')
"LUMO lower bound: ", e_lumo - maxdev
812 WRITE (unit_nr,
'(T6,A,1X,L12)')
"Predicts a gap ? ", ((e_lumo - maxdev) - (e_homo + maxdev)) > 0
815 CALL dbcsr_copy(matrix_ks_deviation, matrix_x_nosym)
820 CALL arnoldi_extremal(matrix_x_nosym, max_eig, min_eig, max_iter=max_iter_lanczos, threshold=eps_lanczos, &
821 converged=arnoldi_converged)
822 IF (unit_nr > 0)
WRITE (unit_nr,
'(T6,A,1X,2F12.5,1X,A,1X,L1)')
"Est. extremal eigenvalues", &
823 min_eig, max_eig,
" converged: ", arnoldi_converged
828 IF (eps_max == eps_min)
THEN
832 CALL dbcsr_scale(matrix_x, -1.0_dp/(eps_max - eps_min))
835 current_threshold = threshold
836 IF (do_dyn_threshold)
THEN
838 scaled_homo_bound = (eps_max - (e_homo + maxdev))/(eps_max - eps_min)
839 scaled_lumo_bound = (eps_max - (e_lumo - maxdev))/(eps_max - eps_min)
842 CALL dbcsr_create(matrix_xsq, template=matrix_ks, matrix_type=
"S")
844 CALL dbcsr_create(matrix_xidsq, template=matrix_ks, matrix_type=
"S")
846 CALL dbcsr_create(tmp_gx, template=matrix_ks, matrix_type=
"S")
848 ALLOCATE (gamma_values(max_iter))
856 0.0_dp, matrix_xsq, &
857 filter_eps=current_threshold, flop=flop1)
861 CALL dbcsr_add(matrix_xidsq, matrix_xsq, -1.0_dp, 1.0_dp)
868 CALL dbcsr_add(matrix_xidsq, matrix_xsq, -2.0_dp, 1.0_dp)
873 CALL dbcsr_add(tmp_gx, matrix_xsq, 4.0_dp, -3.0_dp)
877 CALL dbcsr_dot(matrix_xsq, matrix_xidsq, trace_gx)
878 CALL dbcsr_dot(matrix_xsq, tmp_gx, trace_fx)
883 delta_n = nelectron - trace_fx
885 IF (((frob_id*frob_id) < (threshold*frob_x*frob_x)) .AND. (abs(delta_n) < 0.5_dp))
THEN
887 ELSE IF (abs(delta_n) < 1e-14_dp)
THEN
891 gam = delta_n/max(trace_gx, abs(delta_n)/100)
893 gamma_values(i) = gam
895 IF (unit_nr > 0 .AND. .false.)
THEN
896 WRITE (unit_nr, *)
"trace_fx", trace_fx,
"trace_gx", trace_gx,
"gam", gam, &
897 "frob_id", frob_id,
"conv", abs(frob_id/frob_x)
900 IF (do_dyn_threshold)
THEN
902 xi = (scaled_homo_bound - scaled_lumo_bound)
903 IF (xi > 0.0_dp)
THEN
904 mmin = 0.5*(scaled_homo_bound + scaled_lumo_bound)
905 max_threshold = abs(1 - 2*mmin)*xi
907 scaled_homo_bound = evaluate_trs4_polynomial(scaled_homo_bound, gamma_values(i:), 1)
908 scaled_lumo_bound = evaluate_trs4_polynomial(scaled_lumo_bound, gamma_values(i:), 1)
909 estimated_steps = estimate_steps(scaled_homo_bound, scaled_lumo_bound, threshold)
911 est_threshold = (threshold/(estimated_steps + i + 1))*xi/(1 + threshold/(estimated_steps + i + 1))
912 est_threshold = min(max_threshold, est_threshold)
913 IF (i > 1) est_threshold = max(est_threshold, 0.1_dp*current_threshold)
914 current_threshold = est_threshold
916 current_threshold = threshold
920 IF (gam > gamma_max)
THEN
922 CALL dbcsr_add(matrix_x, matrix_xsq, 2.0_dp, -1.0_dp)
925 ELSE IF (gam < gamma_min)
THEN
931 CALL dbcsr_add(tmp_gx, matrix_xidsq, 1.0_dp, gam)
934 flop=flop2, filter_eps=current_threshold)
940 IF (unit_nr > 0)
THEN
942 '(T6,A,I3,1X,F10.8,E12.3,F12.3,F13.3,E12.3)')
"TRS4 it ", &
943 i, occ_matrix, abs(trace_gx), t2 - t1, &
944 (flop1 + flop2)/(1.0e6_dp*max(t2 - t1, 0.001_dp)), current_threshold
949 cpabort(
"trace_gx is an abnormal value (NaN/Inf).")
955 IF ((frob_id*frob_id) < (threshold*frob_x*frob_x) .AND. branch == 3 .AND. (abs(delta_n) < 0.5_dp))
THEN
956 IF (
PRESENT(converged)) converged = .true.
963 IF (unit_nr > 0)
WRITE (unit_nr,
'(T6,A,I3,1X,F10.8,E12.3)')
'Final TRS4 iteration ', i, occ_matrix, abs(trace_gx)
971 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_x, matrix_s_sqrt_inv, &
972 0.0_dp, matrix_x_nosym, filter_eps=threshold)
973 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_s_sqrt_inv, matrix_x_nosym, &
974 0.0_dp, matrix_p, filter_eps=threshold)
979 mu_a = 0.0_dp; mu_b = 1.0_dp
980 mu_fa = evaluate_trs4_polynomial(mu_a, gamma_values, i - 1) - 0.5_dp
982 mu_c = 0.5*(mu_a + mu_b)
984 mu_fc = evaluate_trs4_polynomial(mu_c, gamma_values, i - 1) - 0.5_dp
985 IF (abs(mu_fc) < 1.0e-6_dp .OR. (mu_b - mu_a)/2 < 1.0e-6_dp)
EXIT
987 IF (mu_fc*mu_fa > 0)
THEN
994 mu = (eps_min - eps_max)*mu_c + eps_max
995 DEALLOCATE (gamma_values)
996 IF (unit_nr > 0)
THEN
997 WRITE (unit_nr,
'(T6,A,1X,F12.5)')
'Chemical potential (mu): ', mu
1001 IF (do_dyn_threshold)
THEN
1004 threshold, max_iter_lanczos, eps_lanczos, homo, lumo, unit_nr)
1012 CALL timestop(handle)
1034 nelectron, threshold, e_homo, e_lumo, &
1035 non_monotonic, eps_lanczos, max_iter_lanczos, iounit)
1038 TYPE(
dbcsr_type),
INTENT(IN) :: matrix_ks, matrix_s_sqrt_inv
1039 INTEGER,
INTENT(IN) :: nelectron
1040 REAL(kind=
dp),
INTENT(IN) :: threshold
1041 REAL(kind=
dp),
INTENT(INOUT) :: e_homo, e_lumo
1042 LOGICAL,
INTENT(IN),
OPTIONAL :: non_monotonic
1043 REAL(kind=
dp),
INTENT(IN) :: eps_lanczos
1044 INTEGER,
INTENT(IN) :: max_iter_lanczos
1045 INTEGER,
INTENT(IN),
OPTIONAL :: iounit
1047 CHARACTER(LEN=*),
PARAMETER :: routinen =
'density_matrix_tc2'
1048 INTEGER,
PARAMETER :: max_iter = 100
1050 INTEGER :: handle, i, j, k, unit_nr
1051 INTEGER(kind=int_8) :: flop1, flop2
1052 LOGICAL :: converged, do_non_monotonic, &
1054 REAL(kind=
dp) :: beta, betab, eps_max, eps_min, gama, &
1055 max_eig, min_eig, occ_matrix, t1, t2, &
1057 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: alpha, lambda, nu, poly, wu, x, y
1059 TYPE(
dbcsr_type) :: matrix_tmp, matrix_x, matrix_xsq
1061 CALL timeset(routinen, handle)
1063 IF (
PRESENT(iounit))
THEN
1067 IF (logger%para_env%is_source())
THEN
1074 do_non_monotonic = .false.
1075 IF (
PRESENT(non_monotonic)) do_non_monotonic = non_monotonic
1078 CALL dbcsr_create(matrix_x, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
1079 CALL dbcsr_create(matrix_xsq, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
1081 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_s_sqrt_inv, matrix_ks, &
1082 0.0_dp, matrix_xsq, filter_eps=threshold)
1083 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_xsq, matrix_s_sqrt_inv, &
1084 0.0_dp, matrix_x, filter_eps=threshold)
1086 IF (unit_nr > 0)
THEN
1087 WRITE (unit_nr,
'(T6,A,1X,F12.5)')
"HOMO upper bound: ", e_homo
1088 WRITE (unit_nr,
'(T6,A,1X,F12.5)')
"LUMO lower bound: ", e_lumo
1089 WRITE (unit_nr,
'(T6,A,1X,L12)')
"Predicts a gap ? ", ((e_lumo) - (e_homo)) > 0
1093 CALL arnoldi_extremal(matrix_x, max_eig, min_eig, max_iter=max_iter_lanczos, threshold=eps_lanczos, &
1094 converged=converged)
1095 IF (unit_nr > 0)
WRITE (unit_nr,
'(T6,A,1X,2F12.5,1X,A,1X,L1)')
"Est. extremal eigenvalues", &
1096 min_eig, max_eig,
" converged: ", converged
1108 CALL dbcsr_create(matrix_tmp, template=matrix_ks, matrix_type=dbcsr_type_no_symmetry)
1110 ALLOCATE (poly(max_iter))
1111 ALLOCATE (nu(max_iter))
1112 ALLOCATE (wu(max_iter))
1113 ALLOCATE (alpha(max_iter))
1116 ALLOCATE (lambda(4))
1119 beta = (eps_max - abs(e_lumo))/(eps_max - eps_min)
1120 betab = (eps_max + abs(e_homo))/(eps_max - eps_min)
1122 IF ((beta - betab) < 0.005_dp)
THEN
1123 beta = beta - 0.002_dp
1124 betab = betab + 0.002_dp
1127 IF (.NOT. do_non_monotonic)
THEN
1132 IF (e_homo == 0.0_dp)
THEN
1138 trace_fx = nelectron
1141 tc2_converged = .false.
1144 flop1 = 0; flop2 = 0
1146 IF (abs(trace_fx - nelectron) <= abs(trace_gx - nelectron))
THEN
1149 alpha(i) = 2.0_dp/(2.0_dp - beta)
1154 0.0_dp, matrix_xsq, &
1155 filter_eps=threshold, flop=flop1)
1162 beta = (1.0_dp - alpha(i)) + alpha(i)*beta
1164 betab = (1.0_dp - alpha(i)) + alpha(i)*betab
1169 alpha(i) = 2.0_dp/(1.0_dp + betab)
1173 0.0_dp, matrix_xsq, &
1174 filter_eps=threshold, flop=flop1)
1179 CALL dbcsr_add(matrix_x, matrix_xsq, 2.0_dp, -1.0_dp)
1181 beta = alpha(i)*beta
1182 beta = 2.0_dp*beta - beta*beta
1183 betab = alpha(i)*betab
1184 betab = 2.0_dp*betab - betab*betab
1189 IF (unit_nr > 0)
THEN
1191 '(T6,A,I3,1X,F10.8,E12.3,F12.3,F13.3,E12.3)')
"TC2 it ", &
1192 i, occ_matrix, t2 - t1, &
1193 (flop1 + flop2)/(1.0e6_dp*(t2 - t1)), threshold
1201 CALL dbcsr_add(matrix_xsq, matrix_tmp, -1.0_dp, 1.0_dp)
1207 CALL dbcsr_add(matrix_xsq, matrix_tmp, 1.0_dp, 1.0_dp)
1210 IF (abs(nu(i)) < (threshold))
THEN
1211 tc2_converged = .true.
1215 IF (.NOT. tc2_converged) i = max_iter
1218 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))
1221 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_x, matrix_s_sqrt_inv, &
1222 0.0_dp, matrix_tmp, filter_eps=threshold)
1223 CALL dbcsr_multiply(
"N",
"N", 1.0_dp, matrix_s_sqrt_inv, matrix_tmp, &
1224 0.0_dp, matrix_p, filter_eps=threshold)
1234 gama = 6.0_dp - 4.0_dp*(sqrt(2.0_dp))
1235 gama = gama - gama*gama
1238 IF (nu(i) >= gama)
EXIT
1240 IF (wu(i) < 1.0e-14_dp)
THEN
1244 IF ((1.0_dp - 4.0_dp*nu(i)*nu(i)/wu(i)) < 0.0_dp)
THEN
1248 y(1) = 0.5_dp*(1.0_dp - sqrt(1.0_dp - 4.0_dp*nu(i)*nu(i)/wu(i)))
1249 y(2) = 0.5_dp*(1.0_dp - sqrt(1.0_dp - 4.0_dp*nu(i)))
1250 y(3) = 0.5_dp*(1.0_dp + sqrt(1.0_dp - 4.0_dp*nu(i)))
1251 y(4) = 0.5_dp*(1.0_dp + sqrt(1.0_dp - 4.0_dp*nu(i)*nu(i)/wu(i)))
1252 y(:) = min(1.0_dp, max(0.0_dp, y(:)))
1254 IF (poly(j) == 1.0_dp)
THEN
1257 y(k) = (y(k) - 1.0_dp + alpha(j))/alpha(j)
1261 y(k) = 1.0_dp - sqrt(1.0_dp - y(k))
1262 y(k) = y(k)/alpha(j)
1266 x(1) = min(x(1), y(1))
1267 x(2) = min(x(2), y(2))
1268 x(3) = max(x(3), y(3))
1269 x(4) = max(x(4), y(4))
1274 lambda(k) = eps_max - (eps_max - eps_min)*x(k)
1279 IF (unit_nr > 0)
WRITE (unit_nr,
'(T6,A,3E12.4)')
"outer homo/lumo/gap", e_homo, e_lumo, (e_lumo - e_homo)
1280 IF (unit_nr > 0)
WRITE (unit_nr,
'(T6,A,3E12.4)')
"inner homo/lumo/gap", lambda(3), lambda(2), (lambda(2) - lambda(3))
1291 CALL timestop(handle)
1312 SUBROUTINE compute_homo_lumo(matrix_k, matrix_p, eps_min, eps_max, threshold, max_iter_lanczos, eps_lanczos, homo, lumo, unit_nr)
1314 REAL(kind=
dp) :: eps_min, eps_max, threshold
1315 INTEGER,
INTENT(IN) :: max_iter_lanczos
1316 REAL(kind=
dp),
INTENT(IN) :: eps_lanczos
1317 REAL(kind=
dp) :: homo, lumo
1320 LOGICAL :: converged
1321 REAL(kind=
dp) :: max_eig, min_eig, shift1, shift2
1326 CALL dbcsr_create(tmp1, template=matrix_k, matrix_type=dbcsr_type_no_symmetry)
1328 CALL dbcsr_create(tmp2, template=matrix_k, matrix_type=dbcsr_type_no_symmetry)
1330 CALL dbcsr_create(tmp3, template=matrix_k, matrix_type=dbcsr_type_no_symmetry)
1339 0.0_dp, tmp1, filter_eps=threshold)
1341 threshold=eps_lanczos, max_iter=max_iter_lanczos)
1342 homo = max_eig - shift1
1343 IF (unit_nr > 0)
THEN
1344 WRITE (unit_nr,
'(T6,A,1X,L12)')
"Lanczos converged: ", converged
1354 0.0_dp, tmp1, filter_eps=threshold)
1356 threshold=eps_lanczos, max_iter=max_iter_lanczos)
1357 lumo = -max_eig + shift2
1359 IF (unit_nr > 0)
THEN
1360 WRITE (unit_nr,
'(T6,A,1X,L12)')
"Lanczos converged: ", converged
1361 WRITE (unit_nr,
'(T6,A,1X,3F12.5)')
'HOMO/LUMO/gap', homo, lumo, lumo - homo
1376 FUNCTION evaluate_trs4_polynomial(x, gamma_values, i)
RESULT(xr)
1378 REAL(kind=
dp),
DIMENSION(:) :: gamma_values
1382 REAL(kind=
dp),
PARAMETER :: gam_max = 6.0_dp, gam_min = 0.0_dp
1388 IF (gamma_values(k) > gam_max)
THEN
1390 ELSE IF (gamma_values(k) < gam_min)
THEN
1393 xr = (xr*xr)*(4*xr - 3*xr*xr) + gamma_values(k)*xr*xr*((1 - xr)**2)
1396 END FUNCTION evaluate_trs4_polynomial
1405 FUNCTION estimate_steps(homo, lumo, threshold)
RESULT(steps)
1406 REAL(kind=
dp) :: homo, lumo, threshold
1410 REAL(kind=
dp) :: h, l, m
1416 IF (abs(l) < threshold .AND. abs(1 - h) < threshold)
EXIT
1418 IF (m > 0.5_dp)
THEN
1427 END FUNCTION estimate_steps
arnoldi iteration using dbcsr
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 dbcsr_scale(matrix, alpha_scalar)
...
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_multiply(transa, transb, alpha, matrix_a, matrix_b, beta, matrix_c, first_row, last_row, first_column, last_column, first_k, last_k, retain_sparsity, filter_eps, flop)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
subroutine, public dbcsr_filter(matrix, eps)
...
real(kind=dp) function, public dbcsr_get_occupation(matrix)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_put_block(matrix, row, col, block, summation)
...
subroutine, public dbcsr_add(matrix_a, matrix_b, alpha_scalar, beta_scalar)
...
subroutine, public dbcsr_add_on_diag(matrix, alpha)
Adds the given scalar to the diagonal of the matrix. Reserves any missing diagonal blocks.
subroutine, public dbcsr_trace(matrix, trace)
Computes the trace of the given matrix, also known as the sum of its diagonal elements.
real(dp) function, public dbcsr_frobenius_norm(matrix)
Compute the frobenius norm of a dbcsr matrix.
subroutine, public dbcsr_dot(matrix_a, matrix_b, trace)
Computes the dot product of two matrices, also known as the trace of their matrix product.
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 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, iounit)
compute the density matrix using a trace-resetting algorithm
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 density_matrix_tc2(matrix_p, matrix_ks, matrix_s_sqrt_inv, nelectron, threshold, e_homo, e_lumo, non_monotonic, eps_lanczos, max_iter_lanczos, iounit)
compute the density matrix using a non monotonic trace conserving algorithm based on SIAM DOI....
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...
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.
Routines useful for iterative matrix calculations.
subroutine, public matrix_sign_newton_schulz(matrix_sign, matrix, threshold, sign_order, iounit)
compute the sign a matrix using Newton-Schulz iterations
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_sqrt_newton_schulz(matrix_sqrt, matrix_sqrt_inv, matrix, threshold, order, eps_lanczos, max_iter_lanczos, symmetrize, converged, iounit)
compute the sqrt of a matrix via the sign function and the corresponding Newton-Schulz iterations the...
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.
integer, parameter, public int_8
integer, parameter, public dp
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Collection of simple mathematical functions and subroutines.
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...
type of a logger, at the moment it contains just a print level starting at which level it should be l...