LCOV - code coverage report
Current view: top level - src - almo_scf_optimizer.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 54.6 % 3133 1711
Test Date: 2026-09-03 07:32:15 Functions: 62.9 % 35 22

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Optimization routines for all ALMO-based SCF methods
      10              : !> \par History
      11              : !>       2011.05 created [Rustam Z Khaliullin]
      12              : !>       2014.10 as a separate file [Rustam Z Khaliullin]
      13              : !> \author Rustam Z Khaliullin
      14              : ! **************************************************************************************************
      15              : MODULE almo_scf_optimizer
      16              :    USE almo_scf_diis_types,             ONLY: almo_scf_diis_extrapolate,&
      17              :                                               almo_scf_diis_init,&
      18              :                                               almo_scf_diis_push,&
      19              :                                               almo_scf_diis_release,&
      20              :                                               almo_scf_diis_type
      21              :    USE almo_scf_lbfgs_types,            ONLY: lbfgs_create,&
      22              :                                               lbfgs_get_direction,&
      23              :                                               lbfgs_history_type,&
      24              :                                               lbfgs_release,&
      25              :                                               lbfgs_seed
      26              :    USE almo_scf_methods,                ONLY: &
      27              :         almo_scf_ks_blk_to_tv_blk, almo_scf_ks_to_ks_blk, almo_scf_ks_to_ks_xx, &
      28              :         almo_scf_ks_xx_to_tv_xx, almo_scf_p_blk_to_t_blk, almo_scf_t_rescaling, &
      29              :         almo_scf_t_to_proj, apply_domain_operators, apply_projector, &
      30              :         construct_domain_preconditioner, construct_domain_r_down, construct_domain_s_inv, &
      31              :         construct_domain_s_sqrt, fill_matrix_with_ones, get_overlap, orthogonalize_mos, &
      32              :         pseudo_invert_diagonal_blk, xalmo_initial_guess
      33              :    USE almo_scf_qs,                     ONLY: almo_dm_to_almo_ks,&
      34              :                                               almo_dm_to_qs_env,&
      35              :                                               almo_scf_update_ks_energy,&
      36              :                                               matrix_qs_to_almo
      37              :    USE almo_scf_types,                  ONLY: almo_scf_env_type,&
      38              :                                               optimizer_options_type
      39              :    USE cell_types,                      ONLY: cell_type
      40              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      41              :    USE cp_dbcsr_api,                    ONLY: &
      42              :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_desymmetrize, dbcsr_distribution_get, &
      43              :         dbcsr_distribution_type, dbcsr_filter, dbcsr_finalize, dbcsr_get_block_p, dbcsr_get_info, &
      44              :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_readonly_start, &
      45              :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, &
      46              :         dbcsr_p_type, dbcsr_put_block, dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_type, &
      47              :         dbcsr_type_no_symmetry, dbcsr_work_create
      48              :    USE cp_dbcsr_cholesky,               ONLY: cp_dbcsr_cholesky_decompose,&
      49              :                                               cp_dbcsr_cholesky_invert,&
      50              :                                               cp_dbcsr_cholesky_restore
      51              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_add_on_diag,&
      52              :                                               dbcsr_dot,&
      53              :                                               dbcsr_frobenius_norm,&
      54              :                                               dbcsr_get_diag,&
      55              :                                               dbcsr_hadamard_product,&
      56              :                                               dbcsr_maxabs,&
      57              :                                               dbcsr_set_diag
      58              :    USE cp_external_control,             ONLY: external_control
      59              :    USE cp_files,                        ONLY: close_file,&
      60              :                                               open_file
      61              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      62              :                                               cp_logger_get_default_unit_nr,&
      63              :                                               cp_logger_type,&
      64              :                                               cp_to_string
      65              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      66              :                                               cp_print_key_unit_nr
      67              :    USE ct_methods,                      ONLY: analytic_line_search,&
      68              :                                               ct_step_execute,&
      69              :                                               diagonalize_diagonal_blocks
      70              :    USE ct_types,                        ONLY: ct_step_env_clean,&
      71              :                                               ct_step_env_get,&
      72              :                                               ct_step_env_init,&
      73              :                                               ct_step_env_set,&
      74              :                                               ct_step_env_type
      75              :    USE domain_submatrix_methods,        ONLY: construct_submatrices,&
      76              :                                               copy_submatrices,&
      77              :                                               init_submatrices,&
      78              :                                               maxnorm_submatrices,&
      79              :                                               release_submatrices
      80              :    USE domain_submatrix_types,          ONLY: domain_map_type,&
      81              :                                               domain_submatrix_type,&
      82              :                                               select_row
      83              :    USE input_constants,                 ONLY: &
      84              :         almo_scf_diag, almo_scf_dm_sign, cg_dai_yuan, cg_fletcher, cg_fletcher_reeves, &
      85              :         cg_hager_zhang, cg_hestenes_stiefel, cg_liu_storey, cg_polak_ribiere, cg_zero, &
      86              :         op_loc_berry, op_loc_pipek, trustr_cauchy, trustr_dogleg, virt_full, &
      87              :         xalmo_case_block_diag, xalmo_case_fully_deloc, xalmo_case_normal, xalmo_prec_domain, &
      88              :         xalmo_prec_full, xalmo_prec_zero
      89              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      90              :                                               section_vals_type
      91              :    USE iterate_matrix,                  ONLY: determinant,&
      92              :                                               invert_Hotelling,&
      93              :                                               matrix_sqrt_Newton_Schulz
      94              :    USE kinds,                           ONLY: dp
      95              :    USE machine,                         ONLY: m_flush,&
      96              :                                               m_walltime
      97              :    USE message_passing,                 ONLY: mp_comm_type,&
      98              :                                               mp_para_env_type
      99              :    USE particle_methods,                ONLY: get_particle_set
     100              :    USE particle_types,                  ONLY: particle_type
     101              :    USE qs_energy_types,                 ONLY: qs_energy_type
     102              :    USE qs_environment_types,            ONLY: get_qs_env,&
     103              :                                               qs_environment_type
     104              :    USE qs_kind_types,                   ONLY: qs_kind_type
     105              :    USE qs_loc_utils,                    ONLY: compute_berry_operator
     106              :    USE qs_localization_methods,         ONLY: initialize_weights
     107              : #include "./base/base_uses.f90"
     108              : 
     109              :    IMPLICIT NONE
     110              : 
     111              :    PRIVATE
     112              : 
     113              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'almo_scf_optimizer'
     114              : 
     115              :    PUBLIC :: almo_scf_block_diagonal, &
     116              :              almo_scf_xalmo_eigensolver, &
     117              :              almo_scf_xalmo_trustr, &
     118              :              almo_scf_xalmo_pcg, &
     119              :              almo_scf_construct_nlmos
     120              : 
     121              :    LOGICAL, PARAMETER :: debug_mode = .FALSE.
     122              :    LOGICAL, PARAMETER :: safe_mode = .FALSE.
     123              :    LOGICAL, PARAMETER :: almo_mathematica = .FALSE.
     124              :    INTEGER, PARAMETER :: hessian_path_reuse = 1, &
     125              :                          hessian_path_assemble = 2
     126              : 
     127              : CONTAINS
     128              : 
     129              : ! **************************************************************************************************
     130              : !> \brief An SCF procedure that optimizes block-diagonal ALMOs using DIIS
     131              : !> \param qs_env ...
     132              : !> \param almo_scf_env ...
     133              : !> \param optimizer ...
     134              : !> \par History
     135              : !>       2011.06 created [Rustam Z Khaliullin]
     136              : !>       2018.09 smearing support [Ruben Staub]
     137              : !> \author Rustam Z Khaliullin
     138              : ! **************************************************************************************************
     139           76 :    SUBROUTINE almo_scf_block_diagonal(qs_env, almo_scf_env, optimizer)
     140              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     141              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
     142              :       TYPE(optimizer_options_type), INTENT(IN)           :: optimizer
     143              : 
     144              :       CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_block_diagonal'
     145              : 
     146              :       INTEGER                                            :: handle, iscf, ispin, nspin, unit_nr
     147           76 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: local_nocc_of_domain
     148              :       LOGICAL                                            :: converged, prepare_to_exit, should_stop, &
     149              :                                                             use_diis, use_prev_as_guess
     150              :       REAL(KIND=dp) :: density_rec, energy_diff, energy_new, energy_old, error_norm, &
     151              :          error_norm_ispin, kTS_sum, prev_error_norm, t1, t2, true_mixing_fraction
     152           76 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: local_mu
     153              :       TYPE(almo_scf_diis_type), ALLOCATABLE, &
     154           76 :          DIMENSION(:)                                    :: almo_diis
     155              :       TYPE(cp_logger_type), POINTER                      :: logger
     156           76 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: matrix_mixing_old_blk
     157              :       TYPE(qs_energy_type), POINTER                      :: qs_energy
     158              : 
     159           76 :       CALL timeset(routineN, handle)
     160              : 
     161              :       ! get a useful output_unit
     162           76 :       logger => cp_get_default_logger()
     163           76 :       IF (logger%para_env%is_source()) THEN
     164           38 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     165              :       ELSE
     166              :          unit_nr = -1
     167              :       END IF
     168              : 
     169              :       ! use DIIS, it's superior to simple mixing
     170           76 :       use_diis = .TRUE.
     171              :       use_prev_as_guess = .FALSE.
     172              : 
     173           76 :       nspin = almo_scf_env%nspins
     174          228 :       ALLOCATE (local_mu(almo_scf_env%ndomains))
     175          228 :       ALLOCATE (local_nocc_of_domain(almo_scf_env%ndomains))
     176              : 
     177              :       ! init mixing matrices
     178          304 :       ALLOCATE (matrix_mixing_old_blk(nspin))
     179          304 :       ALLOCATE (almo_diis(nspin))
     180          152 :       DO ispin = 1, nspin
     181              :          CALL dbcsr_create(matrix_mixing_old_blk(ispin), &
     182           76 :                            template=almo_scf_env%matrix_ks_blk(ispin))
     183              :          CALL almo_scf_diis_init(diis_env=almo_diis(ispin), &
     184              :                                  sample_err=almo_scf_env%matrix_ks_blk(ispin), &
     185              :                                  sample_var=almo_scf_env%matrix_s_blk(1), &
     186              :                                  error_type=1, &
     187          152 :                                  max_length=optimizer%ndiis)
     188              :       END DO
     189              : 
     190           76 :       CALL get_qs_env(qs_env, energy=qs_energy)
     191           76 :       energy_old = qs_energy%total
     192              : 
     193           76 :       iscf = 0
     194           76 :       prepare_to_exit = .FALSE.
     195           76 :       true_mixing_fraction = 0.0_dp
     196           76 :       error_norm = 1.0E+10_dp ! arbitrary big step
     197              : 
     198           76 :       IF (unit_nr > 0) THEN
     199           38 :          WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 20), &
     200           76 :             " Optimization of block-diagonal ALMOs ", REPEAT("-", 21)
     201           38 :          WRITE (unit_nr, *)
     202           38 :          WRITE (unit_nr, '(T2,A13,A6,A23,A14,A14,A9)') "Method", "Iter", &
     203           76 :             "Total Energy", "Change", "Convergence", "Time"
     204           38 :          WRITE (unit_nr, '(T2,A)') REPEAT("-", 79)
     205              :       END IF
     206              : 
     207              :       ! the real SCF loop
     208           76 :       t1 = m_walltime()
     209          424 :       DO
     210              : 
     211          424 :          iscf = iscf + 1
     212              : 
     213              :          ! obtain projected KS matrix and the DIIS-error vector
     214          424 :          CALL almo_scf_ks_to_ks_blk(almo_scf_env)
     215              : 
     216              :          ! inform the DIIS handler about the new KS matrix and its error vector
     217              :          IF (use_diis) THEN
     218          848 :             DO ispin = 1, nspin
     219              :                CALL almo_scf_diis_push(diis_env=almo_diis(ispin), &
     220              :                                        var=almo_scf_env%matrix_ks_blk(ispin), &
     221          848 :                                        err=almo_scf_env%matrix_err_blk(ispin))
     222              :             END DO
     223              :          END IF
     224              : 
     225              :          ! get error_norm: choose the largest of the two spins
     226              :          prev_error_norm = error_norm
     227          848 :          DO ispin = 1, nspin
     228          424 :             error_norm_ispin = dbcsr_maxabs(almo_scf_env%matrix_err_blk(ispin))
     229          424 :             IF (ispin == 1) error_norm = error_norm_ispin
     230          424 :             IF (ispin > 1 .AND. error_norm_ispin > error_norm) THEN
     231            0 :                error_norm = error_norm_ispin
     232              :             END IF
     233              :          END DO
     234              : 
     235          424 :          IF (error_norm < almo_scf_env%eps_prev_guess) THEN
     236            0 :             use_prev_as_guess = .TRUE.
     237              :          ELSE
     238          424 :             use_prev_as_guess = .FALSE.
     239              :          END IF
     240              : 
     241              :          ! check convergence
     242          424 :          converged = .TRUE.
     243          424 :          IF (error_norm > optimizer%eps_error) converged = .FALSE.
     244              : 
     245              :          ! check other exit criteria: max SCF steps and timing
     246              :          CALL external_control(should_stop, "SCF", &
     247              :                                start_time=qs_env%start_time, &
     248          424 :                                target_time=qs_env%target_time)
     249          424 :          IF (should_stop .OR. iscf >= optimizer%max_iter .OR. converged) THEN
     250           76 :             prepare_to_exit = .TRUE.
     251           76 :             IF (iscf == 1) energy_new = energy_old
     252              :          END IF
     253              : 
     254              :          ! if early stopping is on do at least one iteration
     255          424 :          IF (optimizer%early_stopping_on .AND. iscf == 1) THEN
     256              :             prepare_to_exit = .FALSE.
     257              :          END IF
     258              : 
     259          424 :          IF (.NOT. prepare_to_exit) THEN ! update the ALMOs and density matrix
     260              : 
     261              :             ! perform mixing of KS matrices
     262          348 :             IF (iscf /= 1) THEN
     263              :                IF (use_diis) THEN ! use diis instead of mixing
     264          544 :                   DO ispin = 1, nspin
     265              :                      CALL almo_scf_diis_extrapolate(diis_env=almo_diis(ispin), &
     266          544 :                                                     extr_var=almo_scf_env%matrix_ks_blk(ispin))
     267              :                   END DO
     268              :                ELSE ! use mixing
     269              :                   true_mixing_fraction = almo_scf_env%mixing_fraction
     270              :                   DO ispin = 1, nspin
     271              :                      CALL dbcsr_add(almo_scf_env%matrix_ks_blk(ispin), &
     272              :                                     matrix_mixing_old_blk(ispin), &
     273              :                                     true_mixing_fraction, &
     274              :                                     1.0_dp - true_mixing_fraction)
     275              :                   END DO
     276              :                END IF
     277              :             END IF
     278              :             ! save the new matrix for the future mixing
     279          696 :             DO ispin = 1, nspin
     280              :                CALL dbcsr_copy(matrix_mixing_old_blk(ispin), &
     281          696 :                                almo_scf_env%matrix_ks_blk(ispin))
     282              :             END DO
     283              : 
     284              :             ! obtain ALMOs from the new KS matrix
     285          696 :             SELECT CASE (almo_scf_env%almo_update_algorithm)
     286              :             CASE (almo_scf_diag)
     287              : 
     288          348 :                CALL almo_scf_ks_blk_to_tv_blk(almo_scf_env)
     289              : 
     290              :             CASE (almo_scf_dm_sign)
     291              : 
     292              :                ! update the density matrix
     293            0 :                DO ispin = 1, nspin
     294              : 
     295            0 :                   local_nocc_of_domain(:) = almo_scf_env%nocc_of_domain(:, ispin)
     296            0 :                   local_mu(:) = almo_scf_env%mu_of_domain(:, ispin)
     297            0 :                   CPABORT("Density_matrix_sign has not been tested yet")
     298            0 :                   almo_scf_env%mu_of_domain(:, ispin) = local_mu(:)
     299              : 
     300              :                END DO
     301              : 
     302              :                ! obtain ALMOs from matrix_p_blk: T_new = P_blk S_blk T_old
     303            0 :                CALL almo_scf_p_blk_to_t_blk(almo_scf_env, ionic=.FALSE.)
     304              : 
     305          348 :                DO ispin = 1, almo_scf_env%nspins
     306              : 
     307              :                   CALL orthogonalize_mos(ket=almo_scf_env%matrix_t_blk(ispin), &
     308              :                                          overlap=almo_scf_env%matrix_sigma_blk(ispin), &
     309              :                                          metric=almo_scf_env%matrix_s_blk(1), &
     310              :                                          retain_locality=.TRUE., &
     311              :                                          only_normalize=.FALSE., &
     312              :                                          nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
     313              :                                          eps_filter=almo_scf_env%eps_filter, &
     314              :                                          order_lanczos=almo_scf_env%order_lanczos, &
     315              :                                          eps_lanczos=almo_scf_env%eps_lanczos, &
     316            0 :                                          max_iter_lanczos=almo_scf_env%max_iter_lanczos)
     317              : 
     318              :                END DO
     319              : 
     320              :             END SELECT
     321              : 
     322              :             ! obtain density matrix from ALMOs
     323          696 :             DO ispin = 1, almo_scf_env%nspins
     324              : 
     325              :                !! Application of an occupation-rescaling trick for smearing, if requested
     326          348 :                IF (almo_scf_env%smear) THEN
     327              :                   CALL almo_scf_t_rescaling(matrix_t=almo_scf_env%matrix_t_blk(ispin), &
     328              :                                             mo_energies=almo_scf_env%mo_energies(:, ispin), &
     329              :                                             mu_of_domain=almo_scf_env%mu_of_domain(:, ispin), &
     330              :                                             real_ne_of_domain=almo_scf_env%real_ne_of_domain(:, ispin), &
     331              :                                             spin_kTS=almo_scf_env%kTS(ispin), &
     332              :                                             smear_e_temp=almo_scf_env%smear_e_temp, &
     333              :                                             ndomains=almo_scf_env%ndomains, &
     334           16 :                                             nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin))
     335              :                END IF
     336              : 
     337              :                CALL almo_scf_t_to_proj(t=almo_scf_env%matrix_t_blk(ispin), &
     338              :                                        p=almo_scf_env%matrix_p(ispin), &
     339              :                                        eps_filter=almo_scf_env%eps_filter, &
     340              :                                        orthog_orbs=.FALSE., &
     341              :                                        nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
     342              :                                        s=almo_scf_env%matrix_s(1), &
     343              :                                        sigma=almo_scf_env%matrix_sigma(ispin), &
     344              :                                        sigma_inv=almo_scf_env%matrix_sigma_inv(ispin), &
     345              :                                        use_guess=use_prev_as_guess, &
     346              :                                        smear=almo_scf_env%smear, &
     347              :                                        algorithm=almo_scf_env%sigma_inv_algorithm, &
     348              :                                        inverse_accelerator=almo_scf_env%order_lanczos, &
     349              :                                        inv_eps_factor=almo_scf_env%matrix_iter_eps_error_factor, &
     350              :                                        eps_lanczos=almo_scf_env%eps_lanczos, &
     351              :                                        max_iter_lanczos=almo_scf_env%max_iter_lanczos, &
     352              :                                        para_env=almo_scf_env%para_env, &
     353          696 :                                        blacs_env=almo_scf_env%blacs_env)
     354              : 
     355              :             END DO
     356              : 
     357          348 :             IF (almo_scf_env%nspins == 1) THEN
     358          348 :                CALL dbcsr_scale(almo_scf_env%matrix_p(1), 2.0_dp)
     359              :                !! Rescaling electronic entropy contribution by spin_factor
     360          348 :                IF (almo_scf_env%smear) THEN
     361           16 :                   almo_scf_env%kTS(1) = almo_scf_env%kTS(1)*2.0_dp
     362              :                END IF
     363              :             END IF
     364              : 
     365          348 :             IF (almo_scf_env%smear) THEN
     366           32 :                kTS_sum = SUM(almo_scf_env%kTS)
     367              :             ELSE
     368          332 :                kTS_sum = 0.0_dp
     369              :             END IF
     370              : 
     371              :             ! compute the new KS matrix and new energy
     372              :             CALL almo_dm_to_almo_ks(qs_env, &
     373              :                                     almo_scf_env%matrix_p, &
     374              :                                     almo_scf_env%matrix_ks, &
     375              :                                     energy_new, &
     376              :                                     almo_scf_env%eps_filter, &
     377              :                                     almo_scf_env%mat_distr_aos, &
     378              :                                     smear=almo_scf_env%smear, &
     379          348 :                                     kTS_sum=kTS_sum)
     380              : 
     381              :          END IF ! prepare_to_exit
     382              : 
     383          424 :          energy_diff = energy_new - energy_old
     384          424 :          energy_old = energy_new
     385          424 :          almo_scf_env%almo_scf_energy = energy_new
     386              : 
     387          424 :          t2 = m_walltime()
     388              :          ! brief report on the current SCF loop
     389          424 :          IF (unit_nr > 0) THEN
     390          212 :             WRITE (unit_nr, '(T2,A13,I6,F23.10,E14.5,F14.9,F9.2)') "ALMO SCF DIIS", &
     391          212 :                iscf, &
     392          424 :                energy_new, energy_diff, error_norm, t2 - t1
     393              :          END IF
     394          424 :          t1 = m_walltime()
     395              : 
     396          424 :          IF (prepare_to_exit) EXIT
     397              : 
     398              :       END DO ! end scf cycle
     399              : 
     400              :       !! Print number of electrons recovered if smearing was requested
     401           76 :       IF (almo_scf_env%smear) THEN
     402            8 :          DO ispin = 1, nspin
     403            4 :             CALL dbcsr_dot(almo_scf_env%matrix_p(ispin), almo_scf_env%matrix_s(1), density_rec)
     404            8 :             IF (unit_nr > 0) THEN
     405            2 :                WRITE (unit_nr, '(T2,A20,F23.10)') "Electrons recovered:", density_rec
     406              :             END IF
     407              :          END DO
     408              :       END IF
     409              : 
     410           76 :       IF (.NOT. converged .AND. (.NOT. optimizer%early_stopping_on)) THEN
     411            0 :          IF (unit_nr > 0) THEN
     412            0 :             CPABORT("SCF for block-diagonal ALMOs not converged!")
     413              :          END IF
     414              :       END IF
     415              : 
     416          152 :       DO ispin = 1, nspin
     417           76 :          CALL dbcsr_release(matrix_mixing_old_blk(ispin))
     418          152 :          CALL almo_scf_diis_release(diis_env=almo_diis(ispin))
     419              :       END DO
     420          152 :       DEALLOCATE (almo_diis)
     421           76 :       DEALLOCATE (matrix_mixing_old_blk)
     422           76 :       DEALLOCATE (local_mu)
     423           76 :       DEALLOCATE (local_nocc_of_domain)
     424              : 
     425           76 :       CALL timestop(handle)
     426              : 
     427           76 :    END SUBROUTINE almo_scf_block_diagonal
     428              : 
     429              : ! **************************************************************************************************
     430              : !> \brief An eigensolver-based SCF to optimize extended ALMOs (i.e. ALMOs on
     431              : !>        overlapping domains)
     432              : !> \param qs_env ...
     433              : !> \param almo_scf_env ...
     434              : !> \param optimizer ...
     435              : !> \par History
     436              : !>       2013.03 created [Rustam Z Khaliullin]
     437              : !>       2018.09 smearing support [Ruben Staub]
     438              : !> \author Rustam Z Khaliullin
     439              : ! **************************************************************************************************
     440            2 :    SUBROUTINE almo_scf_xalmo_eigensolver(qs_env, almo_scf_env, optimizer)
     441              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     442              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
     443              :       TYPE(optimizer_options_type), INTENT(IN)           :: optimizer
     444              : 
     445              :       CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_xalmo_eigensolver'
     446              : 
     447              :       INTEGER                                            :: handle, iscf, ispin, nspin, unit_nr
     448              :       LOGICAL                                            :: converged, prepare_to_exit, should_stop
     449              :       REAL(KIND=dp) :: denergy_tot, density_rec, energy_diff, energy_new, energy_old, error_norm, &
     450              :          error_norm_0, kTS_sum, spin_factor, t1, t2
     451              :       REAL(KIND=dp), DIMENSION(2)                        :: denergy_spin
     452              :       TYPE(almo_scf_diis_type), ALLOCATABLE, &
     453            2 :          DIMENSION(:)                                    :: almo_diis
     454              :       TYPE(cp_logger_type), POINTER                      :: logger
     455              :       TYPE(dbcsr_type)                                   :: matrix_p_almo_scf_converged
     456              :       TYPE(domain_submatrix_type), ALLOCATABLE, &
     457              :          DIMENSION(:, :)                                 :: submatrix_mixing_old_blk
     458              : 
     459            2 :       CALL timeset(routineN, handle)
     460              : 
     461              :       ! get a useful output_unit
     462            2 :       logger => cp_get_default_logger()
     463            2 :       IF (logger%para_env%is_source()) THEN
     464            1 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     465              :       ELSE
     466            1 :          unit_nr = -1
     467              :       END IF
     468              : 
     469            2 :       nspin = almo_scf_env%nspins
     470            2 :       IF (nspin == 1) THEN
     471            2 :          spin_factor = 2.0_dp
     472              :       ELSE
     473            0 :          spin_factor = 1.0_dp
     474              :       END IF
     475              : 
     476              :       ! RZK-warning domain_s_sqrt and domain_s_sqrt_inv do not have spin
     477              :       ! components yet (may be used later)
     478            2 :       ispin = 1
     479              :       CALL construct_domain_s_sqrt( &
     480              :          matrix_s=almo_scf_env%matrix_s(1), &
     481              :          subm_s_sqrt=almo_scf_env%domain_s_sqrt(:, ispin), &
     482              :          subm_s_sqrt_inv=almo_scf_env%domain_s_sqrt_inv(:, ispin), &
     483              :          dpattern=almo_scf_env%quench_t(ispin), &
     484              :          map=almo_scf_env%domain_map(ispin), &
     485            2 :          node_of_domain=almo_scf_env%cpu_of_domain)
     486              : 
     487              :       ! construct the domain template for the occupied orbitals
     488            4 :       DO ispin = 1, nspin
     489              :          ! RZK-warning we need only the matrix structure, not data
     490              :          ! replace construct_submatrices with lighter procedure with
     491              :          ! no heavy communications
     492              :          CALL construct_submatrices( &
     493              :             matrix=almo_scf_env%quench_t(ispin), &
     494              :             submatrix=almo_scf_env%domain_t(:, ispin), &
     495              :             distr_pattern=almo_scf_env%quench_t(ispin), &
     496              :             domain_map=almo_scf_env%domain_map(ispin), &
     497              :             node_of_domain=almo_scf_env%cpu_of_domain, &
     498            4 :             job_type=select_row)
     499              :       END DO
     500              : 
     501              :       ! init mixing matrices
     502           20 :       ALLOCATE (submatrix_mixing_old_blk(almo_scf_env%ndomains, nspin))
     503            2 :       CALL init_submatrices(submatrix_mixing_old_blk)
     504            8 :       ALLOCATE (almo_diis(nspin))
     505              : 
     506            4 :       DO ispin = 1, nspin
     507              :          ! use s_sqrt since they are already properly constructed
     508              :          ! and have the same distributions as domain_err and domain_ks_xx
     509              :          CALL almo_scf_diis_init(diis_env=almo_diis(ispin), &
     510              :                                  sample_err=almo_scf_env%domain_s_sqrt(:, ispin), &
     511              :                                  error_type=1, &
     512            4 :                                  max_length=optimizer%ndiis)
     513              :       END DO
     514              : 
     515            2 :       denergy_tot = 0.0_dp
     516            2 :       energy_old = 0.0_dp
     517            2 :       iscf = 0
     518            2 :       prepare_to_exit = .FALSE.
     519              : 
     520              :       ! the SCF loop
     521            2 :       t1 = m_walltime()
     522            2 :       DO
     523              : 
     524            2 :          iscf = iscf + 1
     525              : 
     526              :          ! obtain projected KS matrix and the DIIS-error vector
     527            2 :          CALL almo_scf_ks_to_ks_xx(almo_scf_env)
     528              : 
     529              :          ! inform the DIIS handler about the new KS matrix and its error vector
     530            4 :          DO ispin = 1, nspin
     531              :             CALL almo_scf_diis_push(diis_env=almo_diis(ispin), &
     532              :                                     d_var=almo_scf_env%domain_ks_xx(:, ispin), &
     533            4 :                                     d_err=almo_scf_env%domain_err(:, ispin))
     534              :          END DO
     535              : 
     536              :          ! check convergence
     537            2 :          converged = .TRUE.
     538            2 :          DO ispin = 1, nspin
     539            2 :             error_norm = dbcsr_maxabs(almo_scf_env%matrix_err_xx(ispin))
     540              :             CALL maxnorm_submatrices(almo_scf_env%domain_err(:, ispin), &
     541            2 :                                      norm=error_norm_0)
     542            2 :             IF (error_norm > optimizer%eps_error) THEN
     543              :                converged = .FALSE.
     544              :                EXIT ! no need to check the other spin
     545              :             END IF
     546              :          END DO
     547              :          ! check other exit criteria: max SCF steps and timing
     548              :          CALL external_control(should_stop, "SCF", &
     549              :                                start_time=qs_env%start_time, &
     550            2 :                                target_time=qs_env%target_time)
     551            2 :          IF (should_stop .OR. iscf >= optimizer%max_iter .OR. converged) THEN
     552            0 :             prepare_to_exit = .TRUE.
     553              :          END IF
     554              : 
     555              :          ! if early stopping is on do at least one iteration
     556            2 :          IF (optimizer%early_stopping_on .AND. iscf == 1) THEN
     557              :             prepare_to_exit = .FALSE.
     558              :          END IF
     559              : 
     560            2 :          IF (.NOT. prepare_to_exit) THEN ! update the ALMOs and density matrix
     561              : 
     562              :             ! perform mixing of KS matrices
     563            2 :             IF (iscf /= 1) THEN
     564            0 :                DO ispin = 1, nspin
     565              :                   CALL almo_scf_diis_extrapolate(diis_env=almo_diis(ispin), &
     566            0 :                                                  d_extr_var=almo_scf_env%domain_ks_xx(:, ispin))
     567              :                END DO
     568              :             END IF
     569              :             ! save the new matrix for the future mixing
     570            4 :             DO ispin = 1, nspin
     571              :                CALL copy_submatrices( &
     572              :                   almo_scf_env%domain_ks_xx(:, ispin), &
     573              :                   submatrix_mixing_old_blk(:, ispin), &
     574            4 :                   copy_data=.TRUE.)
     575              :             END DO
     576              : 
     577              :             ! obtain a new set of ALMOs from the updated KS matrix
     578            2 :             CALL almo_scf_ks_xx_to_tv_xx(almo_scf_env)
     579              : 
     580              :             ! update the density matrix
     581            4 :             DO ispin = 1, nspin
     582              : 
     583              :                ! save the initial density matrix (to get the perturbative energy lowering)
     584            2 :                IF (iscf == 1) THEN
     585              :                   CALL dbcsr_create(matrix_p_almo_scf_converged, &
     586            2 :                                     template=almo_scf_env%matrix_p(ispin))
     587              :                   CALL dbcsr_copy(matrix_p_almo_scf_converged, &
     588            2 :                                   almo_scf_env%matrix_p(ispin))
     589              :                END IF
     590              : 
     591              :                !! Application of an occupation-rescaling trick for smearing, if requested
     592            2 :                IF (almo_scf_env%smear) THEN
     593              :                   CALL almo_scf_t_rescaling(matrix_t=almo_scf_env%matrix_t_blk(ispin), &
     594              :                                             mo_energies=almo_scf_env%mo_energies(:, ispin), &
     595              :                                             mu_of_domain=almo_scf_env%mu_of_domain(:, ispin), &
     596              :                                             real_ne_of_domain=almo_scf_env%real_ne_of_domain(:, ispin), &
     597              :                                             spin_kTS=almo_scf_env%kTS(ispin), &
     598              :                                             smear_e_temp=almo_scf_env%smear_e_temp, &
     599              :                                             ndomains=almo_scf_env%ndomains, &
     600            0 :                                             nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin))
     601              :                END IF
     602              : 
     603              :                ! update now
     604              :                CALL almo_scf_t_to_proj( &
     605              :                   t=almo_scf_env%matrix_t(ispin), &
     606              :                   p=almo_scf_env%matrix_p(ispin), &
     607              :                   eps_filter=almo_scf_env%eps_filter, &
     608              :                   orthog_orbs=.FALSE., &
     609              :                   nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
     610              :                   s=almo_scf_env%matrix_s(1), &
     611              :                   sigma=almo_scf_env%matrix_sigma(ispin), &
     612              :                   sigma_inv=almo_scf_env%matrix_sigma_inv(ispin), &
     613              :                   use_guess=.TRUE., &
     614              :                   smear=almo_scf_env%smear, &
     615              :                   algorithm=almo_scf_env%sigma_inv_algorithm, &
     616              :                   inverse_accelerator=almo_scf_env%order_lanczos, &
     617              :                   inv_eps_factor=almo_scf_env%matrix_iter_eps_error_factor, &
     618              :                   eps_lanczos=almo_scf_env%eps_lanczos, &
     619              :                   max_iter_lanczos=almo_scf_env%max_iter_lanczos, &
     620              :                   para_env=almo_scf_env%para_env, &
     621            2 :                   blacs_env=almo_scf_env%blacs_env)
     622            2 :                CALL dbcsr_scale(almo_scf_env%matrix_p(ispin), spin_factor)
     623              :                !! Rescaling electronic entropy contribution by spin_factor
     624            2 :                IF (almo_scf_env%smear) THEN
     625            0 :                   almo_scf_env%kTS(ispin) = almo_scf_env%kTS(ispin)*spin_factor
     626              :                END IF
     627              : 
     628              :                ! obtain perturbative estimate (at no additional cost)
     629              :                ! of the energy lowering relative to the block-diagonal ALMOs
     630            4 :                IF (iscf == 1) THEN
     631              : 
     632              :                   CALL dbcsr_add(matrix_p_almo_scf_converged, &
     633            2 :                                  almo_scf_env%matrix_p(ispin), -1.0_dp, 1.0_dp)
     634              :                   CALL dbcsr_dot(almo_scf_env%matrix_ks_0deloc(ispin), &
     635              :                                  matrix_p_almo_scf_converged, &
     636            2 :                                  denergy_spin(ispin))
     637              : 
     638            2 :                   CALL dbcsr_release(matrix_p_almo_scf_converged)
     639              : 
     640              :                   !! RS-WARNING: If smearing ALMO is requested, electronic entropy contribution should probably be included here
     641              : 
     642            2 :                   denergy_tot = denergy_tot + denergy_spin(ispin)
     643              : 
     644              :                END IF ! iscf.eq.1
     645              : 
     646              :             END DO
     647              : 
     648              :             ! print out the energy lowering
     649            2 :             IF (iscf == 1) THEN
     650              :                CALL energy_lowering_report( &
     651              :                   unit_nr=unit_nr, &
     652              :                   ref_energy=almo_scf_env%almo_scf_energy, &
     653            2 :                   energy_lowering=denergy_tot)
     654              :                CALL almo_scf_update_ks_energy(qs_env, &
     655              :                                               energy=almo_scf_env%almo_scf_energy, &
     656            2 :                                               energy_singles_corr=denergy_tot)
     657              :             END IF
     658              : 
     659              :             ! compute the new KS matrix and new energy
     660            2 :             IF (.NOT. almo_scf_env%perturbative_delocalization) THEN
     661              : 
     662            0 :                IF (almo_scf_env%smear) THEN
     663            0 :                   kTS_sum = SUM(almo_scf_env%kTS)
     664              :                ELSE
     665            0 :                   kTS_sum = 0.0_dp
     666              :                END IF
     667              : 
     668              :                CALL almo_dm_to_almo_ks(qs_env, &
     669              :                                        almo_scf_env%matrix_p, &
     670              :                                        almo_scf_env%matrix_ks, &
     671              :                                        energy_new, &
     672              :                                        almo_scf_env%eps_filter, &
     673              :                                        almo_scf_env%mat_distr_aos, &
     674              :                                        smear=almo_scf_env%smear, &
     675            0 :                                        kTS_sum=kTS_sum)
     676              :             END IF
     677              : 
     678              :          END IF ! prepare_to_exit
     679              : 
     680            2 :          IF (almo_scf_env%perturbative_delocalization) THEN
     681              : 
     682              :             ! exit after the first step if we do not need the SCF procedure
     683            2 :             CALL almo_dm_to_qs_env(qs_env, almo_scf_env%matrix_p, almo_scf_env%mat_distr_aos)
     684            2 :             converged = .TRUE.
     685            2 :             prepare_to_exit = .TRUE.
     686              : 
     687              :          ELSE ! not a perturbative treatment
     688              : 
     689            0 :             energy_diff = energy_new - energy_old
     690            0 :             energy_old = energy_new
     691            0 :             almo_scf_env%almo_scf_energy = energy_new
     692              : 
     693            0 :             t2 = m_walltime()
     694              :             ! brief report on the current SCF loop
     695            0 :             IF (unit_nr > 0) THEN
     696            0 :                WRITE (unit_nr, '(T2,A,I6,F20.9,E11.3,E11.3,E11.3,F8.2)') "ALMO SCF", &
     697            0 :                   iscf, &
     698            0 :                   energy_new, energy_diff, error_norm, error_norm_0, t2 - t1
     699              :             END IF
     700            0 :             t1 = m_walltime()
     701              : 
     702              :          END IF
     703              : 
     704            2 :          IF (prepare_to_exit) EXIT
     705              : 
     706              :       END DO ! end scf cycle
     707              : 
     708              :       !! Print number of electrons recovered if smearing was requested
     709            2 :       IF (almo_scf_env%smear) THEN
     710            0 :          DO ispin = 1, nspin
     711            0 :             CALL dbcsr_dot(almo_scf_env%matrix_p(ispin), almo_scf_env%matrix_s(1), density_rec)
     712            0 :             IF (unit_nr > 0) THEN
     713            0 :                WRITE (unit_nr, '(T2,A20,F23.10)') "Electrons recovered:", density_rec
     714              :             END IF
     715              :          END DO
     716              :       END IF
     717              : 
     718            2 :       IF (.NOT. converged .AND. .NOT. optimizer%early_stopping_on) THEN
     719            0 :          CPABORT("SCF for ALMOs on overlapping domains not converged!")
     720              :       END IF
     721              : 
     722            4 :       DO ispin = 1, nspin
     723            2 :          CALL release_submatrices(submatrix_mixing_old_blk(:, ispin))
     724            4 :          CALL almo_scf_diis_release(diis_env=almo_diis(ispin))
     725              :       END DO
     726            4 :       DEALLOCATE (almo_diis)
     727           12 :       DEALLOCATE (submatrix_mixing_old_blk)
     728              : 
     729            2 :       CALL timestop(handle)
     730              : 
     731            2 :    END SUBROUTINE almo_scf_xalmo_eigensolver
     732              : 
     733              : ! **************************************************************************************************
     734              : !> \brief Optimization of ALMOs using PCG-like minimizers
     735              : !> \param qs_env ...
     736              : !> \param almo_scf_env ...
     737              : !> \param optimizer   controls the optimization algorithm
     738              : !> \param quench_t ...
     739              : !> \param matrix_t_in ...
     740              : !> \param matrix_t_out ...
     741              : !> \param assume_t0_q0x - since it is extremely difficult to converge the iterative
     742              : !>                        procedure using T as an optimized variable, assume
     743              : !>                        T = T_0 + (1-R_0)*X and optimize X
     744              : !>                        T_0 is assumed to be the zero-delocalization reference
     745              : !> \param perturbation_only - perturbative (do not update Hamiltonian)
     746              : !> \param special_case   to reduce the overhead special cases are implemented:
     747              : !>                       xalmo_case_normal - no special case (i.e. xALMOs)
     748              : !>                       xalmo_case_block_diag
     749              : !>                       xalmo_case_fully_deloc
     750              : !> \par History
     751              : !>       2011.11 created [Rustam Z Khaliullin]
     752              : !> \author Rustam Z Khaliullin
     753              : ! **************************************************************************************************
     754           92 :    SUBROUTINE almo_scf_xalmo_pcg(qs_env, almo_scf_env, optimizer, quench_t, &
     755              :                                  matrix_t_in, matrix_t_out, assume_t0_q0x, perturbation_only, &
     756              :                                  special_case)
     757              : 
     758              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     759              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
     760              :       TYPE(optimizer_options_type), INTENT(IN)           :: optimizer
     761              :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:), &
     762              :          INTENT(INOUT)                                   :: quench_t, matrix_t_in, matrix_t_out
     763              :       LOGICAL, INTENT(IN)                                :: assume_t0_q0x, perturbation_only
     764              :       INTEGER, INTENT(IN), OPTIONAL                      :: special_case
     765              : 
     766              :       CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_xalmo_pcg'
     767              : 
     768              :       CHARACTER(LEN=20)                                  :: iter_type
     769              :       INTEGER :: cg_iteration, dim_op, fixed_line_search_niter, handle, idim0, ielem, ispin, &
     770              :          iteration, line_search_iteration, max_iter, my_special_case, ndomains, nmo, nspins, &
     771              :          outer_iteration, outer_max_iter, prec_type, reim, unit_nr
     772           92 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nocc
     773              :       LOGICAL :: blissful_neglect, converged, just_started, line_search, normalize_orbitals, &
     774              :          optimize_theta, outer_prepare_to_exit, penalty_occ_local, penalty_occ_vol, &
     775              :          prepare_to_exit, reset_conjugator, skip_grad, use_guess
     776           92 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: reim_diag, weights, z2
     777              :       REAL(kind=dp) :: appr_sec_der, beta, denom, denom2, e0, e1, energy_coeff, energy_diff, &
     778              :          energy_new, energy_old, eps_skip_gradients, fval, g0, g1, grad_norm, grad_norm_frob, &
     779              :          line_search_error, localiz_coeff, localization_obj_function, next_step_size_guess, &
     780              :          penalty_amplitude, penalty_func_new, spin_factor, step_size, t1, t2, tempreal
     781           92 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: grad_norm_spin, &
     782           92 :                                                             penalty_occ_vol_g_prefactor, &
     783           92 :                                                             penalty_occ_vol_h_prefactor
     784              :       TYPE(cell_type), POINTER                           :: cell
     785              :       TYPE(cp_logger_type), POINTER                      :: logger
     786           92 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: qs_matrix_s
     787           92 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: op_sm_set_almo, op_sm_set_qs
     788           92 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: FTsiginv, grad, m_sig_sqrti_ii, m_t_in_local, &
     789           92 :          m_theta, prec_vv, prev_grad, prev_minus_prec_grad, prev_step, siginvTFTsiginv, ST, step, &
     790           92 :          STsiginv_0, tempNOcc, tempNOcc_1, tempOccOcc
     791              :       TYPE(domain_submatrix_type), ALLOCATABLE, &
     792           92 :          DIMENSION(:, :)                                 :: bad_modes_projector_down, domain_r_down
     793              :       TYPE(mp_comm_type)                                 :: group
     794              : 
     795           92 :       CALL timeset(routineN, handle)
     796              : 
     797           92 :       my_special_case = xalmo_case_normal
     798           92 :       IF (PRESENT(special_case)) my_special_case = special_case
     799              : 
     800              :       ! get a useful output_unit
     801           92 :       logger => cp_get_default_logger()
     802           92 :       IF (logger%para_env%is_source()) THEN
     803           46 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     804              :       ELSE
     805              :          unit_nr = -1
     806              :       END IF
     807              : 
     808           92 :       nspins = almo_scf_env%nspins
     809              : 
     810              :       ! if unprojected XALMOs are optimized
     811              :       ! then we must use the "blissful_neglect" procedure
     812           92 :       blissful_neglect = .FALSE.
     813           92 :       IF (my_special_case == xalmo_case_normal .AND. .NOT. assume_t0_q0x) THEN
     814           14 :          blissful_neglect = .TRUE.
     815              :       END IF
     816              : 
     817           92 :       IF (unit_nr > 0) THEN
     818           46 :          WRITE (unit_nr, *)
     819            5 :          SELECT CASE (my_special_case)
     820              :          CASE (xalmo_case_block_diag)
     821            5 :             WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 20), &
     822           10 :                " Optimization of block-diagonal ALMOs ", REPEAT("-", 21)
     823              :          CASE (xalmo_case_fully_deloc)
     824           22 :             WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 20), &
     825           44 :                " Optimization of fully delocalized MOs ", REPEAT("-", 20)
     826              :          CASE (xalmo_case_normal)
     827           46 :             IF (blissful_neglect) THEN
     828            7 :                WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 25), &
     829           14 :                   " LCP optimization of XALMOs ", REPEAT("-", 26)
     830              :             ELSE
     831           12 :                WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 27), &
     832           24 :                   " Optimization of XALMOs ", REPEAT("-", 28)
     833              :             END IF
     834              :          END SELECT
     835           46 :          WRITE (unit_nr, *)
     836           46 :          WRITE (unit_nr, '(T2,A13,A6,A23,A14,A14,A9)') "Method", "Iter", &
     837           92 :             "Objective Function", "Change", "Convergence", "Time"
     838           46 :          WRITE (unit_nr, '(T2,A)') REPEAT("-", 79)
     839              :       END IF
     840              : 
     841              :       ! set local parameters using developer's keywords
     842              :       ! RZK-warning: change to normal keywords later
     843           92 :       optimize_theta = almo_scf_env%logical05
     844           92 :       eps_skip_gradients = almo_scf_env%real01
     845              : 
     846              :       ! penalty amplitude adjusts the strength of volume conservation
     847           92 :       energy_coeff = 1.0_dp
     848           92 :       localiz_coeff = 0.0_dp
     849           92 :       penalty_amplitude = 0.0_dp
     850           92 :       penalty_occ_vol = .FALSE.
     851           92 :       penalty_occ_local = .FALSE.
     852           92 :       normalize_orbitals = penalty_occ_vol .OR. penalty_occ_local
     853          276 :       ALLOCATE (penalty_occ_vol_g_prefactor(nspins))
     854          184 :       ALLOCATE (penalty_occ_vol_h_prefactor(nspins))
     855           92 :       penalty_occ_vol_g_prefactor(:) = 0.0_dp
     856           92 :       penalty_occ_vol_h_prefactor(:) = 0.0_dp
     857           92 :       penalty_func_new = 0.0_dp
     858              : 
     859              :       ! preconditioner control
     860           92 :       prec_type = optimizer%preconditioner
     861              : 
     862              :       ! control of the line search
     863           92 :       fixed_line_search_niter = 0 ! init to zero, change when eps is small enough
     864              : 
     865           92 :       IF (nspins == 1) THEN
     866           86 :          spin_factor = 2.0_dp
     867              :       ELSE
     868            6 :          spin_factor = 1.0_dp
     869              :       END IF
     870              : 
     871          184 :       ALLOCATE (grad_norm_spin(nspins))
     872          276 :       ALLOCATE (nocc(nspins))
     873              : 
     874              :       ! create a local copy of matrix_t_in because
     875              :       ! matrix_t_in and matrix_t_out can be the same matrix
     876              :       ! we need to make sure data in matrix_t_in is intact
     877              :       ! after we start writing to matrix_t_out
     878          374 :       ALLOCATE (m_t_in_local(nspins))
     879          190 :       DO ispin = 1, nspins
     880              :          CALL dbcsr_create(m_t_in_local(ispin), &
     881              :                            template=matrix_t_in(ispin), &
     882           98 :                            matrix_type=dbcsr_type_no_symmetry)
     883          190 :          CALL dbcsr_copy(m_t_in_local(ispin), matrix_t_in(ispin))
     884              :       END DO
     885              : 
     886              :       ! m_theta contains a set of variational parameters
     887              :       ! that define one-electron orbitals (simple, projected, etc.)
     888          282 :       ALLOCATE (m_theta(nspins))
     889          190 :       DO ispin = 1, nspins
     890              :          CALL dbcsr_create(m_theta(ispin), &
     891              :                            template=matrix_t_out(ispin), &
     892          190 :                            matrix_type=dbcsr_type_no_symmetry)
     893              :       END DO
     894              : 
     895              :       ! Compute localization matrices
     896              :       IF (penalty_occ_local) THEN
     897              : 
     898              :          CALL get_qs_env(qs_env=qs_env, &
     899              :                          matrix_s=qs_matrix_s, &
     900              :                          cell=cell)
     901              : 
     902              :          IF (cell%orthorhombic) THEN
     903              :             dim_op = 3
     904              :          ELSE
     905              :             dim_op = 6
     906              :          END IF
     907              :          ALLOCATE (weights(6))
     908              :          weights = 0.0_dp
     909              : 
     910              :          CALL initialize_weights(cell, weights)
     911              : 
     912              :          ALLOCATE (op_sm_set_qs(2, dim_op))
     913              :          ALLOCATE (op_sm_set_almo(2, dim_op))
     914              : 
     915              :          DO idim0 = 1, dim_op
     916              :             DO reim = 1, SIZE(op_sm_set_qs, 1)
     917              :                NULLIFY (op_sm_set_qs(reim, idim0)%matrix)
     918              :                ALLOCATE (op_sm_set_qs(reim, idim0)%matrix)
     919              :                CALL dbcsr_copy(op_sm_set_qs(reim, idim0)%matrix, qs_matrix_s(1)%matrix, &
     920              :                              name="almo_scf_env%op_sm_"//TRIM(ADJUSTL(cp_to_string(reim)))//"-"//TRIM(ADJUSTL(cp_to_string(idim0))))
     921              :                NULLIFY (op_sm_set_almo(reim, idim0)%matrix)
     922              :                ALLOCATE (op_sm_set_almo(reim, idim0)%matrix)
     923              :                CALL dbcsr_copy(op_sm_set_almo(reim, idim0)%matrix, almo_scf_env%matrix_s(1), &
     924              :                              name="almo_scf_env%op_sm_"//TRIM(ADJUSTL(cp_to_string(reim)))//"-"//TRIM(ADJUSTL(cp_to_string(idim0))))
     925              :                CALL dbcsr_set(op_sm_set_almo(reim, idim0)%matrix, 0.0_dp)
     926              :             END DO
     927              :          END DO
     928              : 
     929              :          CALL compute_berry_operator(qs_env, cell, op_sm_set_qs, dim_op)
     930              : 
     931              :          !CALL matrix_qs_to_almo(op_sm_set_qs, op_sm_set_almo, almo_scf_env%mat_distr_aos)
     932              : 
     933              :       END IF
     934              : 
     935              :       ! create initial guess from the initial orbitals
     936              :       CALL xalmo_initial_guess(m_guess=m_theta, &
     937              :                                m_t_in=m_t_in_local, &
     938              :                                m_t0=almo_scf_env%matrix_t_blk, &
     939              :                                m_quench_t=quench_t, &
     940              :                                m_overlap=almo_scf_env%matrix_s(1), &
     941              :                                m_sigma_tmpl=almo_scf_env%matrix_sigma_inv, &
     942              :                                nspins=nspins, &
     943              :                                xalmo_history=almo_scf_env%xalmo_history, &
     944              :                                assume_t0_q0x=assume_t0_q0x, &
     945              :                                optimize_theta=optimize_theta, &
     946              :                                envelope_amplitude=almo_scf_env%envelope_amplitude, &
     947              :                                eps_filter=almo_scf_env%eps_filter, &
     948              :                                order_lanczos=almo_scf_env%order_lanczos, &
     949              :                                eps_lanczos=almo_scf_env%eps_lanczos, &
     950              :                                max_iter_lanczos=almo_scf_env%max_iter_lanczos, &
     951           92 :                                nocc_of_domain=almo_scf_env%nocc_of_domain)
     952              : 
     953           92 :       ndomains = almo_scf_env%ndomains
     954         1088 :       ALLOCATE (domain_r_down(ndomains, nspins))
     955           92 :       CALL init_submatrices(domain_r_down)
     956          996 :       ALLOCATE (bad_modes_projector_down(ndomains, nspins))
     957           92 :       CALL init_submatrices(bad_modes_projector_down)
     958              : 
     959          282 :       ALLOCATE (prec_vv(nspins))
     960          282 :       ALLOCATE (siginvTFTsiginv(nspins))
     961          282 :       ALLOCATE (STsiginv_0(nspins))
     962          282 :       ALLOCATE (FTsiginv(nspins))
     963          282 :       ALLOCATE (ST(nspins))
     964          282 :       ALLOCATE (prev_grad(nspins))
     965          374 :       ALLOCATE (grad(nspins))
     966          282 :       ALLOCATE (prev_step(nspins))
     967          282 :       ALLOCATE (step(nspins))
     968          282 :       ALLOCATE (prev_minus_prec_grad(nspins))
     969          282 :       ALLOCATE (m_sig_sqrti_ii(nspins))
     970          282 :       ALLOCATE (tempNOcc(nspins))
     971          282 :       ALLOCATE (tempNOcc_1(nspins))
     972          282 :       ALLOCATE (tempOccOcc(nspins))
     973          190 :       DO ispin = 1, nspins
     974              : 
     975              :          ! init temporary storage
     976              :          CALL dbcsr_create(prec_vv(ispin), &
     977              :                            template=almo_scf_env%matrix_ks(ispin), &
     978           98 :                            matrix_type=dbcsr_type_no_symmetry)
     979              :          CALL dbcsr_create(siginvTFTsiginv(ispin), &
     980              :                            template=almo_scf_env%matrix_sigma(ispin), &
     981           98 :                            matrix_type=dbcsr_type_no_symmetry)
     982              :          CALL dbcsr_create(STsiginv_0(ispin), &
     983              :                            template=matrix_t_out(ispin), &
     984           98 :                            matrix_type=dbcsr_type_no_symmetry)
     985              :          CALL dbcsr_create(FTsiginv(ispin), &
     986              :                            template=matrix_t_out(ispin), &
     987           98 :                            matrix_type=dbcsr_type_no_symmetry)
     988              :          CALL dbcsr_create(ST(ispin), &
     989              :                            template=matrix_t_out(ispin), &
     990           98 :                            matrix_type=dbcsr_type_no_symmetry)
     991              :          CALL dbcsr_create(prev_grad(ispin), &
     992              :                            template=matrix_t_out(ispin), &
     993           98 :                            matrix_type=dbcsr_type_no_symmetry)
     994              :          CALL dbcsr_create(grad(ispin), &
     995              :                            template=matrix_t_out(ispin), &
     996           98 :                            matrix_type=dbcsr_type_no_symmetry)
     997              :          CALL dbcsr_create(prev_step(ispin), &
     998              :                            template=matrix_t_out(ispin), &
     999           98 :                            matrix_type=dbcsr_type_no_symmetry)
    1000              :          CALL dbcsr_create(step(ispin), &
    1001              :                            template=matrix_t_out(ispin), &
    1002           98 :                            matrix_type=dbcsr_type_no_symmetry)
    1003              :          CALL dbcsr_create(prev_minus_prec_grad(ispin), &
    1004              :                            template=matrix_t_out(ispin), &
    1005           98 :                            matrix_type=dbcsr_type_no_symmetry)
    1006              :          CALL dbcsr_create(m_sig_sqrti_ii(ispin), &
    1007              :                            template=almo_scf_env%matrix_sigma_inv(ispin), &
    1008           98 :                            matrix_type=dbcsr_type_no_symmetry)
    1009              :          CALL dbcsr_create(tempNOcc(ispin), &
    1010              :                            template=matrix_t_out(ispin), &
    1011           98 :                            matrix_type=dbcsr_type_no_symmetry)
    1012              :          CALL dbcsr_create(tempNOcc_1(ispin), &
    1013              :                            template=matrix_t_out(ispin), &
    1014           98 :                            matrix_type=dbcsr_type_no_symmetry)
    1015              :          CALL dbcsr_create(tempOccOcc(ispin), &
    1016              :                            template=almo_scf_env%matrix_sigma_inv(ispin), &
    1017           98 :                            matrix_type=dbcsr_type_no_symmetry)
    1018              : 
    1019           98 :          CALL dbcsr_set(step(ispin), 0.0_dp)
    1020           98 :          CALL dbcsr_set(prev_step(ispin), 0.0_dp)
    1021              : 
    1022              :          CALL dbcsr_get_info(almo_scf_env%matrix_sigma_inv(ispin), &
    1023           98 :                              nfullrows_total=nocc(ispin))
    1024              : 
    1025              :          ! invert S domains if necessary
    1026              :          ! Note: domains for alpha and beta electrons might be different
    1027              :          ! that is why the inversion of the AO overlap is inside the spin loop
    1028           98 :          IF (my_special_case == xalmo_case_normal) THEN
    1029              :             CALL construct_domain_s_inv( &
    1030              :                matrix_s=almo_scf_env%matrix_s(1), &
    1031              :                subm_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    1032              :                dpattern=quench_t(ispin), &
    1033              :                map=almo_scf_env%domain_map(ispin), &
    1034           38 :                node_of_domain=almo_scf_env%cpu_of_domain)
    1035              : 
    1036              :             CALL construct_domain_s_sqrt( &
    1037              :                matrix_s=almo_scf_env%matrix_s(1), &
    1038              :                subm_s_sqrt=almo_scf_env%domain_s_sqrt(:, ispin), &
    1039              :                subm_s_sqrt_inv=almo_scf_env%domain_s_sqrt_inv(:, ispin), &
    1040              :                dpattern=almo_scf_env%quench_t(ispin), &
    1041              :                map=almo_scf_env%domain_map(ispin), &
    1042           38 :                node_of_domain=almo_scf_env%cpu_of_domain)
    1043              : 
    1044              :          END IF
    1045              : 
    1046           98 :          IF (assume_t0_q0x) THEN
    1047              : 
    1048              :             ! save S.T_0.siginv_0
    1049           42 :             IF (my_special_case == xalmo_case_fully_deloc) THEN
    1050              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    1051              :                                    almo_scf_env%matrix_s(1), &
    1052              :                                    almo_scf_env%matrix_t_blk(ispin), &
    1053              :                                    0.0_dp, ST(ispin), &
    1054           18 :                                    filter_eps=almo_scf_env%eps_filter)
    1055              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    1056              :                                    ST(ispin), &
    1057              :                                    almo_scf_env%matrix_sigma_inv_0deloc(ispin), &
    1058              :                                    0.0_dp, STsiginv_0(ispin), &
    1059           18 :                                    filter_eps=almo_scf_env%eps_filter)
    1060              :             END IF
    1061              : 
    1062              :             ! construct domain-projector
    1063           42 :             IF (my_special_case == xalmo_case_normal) THEN
    1064              :                CALL construct_domain_r_down( &
    1065              :                   matrix_t=almo_scf_env%matrix_t_blk(ispin), &
    1066              :                   matrix_sigma_inv=almo_scf_env%matrix_sigma_inv(ispin), &
    1067              :                   matrix_s=almo_scf_env%matrix_s(1), &
    1068              :                   subm_r_down=domain_r_down(:, ispin), &
    1069              :                   dpattern=quench_t(ispin), &
    1070              :                   map=almo_scf_env%domain_map(ispin), &
    1071              :                   node_of_domain=almo_scf_env%cpu_of_domain, &
    1072           24 :                   filter_eps=almo_scf_env%eps_filter)
    1073              :             END IF
    1074              : 
    1075              :          END IF ! assume_t0_q0x
    1076              : 
    1077              :          ! localization functional
    1078          190 :          IF (penalty_occ_local) THEN
    1079              : 
    1080              :             ! compute S.R0.B.R0.S
    1081              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    1082              :                                 almo_scf_env%matrix_s(1), &
    1083              :                                 matrix_t_in(ispin), &
    1084              :                                 0.0_dp, tempNOcc(ispin), &
    1085            0 :                                 filter_eps=almo_scf_env%eps_filter)
    1086              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    1087              :                                 tempNOcc(ispin), &
    1088              :                                 almo_scf_env%matrix_sigma_inv(ispin), &
    1089              :                                 0.0_dp, tempNOCC_1(ispin), &
    1090            0 :                                 filter_eps=almo_scf_env%eps_filter)
    1091              : 
    1092            0 :             DO idim0 = 1, SIZE(op_sm_set_qs, 2) ! this loop is over miller ind
    1093            0 :                DO reim = 1, SIZE(op_sm_set_qs, 1) ! this loop is over Re/Im
    1094              : 
    1095              :                   CALL matrix_qs_to_almo(op_sm_set_qs(reim, idim0)%matrix, &
    1096            0 :                                          op_sm_set_almo(reim, idim0)%matrix, almo_scf_env%mat_distr_aos)
    1097              : 
    1098              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, &
    1099              :                                       op_sm_set_almo(reim, idim0)%matrix, &
    1100              :                                       matrix_t_in(ispin), &
    1101              :                                       0.0_dp, tempNOcc(ispin), &
    1102            0 :                                       filter_eps=almo_scf_env%eps_filter)
    1103              : 
    1104              :                   CALL dbcsr_multiply("T", "N", 1.0_dp, &
    1105              :                                       matrix_t_in(ispin), &
    1106              :                                       tempNOcc(ispin), &
    1107              :                                       0.0_dp, tempOccOcc(ispin), &
    1108            0 :                                       filter_eps=almo_scf_env%eps_filter)
    1109              : 
    1110              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, &
    1111              :                                       tempNOCC_1(ispin), &
    1112              :                                       tempOccOcc(ispin), &
    1113              :                                       0.0_dp, tempNOcc(ispin), &
    1114            0 :                                       filter_eps=almo_scf_env%eps_filter)
    1115              : 
    1116              :                   CALL dbcsr_multiply("N", "T", 1.0_dp, &
    1117              :                                       tempNOcc(ispin), &
    1118              :                                       tempNOcc_1(ispin), &
    1119              :                                       0.0_dp, op_sm_set_almo(reim, idim0)%matrix, &
    1120            0 :                                       filter_eps=almo_scf_env%eps_filter)
    1121              : 
    1122              :                END DO
    1123              :             END DO ! end loop over idim0
    1124              : 
    1125              :          END IF !penalty_occ_local
    1126              : 
    1127              :       END DO ! ispin
    1128              : 
    1129              :       ! start the outer SCF loop
    1130           92 :       outer_max_iter = optimizer%max_iter_outer_loop
    1131           92 :       outer_prepare_to_exit = .FALSE.
    1132           92 :       outer_iteration = 0
    1133           92 :       grad_norm = 0.0_dp
    1134           92 :       grad_norm_frob = 0.0_dp
    1135           92 :       use_guess = .FALSE.
    1136              : 
    1137              :       DO
    1138              : 
    1139              :          ! start the inner SCF loop
    1140           98 :          max_iter = optimizer%max_iter
    1141           98 :          prepare_to_exit = .FALSE.
    1142           98 :          line_search = .FALSE.
    1143           98 :          converged = .FALSE.
    1144           98 :          iteration = 0
    1145           98 :          cg_iteration = 0
    1146           98 :          line_search_iteration = 0
    1147              :          energy_new = 0.0_dp
    1148           98 :          energy_old = 0.0_dp
    1149           98 :          energy_diff = 0.0_dp
    1150              :          localization_obj_function = 0.0_dp
    1151           98 :          line_search_error = 0.0_dp
    1152              : 
    1153           98 :          t1 = m_walltime()
    1154              : 
    1155         1060 :          DO
    1156              : 
    1157         1060 :             just_started = (iteration == 0) .AND. (outer_iteration == 0)
    1158              : 
    1159              :             CALL main_var_to_xalmos_and_loss_func( &
    1160              :                almo_scf_env=almo_scf_env, &
    1161              :                qs_env=qs_env, &
    1162              :                m_main_var_in=m_theta, &
    1163              :                m_t_out=matrix_t_out, &
    1164              :                m_sig_sqrti_ii_out=m_sig_sqrti_ii, &
    1165              :                energy_out=energy_new, &
    1166              :                penalty_out=penalty_func_new, &
    1167              :                m_FTsiginv_out=FTsiginv, &
    1168              :                m_siginvTFTsiginv_out=siginvTFTsiginv, &
    1169              :                m_ST_out=ST, &
    1170              :                m_STsiginv0_in=STsiginv_0, &
    1171              :                m_quench_t_in=quench_t, &
    1172              :                domain_r_down_in=domain_r_down, &
    1173              :                assume_t0_q0x=assume_t0_q0x, &
    1174              :                just_started=just_started, &
    1175              :                optimize_theta=optimize_theta, &
    1176              :                normalize_orbitals=normalize_orbitals, &
    1177              :                perturbation_only=perturbation_only, &
    1178              :                do_penalty=penalty_occ_vol, &
    1179         1060 :                special_case=my_special_case)
    1180         1060 :             IF (penalty_occ_vol) THEN
    1181              :                ! this is not pure energy anymore
    1182            0 :                energy_new = energy_new + penalty_func_new
    1183              :             END IF
    1184         2132 :             DO ispin = 1, nspins
    1185         2132 :                IF (penalty_occ_vol) THEN
    1186              :                   penalty_occ_vol_g_prefactor(ispin) = &
    1187            0 :                      -2.0_dp*penalty_amplitude*spin_factor*nocc(ispin)
    1188            0 :                   penalty_occ_vol_h_prefactor(ispin) = 0.0_dp
    1189              :                END IF
    1190              :             END DO
    1191              : 
    1192         1060 :             localization_obj_function = 0.0_dp
    1193              :             ! RZK-warning: This block must be combined with the loss function
    1194         1060 :             IF (penalty_occ_local) THEN
    1195            0 :                DO ispin = 1, nspins
    1196              : 
    1197              :                   ! LzL insert localization penalty
    1198            0 :                   localization_obj_function = 0.0_dp
    1199            0 :                   CALL dbcsr_get_info(almo_scf_env%matrix_sigma_inv(ispin), nfullrows_total=nmo)
    1200            0 :                   ALLOCATE (z2(nmo))
    1201            0 :                   ALLOCATE (reim_diag(nmo))
    1202              : 
    1203            0 :                   CALL dbcsr_get_info(tempOccOcc(ispin), group=group)
    1204              : 
    1205            0 :                   DO idim0 = 1, SIZE(op_sm_set_qs, 2) ! this loop is over miller ind
    1206              : 
    1207            0 :                      z2(:) = 0.0_dp
    1208              : 
    1209            0 :                      DO reim = 1, SIZE(op_sm_set_qs, 1) ! this loop is over Re/Im
    1210              : 
    1211              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, &
    1212              :                                             op_sm_set_almo(reim, idim0)%matrix, &
    1213              :                                             matrix_t_out(ispin), &
    1214              :                                             0.0_dp, tempNOcc(ispin), &
    1215            0 :                                             filter_eps=almo_scf_env%eps_filter)
    1216              :                         !warning - save time by computing only the diagonal elements
    1217              :                         CALL dbcsr_multiply("T", "N", 1.0_dp, &
    1218              :                                             matrix_t_out(ispin), &
    1219              :                                             tempNOcc(ispin), &
    1220              :                                             0.0_dp, tempOccOcc(ispin), &
    1221            0 :                                             filter_eps=almo_scf_env%eps_filter)
    1222              : 
    1223            0 :                         reim_diag = 0.0_dp
    1224            0 :                         CALL dbcsr_get_diag(tempOccOcc(ispin), reim_diag)
    1225            0 :                         CALL group%sum(reim_diag)
    1226            0 :                         z2(:) = z2(:) + reim_diag(:)*reim_diag(:)
    1227              : 
    1228              :                      END DO
    1229              : 
    1230            0 :                      DO ielem = 1, nmo
    1231              :                         SELECT CASE (2) ! allows for selection of different spread functionals
    1232              :                         CASE (1) ! functional =  -W_I * log( |z_I|^2 )
    1233            0 :                            fval = -weights(idim0)*LOG(ABS(z2(ielem)))
    1234              :                         CASE (2) ! functional =  W_I * ( 1 - |z_I|^2 )
    1235            0 :                            fval = weights(idim0) - weights(idim0)*ABS(z2(ielem))
    1236              :                         CASE (3) ! functional =  W_I * ( 1 - |z_I| )
    1237              :                            fval = weights(idim0) - weights(idim0)*SQRT(ABS(z2(ielem)))
    1238              :                         END SELECT
    1239            0 :                         localization_obj_function = localization_obj_function + fval
    1240              :                      END DO
    1241              : 
    1242              :                   END DO ! end loop over idim0
    1243              : 
    1244            0 :                   DEALLOCATE (z2)
    1245            0 :                   DEALLOCATE (reim_diag)
    1246              : 
    1247            0 :                   energy_new = energy_new + localiz_coeff*localization_obj_function
    1248              : 
    1249              :                END DO ! ispin
    1250              :             END IF ! penalty_occ_local
    1251              : 
    1252         2132 :             DO ispin = 1, nspins
    1253              : 
    1254              :                IF (just_started .AND. almo_mathematica) THEN
    1255              :                   CPWARN_IF(ispin > 1, "Mathematica files will be overwritten")
    1256              :                   CALL print_mathematica_matrix(almo_scf_env%matrix_s(1), "matrixS.dat")
    1257              :                   CALL print_mathematica_matrix(almo_scf_env%matrix_ks(ispin), "matrixF.dat")
    1258              :                   CALL print_mathematica_matrix(matrix_t_out(ispin), "matrixT.dat")
    1259              :                   CALL print_mathematica_matrix(quench_t(ispin), "matrixQ.dat")
    1260              :                END IF
    1261              : 
    1262              :                ! save the previous gradient to compute beta
    1263              :                ! do it only if the previous grad was computed
    1264              :                ! for .NOT.line_search
    1265         2132 :                IF (line_search_iteration == 0 .AND. iteration /= 0) THEN
    1266          502 :                   CALL dbcsr_copy(prev_grad(ispin), grad(ispin))
    1267              :                END IF
    1268              : 
    1269              :             END DO ! ispin
    1270              : 
    1271              :             ! compute the energy gradient if necessary
    1272              :             skip_grad = (iteration > 0 .AND. &
    1273              :                          fixed_line_search_niter /= 0 .AND. &
    1274         1060 :                          line_search_iteration /= fixed_line_search_niter)
    1275              : 
    1276              :             IF (.NOT. skip_grad) THEN
    1277              : 
    1278         2132 :                DO ispin = 1, nspins
    1279              : 
    1280              :                   CALL compute_gradient( &
    1281              :                      m_grad_out=grad(ispin), &
    1282              :                      m_ks=almo_scf_env%matrix_ks(ispin), &
    1283              :                      m_s=almo_scf_env%matrix_s(1), &
    1284              :                      m_t=matrix_t_out(ispin), &
    1285              :                      m_t0=almo_scf_env%matrix_t_blk(ispin), &
    1286              :                      m_siginv=almo_scf_env%matrix_sigma_inv(ispin), &
    1287              :                      m_quench_t=quench_t(ispin), &
    1288              :                      m_FTsiginv=FTsiginv(ispin), &
    1289              :                      m_siginvTFTsiginv=siginvTFTsiginv(ispin), &
    1290              :                      m_ST=ST(ispin), &
    1291              :                      m_STsiginv0=STsiginv_0(ispin), &
    1292              :                      m_theta=m_theta(ispin), &
    1293              :                      m_sig_sqrti_ii=m_sig_sqrti_ii(ispin), &
    1294              :                      domain_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    1295              :                      domain_r_down=domain_r_down(:, ispin), &
    1296              :                      cpu_of_domain=almo_scf_env%cpu_of_domain, &
    1297              :                      domain_map=almo_scf_env%domain_map(ispin), &
    1298              :                      assume_t0_q0x=assume_t0_q0x, &
    1299              :                      optimize_theta=optimize_theta, &
    1300              :                      normalize_orbitals=normalize_orbitals, &
    1301              :                      penalty_occ_vol=penalty_occ_vol, &
    1302              :                      penalty_occ_vol_prefactor=penalty_occ_vol_g_prefactor(ispin), &
    1303              :                      envelope_amplitude=almo_scf_env%envelope_amplitude, &
    1304              :                      eps_filter=almo_scf_env%eps_filter, &
    1305              :                      spin_factor=spin_factor, &
    1306              :                      special_case=my_special_case, &
    1307              :                      penalty_occ_local=penalty_occ_local, &
    1308              :                      op_sm_set=op_sm_set_almo, &
    1309              :                      weights=weights, &
    1310              :                      energy_coeff=energy_coeff, &
    1311         2132 :                      localiz_coeff=localiz_coeff)
    1312              : 
    1313              :                END DO ! ispin
    1314              : 
    1315              :             END IF ! skip_grad
    1316              : 
    1317              :             ! if unprojected XALMOs are optimized then compute both
    1318              :             ! HessianInv/preconditioner and the "bad-mode" projector
    1319              : 
    1320         1060 :             IF (blissful_neglect) THEN
    1321          460 :                DO ispin = 1, nspins
    1322              :                   !compute the prec only for the first step,
    1323              :                   !but project the gradient every step
    1324          230 :                   IF (iteration == 0) THEN
    1325              :                      CALL compute_preconditioner( &
    1326              :                         domain_prec_out=almo_scf_env%domain_preconditioner(:, ispin), &
    1327              :                         bad_modes_projector_down_out=bad_modes_projector_down(:, ispin), &
    1328              :                         m_prec_out=prec_vv(ispin), &
    1329              :                         m_ks=almo_scf_env%matrix_ks(ispin), &
    1330              :                         m_s=almo_scf_env%matrix_s(1), &
    1331              :                         m_siginv=almo_scf_env%matrix_sigma_inv(ispin), &
    1332              :                         m_quench_t=quench_t(ispin), &
    1333              :                         m_FTsiginv=FTsiginv(ispin), &
    1334              :                         m_siginvTFTsiginv=siginvTFTsiginv(ispin), &
    1335              :                         m_ST=ST(ispin), &
    1336              :                         para_env=almo_scf_env%para_env, &
    1337              :                         blacs_env=almo_scf_env%blacs_env, &
    1338              :                         nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
    1339              :                         domain_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    1340              :                         domain_s_inv_half=almo_scf_env%domain_s_sqrt_inv(:, ispin), &
    1341              :                         domain_s_half=almo_scf_env%domain_s_sqrt(:, ispin), &
    1342              :                         domain_r_down=domain_r_down(:, ispin), &
    1343              :                         cpu_of_domain=almo_scf_env%cpu_of_domain, &
    1344              :                         domain_map=almo_scf_env%domain_map(ispin), &
    1345              :                         assume_t0_q0x=assume_t0_q0x, &
    1346              :                         penalty_occ_vol=penalty_occ_vol, &
    1347              :                         penalty_occ_vol_prefactor=penalty_occ_vol_g_prefactor(ispin), &
    1348              :                         eps_filter=almo_scf_env%eps_filter, &
    1349              :                         neg_thr=optimizer%neglect_threshold, &
    1350              :                         spin_factor=spin_factor, &
    1351              :                         skip_inversion=.FALSE., &
    1352           18 :                         special_case=my_special_case)
    1353              :                   END IF
    1354              :                   ! remove bad modes from the gradient
    1355              :                   CALL apply_domain_operators( &
    1356              :                      matrix_in=grad(ispin), &
    1357              :                      matrix_out=grad(ispin), &
    1358              :                      operator1=almo_scf_env%domain_s_inv(:, ispin), &
    1359              :                      operator2=bad_modes_projector_down(:, ispin), &
    1360              :                      dpattern=quench_t(ispin), &
    1361              :                      map=almo_scf_env%domain_map(ispin), &
    1362              :                      node_of_domain=almo_scf_env%cpu_of_domain, &
    1363              :                      my_action=1, &
    1364          460 :                      filter_eps=almo_scf_env%eps_filter)
    1365              : 
    1366              :                END DO ! ispin
    1367              : 
    1368              :             END IF ! blissful neglect
    1369              : 
    1370              :             ! check convergence and other exit criteria
    1371         2132 :             DO ispin = 1, nspins
    1372         2132 :                grad_norm_spin(ispin) = dbcsr_maxabs(grad(ispin))
    1373              :             END DO ! ispin
    1374         2132 :             grad_norm = MAXVAL(grad_norm_spin)
    1375              : 
    1376         1060 :             converged = (grad_norm <= optimizer%eps_error)
    1377         1060 :             IF (converged .OR. (iteration >= max_iter)) THEN
    1378           98 :                prepare_to_exit = .TRUE.
    1379              :             END IF
    1380              :             ! if early stopping is on do at least one iteration
    1381         1060 :             IF (optimizer%early_stopping_on .AND. just_started) THEN
    1382            0 :                prepare_to_exit = .FALSE.
    1383              :             END IF
    1384              : 
    1385              :             IF (grad_norm < almo_scf_env%eps_prev_guess) THEN
    1386         1060 :                use_guess = .TRUE.
    1387              :             END IF
    1388              : 
    1389              :             ! it is not time to exit just yet
    1390         1060 :             IF (.NOT. prepare_to_exit) THEN
    1391              : 
    1392              :                ! check the gradient along the step direction
    1393              :                ! and decide whether to switch to the line-search mode
    1394              :                ! do not do this in the first iteration
    1395          962 :                IF (iteration /= 0) THEN
    1396              : 
    1397          866 :                   IF (fixed_line_search_niter == 0) THEN
    1398              : 
    1399              :                      ! enforce at least one line search
    1400              :                      ! without even checking the error
    1401          866 :                      IF (.NOT. line_search) THEN
    1402              : 
    1403          424 :                         line_search = .TRUE.
    1404          424 :                         line_search_iteration = line_search_iteration + 1
    1405              : 
    1406              :                      ELSE
    1407              : 
    1408              :                         ! check the line-search error and decide whether to
    1409              :                         ! change the direction
    1410              :                         line_search_error = 0.0_dp
    1411              :                         denom = 0.0_dp
    1412              :                         denom2 = 0.0_dp
    1413              : 
    1414          884 :                         DO ispin = 1, nspins
    1415              : 
    1416          442 :                            CALL dbcsr_dot(grad(ispin), step(ispin), tempreal)
    1417          442 :                            line_search_error = line_search_error + tempreal
    1418          442 :                            CALL dbcsr_dot(grad(ispin), grad(ispin), tempreal)
    1419          442 :                            denom = denom + tempreal
    1420          442 :                            CALL dbcsr_dot(step(ispin), step(ispin), tempreal)
    1421          884 :                            denom2 = denom2 + tempreal
    1422              : 
    1423              :                         END DO ! ispin
    1424              : 
    1425              :                         ! cosine of the angle between the step and grad
    1426              :                         ! (must be close to zero at convergence)
    1427          442 :                         line_search_error = line_search_error/SQRT(denom)/SQRT(denom2)
    1428              : 
    1429          442 :                         IF (ABS(line_search_error) > optimizer%lin_search_eps_error) THEN
    1430           40 :                            line_search = .TRUE.
    1431           40 :                            line_search_iteration = line_search_iteration + 1
    1432              :                         ELSE
    1433          402 :                            line_search = .FALSE.
    1434          402 :                            line_search_iteration = 0
    1435          402 :                            IF (grad_norm < eps_skip_gradients) THEN
    1436            0 :                               fixed_line_search_niter = ABS(almo_scf_env%integer04)
    1437              :                            END IF
    1438              :                         END IF
    1439              : 
    1440              :                      END IF
    1441              : 
    1442              :                   ELSE ! decision for fixed_line_search_niter
    1443              : 
    1444            0 :                      IF (.NOT. line_search) THEN
    1445            0 :                         line_search = .TRUE.
    1446            0 :                         line_search_iteration = line_search_iteration + 1
    1447              :                      ELSE
    1448            0 :                         IF (line_search_iteration == fixed_line_search_niter) THEN
    1449              :                            line_search = .FALSE.
    1450              :                            line_search_iteration = 0
    1451              :                            line_search_iteration = line_search_iteration + 1
    1452              :                         END IF
    1453              :                      END IF
    1454              : 
    1455              :                   END IF ! fixed_line_search_niter fork
    1456              : 
    1457              :                END IF ! iteration.ne.0
    1458              : 
    1459           96 :                IF (line_search) THEN
    1460          464 :                   energy_diff = 0.0_dp
    1461              :                ELSE
    1462          498 :                   energy_diff = energy_new - energy_old
    1463              :                   energy_old = energy_new
    1464              :                END IF
    1465              : 
    1466              :                ! update the step direction
    1467          498 :                IF (.NOT. line_search) THEN
    1468              : 
    1469         1000 :                   cg_iteration = cg_iteration + 1
    1470              : 
    1471              :                   ! save the previous step
    1472         1000 :                   DO ispin = 1, nspins
    1473         1000 :                      CALL dbcsr_copy(prev_step(ispin), step(ispin))
    1474              :                   END DO ! ispin
    1475              : 
    1476              :                   ! compute the new step (apply preconditioner if available)
    1477            0 :                   SELECT CASE (prec_type)
    1478              :                   CASE (xalmo_prec_full)
    1479              : 
    1480              :                      ! solving approximate Newton eq in the full (linearized) space
    1481              :                      CALL newton_grad_to_step( &
    1482              :                         optimizer=almo_scf_env%opt_xalmo_newton_pcg_solver, &
    1483              :                         m_grad=grad(:), &
    1484              :                         m_delta=step(:), &
    1485              :                         m_s=almo_scf_env%matrix_s(:), &
    1486              :                         m_ks=almo_scf_env%matrix_ks(:), &
    1487              :                         m_siginv=almo_scf_env%matrix_sigma_inv(:), &
    1488              :                         m_quench_t=quench_t(:), &
    1489              :                         m_FTsiginv=FTsiginv(:), &
    1490              :                         m_siginvTFTsiginv=siginvTFTsiginv(:), &
    1491              :                         m_ST=ST(:), &
    1492              :                         m_t=matrix_t_out(:), &
    1493              :                         m_sig_sqrti_ii=m_sig_sqrti_ii(:), &
    1494              :                         domain_s_inv=almo_scf_env%domain_s_inv(:, :), &
    1495              :                         domain_r_down=domain_r_down(:, :), &
    1496              :                         domain_map=almo_scf_env%domain_map(:), &
    1497              :                         cpu_of_domain=almo_scf_env%cpu_of_domain, &
    1498              :                         nocc_of_domain=almo_scf_env%nocc_of_domain(:, :), &
    1499              :                         para_env=almo_scf_env%para_env, &
    1500              :                         blacs_env=almo_scf_env%blacs_env, &
    1501              :                         eps_filter=almo_scf_env%eps_filter, &
    1502              :                         optimize_theta=optimize_theta, &
    1503              :                         penalty_occ_vol=penalty_occ_vol, &
    1504              :                         normalize_orbitals=normalize_orbitals, &
    1505              :                         penalty_occ_vol_prefactor=penalty_occ_vol_g_prefactor(:), &
    1506              :                         penalty_occ_vol_pf2=penalty_occ_vol_h_prefactor(:), &
    1507              :                         special_case=my_special_case &
    1508            0 :                         )
    1509              : 
    1510              :                   CASE (xalmo_prec_domain)
    1511              : 
    1512              :                      ! compute and invert preconditioner?
    1513          498 :                      IF (.NOT. blissful_neglect .AND. &
    1514              :                          ((just_started .AND. perturbation_only) .OR. &
    1515              :                           (iteration == 0 .AND. (.NOT. perturbation_only))) &
    1516              :                          ) THEN
    1517              : 
    1518              :                         ! computing preconditioner
    1519          160 :                         DO ispin = 1, nspins
    1520              :                            CALL compute_preconditioner( &
    1521              :                               domain_prec_out=almo_scf_env%domain_preconditioner(:, ispin), &
    1522              :                               m_prec_out=prec_vv(ispin), &
    1523              :                               m_ks=almo_scf_env%matrix_ks(ispin), &
    1524              :                               m_s=almo_scf_env%matrix_s(1), &
    1525              :                               m_siginv=almo_scf_env%matrix_sigma_inv(ispin), &
    1526              :                               m_quench_t=quench_t(ispin), &
    1527              :                               m_FTsiginv=FTsiginv(ispin), &
    1528              :                               m_siginvTFTsiginv=siginvTFTsiginv(ispin), &
    1529              :                               m_ST=ST(ispin), &
    1530              :                               para_env=almo_scf_env%para_env, &
    1531              :                               blacs_env=almo_scf_env%blacs_env, &
    1532              :                               nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
    1533              :                               domain_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    1534              :                               domain_r_down=domain_r_down(:, ispin), &
    1535              :                               cpu_of_domain=almo_scf_env%cpu_of_domain, &
    1536              :                               domain_map=almo_scf_env%domain_map(ispin), &
    1537              :                               assume_t0_q0x=assume_t0_q0x, &
    1538              :                               penalty_occ_vol=penalty_occ_vol, &
    1539              :                               penalty_occ_vol_prefactor=penalty_occ_vol_g_prefactor(ispin), &
    1540              :                               eps_filter=almo_scf_env%eps_filter, &
    1541              :                               neg_thr=0.5_dp, &
    1542              :                               spin_factor=spin_factor, &
    1543              :                               skip_inversion=.FALSE., &
    1544          580 :                               special_case=my_special_case)
    1545              :                         END DO ! ispin
    1546              :                      END IF ! compute_prec
    1547              : 
    1548          498 :                      IF (my_special_case == xalmo_case_block_diag .OR. &
    1549              :                          my_special_case == xalmo_case_fully_deloc) THEN
    1550              : 
    1551          500 :                         DO ispin = 1, nspins
    1552              : 
    1553              :                            CALL dbcsr_multiply("N", "N", -1.0_dp, &
    1554              :                                                prec_vv(ispin), &
    1555              :                                                grad(ispin), &
    1556              :                                                0.0_dp, step(ispin), &
    1557          500 :                                                filter_eps=almo_scf_env%eps_filter)
    1558              : 
    1559              :                         END DO ! ispin
    1560              : 
    1561              :                      ELSE
    1562              : 
    1563              :                         !!! RZK-warning Currently for non-theta only
    1564          250 :                         IF (optimize_theta) THEN
    1565            0 :                            CPABORT("theta is NYI")
    1566              :                         END IF
    1567              : 
    1568          500 :                         DO ispin = 1, nspins
    1569              : 
    1570              :                            CALL apply_domain_operators( &
    1571              :                               matrix_in=grad(ispin), &
    1572              :                               matrix_out=step(ispin), &
    1573              :                               operator1=almo_scf_env%domain_preconditioner(:, ispin), &
    1574              :                               dpattern=quench_t(ispin), &
    1575              :                               map=almo_scf_env%domain_map(ispin), &
    1576              :                               node_of_domain=almo_scf_env%cpu_of_domain, &
    1577              :                               my_action=0, &
    1578          250 :                               filter_eps=almo_scf_env%eps_filter)
    1579          500 :                            CALL dbcsr_scale(step(ispin), -1.0_dp)
    1580              : 
    1581              :                         END DO ! ispin
    1582              : 
    1583              :                      END IF ! special case
    1584              : 
    1585              :                   CASE (xalmo_prec_zero)
    1586              : 
    1587              :                      ! no preconditioner
    1588          498 :                      DO ispin = 1, nspins
    1589              : 
    1590            0 :                         CALL dbcsr_copy(step(ispin), grad(ispin))
    1591            0 :                         CALL dbcsr_scale(step(ispin), -1.0_dp)
    1592              : 
    1593              :                      END DO ! ispin
    1594              : 
    1595              :                   END SELECT ! preconditioner type fork
    1596              : 
    1597              :                   ! check whether we need to reset conjugate directions
    1598          498 :                   IF (iteration == 0) THEN
    1599           96 :                      reset_conjugator = .TRUE.
    1600              :                   END IF
    1601              : 
    1602              :                   ! compute the conjugation coefficient - beta
    1603          498 :                   IF (.NOT. reset_conjugator) THEN
    1604              : 
    1605              :                      CALL compute_cg_beta( &
    1606              :                         beta=beta, &
    1607              :                         reset_conjugator=reset_conjugator, &
    1608              :                         conjugator=optimizer%conjugator, &
    1609              :                         grad=grad(:), &
    1610              :                         prev_grad=prev_grad(:), &
    1611              :                         step=step(:), &
    1612              :                         prev_step=prev_step(:), &
    1613              :                         prev_minus_prec_grad=prev_minus_prec_grad(:) &
    1614          402 :                         )
    1615              : 
    1616              :                   END IF
    1617              : 
    1618          498 :                   IF (reset_conjugator) THEN
    1619              : 
    1620           96 :                      beta = 0.0_dp
    1621           96 :                      IF (unit_nr > 0 .AND. (.NOT. just_started)) THEN
    1622            3 :                         WRITE (unit_nr, '(T2,A35)') "Re-setting conjugator to zero"
    1623              :                      END IF
    1624           96 :                      reset_conjugator = .FALSE.
    1625              : 
    1626              :                   END IF
    1627              : 
    1628              :                   ! save the preconditioned gradient (useful for beta)
    1629         1000 :                   DO ispin = 1, nspins
    1630              : 
    1631          502 :                      CALL dbcsr_copy(prev_minus_prec_grad(ispin), step(ispin))
    1632              : 
    1633              :                      ! conjugate the step direction
    1634         1000 :                      CALL dbcsr_add(step(ispin), prev_step(ispin), 1.0_dp, beta)
    1635              : 
    1636              :                   END DO ! ispin
    1637              : 
    1638              :                END IF ! update the step direction
    1639              : 
    1640              :                ! estimate the step size
    1641              :                IF (.NOT. line_search) THEN
    1642              :                   ! we just changed the direction and
    1643              :                   ! we have only E and grad from the current step
    1644              :                   ! it is not enouhg to compute step_size - just guess it
    1645         1000 :                   e0 = energy_new
    1646              :                   g0 = 0.0_dp
    1647         1000 :                   DO ispin = 1, nspins
    1648          502 :                      CALL dbcsr_dot(grad(ispin), step(ispin), tempreal)
    1649         1000 :                      g0 = g0 + tempreal
    1650              :                   END DO ! ispin
    1651          498 :                   IF (iteration == 0) THEN
    1652           96 :                      step_size = optimizer%lin_search_step_size_guess
    1653              :                   ELSE
    1654          402 :                      IF (next_step_size_guess <= 0.0_dp) THEN
    1655            2 :                         step_size = optimizer%lin_search_step_size_guess
    1656              :                      ELSE
    1657              :                         ! take the last value
    1658          400 :                         step_size = next_step_size_guess*1.05_dp
    1659              :                      END IF
    1660              :                   END IF
    1661          498 :                   next_step_size_guess = step_size
    1662              :                ELSE
    1663          464 :                   IF (fixed_line_search_niter == 0) THEN
    1664          464 :                      e1 = energy_new
    1665          464 :                      g1 = 0.0_dp
    1666          930 :                      DO ispin = 1, nspins
    1667          466 :                         CALL dbcsr_dot(grad(ispin), step(ispin), tempreal)
    1668          930 :                         g1 = g1 + tempreal
    1669              :                      END DO ! ispin
    1670              :                      ! we have accumulated some points along this direction
    1671              :                      ! use only the most recent g0 (quadratic approximation)
    1672          464 :                      appr_sec_der = (g1 - g0)/step_size
    1673          464 :                      step_size = -g1/appr_sec_der
    1674          464 :                      e0 = e1
    1675          464 :                      g0 = g1
    1676              :                   ELSE
    1677              :                      ! use e0, g0 and e1 to compute g1 and make a step
    1678              :                      ! if the next iteration is also line_search
    1679              :                      ! use e1 and the calculated g1 as e0 and g0
    1680            0 :                      e1 = energy_new
    1681            0 :                      appr_sec_der = 2.0*((e1 - e0)/step_size - g0)/step_size
    1682            0 :                      g1 = appr_sec_der*step_size + g0
    1683            0 :                      step_size = -g1/appr_sec_der
    1684            0 :                      e0 = e1
    1685            0 :                      g0 = g1
    1686              :                   END IF
    1687          464 :                   next_step_size_guess = next_step_size_guess + step_size
    1688              :                END IF
    1689              : 
    1690              :                ! update theta
    1691         1930 :                DO ispin = 1, nspins
    1692         1930 :                   CALL dbcsr_add(m_theta(ispin), step(ispin), 1.0_dp, step_size)
    1693              :                END DO ! ispin
    1694              : 
    1695              :             END IF ! not.prepare_to_exit
    1696              : 
    1697         1060 :             IF (line_search) THEN
    1698          486 :                iter_type = "LS"
    1699              :             ELSE
    1700          574 :                iter_type = "CG"
    1701              :             END IF
    1702              : 
    1703         1060 :             t2 = m_walltime()
    1704         1060 :             IF (unit_nr > 0) THEN
    1705          530 :                iter_type = TRIM("ALMO SCF "//iter_type)
    1706              :                WRITE (unit_nr, '(T2,A13,I6,F23.10,E14.5,F14.9,F9.2)') &
    1707          530 :                   iter_type, iteration, &
    1708          530 :                   energy_new, energy_diff, grad_norm, &
    1709         1060 :                   t2 - t1
    1710          530 :                IF (penalty_occ_local .OR. penalty_occ_vol) THEN
    1711              :                   WRITE (unit_nr, '(T2,A25,F23.10)') &
    1712            0 :                      "Energy component:", (energy_new - penalty_func_new - localization_obj_function)
    1713              :                END IF
    1714          530 :                IF (penalty_occ_local) THEN
    1715              :                   WRITE (unit_nr, '(T2,A25,F23.10)') &
    1716            0 :                      "Localization component:", localization_obj_function
    1717              :                END IF
    1718          530 :                IF (penalty_occ_vol) THEN
    1719              :                   WRITE (unit_nr, '(T2,A25,F23.10)') &
    1720            0 :                      "Penalty component:", penalty_func_new
    1721              :                END IF
    1722              :             END IF
    1723              : 
    1724         1060 :             IF (my_special_case == xalmo_case_block_diag) THEN
    1725           58 :                IF (penalty_occ_vol) THEN
    1726            0 :                   almo_scf_env%almo_scf_energy = energy_new - penalty_func_new - localization_obj_function
    1727              :                ELSE
    1728           58 :                   almo_scf_env%almo_scf_energy = energy_new - localization_obj_function
    1729              :                END IF
    1730              :             END IF
    1731              : 
    1732         1060 :             t1 = m_walltime()
    1733              : 
    1734         1060 :             iteration = iteration + 1
    1735         1060 :             IF (prepare_to_exit) EXIT
    1736              : 
    1737              :          END DO ! inner SCF loop
    1738              : 
    1739           98 :          IF (converged .OR. (outer_iteration >= outer_max_iter)) THEN
    1740           92 :             outer_prepare_to_exit = .TRUE.
    1741              :          END IF
    1742              : 
    1743           98 :          outer_iteration = outer_iteration + 1
    1744           98 :          IF (outer_prepare_to_exit) EXIT
    1745              : 
    1746              :       END DO ! outer SCF loop
    1747              : 
    1748          190 :       DO ispin = 1, nspins
    1749           92 :          IF (converged .AND. almo_mathematica) THEN
    1750              :             CPWARN_IF(ispin > 1, "Mathematica files will be overwritten")
    1751              :             CALL print_mathematica_matrix(matrix_t_out(ispin), "matrixTf.dat")
    1752              :          END IF
    1753              :       END DO ! ispin
    1754              : 
    1755              :       ! post SCF-loop calculations
    1756           92 :       IF (converged) THEN
    1757              : 
    1758              :          CALL wrap_up_xalmo_scf( &
    1759              :             qs_env=qs_env, &
    1760              :             almo_scf_env=almo_scf_env, &
    1761              :             perturbation_in=perturbation_only, &
    1762              :             m_xalmo_in=matrix_t_out, &
    1763              :             m_quench_in=quench_t, &
    1764           92 :             energy_inout=energy_new)
    1765              : 
    1766              :       END IF ! if converged
    1767              : 
    1768          190 :       DO ispin = 1, nspins
    1769           98 :          CALL dbcsr_release(prec_vv(ispin))
    1770           98 :          CALL dbcsr_release(STsiginv_0(ispin))
    1771           98 :          CALL dbcsr_release(ST(ispin))
    1772           98 :          CALL dbcsr_release(FTsiginv(ispin))
    1773           98 :          CALL dbcsr_release(siginvTFTsiginv(ispin))
    1774           98 :          CALL dbcsr_release(prev_grad(ispin))
    1775           98 :          CALL dbcsr_release(prev_step(ispin))
    1776           98 :          CALL dbcsr_release(grad(ispin))
    1777           98 :          CALL dbcsr_release(step(ispin))
    1778           98 :          CALL dbcsr_release(prev_minus_prec_grad(ispin))
    1779           98 :          CALL dbcsr_release(m_theta(ispin))
    1780           98 :          CALL dbcsr_release(m_t_in_local(ispin))
    1781           98 :          CALL dbcsr_release(m_sig_sqrti_ii(ispin))
    1782           98 :          CALL release_submatrices(domain_r_down(:, ispin))
    1783           98 :          CALL release_submatrices(bad_modes_projector_down(:, ispin))
    1784           98 :          CALL dbcsr_release(tempNOcc(ispin))
    1785           98 :          CALL dbcsr_release(tempNOcc_1(ispin))
    1786          190 :          CALL dbcsr_release(tempOccOcc(ispin))
    1787              :       END DO ! ispin
    1788              : 
    1789           92 :       DEALLOCATE (tempNOcc)
    1790           92 :       DEALLOCATE (tempNOcc_1)
    1791           92 :       DEALLOCATE (tempOccOcc)
    1792           92 :       DEALLOCATE (prec_vv)
    1793           92 :       DEALLOCATE (siginvTFTsiginv)
    1794           92 :       DEALLOCATE (STsiginv_0)
    1795           92 :       DEALLOCATE (FTsiginv)
    1796           92 :       DEALLOCATE (ST)
    1797           92 :       DEALLOCATE (prev_grad)
    1798           92 :       DEALLOCATE (grad)
    1799           92 :       DEALLOCATE (prev_step)
    1800           92 :       DEALLOCATE (step)
    1801           92 :       DEALLOCATE (prev_minus_prec_grad)
    1802           92 :       DEALLOCATE (m_sig_sqrti_ii)
    1803              : 
    1804          714 :       DEALLOCATE (domain_r_down)
    1805          714 :       DEALLOCATE (bad_modes_projector_down)
    1806              : 
    1807           92 :       DEALLOCATE (penalty_occ_vol_g_prefactor)
    1808           92 :       DEALLOCATE (penalty_occ_vol_h_prefactor)
    1809           92 :       DEALLOCATE (grad_norm_spin)
    1810           92 :       DEALLOCATE (nocc)
    1811              : 
    1812           92 :       DEALLOCATE (m_theta, m_t_in_local)
    1813           92 :       IF (penalty_occ_local) THEN
    1814            0 :          DO idim0 = 1, dim_op
    1815            0 :             DO reim = 1, SIZE(op_sm_set_qs, 1)
    1816            0 :                DEALLOCATE (op_sm_set_qs(reim, idim0)%matrix)
    1817            0 :                DEALLOCATE (op_sm_set_almo(reim, idim0)%matrix)
    1818              :             END DO
    1819              :          END DO
    1820            0 :          DEALLOCATE (op_sm_set_qs)
    1821            0 :          DEALLOCATE (op_sm_set_almo)
    1822            0 :          DEALLOCATE (weights)
    1823              :       END IF
    1824              : 
    1825           92 :       IF (.NOT. converged .AND. .NOT. optimizer%early_stopping_on) THEN
    1826            0 :          CPABORT("Optimization not converged! ")
    1827              :       END IF
    1828              : 
    1829           92 :       CALL timestop(handle)
    1830              : 
    1831          184 :    END SUBROUTINE almo_scf_xalmo_pcg
    1832              : 
    1833              : ! **************************************************************************************************
    1834              : !> \brief Optimization of NLMOs using PCG minimizers
    1835              : !> \param qs_env ...
    1836              : !> \param optimizer   controls the optimization algorithm
    1837              : !> \param matrix_s - AO overlap (NAOs x NAOs)
    1838              : !> \param matrix_mo_in - initial MOs (NAOs x NMOs)
    1839              : !> \param matrix_mo_out - final MOs (NAOs x NMOs)
    1840              : !> \param template_matrix_sigma - template (NMOs x NMOs)
    1841              : !> \param overlap_determinant - the determinant of the MOs overlap
    1842              : !> \param mat_distr_aos - info on the distribution of AOs
    1843              : !> \param virtuals ...
    1844              : !> \param eps_filter ...
    1845              : !> \par History
    1846              : !>       2018.10 created [Rustam Z Khaliullin]
    1847              : !> \author Rustam Z Khaliullin
    1848              : ! **************************************************************************************************
    1849            8 :    SUBROUTINE almo_scf_construct_nlmos(qs_env, optimizer, &
    1850              :                                        matrix_s, matrix_mo_in, matrix_mo_out, &
    1851              :                                        template_matrix_sigma, overlap_determinant, &
    1852              :                                        mat_distr_aos, virtuals, eps_filter)
    1853              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1854              :       TYPE(optimizer_options_type), INTENT(INOUT)        :: optimizer
    1855              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix_s
    1856              :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:), &
    1857              :          INTENT(INOUT)                                   :: matrix_mo_in, matrix_mo_out
    1858              :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:), &
    1859              :          INTENT(IN)                                      :: template_matrix_sigma
    1860              :       REAL(KIND=dp), INTENT(INOUT)                       :: overlap_determinant
    1861              :       INTEGER, INTENT(IN)                                :: mat_distr_aos
    1862              :       LOGICAL, INTENT(IN)                                :: virtuals
    1863              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    1864              : 
    1865              :       CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_construct_nlmos'
    1866              : 
    1867              :       CHARACTER(LEN=30)                                  :: iter_type, print_string
    1868              :       INTEGER :: cg_iteration, dim_op, handle, iatom, idim0, isgf, ispin, iteration, &
    1869              :          line_search_iteration, linear_search_type, max_iter, natom, ncol, nspins, &
    1870              :          outer_iteration, outer_max_iter, prec_type, reim, unit_nr
    1871           16 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: first_sgf, last_sgf, nocc, nsgf
    1872              :       LOGICAL                                            :: converged, d_bfgs, just_started, l_bfgs, &
    1873              :                                                             line_search, outer_prepare_to_exit, &
    1874              :                                                             prepare_to_exit, reset_conjugator
    1875              :       REAL(KIND=dp) :: appr_sec_der, beta, bfgs_rho, bfgs_sum, denom, denom2, e0, e1, g0, g0sign, &
    1876              :          g1, g1sign, grad_norm, line_search_error, localization_obj_function, &
    1877              :          localization_obj_function_ispin, next_step_size_guess, obj_function_ispin, objf_diff, &
    1878              :          objf_new, objf_old, penalty_amplitude, penalty_func_ispin, penalty_func_new, spin_factor, &
    1879              :          step_size, t1, t2, tempreal
    1880            8 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: diagonal, grad_norm_spin, &
    1881            8 :                                                             penalty_vol_prefactor, &
    1882            8 :                                                             suggested_vol_penalty, weights
    1883              :       TYPE(cell_type), POINTER                           :: cell
    1884              :       TYPE(cp_logger_type), POINTER                      :: logger
    1885            8 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: qs_matrix_s
    1886            8 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: op_sm_set_almo, op_sm_set_qs
    1887            8 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: approx_inv_hessian, bfgs_s, bfgs_y, grad, &
    1888            8 :          m_S0, m_sig_sqrti_ii, m_siginv, m_sigma, m_t_mo_local, m_theta, m_theta_normalized, &
    1889            8 :          prev_grad, prev_m_theta, prev_minus_prec_grad, prev_step, step, tempNOcc1, tempOccOcc1, &
    1890            8 :          tempOccOcc2, tempOccOcc3
    1891            8 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:, :, :)  :: m_B0
    1892           24 :       TYPE(lbfgs_history_type)                           :: nlmo_lbfgs_history
    1893              :       TYPE(mp_comm_type)                                 :: group
    1894            8 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1895            8 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1896              : 
    1897            8 :       CALL timeset(routineN, handle)
    1898              : 
    1899              :       ! get a useful output_unit
    1900            8 :       logger => cp_get_default_logger()
    1901            8 :       IF (logger%para_env%is_source()) THEN
    1902            4 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    1903              :       ELSE
    1904              :          unit_nr = -1
    1905              :       END IF
    1906              : 
    1907            8 :       nspins = SIZE(matrix_mo_in)
    1908              : 
    1909            8 :       IF (unit_nr > 0) THEN
    1910            4 :          WRITE (unit_nr, *)
    1911            4 :          IF (.NOT. virtuals) THEN
    1912            4 :             WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 24), &
    1913            8 :                " Optimization of occupied NLMOs ", REPEAT("-", 23)
    1914              :          ELSE
    1915            0 :             WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 24), &
    1916            0 :                " Optimization of virtual NLMOs ", REPEAT("-", 24)
    1917              :          END IF
    1918            4 :          WRITE (unit_nr, *)
    1919            4 :          WRITE (unit_nr, '(T2,A13,A6,A23,A14,A14,A9)') "Method", "Iter", &
    1920            8 :             "Objective Function", "Change", "Convergence", "Time"
    1921            4 :          WRITE (unit_nr, '(T2,A)') REPEAT("-", 79)
    1922              :       END IF
    1923              : 
    1924            8 :       NULLIFY (particle_set)
    1925              : 
    1926              :       CALL get_qs_env(qs_env=qs_env, &
    1927              :                       matrix_s=qs_matrix_s, &
    1928              :                       cell=cell, &
    1929              :                       particle_set=particle_set, &
    1930            8 :                       qs_kind_set=qs_kind_set)
    1931              : 
    1932            8 :       natom = SIZE(particle_set, 1)
    1933           24 :       ALLOCATE (first_sgf(natom))
    1934           16 :       ALLOCATE (last_sgf(natom))
    1935           16 :       ALLOCATE (nsgf(natom))
    1936              :       !   construction of
    1937              :       CALL get_particle_set(particle_set, qs_kind_set, &
    1938            8 :                             first_sgf=first_sgf, last_sgf=last_sgf, nsgf=nsgf)
    1939              : 
    1940              :       ! m_theta contains a set of variational parameters
    1941              :       ! that define one-electron orbitals
    1942           32 :       ALLOCATE (m_theta(nspins))
    1943           16 :       DO ispin = 1, nspins
    1944              :          CALL dbcsr_create(m_theta(ispin), &
    1945              :                            template=template_matrix_sigma(ispin), &
    1946            8 :                            matrix_type=dbcsr_type_no_symmetry)
    1947              :          ! create initial guess for the main variable - identity matrix
    1948            8 :          CALL dbcsr_set(m_theta(ispin), 0.0_dp)
    1949           16 :          CALL dbcsr_add_on_diag(m_theta(ispin), 1.0_dp)
    1950              :       END DO
    1951              : 
    1952            8 :       SELECT CASE (optimizer%opt_penalty%operator_type)
    1953              :       CASE (op_loc_berry)
    1954              : 
    1955            0 :          IF (cell%orthorhombic) THEN
    1956            0 :             dim_op = 3
    1957              :          ELSE
    1958            0 :             dim_op = 6
    1959              :          END IF
    1960            0 :          ALLOCATE (weights(6))
    1961            0 :          weights = 0.0_dp
    1962            0 :          CALL initialize_weights(cell, weights)
    1963            0 :          ALLOCATE (op_sm_set_qs(2, dim_op))
    1964            0 :          ALLOCATE (op_sm_set_almo(2, dim_op))
    1965              :          ! allocate space for T0^t.B.T0
    1966            0 :          ALLOCATE (m_B0(2, dim_op, nspins))
    1967            0 :          DO idim0 = 1, dim_op
    1968            0 :             DO reim = 1, SIZE(op_sm_set_qs, 1)
    1969            0 :                NULLIFY (op_sm_set_qs(reim, idim0)%matrix, op_sm_set_almo(reim, idim0)%matrix)
    1970            0 :                ALLOCATE (op_sm_set_qs(reim, idim0)%matrix)
    1971            0 :                ALLOCATE (op_sm_set_almo(reim, idim0)%matrix)
    1972              :                CALL dbcsr_copy(op_sm_set_qs(reim, idim0)%matrix, qs_matrix_s(1)%matrix, &
    1973            0 :                              name="almo_scf_env%op_sm_"//TRIM(ADJUSTL(cp_to_string(reim)))//"-"//TRIM(ADJUSTL(cp_to_string(idim0))))
    1974              :                CALL dbcsr_copy(op_sm_set_almo(reim, idim0)%matrix, matrix_s, &
    1975            0 :                              name="almo_scf_env%op_sm_"//TRIM(ADJUSTL(cp_to_string(reim)))//"-"//TRIM(ADJUSTL(cp_to_string(idim0))))
    1976            0 :                CALL dbcsr_set(op_sm_set_almo(reim, idim0)%matrix, 0.0_dp)
    1977            0 :                DO ispin = 1, nspins
    1978              :                   CALL dbcsr_create(m_B0(reim, idim0, ispin), &
    1979              :                                     template=m_theta(ispin), &
    1980            0 :                                     matrix_type=dbcsr_type_no_symmetry)
    1981            0 :                   CALL dbcsr_set(m_B0(reim, idim0, ispin), 0.0_dp)
    1982              :                END DO
    1983              :             END DO
    1984              :          END DO
    1985              : 
    1986            0 :          CALL compute_berry_operator(qs_env, cell, op_sm_set_qs, dim_op)
    1987              : 
    1988              :       CASE (op_loc_pipek)
    1989              : 
    1990            8 :          dim_op = natom
    1991           24 :          ALLOCATE (weights(dim_op))
    1992           80 :          weights = 1.0_dp
    1993              : 
    1994          184 :          ALLOCATE (m_B0(1, dim_op, nspins))
    1995              :          !m_B0 first dim is 1 now!
    1996           88 :          DO idim0 = 1, dim_op
    1997          152 :             DO reim = 1, 1
    1998          216 :                DO ispin = 1, nspins
    1999              :                   CALL dbcsr_create(m_B0(reim, idim0, ispin), &
    2000              :                                     template=m_theta(ispin), &
    2001           72 :                                     matrix_type=dbcsr_type_no_symmetry)
    2002          144 :                   CALL dbcsr_set(m_B0(reim, idim0, ispin), 0.0_dp)
    2003              :                END DO
    2004              :             END DO
    2005              :          END DO
    2006              : 
    2007              :       END SELECT
    2008              : 
    2009              :       ! penalty amplitude adjusts the strenght of volume conservation
    2010            8 :       penalty_amplitude = optimizer%opt_penalty%penalty_strength
    2011              : 
    2012              :       ! preconditioner control
    2013            8 :       prec_type = optimizer%preconditioner
    2014              : 
    2015              :       ! use diagonal BFGS if preconditioner is set
    2016            8 :       d_bfgs = .FALSE.
    2017            8 :       l_bfgs = .FALSE.
    2018            8 :       IF (prec_type /= xalmo_prec_zero) l_bfgs = .TRUE.
    2019            8 :       IF (l_bfgs .AND. (optimizer%conjugator /= cg_zero)) THEN
    2020            0 :          CPABORT("Cannot use conjugators with BFGS")
    2021              :       END IF
    2022            8 :       IF (l_bfgs) THEN
    2023            8 :          CALL lbfgs_create(nlmo_lbfgs_history, nspins, nstore=10)
    2024              :       END IF
    2025              : 
    2026              :       IF (nspins == 1) THEN
    2027              :          spin_factor = 2.0_dp
    2028              :       ELSE
    2029              :          spin_factor = 1.0_dp
    2030              :       END IF
    2031              : 
    2032           24 :       ALLOCATE (grad_norm_spin(nspins))
    2033           24 :       ALLOCATE (nocc(nspins))
    2034           16 :       ALLOCATE (penalty_vol_prefactor(nspins))
    2035           16 :       ALLOCATE (suggested_vol_penalty(nspins))
    2036              : 
    2037              :       ! create a local copy of matrix_mo_in because
    2038              :       ! matrix_mo_in and matrix_mo_out can be the same matrix
    2039              :       ! we need to make sure data in matrix_mo_in is intact
    2040              :       ! after we start writing to matrix_mo_out
    2041           24 :       ALLOCATE (m_t_mo_local(nspins))
    2042           16 :       DO ispin = 1, nspins
    2043              :          CALL dbcsr_create(m_t_mo_local(ispin), &
    2044              :                            template=matrix_mo_in(ispin), &
    2045            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2046           16 :          CALL dbcsr_copy(m_t_mo_local(ispin), matrix_mo_in(ispin))
    2047              :       END DO
    2048              : 
    2049           24 :       ALLOCATE (approx_inv_hessian(nspins))
    2050           24 :       ALLOCATE (m_theta_normalized(nspins))
    2051           32 :       ALLOCATE (prev_m_theta(nspins))
    2052           24 :       ALLOCATE (m_S0(nspins))
    2053           24 :       ALLOCATE (prev_grad(nspins))
    2054           24 :       ALLOCATE (grad(nspins))
    2055           24 :       ALLOCATE (prev_step(nspins))
    2056           24 :       ALLOCATE (step(nspins))
    2057           24 :       ALLOCATE (prev_minus_prec_grad(nspins))
    2058           24 :       ALLOCATE (m_sig_sqrti_ii(nspins))
    2059           24 :       ALLOCATE (m_sigma(nspins))
    2060           24 :       ALLOCATE (m_siginv(nspins))
    2061           32 :       ALLOCATE (tempNOcc1(nspins))
    2062           24 :       ALLOCATE (tempOccOcc1(nspins))
    2063           24 :       ALLOCATE (tempOccOcc2(nspins))
    2064           24 :       ALLOCATE (tempOccOcc3(nspins))
    2065           24 :       ALLOCATE (bfgs_y(nspins))
    2066           24 :       ALLOCATE (bfgs_s(nspins))
    2067              : 
    2068           16 :       DO ispin = 1, nspins
    2069              : 
    2070              :          ! init temporary storage
    2071              :          CALL dbcsr_create(tempNOcc1(ispin), &
    2072              :                            template=matrix_mo_out(ispin), &
    2073            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2074              :          CALL dbcsr_create(approx_inv_hessian(ispin), &
    2075              :                            template=m_theta(ispin), &
    2076            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2077              :          CALL dbcsr_create(m_theta_normalized(ispin), &
    2078              :                            template=m_theta(ispin), &
    2079            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2080              :          CALL dbcsr_create(prev_m_theta(ispin), &
    2081              :                            template=m_theta(ispin), &
    2082            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2083              :          CALL dbcsr_create(m_S0(ispin), &
    2084              :                            template=m_theta(ispin), &
    2085            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2086              :          CALL dbcsr_create(prev_grad(ispin), &
    2087              :                            template=m_theta(ispin), &
    2088            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2089              :          CALL dbcsr_create(grad(ispin), &
    2090              :                            template=m_theta(ispin), &
    2091            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2092              :          CALL dbcsr_create(prev_step(ispin), &
    2093              :                            template=m_theta(ispin), &
    2094            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2095              :          CALL dbcsr_create(step(ispin), &
    2096              :                            template=m_theta(ispin), &
    2097            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2098              :          CALL dbcsr_create(prev_minus_prec_grad(ispin), &
    2099              :                            template=m_theta(ispin), &
    2100            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2101              :          CALL dbcsr_create(m_sig_sqrti_ii(ispin), &
    2102              :                            template=m_theta(ispin), &
    2103            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2104              :          CALL dbcsr_create(m_sigma(ispin), &
    2105              :                            template=m_theta(ispin), &
    2106            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2107              :          CALL dbcsr_create(m_siginv(ispin), &
    2108              :                            template=m_theta(ispin), &
    2109            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2110              :          CALL dbcsr_create(tempOccOcc1(ispin), &
    2111              :                            template=m_theta(ispin), &
    2112            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2113              :          CALL dbcsr_create(tempOccOcc2(ispin), &
    2114              :                            template=m_theta(ispin), &
    2115            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2116              :          CALL dbcsr_create(tempOccOcc3(ispin), &
    2117              :                            template=m_theta(ispin), &
    2118            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2119              :          CALL dbcsr_create(bfgs_s(ispin), &
    2120              :                            template=m_theta(ispin), &
    2121            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2122              :          CALL dbcsr_create(bfgs_y(ispin), &
    2123              :                            template=m_theta(ispin), &
    2124            8 :                            matrix_type=dbcsr_type_no_symmetry)
    2125              : 
    2126            8 :          CALL dbcsr_set(step(ispin), 0.0_dp)
    2127            8 :          CALL dbcsr_set(prev_step(ispin), 0.0_dp)
    2128              : 
    2129              :          CALL dbcsr_get_info(template_matrix_sigma(ispin), &
    2130            8 :                              nfullrows_total=nocc(ispin))
    2131              : 
    2132            8 :          penalty_vol_prefactor(ispin) = -penalty_amplitude !KEEP: * spin_factor * nocc(ispin)
    2133              : 
    2134              :          ! compute m_S0=T0^t.S.T0
    2135              :          CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2136              :                              matrix_s, &
    2137              :                              m_t_mo_local(ispin), &
    2138              :                              0.0_dp, tempNOcc1(ispin), &
    2139            8 :                              filter_eps=eps_filter)
    2140              :          CALL dbcsr_multiply("T", "N", 1.0_dp, &
    2141              :                              m_t_mo_local(ispin), &
    2142              :                              tempNOcc1(ispin), &
    2143              :                              0.0_dp, m_S0(ispin), &
    2144            8 :                              filter_eps=eps_filter)
    2145              : 
    2146            8 :          SELECT CASE (optimizer%opt_penalty%operator_type)
    2147              : 
    2148              :          CASE (op_loc_berry)
    2149              : 
    2150              :             ! compute m_B0=T0^t.B.T0
    2151            0 :             DO idim0 = 1, SIZE(op_sm_set_qs, 2) ! this loop is over miller ind
    2152              : 
    2153            0 :                DO reim = 1, SIZE(op_sm_set_qs, 1) ! this loop is over Re/Im
    2154              : 
    2155              :                   CALL matrix_qs_to_almo(op_sm_set_qs(reim, idim0)%matrix, &
    2156            0 :                                          op_sm_set_almo(reim, idim0)%matrix, mat_distr_aos)
    2157              : 
    2158              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2159              :                                       op_sm_set_almo(reim, idim0)%matrix, &
    2160              :                                       m_t_mo_local(ispin), &
    2161              :                                       0.0_dp, tempNOcc1(ispin), &
    2162            0 :                                       filter_eps=eps_filter)
    2163              : 
    2164              :                   CALL dbcsr_multiply("T", "N", 1.0_dp, &
    2165              :                                       m_t_mo_local(ispin), &
    2166              :                                       tempNOcc1(ispin), &
    2167              :                                       0.0_dp, m_B0(reim, idim0, ispin), &
    2168            0 :                                       filter_eps=eps_filter)
    2169              : 
    2170            0 :                   DEALLOCATE (op_sm_set_qs(reim, idim0)%matrix)
    2171            0 :                   DEALLOCATE (op_sm_set_almo(reim, idim0)%matrix)
    2172              : 
    2173              :                END DO
    2174              : 
    2175              :             END DO ! end loop over idim0
    2176              : 
    2177              :          CASE (op_loc_pipek)
    2178              : 
    2179              :             ! compute m_B0=T0^t.B.T0
    2180           80 :             DO iatom = 1, natom ! this loop is over "miller" ind
    2181              : 
    2182           72 :                isgf = first_sgf(iatom)
    2183           72 :                ncol = nsgf(iatom)
    2184              : 
    2185              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2186              :                                    matrix_s, &
    2187              :                                    m_t_mo_local(ispin), &
    2188              :                                    0.0_dp, tempNOcc1(ispin), &
    2189           72 :                                    filter_eps=eps_filter)
    2190              : 
    2191              :                CALL dbcsr_multiply("T", "N", 0.5_dp, &
    2192              :                                    m_t_mo_local(ispin), &
    2193              :                                    tempNOcc1(ispin), &
    2194              :                                    0.0_dp, m_B0(1, iatom, ispin), &
    2195              :                                    first_k=isgf, last_k=isgf + ncol - 1, &
    2196           72 :                                    filter_eps=eps_filter)
    2197              : 
    2198              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2199              :                                    matrix_s, &
    2200              :                                    m_t_mo_local(ispin), &
    2201              :                                    0.0_dp, tempNOcc1(ispin), &
    2202              :                                    first_k=isgf, last_k=isgf + ncol - 1, &
    2203           72 :                                    filter_eps=eps_filter)
    2204              : 
    2205              :                CALL dbcsr_multiply("T", "N", 0.5_dp, &
    2206              :                                    m_t_mo_local(ispin), &
    2207              :                                    tempNOcc1(ispin), &
    2208              :                                    1.0_dp, m_B0(1, iatom, ispin), &
    2209           80 :                                    filter_eps=eps_filter)
    2210              : 
    2211              :             END DO ! end loop over iatom
    2212              : 
    2213              :          END SELECT
    2214              : 
    2215              :       END DO ! ispin
    2216              : 
    2217            8 :       IF (optimizer%opt_penalty%operator_type == op_loc_berry) THEN
    2218            0 :          DO idim0 = 1, SIZE(op_sm_set_qs, 2) ! this loop is over miller ind
    2219            0 :             DO reim = 1, SIZE(op_sm_set_qs, 1) ! this loop is over Re/Im
    2220            0 :                DEALLOCATE (op_sm_set_qs(reim, idim0)%matrix)
    2221            0 :                DEALLOCATE (op_sm_set_almo(reim, idim0)%matrix)
    2222              :             END DO
    2223              :          END DO
    2224            0 :          DEALLOCATE (op_sm_set_qs, op_sm_set_almo)
    2225              :       END IF
    2226              : 
    2227              :       ! start the outer SCF loop
    2228            8 :       outer_max_iter = optimizer%max_iter_outer_loop
    2229            8 :       outer_prepare_to_exit = .FALSE.
    2230            8 :       outer_iteration = 0
    2231              :       grad_norm = 0.0_dp
    2232              :       penalty_func_new = 0.0_dp
    2233            8 :       linear_search_type = 1 ! safe restart, no quadratic assumption, takes more steps
    2234              :       localization_obj_function = 0.0_dp
    2235              :       penalty_func_new = 0.0_dp
    2236              : 
    2237              :       DO
    2238              : 
    2239              :          ! start the inner SCF loop
    2240            8 :          max_iter = optimizer%max_iter
    2241            8 :          prepare_to_exit = .FALSE.
    2242            8 :          line_search = .FALSE.
    2243            8 :          converged = .FALSE.
    2244            8 :          iteration = 0
    2245            8 :          cg_iteration = 0
    2246            8 :          line_search_iteration = 0
    2247            8 :          obj_function_ispin = 0.0_dp
    2248              :          objf_new = 0.0_dp
    2249            8 :          objf_old = 0.0_dp
    2250            8 :          objf_diff = 0.0_dp
    2251            8 :          line_search_error = 0.0_dp
    2252            8 :          t1 = m_walltime()
    2253            8 :          next_step_size_guess = 0.0_dp
    2254              : 
    2255              :          DO
    2256              : 
    2257           82 :             just_started = (iteration == 0) .AND. (outer_iteration == 0)
    2258              : 
    2259          164 :             DO ispin = 1, nspins
    2260              : 
    2261           82 :                CALL dbcsr_get_info(m_sig_sqrti_ii(ispin), group=group)
    2262              : 
    2263              :                ! compute diagonal (a^t.sigma0.a)^(-1/2)
    2264              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2265              :                                    m_S0(ispin), m_theta(ispin), 0.0_dp, &
    2266              :                                    tempOccOcc1(ispin), &
    2267           82 :                                    filter_eps=eps_filter)
    2268           82 :                CALL dbcsr_set(m_sig_sqrti_ii(ispin), 0.0_dp)
    2269           82 :                CALL dbcsr_add_on_diag(m_sig_sqrti_ii(ispin), 1.0_dp)
    2270              :                CALL dbcsr_multiply("T", "N", 1.0_dp, &
    2271              :                                    m_theta(ispin), tempOccOcc1(ispin), 0.0_dp, &
    2272              :                                    m_sig_sqrti_ii(ispin), &
    2273           82 :                                    retain_sparsity=.TRUE.)
    2274          246 :                ALLOCATE (diagonal(nocc(ispin)))
    2275           82 :                CALL dbcsr_get_diag(m_sig_sqrti_ii(ispin), diagonal)
    2276           82 :                CALL group%sum(diagonal)
    2277              :                ! TODO: works for zero diagonal elements?
    2278         1368 :                diagonal(:) = 1.0_dp/SQRT(diagonal(:))
    2279           82 :                CALL dbcsr_set(m_sig_sqrti_ii(ispin), 0.0_dp)
    2280           82 :                CALL dbcsr_set_diag(m_sig_sqrti_ii(ispin), diagonal)
    2281           82 :                DEALLOCATE (diagonal)
    2282              : 
    2283              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2284              :                                    m_theta(ispin), &
    2285              :                                    m_sig_sqrti_ii(ispin), &
    2286              :                                    0.0_dp, m_theta_normalized(ispin), &
    2287           82 :                                    filter_eps=eps_filter)
    2288              : 
    2289              :                ! compute new orbitals
    2290              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2291              :                                    m_t_mo_local(ispin), &
    2292              :                                    m_theta_normalized(ispin), &
    2293              :                                    0.0_dp, matrix_mo_out(ispin), &
    2294          246 :                                    filter_eps=eps_filter)
    2295              : 
    2296              :             END DO
    2297              : 
    2298              :             ! compute objective function
    2299           82 :             localization_obj_function = 0.0_dp
    2300           82 :             penalty_func_new = 0.0_dp
    2301          164 :             DO ispin = 1, nspins
    2302              : 
    2303              :                CALL compute_obj_nlmos( &
    2304              :                   localization_obj_function_ispin=localization_obj_function_ispin, &
    2305              :                   penalty_func_ispin=penalty_func_ispin, &
    2306              :                   overlap_determinant=overlap_determinant, &
    2307              :                   m_sigma=m_sigma(ispin), &
    2308              :                   nocc=nocc(ispin), &
    2309              :                   m_B0=m_B0(:, :, ispin), &
    2310              :                   m_theta_normalized=m_theta_normalized(ispin), &
    2311              :                   template_matrix_mo=matrix_mo_out(ispin), &
    2312              :                   weights=weights, &
    2313              :                   m_S0=m_S0(ispin), &
    2314              :                   just_started=just_started, &
    2315              :                   penalty_vol_prefactor=penalty_vol_prefactor(ispin), &
    2316              :                   penalty_amplitude=penalty_amplitude, &
    2317           82 :                   eps_filter=eps_filter)
    2318              : 
    2319           82 :                localization_obj_function = localization_obj_function + localization_obj_function_ispin
    2320          164 :                penalty_func_new = penalty_func_new + penalty_func_ispin
    2321              : 
    2322              :             END DO ! ispin
    2323           82 :             objf_new = penalty_func_new + localization_obj_function
    2324              : 
    2325          164 :             DO ispin = 1, nspins
    2326              :                ! save the previous gradient to compute beta
    2327              :                ! do it only if the previous grad was computed
    2328              :                ! for .NOT.line_search
    2329          164 :                IF (line_search_iteration == 0 .AND. iteration /= 0) THEN
    2330           30 :                   CALL dbcsr_copy(prev_grad(ispin), grad(ispin))
    2331              :                END IF
    2332              : 
    2333              :             END DO ! ispin
    2334              : 
    2335              :             ! compute the gradient
    2336          164 :             DO ispin = 1, nspins
    2337              : 
    2338              :                CALL invert_Hotelling( &
    2339              :                   matrix_inverse=m_siginv(ispin), &
    2340              :                   matrix=m_sigma(ispin), &
    2341              :                   threshold=eps_filter*10.0_dp, &
    2342              :                   filter_eps=eps_filter, &
    2343           82 :                   silent=.FALSE.)
    2344              : 
    2345              :                CALL compute_gradient_nlmos( &
    2346              :                   m_grad_out=grad(ispin), &
    2347              :                   m_B0=m_B0(:, :, ispin), &
    2348              :                   weights=weights, &
    2349              :                   m_S0=m_S0(ispin), &
    2350              :                   m_theta_normalized=m_theta_normalized(ispin), &
    2351              :                   m_siginv=m_siginv(ispin), &
    2352              :                   m_sig_sqrti_ii=m_sig_sqrti_ii(ispin), &
    2353              :                   penalty_vol_prefactor=penalty_vol_prefactor(ispin), &
    2354              :                   eps_filter=eps_filter, &
    2355          164 :                   suggested_vol_penalty=suggested_vol_penalty(ispin))
    2356              : 
    2357              :             END DO ! ispin
    2358              : 
    2359              :             ! check convergence and other exit criteria
    2360          164 :             DO ispin = 1, nspins
    2361          164 :                grad_norm_spin(ispin) = dbcsr_maxabs(grad(ispin))
    2362              :             END DO ! ispin
    2363          164 :             grad_norm = MAXVAL(grad_norm_spin)
    2364              : 
    2365           82 :             converged = (grad_norm <= optimizer%eps_error)
    2366           82 :             IF (converged .OR. (iteration >= max_iter)) THEN
    2367              :                prepare_to_exit = .TRUE.
    2368              :             END IF
    2369              : 
    2370              :             ! it is not time to exit just yet
    2371           74 :             IF (.NOT. prepare_to_exit) THEN
    2372              : 
    2373              :                ! check the gradient along the step direction
    2374              :                ! and decide whether to switch to the line-search mode
    2375              :                ! do not do this in the first iteration
    2376           74 :                IF (iteration /= 0) THEN
    2377              : 
    2378              :                   ! enforce at least one line search
    2379              :                   ! without even checking the error
    2380           68 :                   IF (.NOT. line_search) THEN
    2381              : 
    2382           30 :                      line_search = .TRUE.
    2383           30 :                      line_search_iteration = line_search_iteration + 1
    2384              : 
    2385              :                   ELSE
    2386              : 
    2387              :                      ! check the line-search error and decide whether to
    2388              :                      ! change the direction
    2389              :                      line_search_error = 0.0_dp
    2390              :                      denom = 0.0_dp
    2391              :                      denom2 = 0.0_dp
    2392              : 
    2393           76 :                      DO ispin = 1, nspins
    2394              : 
    2395           38 :                         CALL dbcsr_dot(grad(ispin), step(ispin), tempreal)
    2396           38 :                         line_search_error = line_search_error + tempreal
    2397           38 :                         CALL dbcsr_dot(grad(ispin), grad(ispin), tempreal)
    2398           38 :                         denom = denom + tempreal
    2399           38 :                         CALL dbcsr_dot(step(ispin), step(ispin), tempreal)
    2400           76 :                         denom2 = denom2 + tempreal
    2401              : 
    2402              :                      END DO ! ispin
    2403              : 
    2404              :                      ! cosine of the angle between the step and grad
    2405              :                      ! (must be close to zero at convergence)
    2406           38 :                      line_search_error = line_search_error/SQRT(denom)/SQRT(denom2)
    2407              : 
    2408           38 :                      IF (ABS(line_search_error) > optimizer%lin_search_eps_error) THEN
    2409           14 :                         line_search = .TRUE.
    2410           14 :                         line_search_iteration = line_search_iteration + 1
    2411              :                      ELSE
    2412              :                         line_search = .FALSE.
    2413              :                         line_search_iteration = 0
    2414              :                      END IF
    2415              : 
    2416              :                   END IF
    2417              : 
    2418              :                END IF ! iteration.ne.0
    2419              : 
    2420            6 :                IF (line_search) THEN
    2421           44 :                   objf_diff = 0.0_dp
    2422              :                ELSE
    2423           30 :                   objf_diff = objf_new - objf_old
    2424              :                   objf_old = objf_new
    2425              :                END IF
    2426              : 
    2427              :                ! update the step direction
    2428           30 :                IF (.NOT. line_search) THEN
    2429              : 
    2430           60 :                   cg_iteration = cg_iteration + 1
    2431              : 
    2432              :                   ! save the previous step
    2433           60 :                   DO ispin = 1, nspins
    2434           60 :                      CALL dbcsr_copy(prev_step(ispin), step(ispin))
    2435              :                   END DO ! ispin
    2436              : 
    2437              :                   ! compute the new step:
    2438              :                   ! if available use second derivative info - bfgs, hessian, preconditioner
    2439           30 :                   IF (prec_type == xalmo_prec_zero) THEN ! no second derivatives
    2440              : 
    2441              :                      ! no preconditioner
    2442            0 :                      DO ispin = 1, nspins
    2443              : 
    2444            0 :                         CALL dbcsr_copy(step(ispin), grad(ispin))
    2445            0 :                         CALL dbcsr_scale(step(ispin), -1.0_dp)
    2446              : 
    2447              :                      END DO ! ispin
    2448              : 
    2449              :                   ELSE ! use second derivatives
    2450              : 
    2451              :                      ! compute and invert hessian/precond?
    2452           30 :                      IF (iteration == 0) THEN
    2453              : 
    2454              :                         IF (d_bfgs) THEN
    2455              : 
    2456              :                            ! create matrix filled with 1.0 here
    2457              :                            CALL fill_matrix_with_ones(approx_inv_hessian(1))
    2458              :                            IF (nspins > 1) THEN
    2459              :                               DO ispin = 2, nspins
    2460              :                                  CALL dbcsr_copy(approx_inv_hessian(ispin), approx_inv_hessian(1))
    2461              :                               END DO
    2462              :                            END IF
    2463              : 
    2464            6 :                         ELSE IF (l_bfgs) THEN
    2465              : 
    2466            6 :                            CALL lbfgs_seed(nlmo_lbfgs_history, m_theta, grad)
    2467           12 :                            DO ispin = 1, nspins
    2468            6 :                               CALL dbcsr_copy(step(ispin), grad(ispin))
    2469           12 :                               CALL dbcsr_scale(step(ispin), -1.0_dp)
    2470              :                            END DO ! ispin
    2471              : 
    2472              :                         ELSE
    2473              : 
    2474              :                            ! computing preconditioner
    2475            0 :                            DO ispin = 1, nspins
    2476              : 
    2477              :                               ! TODO: write preconditioner code later
    2478              :                               ! For now, create matrix filled with 1.0 here
    2479            0 :                               CALL fill_matrix_with_ones(approx_inv_hessian(ispin))
    2480              :                            END DO ! ispin
    2481              : 
    2482              :                         END IF
    2483              : 
    2484              :                      ELSE ! not iteration zero
    2485              : 
    2486              :                         ! update approx inverse hessian
    2487              :                         IF (d_bfgs) THEN ! diagonal BFGS
    2488              : 
    2489              :                            DO ispin = 1, nspins
    2490              : 
    2491              :                               ! compute s and y
    2492              :                               CALL dbcsr_copy(bfgs_y(ispin), grad(ispin))
    2493              :                               CALL dbcsr_add(bfgs_y(ispin), prev_grad(ispin), 1.0_dp, -1.0_dp)
    2494              :                               CALL dbcsr_copy(bfgs_s(ispin), m_theta(ispin))
    2495              :                               CALL dbcsr_add(bfgs_s(ispin), prev_m_theta(ispin), 1.0_dp, -1.0_dp)
    2496              : 
    2497              :                               ! compute rho
    2498              :                               CALL dbcsr_dot(grad(ispin), step(ispin), bfgs_rho)
    2499              :                               bfgs_rho = 1.0_dp/bfgs_rho
    2500              : 
    2501              :                               ! compute the sum of the squared elements of bfgs_y
    2502              :                               CALL dbcsr_dot(bfgs_y(ispin), bfgs_y(ispin), bfgs_sum)
    2503              : 
    2504              :                               ! first term: start collecting new inv hessian in this temp matrix
    2505              :                               CALL dbcsr_copy(tempOccOcc2(ispin), approx_inv_hessian(ispin))
    2506              : 
    2507              :                               ! second term: + rho * s * s
    2508              :                               CALL dbcsr_hadamard_product(bfgs_s(ispin), bfgs_s(ispin), tempOccOcc1(ispin))
    2509              :                               CALL dbcsr_add(tempOccOcc2(ispin), tempOccOcc1(ispin), 1.0_dp, bfgs_rho)
    2510              : 
    2511              :                               ! third term: + rho^2 * s * s * H * sum_(y * y)
    2512              :                               CALL dbcsr_hadamard_product(tempOccOcc1(ispin), &
    2513              :                                                           approx_inv_hessian(ispin), tempOccOcc3(ispin))
    2514              :                               CALL dbcsr_add(tempOccOcc2(ispin), tempOccOcc3(ispin), &
    2515              :                                              1.0_dp, bfgs_rho*bfgs_rho*bfgs_sum)
    2516              : 
    2517              :                               ! fourth term: - 2 * rho * s * y * H
    2518              :                               CALL dbcsr_hadamard_product(bfgs_y(ispin), &
    2519              :                                                           approx_inv_hessian(ispin), tempOccOcc1(ispin))
    2520              :                               CALL dbcsr_hadamard_product(bfgs_s(ispin), tempOccOcc1(ispin), tempOccOcc3(ispin))
    2521              :                               CALL dbcsr_add(tempOccOcc2(ispin), tempOccOcc3(ispin), &
    2522              :                                              1.0_dp, -2.0_dp*bfgs_rho)
    2523              : 
    2524              :                               CALL dbcsr_copy(approx_inv_hessian(ispin), tempOccOcc2(ispin))
    2525              : 
    2526              :                            END DO
    2527              : 
    2528           24 :                         ELSE IF (l_bfgs) THEN
    2529              : 
    2530           24 :                            CALL lbfgs_get_direction(nlmo_lbfgs_history, m_theta, grad, step)
    2531              : 
    2532              :                         END IF ! which method?
    2533              : 
    2534              :                      END IF ! compute approximate inverse hessian
    2535              : 
    2536           30 :                      IF (.NOT. l_bfgs) THEN
    2537              : 
    2538            0 :                         DO ispin = 1, nspins
    2539              : 
    2540              :                            CALL dbcsr_hadamard_product(approx_inv_hessian(ispin), &
    2541            0 :                                                        grad(ispin), step(ispin))
    2542            0 :                            CALL dbcsr_scale(step(ispin), -1.0_dp)
    2543              : 
    2544              :                         END DO ! ispin
    2545              : 
    2546              :                      END IF
    2547              : 
    2548              :                   END IF ! second derivative type fork
    2549              : 
    2550              :                   ! check whether we need to reset conjugate directions
    2551           30 :                   IF (iteration == 0) THEN
    2552            6 :                      reset_conjugator = .TRUE.
    2553              :                   END IF
    2554              : 
    2555              :                   ! compute the conjugation coefficient - beta
    2556           30 :                   IF (.NOT. reset_conjugator) THEN
    2557              :                      CALL compute_cg_beta( &
    2558              :                         beta=beta, &
    2559              :                         reset_conjugator=reset_conjugator, &
    2560              :                         conjugator=optimizer%conjugator, &
    2561              :                         grad=grad(:), &
    2562              :                         prev_grad=prev_grad(:), &
    2563              :                         step=step(:), &
    2564              :                         prev_step=prev_step(:), &
    2565              :                         prev_minus_prec_grad=prev_minus_prec_grad(:) &
    2566           24 :                         )
    2567              : 
    2568              :                   END IF
    2569              : 
    2570           30 :                   IF (reset_conjugator) THEN
    2571              : 
    2572            6 :                      beta = 0.0_dp
    2573            6 :                      IF (unit_nr > 0 .AND. (.NOT. just_started)) THEN
    2574            0 :                         WRITE (unit_nr, '(T2,A35)') "Re-setting conjugator to zero"
    2575              :                      END IF
    2576            6 :                      reset_conjugator = .FALSE.
    2577              : 
    2578              :                   END IF
    2579              : 
    2580              :                   ! save the preconditioned gradient (useful for beta)
    2581           60 :                   DO ispin = 1, nspins
    2582              : 
    2583           30 :                      CALL dbcsr_copy(prev_minus_prec_grad(ispin), step(ispin))
    2584              : 
    2585              :                      ! conjugate the step direction
    2586           60 :                      CALL dbcsr_add(step(ispin), prev_step(ispin), 1.0_dp, beta)
    2587              : 
    2588              :                   END DO ! ispin
    2589              : 
    2590              :                END IF ! update the step direction
    2591              : 
    2592              :                ! estimate the step size
    2593              :                IF (.NOT. line_search) THEN
    2594              :                   ! we just changed the direction and
    2595              :                   ! we have only E and grad from the current step
    2596              :                   ! it is not enough to compute step_size - just guess it
    2597           30 :                   e0 = objf_new
    2598           30 :                   g0 = 0.0_dp
    2599           60 :                   DO ispin = 1, nspins
    2600           30 :                      CALL dbcsr_dot(grad(ispin), step(ispin), tempreal)
    2601           60 :                      g0 = g0 + tempreal
    2602              :                   END DO ! ispin
    2603              :                   g0sign = SIGN(1.0_dp, g0) ! sign of g0
    2604              :                   IF (linear_search_type == 1) THEN ! this is quadratic LS
    2605           30 :                      IF (iteration == 0) THEN
    2606            6 :                         step_size = optimizer%lin_search_step_size_guess
    2607              :                      ELSE
    2608           24 :                         IF (next_step_size_guess <= 0.0_dp) THEN
    2609            0 :                            step_size = optimizer%lin_search_step_size_guess
    2610              :                         ELSE
    2611              :                            ! take the last value
    2612           24 :                            step_size = optimizer%lin_search_step_size_guess
    2613              :                            !step_size = next_step_size_guess*1.05_dp
    2614              :                         END IF
    2615              :                      END IF
    2616              :                   ELSE IF (linear_search_type == 2) THEN ! this is cautious LS
    2617              :                      ! this LS type is designed not to trust quadratic appr
    2618              :                      ! so it always restarts from a safe step size
    2619              :                      step_size = optimizer%lin_search_step_size_guess
    2620              :                   END IF
    2621           30 :                   IF (unit_nr > 0) THEN
    2622           15 :                      WRITE (unit_nr, '(T21,3A19)') "Line position", "Line grad", "Next line step"
    2623           15 :                      WRITE (unit_nr, '(T2,A19,3F19.5)') "Line search", 0.0_dp, g0, step_size
    2624              :                   END IF
    2625           30 :                   next_step_size_guess = step_size
    2626              :                ELSE ! this is not the first line search
    2627           44 :                   e1 = objf_new
    2628           44 :                   g1 = 0.0_dp
    2629           88 :                   DO ispin = 1, nspins
    2630           44 :                      CALL dbcsr_dot(grad(ispin), step(ispin), tempreal)
    2631           88 :                      g1 = g1 + tempreal
    2632              :                   END DO ! ispin
    2633           44 :                   g1sign = SIGN(1.0_dp, g1) ! sign of g1
    2634              :                   IF (linear_search_type == 1) THEN
    2635              :                      ! we have accumulated some points along this direction
    2636              :                      ! use only the most recent g0 (quadratic approximation)
    2637           44 :                      appr_sec_der = (g1 - g0)/step_size
    2638           44 :                      step_size = -g1/appr_sec_der
    2639              :                   ELSE IF (linear_search_type == 2) THEN
    2640              :                      ! alternative method for finding step size
    2641              :                      ! do not use quadratic approximation, only gradient signs
    2642              :                      IF (g1sign /= g0sign) THEN
    2643              :                         step_size = -step_size/2.0
    2644              :                      ELSE
    2645              :                         step_size = step_size*1.5
    2646              :                      END IF
    2647              :                   END IF
    2648              :                   ! end alternative LS types
    2649           44 :                   IF (unit_nr > 0) THEN
    2650           22 :                      WRITE (unit_nr, '(T21,3A19)') "Line position", "Line grad", "Next line step"
    2651           22 :                      WRITE (unit_nr, '(T2,A19,3F19.5)') "Line search", next_step_size_guess, g1, step_size
    2652              :                   END IF
    2653           44 :                   e0 = e1
    2654           44 :                   g0 = g1
    2655              :                   g0sign = g1sign
    2656           44 :                   next_step_size_guess = next_step_size_guess + step_size
    2657              :                END IF
    2658              : 
    2659              :                ! update theta
    2660          148 :                DO ispin = 1, nspins
    2661           74 :                   IF (.NOT. line_search) THEN ! we prepared to perform the first line search
    2662              :                      ! "previous" refers to the previous CG step, not the previous LS step
    2663           30 :                      CALL dbcsr_copy(prev_m_theta(ispin), m_theta(ispin))
    2664              :                   END IF
    2665          148 :                   CALL dbcsr_add(m_theta(ispin), step(ispin), 1.0_dp, step_size)
    2666              :                END DO ! ispin
    2667              : 
    2668              :             END IF ! not.prepare_to_exit
    2669              : 
    2670           82 :             IF (line_search) THEN
    2671           50 :                iter_type = "LS"
    2672              :             ELSE
    2673           32 :                iter_type = "CG"
    2674              :             END IF
    2675              : 
    2676           82 :             t2 = m_walltime()
    2677           82 :             IF (unit_nr > 0) THEN
    2678           41 :                iter_type = TRIM("NLMO OPT "//iter_type)
    2679              :                WRITE (unit_nr, '(T2,A13,I6,F23.10,E14.5,F14.9,F9.2)') &
    2680           41 :                   iter_type, iteration, &
    2681           41 :                   objf_new, objf_diff, grad_norm, &
    2682           82 :                   t2 - t1
    2683              :                WRITE (unit_nr, '(T2,A19,F23.10)') &
    2684           41 :                   "Localization:", localization_obj_function
    2685              :                WRITE (unit_nr, '(T2,A19,F23.10)') &
    2686           41 :                   "Orthogonalization:", penalty_func_new
    2687              :             END IF
    2688           82 :             t1 = m_walltime()
    2689              : 
    2690           82 :             iteration = iteration + 1
    2691           82 :             IF (prepare_to_exit) EXIT
    2692              : 
    2693              :          END DO ! inner loop
    2694              : 
    2695            8 :          IF (converged .OR. (outer_iteration >= outer_max_iter)) THEN
    2696            8 :             outer_prepare_to_exit = .TRUE.
    2697              :          END IF
    2698              : 
    2699            8 :          outer_iteration = outer_iteration + 1
    2700            8 :          IF (outer_prepare_to_exit) EXIT
    2701              : 
    2702              :       END DO ! outer loop
    2703              : 
    2704              :       ! return the optimal determinant penalty
    2705            8 :       optimizer%opt_penalty%penalty_strength = 0.0_dp
    2706           16 :       DO ispin = 1, nspins
    2707              :          optimizer%opt_penalty%penalty_strength = optimizer%opt_penalty%penalty_strength + &
    2708           16 :                                                   (-1.0_dp)*penalty_vol_prefactor(ispin)
    2709              :       END DO
    2710            8 :       optimizer%opt_penalty%penalty_strength = optimizer%opt_penalty%penalty_strength/nspins
    2711              : 
    2712            8 :       IF (converged) THEN
    2713            8 :          iter_type = "Final"
    2714              :       ELSE
    2715            0 :          iter_type = "Unconverged"
    2716              :       END IF
    2717              : 
    2718            8 :       IF (unit_nr > 0) THEN
    2719            4 :          WRITE (unit_nr, '()')
    2720            4 :          print_string = TRIM(iter_type)//" localization:"
    2721              :          WRITE (unit_nr, '(T2,A29,F30.10)') &
    2722            4 :             print_string, localization_obj_function
    2723            4 :          print_string = TRIM(iter_type)//" determinant:"
    2724              :          WRITE (unit_nr, '(T2,A29,F30.10)') &
    2725            4 :             print_string, overlap_determinant
    2726            4 :          print_string = TRIM(iter_type)//" penalty strength:"
    2727              :          WRITE (unit_nr, '(T2,A29,F30.10)') &
    2728            4 :             print_string, optimizer%opt_penalty%penalty_strength
    2729              :       END IF
    2730              : 
    2731              :       ! clean up
    2732            8 :       IF (l_bfgs) THEN
    2733            8 :          CALL lbfgs_release(nlmo_lbfgs_history)
    2734              :       END IF
    2735           16 :       DO ispin = 1, nspins
    2736           80 :          DO idim0 = 1, SIZE(m_B0, 2)
    2737          152 :             DO reim = 1, SIZE(m_B0, 1)
    2738          144 :                CALL dbcsr_release(m_B0(reim, idim0, ispin))
    2739              :             END DO
    2740              :          END DO
    2741            8 :          CALL dbcsr_release(m_theta(ispin))
    2742            8 :          CALL dbcsr_release(m_t_mo_local(ispin))
    2743            8 :          CALL dbcsr_release(tempNOcc1(ispin))
    2744            8 :          CALL dbcsr_release(approx_inv_hessian(ispin))
    2745            8 :          CALL dbcsr_release(prev_m_theta(ispin))
    2746            8 :          CALL dbcsr_release(m_theta_normalized(ispin))
    2747            8 :          CALL dbcsr_release(m_S0(ispin))
    2748            8 :          CALL dbcsr_release(prev_grad(ispin))
    2749            8 :          CALL dbcsr_release(grad(ispin))
    2750            8 :          CALL dbcsr_release(prev_step(ispin))
    2751            8 :          CALL dbcsr_release(step(ispin))
    2752            8 :          CALL dbcsr_release(prev_minus_prec_grad(ispin))
    2753            8 :          CALL dbcsr_release(m_sig_sqrti_ii(ispin))
    2754            8 :          CALL dbcsr_release(m_sigma(ispin))
    2755            8 :          CALL dbcsr_release(m_siginv(ispin))
    2756            8 :          CALL dbcsr_release(tempOccOcc1(ispin))
    2757            8 :          CALL dbcsr_release(tempOccOcc2(ispin))
    2758            8 :          CALL dbcsr_release(tempOccOcc3(ispin))
    2759            8 :          CALL dbcsr_release(bfgs_y(ispin))
    2760           16 :          CALL dbcsr_release(bfgs_s(ispin))
    2761              :       END DO ! ispin
    2762              : 
    2763            8 :       DEALLOCATE (grad_norm_spin)
    2764            8 :       DEALLOCATE (nocc)
    2765            8 :       DEALLOCATE (penalty_vol_prefactor)
    2766            8 :       DEALLOCATE (suggested_vol_penalty)
    2767              : 
    2768            8 :       DEALLOCATE (approx_inv_hessian)
    2769            8 :       DEALLOCATE (prev_m_theta)
    2770            8 :       DEALLOCATE (m_theta_normalized)
    2771            8 :       DEALLOCATE (m_S0)
    2772            8 :       DEALLOCATE (prev_grad)
    2773            8 :       DEALLOCATE (grad)
    2774            8 :       DEALLOCATE (prev_step)
    2775            8 :       DEALLOCATE (step)
    2776            8 :       DEALLOCATE (prev_minus_prec_grad)
    2777            8 :       DEALLOCATE (m_sig_sqrti_ii)
    2778            8 :       DEALLOCATE (m_sigma)
    2779            8 :       DEALLOCATE (m_siginv)
    2780            8 :       DEALLOCATE (tempNOcc1)
    2781            8 :       DEALLOCATE (tempOccOcc1)
    2782            8 :       DEALLOCATE (tempOccOcc2)
    2783            8 :       DEALLOCATE (tempOccOcc3)
    2784            8 :       DEALLOCATE (bfgs_y)
    2785            8 :       DEALLOCATE (bfgs_s)
    2786              : 
    2787            8 :       DEALLOCATE (m_theta, m_t_mo_local)
    2788            8 :       DEALLOCATE (m_B0)
    2789            8 :       DEALLOCATE (weights)
    2790            8 :       DEALLOCATE (first_sgf, last_sgf, nsgf)
    2791              : 
    2792            8 :       IF (.NOT. converged) THEN
    2793            0 :          CPABORT("Optimization not converged! ")
    2794              :       END IF
    2795              : 
    2796            8 :       CALL timestop(handle)
    2797              : 
    2798           24 :    END SUBROUTINE almo_scf_construct_nlmos
    2799              : 
    2800              : ! **************************************************************************************************
    2801              : !> \brief Analysis of the orbitals
    2802              : !> \param detailed_analysis ...
    2803              : !> \param eps_filter ...
    2804              : !> \param m_T_in ...
    2805              : !> \param m_T0_in ...
    2806              : !> \param m_siginv_in ...
    2807              : !> \param m_siginv0_in ...
    2808              : !> \param m_S_in ...
    2809              : !> \param m_KS0_in ...
    2810              : !> \param m_quench_t_in ...
    2811              : !> \param energy_out ...
    2812              : !> \param m_eda_out ...
    2813              : !> \param m_cta_out ...
    2814              : !> \par History
    2815              : !>       2017.07 created [Rustam Z Khaliullin]
    2816              : !> \author Rustam Z Khaliullin
    2817              : ! **************************************************************************************************
    2818           24 :    SUBROUTINE xalmo_analysis(detailed_analysis, eps_filter, m_T_in, m_T0_in, &
    2819           24 :                              m_siginv_in, m_siginv0_in, m_S_in, m_KS0_in, m_quench_t_in, energy_out, &
    2820           24 :                              m_eda_out, m_cta_out)
    2821              : 
    2822              :       LOGICAL, INTENT(IN)                                :: detailed_analysis
    2823              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    2824              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: m_T_in, m_T0_in, m_siginv_in, &
    2825              :                                                             m_siginv0_in, m_S_in, m_KS0_in, &
    2826              :                                                             m_quench_t_in
    2827              :       REAL(KIND=dp), INTENT(INOUT)                       :: energy_out
    2828              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT)      :: m_eda_out, m_cta_out
    2829              : 
    2830              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xalmo_analysis'
    2831              : 
    2832              :       INTEGER                                            :: handle, ispin, nspins
    2833              :       REAL(KIND=dp)                                      :: energy_ispin, spin_factor
    2834              :       TYPE(dbcsr_type)                                   :: FTsiginv0, Fvo0, m_X, siginvTFTsiginv0, &
    2835              :                                                             ST0
    2836              : 
    2837           24 :       CALL timeset(routineN, handle)
    2838              : 
    2839           24 :       nspins = SIZE(m_T_in)
    2840              : 
    2841           24 :       IF (nspins == 1) THEN
    2842           24 :          spin_factor = 2.0_dp
    2843              :       ELSE
    2844            0 :          spin_factor = 1.0_dp
    2845              :       END IF
    2846              : 
    2847           24 :       energy_out = 0.0_dp
    2848           48 :       DO ispin = 1, nspins
    2849              : 
    2850              :          ! create temporary matrices
    2851              :          CALL dbcsr_create(Fvo0, &
    2852              :                            template=m_T_in(ispin), &
    2853           24 :                            matrix_type=dbcsr_type_no_symmetry)
    2854              :          CALL dbcsr_create(FTsiginv0, &
    2855              :                            template=m_T_in(ispin), &
    2856           24 :                            matrix_type=dbcsr_type_no_symmetry)
    2857              :          CALL dbcsr_create(ST0, &
    2858              :                            template=m_T_in(ispin), &
    2859           24 :                            matrix_type=dbcsr_type_no_symmetry)
    2860              :          CALL dbcsr_create(m_X, &
    2861              :                            template=m_T_in(ispin), &
    2862           24 :                            matrix_type=dbcsr_type_no_symmetry)
    2863              :          CALL dbcsr_create(siginvTFTsiginv0, &
    2864              :                            template=m_siginv0_in(ispin), &
    2865           24 :                            matrix_type=dbcsr_type_no_symmetry)
    2866              : 
    2867              :          ! compute F_{virt,occ} for the zero-delocalization state
    2868              :          CALL compute_frequently_used_matrices( &
    2869              :             filter_eps=eps_filter, &
    2870              :             m_T_in=m_T0_in(ispin), &
    2871              :             m_siginv_in=m_siginv0_in(ispin), &
    2872              :             m_S_in=m_S_in(1), &
    2873              :             m_F_in=m_KS0_in(ispin), &
    2874              :             m_FTsiginv_out=FTsiginv0, &
    2875              :             m_siginvTFTsiginv_out=siginvTFTsiginv0, &
    2876           24 :             m_ST_out=ST0)
    2877           24 :          CALL dbcsr_copy(Fvo0, m_quench_t_in(ispin))
    2878           24 :          CALL dbcsr_copy(Fvo0, FTsiginv0, keep_sparsity=.TRUE.)
    2879              :          CALL dbcsr_multiply("N", "N", -1.0_dp, &
    2880              :                              ST0, &
    2881              :                              siginvTFTsiginv0, &
    2882              :                              1.0_dp, Fvo0, &
    2883           24 :                              retain_sparsity=.TRUE.)
    2884              : 
    2885              :          ! get single excitation amplitudes
    2886           24 :          CALL dbcsr_copy(m_X, m_T0_in(ispin))
    2887           24 :          CALL dbcsr_add(m_X, m_T_in(ispin), -1.0_dp, 1.0_dp)
    2888              : 
    2889           24 :          CALL dbcsr_dot(m_X, Fvo0, energy_ispin)
    2890           24 :          energy_out = energy_out + energy_ispin*spin_factor
    2891              : 
    2892           24 :          IF (detailed_analysis) THEN
    2893              : 
    2894            2 :             CALL dbcsr_hadamard_product(m_X, Fvo0, m_eda_out(ispin))
    2895            2 :             CALL dbcsr_scale(m_eda_out(ispin), spin_factor)
    2896            2 :             CALL dbcsr_filter(m_eda_out(ispin), eps_filter)
    2897              : 
    2898              :             ! first, compute [QR'R]_mu^i = [(S-SRS).X.siginv']_mu^i
    2899              :             ! a. FTsiginv0 = S.T0*siginv0
    2900              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2901              :                                 ST0, &
    2902              :                                 m_siginv0_in(ispin), &
    2903              :                                 0.0_dp, FTsiginv0, &
    2904            2 :                                 filter_eps=eps_filter)
    2905              :             ! c. tmp1(use ST0) = S.X
    2906              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2907              :                                 m_S_in(1), &
    2908              :                                 m_X, &
    2909              :                                 0.0_dp, ST0, &
    2910            2 :                                 filter_eps=eps_filter)
    2911              :             ! d. tmp2 = tr(T0).tmp1 = tr(T0).S.X
    2912              :             CALL dbcsr_multiply("T", "N", 1.0_dp, &
    2913              :                                 m_T0_in(ispin), &
    2914              :                                 ST0, &
    2915              :                                 0.0_dp, siginvTFTsiginv0, &
    2916            2 :                                 filter_eps=eps_filter)
    2917              :             ! e. tmp1 = tmp1 - tmp3.tmp2 = S.X - S.T0.siginv0*tr(T0).S.X
    2918              :             !         = (1-S.R0).S.X
    2919              :             CALL dbcsr_multiply("N", "N", -1.0_dp, &
    2920              :                                 FTsiginv0, &
    2921              :                                 siginvTFTsiginv0, &
    2922              :                                 1.0_dp, ST0, &
    2923            2 :                                 filter_eps=eps_filter)
    2924              :             ! f. tmp2(use FTsiginv0) = tmp1*siginv
    2925              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2926              :                                 ST0, &
    2927              :                                 m_siginv_in(ispin), &
    2928              :                                 0.0_dp, FTsiginv0, &
    2929            2 :                                 filter_eps=eps_filter)
    2930              :             ! second, compute traces of blocks [RR'Q]^x_y * [X]^y_x
    2931              :             CALL dbcsr_hadamard_product(m_X, &
    2932            2 :                                         FTsiginv0, m_cta_out(ispin))
    2933            2 :             CALL dbcsr_scale(m_cta_out(ispin), spin_factor)
    2934            2 :             CALL dbcsr_filter(m_cta_out(ispin), eps_filter)
    2935              : 
    2936              :          END IF ! do ALMO EDA/CTA
    2937              : 
    2938           24 :          CALL dbcsr_release(Fvo0)
    2939           24 :          CALL dbcsr_release(FTsiginv0)
    2940           24 :          CALL dbcsr_release(ST0)
    2941           24 :          CALL dbcsr_release(m_X)
    2942           72 :          CALL dbcsr_release(siginvTFTsiginv0)
    2943              : 
    2944              :       END DO ! ispin
    2945              : 
    2946           24 :       CALL timestop(handle)
    2947              : 
    2948           24 :    END SUBROUTINE xalmo_analysis
    2949              : 
    2950              : ! **************************************************************************************************
    2951              : !> \brief Compute matrices that are used often in various parts of the
    2952              : !>        optimization procedure
    2953              : !> \param filter_eps ...
    2954              : !> \param m_T_in ...
    2955              : !> \param m_siginv_in ...
    2956              : !> \param m_S_in ...
    2957              : !> \param m_F_in ...
    2958              : !> \param m_FTsiginv_out ...
    2959              : !> \param m_siginvTFTsiginv_out ...
    2960              : !> \param m_ST_out ...
    2961              : !> \par History
    2962              : !>       2016.12 created [Rustam Z Khaliullin]
    2963              : !> \author Rustam Z Khaliullin
    2964              : ! **************************************************************************************************
    2965         1522 :    SUBROUTINE compute_frequently_used_matrices(filter_eps, &
    2966              :                                                m_T_in, m_siginv_in, m_S_in, m_F_in, m_FTsiginv_out, &
    2967              :                                                m_siginvTFTsiginv_out, m_ST_out)
    2968              : 
    2969              :       REAL(KIND=dp), INTENT(IN)                          :: filter_eps
    2970              :       TYPE(dbcsr_type), INTENT(IN)                       :: m_T_in, m_siginv_in, m_S_in, m_F_in
    2971              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: m_FTsiginv_out, m_siginvTFTsiginv_out, &
    2972              :                                                             m_ST_out
    2973              : 
    2974              :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_frequently_used_matrices'
    2975              : 
    2976              :       INTEGER                                            :: handle
    2977              :       TYPE(dbcsr_type)                                   :: m_tmp_no_1, m_tmp_oo_1
    2978              : 
    2979         1522 :       CALL timeset(routineN, handle)
    2980              : 
    2981              :       CALL dbcsr_create(m_tmp_no_1, &
    2982              :                         template=m_T_in, &
    2983         1522 :                         matrix_type=dbcsr_type_no_symmetry)
    2984              :       CALL dbcsr_create(m_tmp_oo_1, &
    2985              :                         template=m_siginv_in, &
    2986         1522 :                         matrix_type=dbcsr_type_no_symmetry)
    2987              : 
    2988              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2989              :                           m_F_in, &
    2990              :                           m_T_in, &
    2991              :                           0.0_dp, m_tmp_no_1, &
    2992         1522 :                           filter_eps=filter_eps)
    2993              : 
    2994              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    2995              :                           m_tmp_no_1, &
    2996              :                           m_siginv_in, &
    2997              :                           0.0_dp, m_FTsiginv_out, &
    2998         1522 :                           filter_eps=filter_eps)
    2999              : 
    3000              :       CALL dbcsr_multiply("T", "N", 1.0_dp, &
    3001              :                           m_T_in, &
    3002              :                           m_FTsiginv_out, &
    3003              :                           0.0_dp, m_tmp_oo_1, &
    3004         1522 :                           filter_eps=filter_eps)
    3005              : 
    3006              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    3007              :                           m_siginv_in, &
    3008              :                           m_tmp_oo_1, &
    3009              :                           0.0_dp, m_siginvTFTsiginv_out, &
    3010         1522 :                           filter_eps=filter_eps)
    3011              : 
    3012              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    3013              :                           m_S_in, &
    3014              :                           m_T_in, &
    3015              :                           0.0_dp, m_ST_out, &
    3016         1522 :                           filter_eps=filter_eps)
    3017              : 
    3018         1522 :       CALL dbcsr_release(m_tmp_no_1)
    3019         1522 :       CALL dbcsr_release(m_tmp_oo_1)
    3020              : 
    3021         1522 :       CALL timestop(handle)
    3022              : 
    3023         1522 :    END SUBROUTINE compute_frequently_used_matrices
    3024              : 
    3025              : ! **************************************************************************************************
    3026              : !> \brief Split the matrix of virtual orbitals into two:
    3027              : !>        retained orbs and discarded
    3028              : !> \param almo_scf_env ...
    3029              : !> \par History
    3030              : !>       2011.09 created [Rustam Z Khaliullin]
    3031              : !> \author Rustam Z Khaliullin
    3032              : ! **************************************************************************************************
    3033            0 :    SUBROUTINE split_v_blk(almo_scf_env)
    3034              : 
    3035              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
    3036              : 
    3037              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'split_v_blk'
    3038              : 
    3039              :       INTEGER                                            :: discarded_v, handle, iblock_col, &
    3040              :                                                             iblock_col_size, iblock_row, &
    3041              :                                                             iblock_row_size, ispin, retained_v
    3042            0 :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: data_p
    3043              :       TYPE(dbcsr_iterator_type)                          :: iter
    3044              : 
    3045            0 :       CALL timeset(routineN, handle)
    3046              : 
    3047            0 :       DO ispin = 1, almo_scf_env%nspins
    3048              : 
    3049              :          CALL dbcsr_work_create(almo_scf_env%matrix_v_blk(ispin), &
    3050            0 :                                 work_mutable=.TRUE.)
    3051              :          CALL dbcsr_work_create(almo_scf_env%matrix_v_disc_blk(ispin), &
    3052            0 :                                 work_mutable=.TRUE.)
    3053              : 
    3054            0 :          CALL dbcsr_iterator_start(iter, almo_scf_env%matrix_v_full_blk(ispin))
    3055              : 
    3056            0 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
    3057              : 
    3058              :             CALL dbcsr_iterator_next_block(iter, iblock_row, iblock_col, data_p, &
    3059            0 :                                            row_size=iblock_row_size, col_size=iblock_col_size)
    3060              : 
    3061            0 :             IF (iblock_row /= iblock_col) THEN
    3062            0 :                CPABORT("off-diagonal block found")
    3063              :             END IF
    3064              : 
    3065            0 :             retained_v = almo_scf_env%nvirt_of_domain(iblock_col, ispin)
    3066            0 :             discarded_v = almo_scf_env%nvirt_disc_of_domain(iblock_col, ispin)
    3067            0 :             CPASSERT(retained_v > 0)
    3068            0 :             CPASSERT(discarded_v > 0)
    3069              :             CALL dbcsr_put_block(almo_scf_env%matrix_v_disc_blk(ispin), iblock_row, iblock_col, &
    3070            0 :                                  block=data_p(:, (retained_v + 1):iblock_col_size))
    3071              :             CALL dbcsr_put_block(almo_scf_env%matrix_v_blk(ispin), iblock_row, iblock_col, &
    3072            0 :                                  block=data_p(:, 1:retained_v))
    3073              : 
    3074              :          END DO ! iterator
    3075            0 :          CALL dbcsr_iterator_stop(iter)
    3076              : 
    3077            0 :          CALL dbcsr_finalize(almo_scf_env%matrix_v_blk(ispin))
    3078            0 :          CALL dbcsr_finalize(almo_scf_env%matrix_v_disc_blk(ispin))
    3079              : 
    3080              :       END DO ! ispin
    3081              : 
    3082            0 :       CALL timestop(handle)
    3083              : 
    3084            0 :    END SUBROUTINE split_v_blk
    3085              : 
    3086              : ! **************************************************************************************************
    3087              : !> \brief various methods for calculating the Harris-Foulkes correction
    3088              : !> \param almo_scf_env ...
    3089              : !> \par History
    3090              : !>       2011.06 created [Rustam Z Khaliullin]
    3091              : !> \author Rustam Z Khaliullin
    3092              : ! **************************************************************************************************
    3093            0 :    SUBROUTINE harris_foulkes_correction(almo_scf_env)
    3094              : 
    3095              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
    3096              : 
    3097              :       CHARACTER(len=*), PARAMETER :: routineN = 'harris_foulkes_correction'
    3098              :       INTEGER, PARAMETER                                 :: cayley_transform = 1, dm_ls_step = 2
    3099              : 
    3100              :       INTEGER :: algorithm_id, handle, handle1, handle2, handle3, handle4, handle5, handle6, &
    3101              :          handle7, handle8, ispin, iteration, n, nmins, nspin, opt_k_max_iter, &
    3102              :          outer_opt_k_iteration, outer_opt_k_max_iter, unit_nr
    3103              :       INTEGER, DIMENSION(1)                              :: fake, nelectron_spin_real
    3104              :       LOGICAL :: converged, line_search, md_in_k_space, outer_opt_k_prepare_to_exit, &
    3105              :          prepare_to_exit, reset_conjugator, reset_step_size, use_cubic_approximation, &
    3106              :          use_quadratic_approximation
    3107              :       REAL(KIND=dp) :: aa, bb, beta, conjugacy_error, conjugacy_error_threshold, &
    3108              :          delta_obj_function, denom, energy_correction_final, frob_matrix, frob_matrix_base, fun0, &
    3109              :          fun1, gfun0, gfun1, grad_norm, grad_norm_frob, kappa, kin_energy, line_search_error, &
    3110              :          line_search_error_threshold, num_threshold, numer, obj_function, quadratic_approx_error, &
    3111              :          quadratic_approx_error_threshold, safety_multiplier, spin_factor, step_size, &
    3112              :          step_size_quadratic_approx, step_size_quadratic_approx2, t1, t1a, t1cholesky, t2, t2a, &
    3113              :          t2cholesky, tau, time_step, x_opt_eps_adaptive, x_opt_eps_adaptive_factor
    3114              :       REAL(KIND=dp), DIMENSION(1)                        :: local_mu
    3115              :       REAL(KIND=dp), DIMENSION(2)                        :: energy_correction
    3116              :       REAL(KIND=dp), DIMENSION(3)                        :: minima
    3117              :       TYPE(cp_logger_type), POINTER                      :: logger
    3118              :       TYPE(ct_step_env_type)                             :: ct_step_env
    3119              :       TYPE(dbcsr_type) :: grad, k_vd_index_down, k_vr_index_down, matrix_k_central, matrix_tmp1, &
    3120              :          matrix_tmp2, prec, prev_grad, prev_minus_prec_grad, prev_step, sigma_oo_curr, &
    3121              :          sigma_oo_curr_inv, sigma_vv_sqrt, sigma_vv_sqrt_guess, sigma_vv_sqrt_inv, &
    3122              :          sigma_vv_sqrt_inv_guess, step, t_curr, tmp1_n_vr, tmp2_n_o, tmp3_vd_vr, tmp4_o_vr, &
    3123              :          tmp_k_blk, vd_fixed, vd_index_sqrt, vd_index_sqrt_inv, velocity, vr_fixed, vr_index_sqrt, &
    3124              :          vr_index_sqrt_inv
    3125            0 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: matrix_p_almo_scf_converged
    3126              : 
    3127            0 :       CALL timeset(routineN, handle)
    3128              : 
    3129              :       ! get a useful output_unit
    3130            0 :       logger => cp_get_default_logger()
    3131            0 :       IF (logger%para_env%is_source()) THEN
    3132            0 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    3133              :       ELSE
    3134            0 :          unit_nr = -1
    3135              :       END IF
    3136              : 
    3137            0 :       nspin = almo_scf_env%nspins
    3138            0 :       energy_correction_final = 0.0_dp
    3139            0 :       IF (nspin == 1) THEN
    3140            0 :          spin_factor = 2.0_dp
    3141              :       ELSE
    3142            0 :          spin_factor = 1.0_dp
    3143              :       END IF
    3144              : 
    3145            0 :       IF (almo_scf_env%deloc_use_occ_orbs) THEN
    3146              :          algorithm_id = cayley_transform
    3147              :       ELSE
    3148            0 :          algorithm_id = dm_ls_step
    3149              :       END IF
    3150              : 
    3151            0 :       t1 = m_walltime()
    3152              : 
    3153            0 :       SELECT CASE (algorithm_id)
    3154              :       CASE (cayley_transform)
    3155              : 
    3156              :          ! rescale density matrix by spin factor
    3157              :          ! so the orbitals and density are consistent with each other
    3158            0 :          IF (almo_scf_env%nspins == 1) THEN
    3159            0 :             CALL dbcsr_scale(almo_scf_env%matrix_p(1), 1.0_dp/spin_factor)
    3160              :          END IF
    3161              : 
    3162              :          ! transform matrix_t not matrix_t_blk (we might need ALMOs later)
    3163            0 :          DO ispin = 1, nspin
    3164              : 
    3165              :             CALL dbcsr_copy(almo_scf_env%matrix_t(ispin), &
    3166            0 :                             almo_scf_env%matrix_t_blk(ispin))
    3167              : 
    3168              :             ! obtain orthogonalization matrices for ALMOs
    3169              :             ! RZK-warning - remove this sqrt(sigma) and inv(sqrt(sigma))
    3170              :             ! ideally ALMO scf should use sigma and sigma_inv in
    3171              :             ! the tensor_up_down representation
    3172              : 
    3173            0 :             IF (unit_nr > 0) THEN
    3174            0 :                WRITE (unit_nr, *) "sqrt and inv(sqrt) of MO overlap matrix"
    3175              :             END IF
    3176              :             CALL dbcsr_create(almo_scf_env%matrix_sigma_sqrt(ispin), &
    3177              :                               template=almo_scf_env%matrix_sigma(ispin), &
    3178            0 :                               matrix_type=dbcsr_type_no_symmetry)
    3179              :             CALL dbcsr_create(almo_scf_env%matrix_sigma_sqrt_inv(ispin), &
    3180              :                               template=almo_scf_env%matrix_sigma(ispin), &
    3181            0 :                               matrix_type=dbcsr_type_no_symmetry)
    3182              : 
    3183              :             CALL matrix_sqrt_Newton_Schulz(almo_scf_env%matrix_sigma_sqrt(ispin), &
    3184              :                                            almo_scf_env%matrix_sigma_sqrt_inv(ispin), &
    3185              :                                            almo_scf_env%matrix_sigma(ispin), &
    3186              :                                            threshold=almo_scf_env%eps_filter, &
    3187              :                                            order=almo_scf_env%order_lanczos, &
    3188              :                                            eps_lanczos=almo_scf_env%eps_lanczos, &
    3189            0 :                                            max_iter_lanczos=almo_scf_env%max_iter_lanczos)
    3190              : 
    3191            0 :             IF (safe_mode) THEN
    3192              :                CALL dbcsr_create(matrix_tmp1, template=almo_scf_env%matrix_sigma(ispin), &
    3193              :                                  matrix_type=dbcsr_type_no_symmetry)
    3194              :                CALL dbcsr_create(matrix_tmp2, template=almo_scf_env%matrix_sigma(ispin), &
    3195              :                                  matrix_type=dbcsr_type_no_symmetry)
    3196              : 
    3197              :                CALL dbcsr_multiply("N", "N", 1.0_dp, almo_scf_env%matrix_sigma_sqrt_inv(ispin), &
    3198              :                                    almo_scf_env%matrix_sigma(ispin), &
    3199              :                                    0.0_dp, matrix_tmp1, filter_eps=almo_scf_env%eps_filter)
    3200              :                CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, &
    3201              :                                    almo_scf_env%matrix_sigma_sqrt_inv(ispin), &
    3202              :                                    0.0_dp, matrix_tmp2, filter_eps=almo_scf_env%eps_filter)
    3203              : 
    3204              :                frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp2)
    3205              :                CALL dbcsr_add_on_diag(matrix_tmp2, -1.0_dp)
    3206              :                frob_matrix = dbcsr_frobenius_norm(matrix_tmp2)
    3207              :                IF (unit_nr > 0) THEN
    3208              :                   WRITE (unit_nr, *) "Error for (inv(sqrt(SIG))*SIG*inv(sqrt(SIG))-I)", frob_matrix/frob_matrix_base
    3209              :                END IF
    3210              : 
    3211              :                CALL dbcsr_release(matrix_tmp1)
    3212              :                CALL dbcsr_release(matrix_tmp2)
    3213              :             END IF
    3214              :          END DO
    3215              : 
    3216            0 :          IF (almo_scf_env%almo_update_algorithm == almo_scf_diag) THEN
    3217              : 
    3218            0 :             DO ispin = 1, nspin
    3219              : 
    3220            0 :                t1a = m_walltime()
    3221              : 
    3222            0 :                line_search_error_threshold = almo_scf_env%real01
    3223            0 :                conjugacy_error_threshold = almo_scf_env%real02
    3224            0 :                quadratic_approx_error_threshold = almo_scf_env%real03
    3225            0 :                x_opt_eps_adaptive_factor = almo_scf_env%real04
    3226              : 
    3227              :                !! the outer loop for k optimization
    3228            0 :                outer_opt_k_max_iter = almo_scf_env%opt_k_outer_max_iter
    3229            0 :                outer_opt_k_prepare_to_exit = .FALSE.
    3230            0 :                outer_opt_k_iteration = 0
    3231            0 :                grad_norm = 0.0_dp
    3232            0 :                grad_norm_frob = 0.0_dp
    3233            0 :                CALL dbcsr_set(almo_scf_env%matrix_x(ispin), 0.0_dp)
    3234            0 :                IF (almo_scf_env%deloc_truncate_virt == virt_full) outer_opt_k_max_iter = 0
    3235              : 
    3236            0 :                DO
    3237              : 
    3238              :                   ! obtain proper retained virtuals (1-R)|ALMO_vr>
    3239              :                   CALL apply_projector(psi_in=almo_scf_env%matrix_v_blk(ispin), &
    3240              :                                        psi_out=almo_scf_env%matrix_v(ispin), &
    3241              :                                        psi_projector=almo_scf_env%matrix_t_blk(ispin), &
    3242              :                                        metric=almo_scf_env%matrix_s(1), &
    3243              :                                        project_out=.TRUE., &
    3244              :                                        psi_projector_orthogonal=.FALSE., &
    3245              :                                        proj_in_template=almo_scf_env%matrix_ov(ispin), &
    3246              :                                        eps_filter=almo_scf_env%eps_filter, &
    3247            0 :                                        sig_inv_projector=almo_scf_env%matrix_sigma_inv(ispin))
    3248              : 
    3249              :                   ! save initial retained virtuals
    3250              :                   CALL dbcsr_create(vr_fixed, &
    3251            0 :                                     template=almo_scf_env%matrix_v(ispin))
    3252            0 :                   CALL dbcsr_copy(vr_fixed, almo_scf_env%matrix_v(ispin))
    3253              : 
    3254              :                   ! init matrices common for optimized and non-optimized virts
    3255              :                   CALL dbcsr_create(sigma_vv_sqrt, &
    3256              :                                     template=almo_scf_env%matrix_sigma_vv(ispin), &
    3257            0 :                                     matrix_type=dbcsr_type_no_symmetry)
    3258              :                   CALL dbcsr_create(sigma_vv_sqrt_inv, &
    3259              :                                     template=almo_scf_env%matrix_sigma_vv(ispin), &
    3260            0 :                                     matrix_type=dbcsr_type_no_symmetry)
    3261              :                   CALL dbcsr_create(sigma_vv_sqrt_inv_guess, &
    3262              :                                     template=almo_scf_env%matrix_sigma_vv(ispin), &
    3263            0 :                                     matrix_type=dbcsr_type_no_symmetry)
    3264              :                   CALL dbcsr_create(sigma_vv_sqrt_guess, &
    3265              :                                     template=almo_scf_env%matrix_sigma_vv(ispin), &
    3266            0 :                                     matrix_type=dbcsr_type_no_symmetry)
    3267            0 :                   CALL dbcsr_set(sigma_vv_sqrt_guess, 0.0_dp)
    3268            0 :                   CALL dbcsr_add_on_diag(sigma_vv_sqrt_guess, 1.0_dp)
    3269            0 :                   CALL dbcsr_filter(sigma_vv_sqrt_guess, almo_scf_env%eps_filter)
    3270            0 :                   CALL dbcsr_set(sigma_vv_sqrt_inv_guess, 0.0_dp)
    3271            0 :                   CALL dbcsr_add_on_diag(sigma_vv_sqrt_inv_guess, 1.0_dp)
    3272            0 :                   CALL dbcsr_filter(sigma_vv_sqrt_inv_guess, almo_scf_env%eps_filter)
    3273              : 
    3274              :                   ! do things required to optimize virtuals
    3275            0 :                   IF (almo_scf_env%deloc_truncate_virt /= virt_full) THEN
    3276              : 
    3277              :                      ! project retained virtuals out of discarded block-by-block
    3278              :                      ! (1-Q^VR_ALMO)|ALMO_vd>
    3279              :                      ! this is probably not necessary, do it just to be safe
    3280              : 
    3281              :                      ! construct discarded virtuals (1-R)|ALMO_vd>
    3282              :                      CALL apply_projector(psi_in=almo_scf_env%matrix_v_disc_blk(ispin), &
    3283              :                                           psi_out=almo_scf_env%matrix_v_disc(ispin), &
    3284              :                                           psi_projector=almo_scf_env%matrix_t_blk(ispin), &
    3285              :                                           metric=almo_scf_env%matrix_s(1), &
    3286              :                                           project_out=.TRUE., &
    3287              :                                           psi_projector_orthogonal=.FALSE., &
    3288              :                                           proj_in_template=almo_scf_env%matrix_ov_disc(ispin), &
    3289              :                                           eps_filter=almo_scf_env%eps_filter, &
    3290            0 :                                           sig_inv_projector=almo_scf_env%matrix_sigma_inv(ispin))
    3291              :                      !sig_inv_template=almo_scf_env%matrix_sigma_inv(ispin),&
    3292              : 
    3293              :                      ! save initial discarded
    3294              :                      CALL dbcsr_create(vd_fixed, &
    3295            0 :                                        template=almo_scf_env%matrix_v_disc(ispin))
    3296            0 :                      CALL dbcsr_copy(vd_fixed, almo_scf_env%matrix_v_disc(ispin))
    3297              : 
    3298              :                      !! create the down metric in the retained k-subspace
    3299              :                      CALL dbcsr_create(k_vr_index_down, &
    3300              :                                        template=almo_scf_env%matrix_sigma_vv_blk(ispin), &
    3301            0 :                                        matrix_type=dbcsr_type_no_symmetry)
    3302              : 
    3303              :                      !! create the up metric in the discarded k-subspace
    3304              :                      CALL dbcsr_create(k_vd_index_down, &
    3305              :                                        template=almo_scf_env%matrix_vv_disc_blk(ispin), &
    3306            0 :                                        matrix_type=dbcsr_type_no_symmetry)
    3307              : 
    3308              :                      ! init matrices necessary for optimization of truncated virts
    3309              :                      ! init blocked gradient before setting K to zero
    3310              :                      ! otherwise the block structure might be lost
    3311              :                      CALL dbcsr_create(grad, &
    3312            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3313            0 :                      CALL dbcsr_copy(grad, almo_scf_env%matrix_k_blk(ispin))
    3314              : 
    3315              :                      ! init MD in the k-space
    3316            0 :                      md_in_k_space = almo_scf_env%logical01
    3317            0 :                      IF (md_in_k_space) THEN
    3318              :                         CALL dbcsr_create(velocity, &
    3319            0 :                                           template=almo_scf_env%matrix_k_blk(ispin))
    3320            0 :                         CALL dbcsr_copy(velocity, almo_scf_env%matrix_k_blk(ispin))
    3321            0 :                         CALL dbcsr_set(velocity, 0.0_dp)
    3322            0 :                         time_step = almo_scf_env%opt_k_trial_step_size
    3323              :                      END IF
    3324              : 
    3325              :                      CALL dbcsr_create(prev_step, &
    3326            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3327              : 
    3328              :                      CALL dbcsr_create(prev_minus_prec_grad, &
    3329            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3330              : 
    3331              :                      ! initialize diagonal blocks of the preconditioner to 1.0_dp
    3332              :                      CALL dbcsr_create(prec, &
    3333            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3334            0 :                      CALL dbcsr_copy(prec, almo_scf_env%matrix_k_blk(ispin))
    3335            0 :                      CALL dbcsr_set(prec, 1.0_dp)
    3336              : 
    3337              :                      ! generate initial K (extrapolate if previous values are available)
    3338            0 :                      CALL dbcsr_set(almo_scf_env%matrix_k_blk(ispin), 0.0_dp)
    3339              :                      ! matrix_k_central stores current k because matrix_k_blk is updated
    3340              :                      ! during linear search
    3341              :                      CALL dbcsr_create(matrix_k_central, &
    3342            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3343              :                      CALL dbcsr_copy(matrix_k_central, &
    3344            0 :                                      almo_scf_env%matrix_k_blk(ispin))
    3345              :                      CALL dbcsr_create(tmp_k_blk, &
    3346            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3347              :                      CALL dbcsr_create(step, &
    3348            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3349            0 :                      CALL dbcsr_set(step, 0.0_dp)
    3350              :                      CALL dbcsr_create(t_curr, &
    3351            0 :                                        template=almo_scf_env%matrix_t(ispin))
    3352              :                      CALL dbcsr_create(sigma_oo_curr, &
    3353              :                                        template=almo_scf_env%matrix_sigma(ispin), &
    3354            0 :                                        matrix_type=dbcsr_type_no_symmetry)
    3355              :                      CALL dbcsr_create(sigma_oo_curr_inv, &
    3356              :                                        template=almo_scf_env%matrix_sigma(ispin), &
    3357            0 :                                        matrix_type=dbcsr_type_no_symmetry)
    3358              :                      CALL dbcsr_create(tmp1_n_vr, &
    3359            0 :                                        template=almo_scf_env%matrix_v(ispin))
    3360              :                      CALL dbcsr_create(tmp3_vd_vr, &
    3361            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3362              :                      CALL dbcsr_create(tmp2_n_o, &
    3363            0 :                                        template=almo_scf_env%matrix_t(ispin))
    3364              :                      CALL dbcsr_create(tmp4_o_vr, &
    3365            0 :                                        template=almo_scf_env%matrix_ov(ispin))
    3366              :                      CALL dbcsr_create(prev_grad, &
    3367            0 :                                        template=almo_scf_env%matrix_k_blk(ispin))
    3368            0 :                      CALL dbcsr_set(prev_grad, 0.0_dp)
    3369              : 
    3370              :                   END IF ! done constructing discarded virtuals
    3371              : 
    3372              :                   ! init variables
    3373            0 :                   opt_k_max_iter = almo_scf_env%opt_k_max_iter
    3374            0 :                   iteration = 0
    3375            0 :                   converged = .FALSE.
    3376            0 :                   prepare_to_exit = .FALSE.
    3377            0 :                   beta = 0.0_dp
    3378            0 :                   line_search = .FALSE.
    3379            0 :                   obj_function = 0.0_dp
    3380            0 :                   conjugacy_error = 0.0_dp
    3381            0 :                   line_search_error = 0.0_dp
    3382            0 :                   fun0 = 0.0_dp
    3383            0 :                   fun1 = 0.0_dp
    3384            0 :                   gfun0 = 0.0_dp
    3385            0 :                   gfun1 = 0.0_dp
    3386            0 :                   step_size_quadratic_approx = 0.0_dp
    3387            0 :                   reset_step_size = .TRUE.
    3388            0 :                   IF (almo_scf_env%deloc_truncate_virt == virt_full) opt_k_max_iter = 0
    3389              : 
    3390              :                   ! start cg iterations to optimize matrix_k_blk
    3391            0 :                   DO
    3392              : 
    3393            0 :                      CALL timeset('k_opt_vr', handle1)
    3394              : 
    3395            0 :                      IF (almo_scf_env%deloc_truncate_virt /= virt_full) THEN
    3396              : 
    3397              :                         ! construct k-excited virtuals
    3398              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, vd_fixed, &
    3399              :                                             almo_scf_env%matrix_k_blk(ispin), &
    3400              :                                             0.0_dp, almo_scf_env%matrix_v(ispin), &
    3401            0 :                                             filter_eps=almo_scf_env%eps_filter)
    3402              :                         CALL dbcsr_add(almo_scf_env%matrix_v(ispin), vr_fixed, &
    3403            0 :                                        +1.0_dp, +1.0_dp)
    3404              :                      END IF
    3405              : 
    3406              :                      ! decompose the overlap matrix of the current retained orbitals
    3407              :                      CALL get_overlap(bra=almo_scf_env%matrix_v(ispin), &
    3408              :                                       ket=almo_scf_env%matrix_v(ispin), &
    3409              :                                       overlap=almo_scf_env%matrix_sigma_vv(ispin), &
    3410              :                                       metric=almo_scf_env%matrix_s(1), &
    3411              :                                       retain_overlap_sparsity=.FALSE., &
    3412            0 :                                       eps_filter=almo_scf_env%eps_filter)
    3413              :                      ! use either cholesky or sqrt
    3414              :                      !! RZK-warning: strangely, cholesky does not work with k-optimization
    3415            0 :                      IF (almo_scf_env%deloc_truncate_virt == virt_full) THEN
    3416            0 :                         CALL timeset('cholesky', handle2)
    3417            0 :                         t1cholesky = m_walltime()
    3418              : 
    3419              :                         ! re-create sigma_vv_sqrt because desymmetrize is buggy -
    3420              :                         ! it will create multiple copies of blocks
    3421              :                         CALL dbcsr_create(sigma_vv_sqrt, &
    3422              :                                           template=almo_scf_env%matrix_sigma_vv(ispin), &
    3423            0 :                                           matrix_type=dbcsr_type_no_symmetry)
    3424              :                         CALL dbcsr_desymmetrize(almo_scf_env%matrix_sigma_vv(ispin), &
    3425            0 :                                                 sigma_vv_sqrt)
    3426              :                         CALL cp_dbcsr_cholesky_decompose(sigma_vv_sqrt, &
    3427              :                                                          para_env=almo_scf_env%para_env, &
    3428            0 :                                                          blacs_env=almo_scf_env%blacs_env)
    3429            0 :                         CALL make_triu(sigma_vv_sqrt)
    3430            0 :                         CALL dbcsr_filter(sigma_vv_sqrt, almo_scf_env%eps_filter)
    3431              :                         ! apply SOLVE to compute U^(-1) : U*U^(-1)=I
    3432            0 :                         CALL dbcsr_get_info(sigma_vv_sqrt, nfullrows_total=n)
    3433              :                         CALL dbcsr_create(matrix_tmp1, template=almo_scf_env%matrix_sigma_vv(ispin), &
    3434            0 :                                           matrix_type=dbcsr_type_no_symmetry)
    3435            0 :                         CALL dbcsr_set(matrix_tmp1, 0.0_dp)
    3436            0 :                         CALL dbcsr_add_on_diag(matrix_tmp1, 1.0_dp)
    3437              :                         CALL cp_dbcsr_cholesky_restore(matrix_tmp1, n, sigma_vv_sqrt, &
    3438              :                                                        sigma_vv_sqrt_inv, op="SOLVE", pos="RIGHT", &
    3439              :                                                        para_env=almo_scf_env%para_env, &
    3440            0 :                                                        blacs_env=almo_scf_env%blacs_env)
    3441            0 :                         CALL dbcsr_filter(sigma_vv_sqrt_inv, almo_scf_env%eps_filter)
    3442            0 :                         CALL dbcsr_release(matrix_tmp1)
    3443              :                         IF (safe_mode) THEN
    3444              :                            CALL dbcsr_create(matrix_tmp1, template=almo_scf_env%matrix_sigma_vv(ispin), &
    3445              :                                              matrix_type=dbcsr_type_no_symmetry)
    3446              :                            CALL dbcsr_desymmetrize(almo_scf_env%matrix_sigma_vv(ispin), &
    3447              :                                                    matrix_tmp1)
    3448              :                            CALL dbcsr_multiply("T", "N", 1.0_dp, sigma_vv_sqrt, &
    3449              :                                                sigma_vv_sqrt, &
    3450              :                                                -1.0_dp, matrix_tmp1, filter_eps=almo_scf_env%eps_filter)
    3451              :                            frob_matrix = dbcsr_frobenius_norm(matrix_tmp1)
    3452              :                            CALL dbcsr_add_on_diag(matrix_tmp1, 1.0_dp)
    3453              :                            frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp1)
    3454              :                            IF (unit_nr > 0) THEN
    3455              :                               WRITE (unit_nr, *) "Error for ( U^T * U - Sig )", &
    3456              :                                  frob_matrix/frob_matrix_base
    3457              :                            END IF
    3458              :                            CALL dbcsr_multiply("N", "N", 1.0_dp, sigma_vv_sqrt_inv, &
    3459              :                                                sigma_vv_sqrt, &
    3460              :                                                0.0_dp, matrix_tmp1, filter_eps=almo_scf_env%eps_filter)
    3461              :                            frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp1)
    3462              :                            CALL dbcsr_add_on_diag(matrix_tmp1, -1.0_dp)
    3463              :                            frob_matrix = dbcsr_frobenius_norm(matrix_tmp1)
    3464              :                            IF (unit_nr > 0) THEN
    3465              :                               WRITE (unit_nr, *) "Error for ( inv(U) * U - I )", &
    3466              :                                  frob_matrix/frob_matrix_base
    3467              :                            END IF
    3468              :                            CALL dbcsr_release(matrix_tmp1)
    3469              :                         END IF ! safe_mode
    3470            0 :                         t2cholesky = m_walltime()
    3471            0 :                         IF (unit_nr > 0) THEN
    3472            0 :                            WRITE (unit_nr, *) "Cholesky+inverse wall-time: ", t2cholesky - t1cholesky
    3473              :                         END IF
    3474            0 :                         CALL timestop(handle2)
    3475              :                      ELSE
    3476              :                         CALL matrix_sqrt_Newton_Schulz(sigma_vv_sqrt, &
    3477              :                                                        sigma_vv_sqrt_inv, &
    3478              :                                                        almo_scf_env%matrix_sigma_vv(ispin), &
    3479              :                                                        threshold=almo_scf_env%eps_filter, &
    3480              :                                                        order=almo_scf_env%order_lanczos, &
    3481              :                                                        eps_lanczos=almo_scf_env%eps_lanczos, &
    3482            0 :                                                        max_iter_lanczos=almo_scf_env%max_iter_lanczos)
    3483            0 :                         CALL dbcsr_copy(sigma_vv_sqrt_inv_guess, sigma_vv_sqrt_inv)
    3484            0 :                         CALL dbcsr_copy(sigma_vv_sqrt_guess, sigma_vv_sqrt)
    3485              :                         IF (safe_mode) THEN
    3486              :                            CALL dbcsr_create(matrix_tmp1, template=almo_scf_env%matrix_sigma_vv(ispin), &
    3487              :                                              matrix_type=dbcsr_type_no_symmetry)
    3488              :                            CALL dbcsr_create(matrix_tmp2, template=almo_scf_env%matrix_sigma_vv(ispin), &
    3489              :                                              matrix_type=dbcsr_type_no_symmetry)
    3490              : 
    3491              :                            CALL dbcsr_multiply("N", "N", 1.0_dp, sigma_vv_sqrt_inv, &
    3492              :                                                almo_scf_env%matrix_sigma_vv(ispin), &
    3493              :                                                0.0_dp, matrix_tmp1, filter_eps=almo_scf_env%eps_filter)
    3494              :                            CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, &
    3495              :                                                sigma_vv_sqrt_inv, &
    3496              :                                                0.0_dp, matrix_tmp2, filter_eps=almo_scf_env%eps_filter)
    3497              : 
    3498              :                            frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp2)
    3499              :                            CALL dbcsr_add_on_diag(matrix_tmp2, -1.0_dp)
    3500              :                            frob_matrix = dbcsr_frobenius_norm(matrix_tmp2)
    3501              :                            IF (unit_nr > 0) THEN
    3502              :                               WRITE (unit_nr, *) "Error for (inv(sqrt(SIGVV))*SIGVV*inv(sqrt(SIGVV))-I)", &
    3503              :                                  frob_matrix/frob_matrix_base
    3504              :                            END IF
    3505              : 
    3506              :                            CALL dbcsr_release(matrix_tmp1)
    3507              :                            CALL dbcsr_release(matrix_tmp2)
    3508              :                         END IF
    3509              :                      END IF
    3510            0 :                      CALL timestop(handle1)
    3511              : 
    3512              :                      ! compute excitation amplitudes (to the current set of retained virtuals)
    3513              :                      ! set convergence criterion for x-optimization
    3514            0 :                      IF ((iteration == 0) .AND. (.NOT. line_search) .AND. &
    3515              :                          (outer_opt_k_iteration == 0)) THEN
    3516              :                         x_opt_eps_adaptive = &
    3517            0 :                            almo_scf_env%deloc_cayley_eps_convergence
    3518              :                      ELSE
    3519              :                         x_opt_eps_adaptive = &
    3520              :                            MAX(ABS(almo_scf_env%deloc_cayley_eps_convergence), &
    3521            0 :                                ABS(x_opt_eps_adaptive_factor*grad_norm))
    3522              :                      END IF
    3523            0 :                      CALL ct_step_env_init(ct_step_env)
    3524              :                      CALL ct_step_env_set(ct_step_env, &
    3525              :                                           para_env=almo_scf_env%para_env, &
    3526              :                                           blacs_env=almo_scf_env%blacs_env, &
    3527              :                                           use_occ_orbs=.TRUE., &
    3528              :                                           use_virt_orbs=.TRUE., &
    3529              :                                           occ_orbs_orthogonal=.FALSE., &
    3530              :                                           virt_orbs_orthogonal=.FALSE., &
    3531              :                                           pp_preconditioner_full=almo_scf_env%deloc_cayley_occ_precond, &
    3532              :                                           qq_preconditioner_full=almo_scf_env%deloc_cayley_vir_precond, &
    3533              :                                           tensor_type=almo_scf_env%deloc_cayley_tensor_type, &
    3534              :                                           neglect_quadratic_term=almo_scf_env%deloc_cayley_linear, &
    3535              :                                           conjugator=almo_scf_env%deloc_cayley_conjugator, &
    3536              :                                           max_iter=almo_scf_env%deloc_cayley_max_iter, &
    3537              :                                           calculate_energy_corr=.TRUE., &
    3538              :                                           update_p=.FALSE., &
    3539              :                                           update_q=.FALSE., &
    3540              :                                           eps_convergence=x_opt_eps_adaptive, &
    3541              :                                           eps_filter=almo_scf_env%eps_filter, &
    3542              :                                           !nspins=1,&
    3543              :                                           q_index_up=sigma_vv_sqrt_inv, &
    3544              :                                           q_index_down=sigma_vv_sqrt, &
    3545              :                                           p_index_up=almo_scf_env%matrix_sigma_sqrt_inv(ispin), &
    3546              :                                           p_index_down=almo_scf_env%matrix_sigma_sqrt(ispin), &
    3547              :                                           matrix_ks=almo_scf_env%matrix_ks_0deloc(ispin), &
    3548              :                                           matrix_t=almo_scf_env%matrix_t(ispin), &
    3549              :                                           matrix_qp_template=almo_scf_env%matrix_vo(ispin), &
    3550              :                                           matrix_pq_template=almo_scf_env%matrix_ov(ispin), &
    3551              :                                           matrix_v=almo_scf_env%matrix_v(ispin), &
    3552            0 :                                           matrix_x_guess=almo_scf_env%matrix_x(ispin))
    3553              :                      ! perform calculations
    3554            0 :                      CALL ct_step_execute(ct_step_env)
    3555              :                      ! get the energy correction
    3556              :                      CALL ct_step_env_get(ct_step_env, &
    3557              :                                           energy_correction=energy_correction(ispin), &
    3558            0 :                                           copy_matrix_x=almo_scf_env%matrix_x(ispin))
    3559            0 :                      CALL ct_step_env_clean(ct_step_env)
    3560              :                      ! RZK-warning matrix_x is being transformed
    3561              :                      ! back and forth between orth and up_down representations
    3562            0 :                      energy_correction(1) = energy_correction(1)*spin_factor
    3563              : 
    3564            0 :                      IF (opt_k_max_iter /= 0) THEN
    3565              : 
    3566            0 :                         CALL timeset('k_opt_t_curr', handle3)
    3567              : 
    3568              :                         ! construct current occupied orbitals T_blk + V_r*X
    3569              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, &
    3570              :                                             almo_scf_env%matrix_v(ispin), &
    3571              :                                             almo_scf_env%matrix_x(ispin), &
    3572              :                                             0.0_dp, t_curr, &
    3573            0 :                                             filter_eps=almo_scf_env%eps_filter)
    3574              :                         CALL dbcsr_add(t_curr, almo_scf_env%matrix_t_blk(ispin), &
    3575            0 :                                        +1.0_dp, +1.0_dp)
    3576              : 
    3577              :                         ! calculate current occupied overlap
    3578              :                         CALL get_overlap(bra=t_curr, &
    3579              :                                          ket=t_curr, &
    3580              :                                          overlap=sigma_oo_curr, &
    3581              :                                          metric=almo_scf_env%matrix_s(1), &
    3582              :                                          retain_overlap_sparsity=.FALSE., &
    3583            0 :                                          eps_filter=almo_scf_env%eps_filter)
    3584            0 :                         IF (iteration == 0) THEN
    3585              :                            CALL invert_Hotelling(sigma_oo_curr_inv, &
    3586              :                                                  sigma_oo_curr, &
    3587              :                                                  threshold=almo_scf_env%eps_filter, &
    3588            0 :                                                  use_inv_as_guess=.FALSE.)
    3589              :                         ELSE
    3590              :                            CALL invert_Hotelling(sigma_oo_curr_inv, &
    3591              :                                                  sigma_oo_curr, &
    3592              :                                                  threshold=almo_scf_env%eps_filter, &
    3593            0 :                                                  use_inv_as_guess=.TRUE.)
    3594              :                         END IF
    3595              :                         IF (safe_mode) THEN
    3596              :                            CALL dbcsr_create(matrix_tmp1, template=sigma_oo_curr, &
    3597              :                                              matrix_type=dbcsr_type_no_symmetry)
    3598              :                            CALL dbcsr_multiply("N", "N", 1.0_dp, sigma_oo_curr, &
    3599              :                                                sigma_oo_curr_inv, &
    3600              :                                                0.0_dp, matrix_tmp1, &
    3601              :                                                filter_eps=almo_scf_env%eps_filter)
    3602              :                            frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp1)
    3603              :                            CALL dbcsr_add_on_diag(matrix_tmp1, -1.0_dp)
    3604              :                            frob_matrix = dbcsr_frobenius_norm(matrix_tmp1)
    3605              :                            IF (unit_nr > 0) THEN
    3606              :                               WRITE (unit_nr, *) "Error for (SIG*inv(SIG)-I)", &
    3607              :                                  frob_matrix/frob_matrix_base, frob_matrix_base
    3608              :                            END IF
    3609              :                            CALL dbcsr_release(matrix_tmp1)
    3610              :                         END IF
    3611              :                         IF (safe_mode) THEN
    3612              :                            CALL dbcsr_create(matrix_tmp1, template=sigma_oo_curr, &
    3613              :                                              matrix_type=dbcsr_type_no_symmetry)
    3614              :                            CALL dbcsr_multiply("N", "N", 1.0_dp, sigma_oo_curr_inv, &
    3615              :                                                sigma_oo_curr, &
    3616              :                                                0.0_dp, matrix_tmp1, &
    3617              :                                                filter_eps=almo_scf_env%eps_filter)
    3618              :                            frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp1)
    3619              :                            CALL dbcsr_add_on_diag(matrix_tmp1, -1.0_dp)
    3620              :                            frob_matrix = dbcsr_frobenius_norm(matrix_tmp1)
    3621              :                            IF (unit_nr > 0) THEN
    3622              :                               WRITE (unit_nr, *) "Error for (inv(SIG)*SIG-I)", &
    3623              :                                  frob_matrix/frob_matrix_base, frob_matrix_base
    3624              :                            END IF
    3625              :                            CALL dbcsr_release(matrix_tmp1)
    3626              :                         END IF
    3627              : 
    3628            0 :                         CALL timestop(handle3)
    3629            0 :                         CALL timeset('k_opt_vd', handle4)
    3630              : 
    3631              :                         ! construct current discarded virtuals:
    3632              :                         ! (1-R_curr)(1-Q^VR_curr)|ALMO_vd_basis> =
    3633              :                         ! = (1-Q^VR_curr)|ALMO_vd_basis>
    3634              :                         ! use sigma_vv_sqrt to store the inverse of the overlap
    3635              :                         ! sigma_vv_inv is computed from sqrt/cholesky
    3636              :                         CALL dbcsr_multiply("N", "T", 1.0_dp, &
    3637              :                                             sigma_vv_sqrt_inv, &
    3638              :                                             sigma_vv_sqrt_inv, &
    3639              :                                             0.0_dp, sigma_vv_sqrt, &
    3640            0 :                                             filter_eps=almo_scf_env%eps_filter)
    3641              :                         CALL apply_projector(psi_in=almo_scf_env%matrix_v_disc_blk(ispin), &
    3642              :                                              psi_out=almo_scf_env%matrix_v_disc(ispin), &
    3643              :                                              psi_projector=almo_scf_env%matrix_v(ispin), &
    3644              :                                              metric=almo_scf_env%matrix_s(1), &
    3645              :                                              project_out=.FALSE., &
    3646              :                                              psi_projector_orthogonal=.FALSE., &
    3647              :                                              proj_in_template=almo_scf_env%matrix_k_tr(ispin), &
    3648              :                                              eps_filter=almo_scf_env%eps_filter, &
    3649            0 :                                              sig_inv_projector=sigma_vv_sqrt)
    3650              :                         !sig_inv_template=almo_scf_env%matrix_sigma_vv(ispin),&
    3651              :                         CALL dbcsr_add(almo_scf_env%matrix_v_disc(ispin), &
    3652            0 :                                        vd_fixed, -1.0_dp, +1.0_dp)
    3653              : 
    3654            0 :                         CALL timestop(handle4)
    3655            0 :                         CALL timeset('k_opt_grad', handle5)
    3656              : 
    3657              :                         ! evaluate the gradient from the assembled components
    3658              :                         ! grad_xx = c0 [ (Vd_curr^tr)*F*T_curr*sigma_oo_curr_inv*(X^tr)]_xx
    3659              :                         ! save previous gradient to calculate conjugation coef
    3660            0 :                         IF (line_search) THEN
    3661            0 :                            CALL dbcsr_copy(prev_grad, grad)
    3662              :                         END IF
    3663              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, &
    3664              :                                             almo_scf_env%matrix_ks_0deloc(ispin), &
    3665              :                                             t_curr, &
    3666              :                                             0.0_dp, tmp2_n_o, &
    3667            0 :                                             filter_eps=almo_scf_env%eps_filter)
    3668              :                         CALL dbcsr_multiply("N", "T", 1.0_dp, &
    3669              :                                             sigma_oo_curr_inv, &
    3670              :                                             almo_scf_env%matrix_x(ispin), &
    3671              :                                             0.0_dp, tmp4_o_vr, &
    3672            0 :                                             filter_eps=almo_scf_env%eps_filter)
    3673              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, &
    3674              :                                             tmp2_n_o, &
    3675              :                                             tmp4_o_vr, &
    3676              :                                             0.0_dp, tmp1_n_vr, &
    3677            0 :                                             filter_eps=almo_scf_env%eps_filter)
    3678              :                         CALL dbcsr_multiply("T", "N", 2.0_dp*spin_factor, &
    3679              :                                             almo_scf_env%matrix_v_disc(ispin), &
    3680              :                                             tmp1_n_vr, &
    3681              :                                             0.0_dp, grad, &
    3682            0 :                                             retain_sparsity=.TRUE.)
    3683              :                         ! keep tmp2_n_o for the next step
    3684              :                         ! keep tmp4_o_vr for the preconditioner
    3685              : 
    3686              :                         ! check convergence and other exit criteria
    3687            0 :                         grad_norm_frob = dbcsr_frobenius_norm(grad)
    3688            0 :                         grad_norm = dbcsr_maxabs(grad)
    3689            0 :                         converged = (grad_norm < almo_scf_env%opt_k_eps_convergence)
    3690            0 :                         IF (converged .OR. (iteration >= opt_k_max_iter)) THEN
    3691            0 :                            prepare_to_exit = .TRUE.
    3692              :                         END IF
    3693            0 :                         CALL timestop(handle5)
    3694              : 
    3695            0 :                         IF (.NOT. prepare_to_exit) THEN
    3696              : 
    3697            0 :                            CALL timeset('k_opt_energy', handle6)
    3698              : 
    3699              :                            ! compute "energy" c0*Tr[sig_inv_oo*t*F*t]
    3700              :                            CALL dbcsr_multiply("T", "N", spin_factor, &
    3701              :                                                t_curr, &
    3702              :                                                tmp2_n_o, &
    3703              :                                                0.0_dp, sigma_oo_curr, &
    3704            0 :                                                filter_eps=almo_scf_env%eps_filter)
    3705              :                            delta_obj_function = fun0
    3706            0 :                            CALL dbcsr_dot(sigma_oo_curr_inv, sigma_oo_curr, obj_function)
    3707            0 :                            delta_obj_function = obj_function - delta_obj_function
    3708            0 :                            IF (line_search) THEN
    3709              :                               fun1 = obj_function
    3710              :                            ELSE
    3711            0 :                               fun0 = obj_function
    3712              :                            END IF
    3713              : 
    3714            0 :                            CALL timestop(handle6)
    3715              : 
    3716              :                            ! update the step direction
    3717            0 :                            IF (.NOT. line_search) THEN
    3718              : 
    3719            0 :                               CALL timeset('k_opt_step', handle7)
    3720              : 
    3721            0 :                               IF ((.NOT. md_in_k_space) .AND. &
    3722              :                                   (iteration >= MAX(0, almo_scf_env%opt_k_prec_iter_start) .AND. &
    3723              :                                    MOD(iteration - almo_scf_env%opt_k_prec_iter_start, &
    3724              :                                        almo_scf_env%opt_k_prec_iter_freq) == 0)) THEN
    3725              : 
    3726              :                                  !IF ((iteration.eq.0).AND.(.NOT.md_in_k_space)) THEN
    3727              : 
    3728              :                                  ! compute the preconditioner
    3729            0 :                                  IF (unit_nr > 0) THEN
    3730            0 :                                     WRITE (unit_nr, *) "Computing preconditioner"
    3731              :                                  END IF
    3732              :                                  CALL opt_k_create_preconditioner_blk(almo_scf_env, &
    3733              :                                                                       almo_scf_env%matrix_v_disc(ispin), &
    3734              :                                                                       tmp4_o_vr, &
    3735              :                                                                       t_curr, &
    3736              :                                                                       ispin, &
    3737            0 :                                                                       spin_factor)
    3738              : 
    3739              :                               END IF
    3740              : 
    3741              :                               ! save the previous step
    3742            0 :                               CALL dbcsr_copy(prev_step, step)
    3743              : 
    3744              :                               ! compute the new step
    3745              :                               CALL opt_k_apply_preconditioner_blk(almo_scf_env, &
    3746            0 :                                                                   step, grad, ispin)
    3747            0 :                               CALL dbcsr_scale(step, -1.0_dp)
    3748              : 
    3749              :                               ! check whether we need to reset conjugate directions
    3750            0 :                               reset_conjugator = .FALSE.
    3751              :                               ! first check if manual reset is active
    3752            0 :                               IF (iteration < MAX(almo_scf_env%opt_k_conj_iter_start, 1) .OR. &
    3753              :                                   MOD(iteration - almo_scf_env%opt_k_conj_iter_start, &
    3754              :                                       almo_scf_env%opt_k_conj_iter_freq) == 0) THEN
    3755              : 
    3756              :                                  reset_conjugator = .TRUE.
    3757              : 
    3758              :                               ELSE
    3759              : 
    3760              :                                  ! check for the errors in the cg algorithm
    3761            0 :                                  CALL dbcsr_dot(grad, prev_minus_prec_grad, numer)
    3762            0 :                                  CALL dbcsr_dot(prev_grad, prev_minus_prec_grad, denom)
    3763            0 :                                  conjugacy_error = numer/denom
    3764              : 
    3765            0 :                                  IF (conjugacy_error > MIN(0.5_dp, conjugacy_error_threshold)) THEN
    3766            0 :                                     reset_conjugator = .TRUE.
    3767            0 :                                     IF (unit_nr > 0) THEN
    3768            0 :                                        WRITE (unit_nr, *) "Lack of progress, conjugacy error is ", conjugacy_error
    3769              :                                     END IF
    3770              :                                  END IF
    3771              : 
    3772              :                                  ! check the gradient along the previous direction
    3773            0 :                                  IF ((iteration /= 0) .AND. (.NOT. reset_conjugator)) THEN
    3774            0 :                                     CALL dbcsr_dot(grad, prev_step, numer)
    3775            0 :                                     CALL dbcsr_dot(prev_grad, prev_step, denom)
    3776            0 :                                     line_search_error = numer/denom
    3777            0 :                                     IF (line_search_error > line_search_error_threshold) THEN
    3778            0 :                                        reset_conjugator = .TRUE.
    3779            0 :                                        IF (unit_nr > 0) THEN
    3780            0 :                                           WRITE (unit_nr, *) "Bad line search, line search error is ", line_search_error
    3781              :                                        END IF
    3782              :                                     END IF
    3783              :                                  END IF
    3784              : 
    3785              :                               END IF
    3786              : 
    3787              :                               ! compute the conjugation coefficient - beta
    3788            0 :                               IF (.NOT. reset_conjugator) THEN
    3789              : 
    3790            0 :                                  SELECT CASE (almo_scf_env%opt_k_conjugator)
    3791              :                                  CASE (cg_hestenes_stiefel)
    3792            0 :                                     CALL dbcsr_copy(tmp_k_blk, grad)
    3793            0 :                                     CALL dbcsr_add(tmp_k_blk, prev_grad, 1.0_dp, -1.0_dp)
    3794            0 :                                     CALL dbcsr_dot(tmp_k_blk, step, numer)
    3795            0 :                                     CALL dbcsr_dot(tmp_k_blk, prev_step, denom)
    3796            0 :                                     beta = -1.0_dp*numer/denom
    3797              :                                  CASE (cg_fletcher_reeves)
    3798            0 :                                     CALL dbcsr_dot(grad, step, numer)
    3799            0 :                                     CALL dbcsr_dot(prev_grad, prev_minus_prec_grad, denom)
    3800            0 :                                     beta = numer/denom
    3801              :                                  CASE (cg_polak_ribiere)
    3802            0 :                                     CALL dbcsr_dot(prev_grad, prev_minus_prec_grad, denom)
    3803            0 :                                     CALL dbcsr_copy(tmp_k_blk, grad)
    3804            0 :                                     CALL dbcsr_add(tmp_k_blk, prev_grad, 1.0_dp, -1.0_dp)
    3805            0 :                                     CALL dbcsr_dot(tmp_k_blk, step, numer)
    3806            0 :                                     beta = numer/denom
    3807              :                                  CASE (cg_fletcher)
    3808            0 :                                     CALL dbcsr_dot(grad, step, numer)
    3809            0 :                                     CALL dbcsr_dot(prev_grad, prev_step, denom)
    3810            0 :                                     beta = numer/denom
    3811              :                                  CASE (cg_liu_storey)
    3812            0 :                                     CALL dbcsr_dot(prev_grad, prev_step, denom)
    3813            0 :                                     CALL dbcsr_copy(tmp_k_blk, grad)
    3814            0 :                                     CALL dbcsr_add(tmp_k_blk, prev_grad, 1.0_dp, -1.0_dp)
    3815            0 :                                     CALL dbcsr_dot(tmp_k_blk, step, numer)
    3816            0 :                                     beta = numer/denom
    3817              :                                  CASE (cg_dai_yuan)
    3818            0 :                                     CALL dbcsr_dot(grad, step, numer)
    3819            0 :                                     CALL dbcsr_copy(tmp_k_blk, grad)
    3820            0 :                                     CALL dbcsr_add(tmp_k_blk, prev_grad, 1.0_dp, -1.0_dp)
    3821            0 :                                     CALL dbcsr_dot(tmp_k_blk, prev_step, denom)
    3822            0 :                                     beta = -1.0_dp*numer/denom
    3823              :                                  CASE (cg_hager_zhang)
    3824            0 :                                     CALL dbcsr_copy(tmp_k_blk, grad)
    3825            0 :                                     CALL dbcsr_add(tmp_k_blk, prev_grad, 1.0_dp, -1.0_dp)
    3826            0 :                                     CALL dbcsr_dot(tmp_k_blk, prev_step, denom)
    3827            0 :                                     CALL dbcsr_dot(tmp_k_blk, prev_minus_prec_grad, numer)
    3828            0 :                                     kappa = -2.0_dp*numer/denom
    3829            0 :                                     CALL dbcsr_dot(tmp_k_blk, step, numer)
    3830            0 :                                     tau = -1.0_dp*numer/denom
    3831            0 :                                     CALL dbcsr_dot(prev_step, grad, numer)
    3832            0 :                                     beta = tau - kappa*numer/denom
    3833              :                                  CASE (cg_zero)
    3834            0 :                                     beta = 0.0_dp
    3835              :                                  CASE DEFAULT
    3836            0 :                                     CPABORT("illegal conjugator")
    3837              :                                  END SELECT
    3838              : 
    3839            0 :                                  IF (beta < 0.0_dp) THEN
    3840            0 :                                     IF (unit_nr > 0) THEN
    3841            0 :                                        WRITE (unit_nr, *) "Beta is negative, ", beta
    3842              :                                     END IF
    3843              :                                     reset_conjugator = .TRUE.
    3844              :                                  END IF
    3845              : 
    3846              :                               END IF
    3847              : 
    3848            0 :                               IF (md_in_k_space) THEN
    3849              :                                  reset_conjugator = .TRUE.
    3850              :                               END IF
    3851              : 
    3852            0 :                               IF (reset_conjugator) THEN
    3853              : 
    3854            0 :                                  beta = 0.0_dp
    3855              : 
    3856            0 :                                  IF (unit_nr > 0) THEN
    3857            0 :                                     WRITE (unit_nr, *) "(Re)-setting conjugator to zero"
    3858              :                                  END IF
    3859              : 
    3860              :                               END IF
    3861              : 
    3862              :                               ! save the preconditioned gradient
    3863            0 :                               CALL dbcsr_copy(prev_minus_prec_grad, step)
    3864              : 
    3865              :                               ! conjugate the step direction
    3866            0 :                               CALL dbcsr_add(step, prev_step, 1.0_dp, beta)
    3867              : 
    3868            0 :                               CALL timestop(handle7)
    3869              : 
    3870              :                               ! update the step direction
    3871              :                            ELSE ! step update
    3872            0 :                               conjugacy_error = 0.0_dp
    3873              :                            END IF
    3874              : 
    3875              :                            ! compute the gradient with respect to the step size in the curr direction
    3876            0 :                            IF (line_search) THEN
    3877            0 :                               CALL dbcsr_dot(grad, step, gfun1)
    3878            0 :                               line_search_error = gfun1/gfun0
    3879              :                            ELSE
    3880            0 :                               CALL dbcsr_dot(grad, step, gfun0)
    3881              :                            END IF
    3882              : 
    3883              :                            ! make a step - update k
    3884            0 :                            IF (line_search) THEN
    3885              : 
    3886              :                               ! check if the trial step provides enough numerical accuracy
    3887            0 :                               safety_multiplier = 1.0E+1_dp ! must be more than one
    3888              :                               num_threshold = MAX(EPSILON(1.0_dp), &
    3889            0 :                                                   safety_multiplier*(almo_scf_env%eps_filter**2)*almo_scf_env%ndomains)
    3890            0 :                               IF (ABS(fun1 - fun0 - gfun0*step_size) < num_threshold) THEN
    3891            0 :                                  IF (unit_nr > 0) THEN
    3892              :                                     WRITE (unit_nr, '(T3,A,1X,E17.7)') &
    3893            0 :                                        "Numerical accuracy is too low to observe non-linear behavior", &
    3894            0 :                                        ABS(fun1 - fun0 - gfun0*step_size)
    3895            0 :                                     WRITE (unit_nr, '(T3,A,1X,E17.7,A,1X,E12.3)') "Error computing ", &
    3896            0 :                                        ABS(gfun0), &
    3897            0 :                                        " is smaller than the threshold", num_threshold
    3898              :                                  END IF
    3899            0 :                                  CPABORT("Unable to continue with low numerical accuracy")
    3900              :                               END IF
    3901            0 :                               IF (ABS(gfun0) < num_threshold) THEN
    3902            0 :                                  IF (unit_nr > 0) THEN
    3903            0 :                                     WRITE (unit_nr, '(T3,A,1X,E17.7,A,1X,E12.3)') "Linear gradient", &
    3904            0 :                                        ABS(gfun0), &
    3905            0 :                                        " is smaller than the threshold", num_threshold
    3906              :                                  END IF
    3907            0 :                                  CPABORT("Unable to continue with low numerical accuracy")
    3908              :                               END IF
    3909              : 
    3910            0 :                               use_quadratic_approximation = .TRUE.
    3911            0 :                               use_cubic_approximation = .FALSE.
    3912              : 
    3913              :                               ! find the minimum assuming quadratic form
    3914              :                               ! use f0, f1, g0
    3915            0 :                               step_size_quadratic_approx = -(gfun0*step_size*step_size)/(2.0_dp*(fun1 - fun0 - gfun0*step_size))
    3916              :                               ! use f0, f1, g1
    3917            0 :                              step_size_quadratic_approx2 = -(fun1 - fun0 - step_size*gfun1/2.0_dp)/(gfun1 - (fun1 - fun0)/step_size)
    3918              : 
    3919            0 :                               IF ((step_size_quadratic_approx < 0.0_dp) .AND. &
    3920              :                                   (step_size_quadratic_approx2 < 0.0_dp)) THEN
    3921            0 :                                  IF (unit_nr > 0) THEN
    3922              :                                     WRITE (unit_nr, '(T3,A,1X,E17.7,1X,E17.7,1X,A)') &
    3923            0 :                                        "Quadratic approximation gives negative steps", &
    3924            0 :                                        step_size_quadratic_approx, step_size_quadratic_approx2, &
    3925            0 :                                        "trying cubic..."
    3926              :                                  END IF
    3927              :                                  use_cubic_approximation = .TRUE.
    3928              :                                  use_quadratic_approximation = .FALSE.
    3929              :                               ELSE
    3930            0 :                                  IF (step_size_quadratic_approx < 0.0_dp) THEN
    3931            0 :                                     step_size_quadratic_approx = step_size_quadratic_approx2
    3932              :                                  END IF
    3933            0 :                                  IF (step_size_quadratic_approx2 < 0.0_dp) THEN
    3934            0 :                                     step_size_quadratic_approx2 = step_size_quadratic_approx
    3935              :                                  END IF
    3936              :                               END IF
    3937              : 
    3938              :                               ! check accuracy of the quadratic approximation
    3939              :                               IF (use_quadratic_approximation) THEN
    3940              :                                  quadratic_approx_error = ABS(step_size_quadratic_approx - &
    3941            0 :                                                               step_size_quadratic_approx2)/step_size_quadratic_approx
    3942            0 :                                  IF (quadratic_approx_error > quadratic_approx_error_threshold) THEN
    3943            0 :                                     IF (unit_nr > 0) THEN
    3944            0 :                                        WRITE (unit_nr, '(T3,A,1X,E17.7,1X,E17.7,1X,A)') "Quadratic approximation is poor", &
    3945            0 :                                           step_size_quadratic_approx, step_size_quadratic_approx2, &
    3946            0 :                                           "Try cubic approximation"
    3947              :                                     END IF
    3948              :                                     use_cubic_approximation = .TRUE.
    3949              :                                     use_quadratic_approximation = .FALSE.
    3950              :                                  END IF
    3951              :                               END IF
    3952              : 
    3953              :                               ! check if numerics is fine enough to capture the cubic form
    3954            0 :                               IF (use_cubic_approximation) THEN
    3955              : 
    3956              :                                  ! if quadratic approximation is not accurate enough
    3957              :                                  ! try to find the minimum assuming cubic form
    3958              :                                  ! aa*x**3 + bb*x**2 + cc*x + dd = f(x)
    3959            0 :                                  bb = (-step_size*gfun1 + 3.0_dp*(fun1 - fun0) - 2.0_dp*step_size*gfun0)/(step_size*step_size)
    3960            0 :                                  aa = (gfun1 - 2.0_dp*step_size*bb - gfun0)/(3.0_dp*step_size*step_size)
    3961              : 
    3962            0 :                                  IF (ABS(gfun1 - 2.0_dp*step_size*bb - gfun0) < num_threshold) THEN
    3963            0 :                                     IF (unit_nr > 0) THEN
    3964              :                                        WRITE (unit_nr, '(T3,A,1X,E17.7)') &
    3965            0 :                                           "Numerical accuracy is too low to observe cubic behavior", &
    3966            0 :                                           ABS(gfun1 - 2.0_dp*step_size*bb - gfun0)
    3967              :                                     END IF
    3968              :                                     use_cubic_approximation = .FALSE.
    3969              :                                     use_quadratic_approximation = .TRUE.
    3970              :                                  END IF
    3971            0 :                                  IF (ABS(gfun1) < num_threshold) THEN
    3972            0 :                                     IF (unit_nr > 0) THEN
    3973            0 :                                        WRITE (unit_nr, '(T3,A,1X,E17.7,A,1X,E12.3)') "Linear gradient", &
    3974            0 :                                           ABS(gfun1), &
    3975            0 :                                           " is smaller than the threshold", num_threshold
    3976              :                                     END IF
    3977              :                                     use_cubic_approximation = .FALSE.
    3978              :                                     use_quadratic_approximation = .TRUE.
    3979              :                                  END IF
    3980              :                               END IF
    3981              : 
    3982              :                               ! find the step assuming cubic approximation
    3983            0 :                               IF (use_cubic_approximation) THEN
    3984              :                                  ! to obtain the minimum of the cubic function solve the quadratic equation
    3985              :                                  ! 0.0*x**3 + 3.0*aa*x**2 + 2.0*bb*x + cc = 0
    3986            0 :                                  CALL analytic_line_search(0.0_dp, 3.0_dp*aa, 2.0_dp*bb, gfun0, minima, nmins)
    3987            0 :                                  IF (nmins < 1) THEN
    3988            0 :                                     IF (unit_nr > 0) THEN
    3989              :                                        WRITE (unit_nr, '(T3,A)') &
    3990            0 :                                           "Cubic approximation gives zero soultions! Use quadratic approximation"
    3991              :                                     END IF
    3992              :                                     use_quadratic_approximation = .TRUE.
    3993              :                                     use_cubic_approximation = .TRUE.
    3994              :                                  ELSE
    3995            0 :                                     step_size = minima(1)
    3996            0 :                                     IF (nmins > 1) THEN
    3997            0 :                                        IF (unit_nr > 0) THEN
    3998              :                                           WRITE (unit_nr, '(T3,A)') &
    3999            0 :                                              "More than one solution found! Use quadratic approximation"
    4000              :                                        END IF
    4001              :                                        use_quadratic_approximation = .TRUE.
    4002            0 :                                        use_cubic_approximation = .TRUE.
    4003              :                                     END IF
    4004              :                                  END IF
    4005              :                               END IF
    4006              : 
    4007            0 :                               IF (use_quadratic_approximation) THEN ! use quadratic approximation
    4008            0 :                                  IF (unit_nr > 0) THEN
    4009            0 :                                     WRITE (unit_nr, '(T3,A)') "Use quadratic approximation"
    4010              :                                  END IF
    4011            0 :                                  step_size = (step_size_quadratic_approx + step_size_quadratic_approx2)*0.5_dp
    4012              :                               END IF
    4013              : 
    4014              :                               ! one more check on the step size
    4015            0 :                               IF (step_size < 0.0_dp) THEN
    4016            0 :                                  CPABORT("Negative step proposed")
    4017              :                               END IF
    4018              : 
    4019              :                               CALL dbcsr_copy(almo_scf_env%matrix_k_blk(ispin), &
    4020            0 :                                               matrix_k_central)
    4021              :                               CALL dbcsr_add(almo_scf_env%matrix_k_blk(ispin), &
    4022            0 :                                              step, 1.0_dp, step_size)
    4023              :                               CALL dbcsr_copy(matrix_k_central, &
    4024            0 :                                               almo_scf_env%matrix_k_blk(ispin))
    4025            0 :                               line_search = .FALSE.
    4026              : 
    4027              :                            ELSE
    4028              : 
    4029            0 :                               IF (md_in_k_space) THEN
    4030              : 
    4031              :                                  ! update velocities v(i) = v(i-1) + 0.5*dT*(a(i-1) + a(i))
    4032            0 :                                  IF (iteration /= 0) THEN
    4033              :                                     CALL dbcsr_add(velocity, &
    4034            0 :                                                    step, 1.0_dp, 0.5_dp*time_step)
    4035              :                                     CALL dbcsr_add(velocity, &
    4036            0 :                                                    prev_step, 1.0_dp, 0.5_dp*time_step)
    4037              :                                  END IF
    4038            0 :                                  kin_energy = dbcsr_frobenius_norm(velocity)
    4039            0 :                                  kin_energy = 0.5_dp*kin_energy*kin_energy
    4040              : 
    4041              :                                  ! update positions k(i) = k(i-1) + dT*v(i-1) + 0.5*dT*dT*a(i-1)
    4042              :                                  CALL dbcsr_add(almo_scf_env%matrix_k_blk(ispin), &
    4043            0 :                                                 velocity, 1.0_dp, time_step)
    4044              :                                  CALL dbcsr_add(almo_scf_env%matrix_k_blk(ispin), &
    4045            0 :                                                 step, 1.0_dp, 0.5_dp*time_step*time_step)
    4046              : 
    4047              :                               ELSE
    4048              : 
    4049            0 :                                  IF (reset_step_size) THEN
    4050            0 :                                     step_size = almo_scf_env%opt_k_trial_step_size
    4051            0 :                                     reset_step_size = .FALSE.
    4052              :                                  ELSE
    4053            0 :                                     step_size = step_size*almo_scf_env%opt_k_trial_step_size_multiplier
    4054              :                                  END IF
    4055              :                                  CALL dbcsr_copy(almo_scf_env%matrix_k_blk(ispin), &
    4056            0 :                                                  matrix_k_central)
    4057              :                                  CALL dbcsr_add(almo_scf_env%matrix_k_blk(ispin), &
    4058            0 :                                                 step, 1.0_dp, step_size)
    4059            0 :                                  line_search = .TRUE.
    4060              :                               END IF
    4061              : 
    4062              :                            END IF
    4063              : 
    4064              :                         END IF ! .NOT.prepare_to_exit
    4065              : 
    4066              :                         ! print the status of the optimization
    4067            0 :                         t2a = m_walltime()
    4068            0 :                         IF (unit_nr > 0) THEN
    4069            0 :                            IF (md_in_k_space) THEN
    4070              :                               WRITE (unit_nr, '(T6,A,1X,I5,1X,E12.3,E16.7,F15.9,F15.9,F15.9,E12.3,F15.9,F15.9,F8.3)') &
    4071            0 :                                  "K iter CG", iteration, time_step, time_step*iteration, &
    4072            0 :                                  energy_correction(ispin), obj_function, delta_obj_function, grad_norm, &
    4073            0 :                                  kin_energy, kin_energy + obj_function, beta
    4074              :                            ELSE
    4075            0 :                               IF (line_search .OR. prepare_to_exit) THEN
    4076              :                                  WRITE (unit_nr, '(T6,A,1X,I3,1X,E12.3,F16.10,F16.10,E12.3,E12.3,E12.3,F8.3,F8.3,F10.3)') &
    4077            0 :                                     "K iter CG", iteration, step_size, &
    4078            0 :                                     energy_correction(ispin), delta_obj_function, grad_norm, &
    4079            0 :                                     gfun0, line_search_error, beta, conjugacy_error, t2a - t1a
    4080              :                               ELSE
    4081              :                                  WRITE (unit_nr, '(T6,A,1X,I3,1X,E12.3,F16.10,F16.10,E12.3,E12.3,E12.3,F8.3,F8.3,F10.3)') &
    4082            0 :                                     "K iter LS", iteration, step_size, &
    4083            0 :                                     energy_correction(ispin), delta_obj_function, grad_norm, &
    4084            0 :                                     gfun1, line_search_error, beta, conjugacy_error, t2a - t1a
    4085              :                               END IF
    4086              :                            END IF
    4087            0 :                            CALL m_flush(unit_nr)
    4088              :                         END IF
    4089            0 :                         t1a = m_walltime()
    4090              : 
    4091              :                      ELSE ! opt_k_max_iter .eq. 0
    4092              :                         prepare_to_exit = .TRUE.
    4093              :                      END IF ! opt_k_max_iter .ne. 0
    4094              : 
    4095            0 :                      IF (.NOT. line_search) iteration = iteration + 1
    4096              : 
    4097            0 :                      IF (prepare_to_exit) EXIT
    4098              : 
    4099              :                   END DO ! end iterations on K
    4100              : 
    4101            0 :                   IF (converged .OR. (outer_opt_k_iteration >= outer_opt_k_max_iter)) THEN
    4102            0 :                      outer_opt_k_prepare_to_exit = .TRUE.
    4103              :                   END IF
    4104              : 
    4105            0 :                   IF (almo_scf_env%deloc_truncate_virt /= virt_full) THEN
    4106              : 
    4107            0 :                      IF (unit_nr > 0) THEN
    4108            0 :                         WRITE (unit_nr, *) "Updating ALMO virtuals"
    4109              :                      END IF
    4110              : 
    4111            0 :                      CALL timeset('k_opt_v0_update', handle8)
    4112              : 
    4113              :                      ! update retained ALMO virtuals to restart the cg iterations
    4114              :                      CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4115              :                                          almo_scf_env%matrix_v_disc_blk(ispin), &
    4116              :                                          almo_scf_env%matrix_k_blk(ispin), &
    4117              :                                          0.0_dp, vr_fixed, &
    4118            0 :                                          filter_eps=almo_scf_env%eps_filter)
    4119              :                      CALL dbcsr_add(vr_fixed, almo_scf_env%matrix_v_blk(ispin), &
    4120            0 :                                     +1.0_dp, +1.0_dp)
    4121              : 
    4122              :                      ! update discarded ALMO virtuals to restart the cg iterations
    4123              :                      CALL dbcsr_multiply("N", "T", 1.0_dp, &
    4124              :                                          almo_scf_env%matrix_v_blk(ispin), &
    4125              :                                          almo_scf_env%matrix_k_blk(ispin), &
    4126              :                                          0.0_dp, vd_fixed, &
    4127            0 :                                          filter_eps=almo_scf_env%eps_filter)
    4128              :                      CALL dbcsr_add(vd_fixed, almo_scf_env%matrix_v_disc_blk(ispin), &
    4129            0 :                                     -1.0_dp, +1.0_dp)
    4130              : 
    4131              :                      ! orthogonalize new orbitals on fragments
    4132              :                      CALL get_overlap(bra=vr_fixed, &
    4133              :                                       ket=vr_fixed, &
    4134              :                                       overlap=k_vr_index_down, &
    4135              :                                       metric=almo_scf_env%matrix_s_blk(1), &
    4136              :                                       retain_overlap_sparsity=.FALSE., &
    4137            0 :                                       eps_filter=almo_scf_env%eps_filter)
    4138              :                      CALL dbcsr_create(vr_index_sqrt_inv, template=k_vr_index_down, &
    4139            0 :                                        matrix_type=dbcsr_type_no_symmetry)
    4140              :                      CALL dbcsr_create(vr_index_sqrt, template=k_vr_index_down, &
    4141            0 :                                        matrix_type=dbcsr_type_no_symmetry)
    4142              :                      CALL matrix_sqrt_Newton_Schulz(vr_index_sqrt, &
    4143              :                                                     vr_index_sqrt_inv, &
    4144              :                                                     k_vr_index_down, &
    4145              :                                                     threshold=almo_scf_env%eps_filter, &
    4146              :                                                     order=almo_scf_env%order_lanczos, &
    4147              :                                                     eps_lanczos=almo_scf_env%eps_lanczos, &
    4148            0 :                                                     max_iter_lanczos=almo_scf_env%max_iter_lanczos)
    4149              :                      IF (safe_mode) THEN
    4150              :                         CALL dbcsr_create(matrix_tmp1, template=k_vr_index_down, &
    4151              :                                           matrix_type=dbcsr_type_no_symmetry)
    4152              :                         CALL dbcsr_create(matrix_tmp2, template=k_vr_index_down, &
    4153              :                                           matrix_type=dbcsr_type_no_symmetry)
    4154              : 
    4155              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, vr_index_sqrt_inv, &
    4156              :                                             k_vr_index_down, &
    4157              :                                             0.0_dp, matrix_tmp1, filter_eps=almo_scf_env%eps_filter)
    4158              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, &
    4159              :                                             vr_index_sqrt_inv, &
    4160              :                                             0.0_dp, matrix_tmp2, filter_eps=almo_scf_env%eps_filter)
    4161              : 
    4162              :                         frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp2)
    4163              :                         CALL dbcsr_add_on_diag(matrix_tmp2, -1.0_dp)
    4164              :                         frob_matrix = dbcsr_frobenius_norm(matrix_tmp2)
    4165              :                         IF (unit_nr > 0) THEN
    4166              :                            WRITE (unit_nr, *) "Error for (inv(sqrt(SIGVV))*SIGVV*inv(sqrt(SIGVV))-I)", &
    4167              :                               frob_matrix/frob_matrix_base
    4168              :                         END IF
    4169              : 
    4170              :                         CALL dbcsr_release(matrix_tmp1)
    4171              :                         CALL dbcsr_release(matrix_tmp2)
    4172              :                      END IF
    4173              :                      CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4174              :                                          vr_fixed, &
    4175              :                                          vr_index_sqrt_inv, &
    4176              :                                          0.0_dp, almo_scf_env%matrix_v_blk(ispin), &
    4177            0 :                                          filter_eps=almo_scf_env%eps_filter)
    4178              : 
    4179              :                      CALL get_overlap(bra=vd_fixed, &
    4180              :                                       ket=vd_fixed, &
    4181              :                                       overlap=k_vd_index_down, &
    4182              :                                       metric=almo_scf_env%matrix_s_blk(1), &
    4183              :                                       retain_overlap_sparsity=.FALSE., &
    4184            0 :                                       eps_filter=almo_scf_env%eps_filter)
    4185              :                      CALL dbcsr_create(vd_index_sqrt_inv, template=k_vd_index_down, &
    4186            0 :                                        matrix_type=dbcsr_type_no_symmetry)
    4187              :                      CALL dbcsr_create(vd_index_sqrt, template=k_vd_index_down, &
    4188            0 :                                        matrix_type=dbcsr_type_no_symmetry)
    4189              :                      CALL matrix_sqrt_Newton_Schulz(vd_index_sqrt, &
    4190              :                                                     vd_index_sqrt_inv, &
    4191              :                                                     k_vd_index_down, &
    4192              :                                                     threshold=almo_scf_env%eps_filter, &
    4193              :                                                     order=almo_scf_env%order_lanczos, &
    4194              :                                                     eps_lanczos=almo_scf_env%eps_lanczos, &
    4195            0 :                                                     max_iter_lanczos=almo_scf_env%max_iter_lanczos)
    4196              :                      IF (safe_mode) THEN
    4197              :                         CALL dbcsr_create(matrix_tmp1, template=k_vd_index_down, &
    4198              :                                           matrix_type=dbcsr_type_no_symmetry)
    4199              :                         CALL dbcsr_create(matrix_tmp2, template=k_vd_index_down, &
    4200              :                                           matrix_type=dbcsr_type_no_symmetry)
    4201              : 
    4202              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, vd_index_sqrt_inv, &
    4203              :                                             k_vd_index_down, &
    4204              :                                             0.0_dp, matrix_tmp1, filter_eps=almo_scf_env%eps_filter)
    4205              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, &
    4206              :                                             vd_index_sqrt_inv, &
    4207              :                                             0.0_dp, matrix_tmp2, filter_eps=almo_scf_env%eps_filter)
    4208              : 
    4209              :                         frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp2)
    4210              :                         CALL dbcsr_add_on_diag(matrix_tmp2, -1.0_dp)
    4211              :                         frob_matrix = dbcsr_frobenius_norm(matrix_tmp2)
    4212              :                         IF (unit_nr > 0) THEN
    4213              :                            WRITE (unit_nr, *) "Error for (inv(sqrt(SIGVV))*SIGVV*inv(sqrt(SIGVV))-I)", &
    4214              :                               frob_matrix/frob_matrix_base
    4215              :                         END IF
    4216              : 
    4217              :                         CALL dbcsr_release(matrix_tmp1)
    4218              :                         CALL dbcsr_release(matrix_tmp2)
    4219              :                      END IF
    4220              :                      CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4221              :                                          vd_fixed, &
    4222              :                                          vd_index_sqrt_inv, &
    4223              :                                          0.0_dp, almo_scf_env%matrix_v_disc_blk(ispin), &
    4224            0 :                                          filter_eps=almo_scf_env%eps_filter)
    4225              : 
    4226            0 :                      CALL dbcsr_release(vr_index_sqrt_inv)
    4227            0 :                      CALL dbcsr_release(vr_index_sqrt)
    4228            0 :                      CALL dbcsr_release(vd_index_sqrt_inv)
    4229            0 :                      CALL dbcsr_release(vd_index_sqrt)
    4230              : 
    4231            0 :                      CALL timestop(handle8)
    4232              : 
    4233              :                   END IF ! ne.virt_full
    4234              : 
    4235              :                   ! RZK-warning released outside the outer loop
    4236            0 :                   CALL dbcsr_release(sigma_vv_sqrt)
    4237            0 :                   CALL dbcsr_release(sigma_vv_sqrt_inv)
    4238            0 :                   IF (almo_scf_env%deloc_truncate_virt /= virt_full) THEN
    4239            0 :                      CALL dbcsr_release(k_vr_index_down)
    4240            0 :                      CALL dbcsr_release(k_vd_index_down)
    4241            0 :                      CALL dbcsr_release(matrix_k_central)
    4242            0 :                      CALL dbcsr_release(vr_fixed)
    4243            0 :                      CALL dbcsr_release(vd_fixed)
    4244            0 :                      CALL dbcsr_release(grad)
    4245            0 :                      CALL dbcsr_release(prec)
    4246            0 :                      CALL dbcsr_release(prev_grad)
    4247            0 :                      CALL dbcsr_release(tmp3_vd_vr)
    4248            0 :                      CALL dbcsr_release(tmp1_n_vr)
    4249            0 :                      CALL dbcsr_release(tmp_k_blk)
    4250            0 :                      CALL dbcsr_release(t_curr)
    4251            0 :                      CALL dbcsr_release(sigma_oo_curr)
    4252            0 :                      CALL dbcsr_release(sigma_oo_curr_inv)
    4253            0 :                      CALL dbcsr_release(step)
    4254            0 :                      CALL dbcsr_release(tmp2_n_o)
    4255            0 :                      CALL dbcsr_release(tmp4_o_vr)
    4256            0 :                      CALL dbcsr_release(prev_step)
    4257            0 :                      CALL dbcsr_release(prev_minus_prec_grad)
    4258            0 :                      IF (md_in_k_space) THEN
    4259            0 :                         CALL dbcsr_release(velocity)
    4260              :                      END IF
    4261              : 
    4262              :                   END IF
    4263              : 
    4264            0 :                   outer_opt_k_iteration = outer_opt_k_iteration + 1
    4265            0 :                   IF (outer_opt_k_prepare_to_exit) EXIT
    4266              : 
    4267              :                END DO ! outer loop for k
    4268              : 
    4269              :             END DO ! ispin
    4270              : 
    4271              :             ! RZK-warning update mo orbitals
    4272              : 
    4273              :          ELSE ! virtual orbitals might not be available use projected AOs
    4274              : 
    4275              :             ! compute sqrt(S) and inv(sqrt(S))
    4276              :             ! RZK-warning - remove this sqrt(S) and inv(sqrt(S))
    4277              :             ! ideally ALMO scf should use sigma and sigma_inv in
    4278              :             ! the tensor_up_down representation
    4279            0 :             IF (.NOT. almo_scf_env%s_sqrt_done) THEN
    4280              : 
    4281            0 :                IF (unit_nr > 0) THEN
    4282            0 :                   WRITE (unit_nr, *) "sqrt and inv(sqrt) of AO overlap matrix"
    4283              :                END IF
    4284              :                CALL dbcsr_create(almo_scf_env%matrix_s_sqrt(1), &
    4285              :                                  template=almo_scf_env%matrix_s(1), &
    4286            0 :                                  matrix_type=dbcsr_type_no_symmetry)
    4287              :                CALL dbcsr_create(almo_scf_env%matrix_s_sqrt_inv(1), &
    4288              :                                  template=almo_scf_env%matrix_s(1), &
    4289            0 :                                  matrix_type=dbcsr_type_no_symmetry)
    4290              : 
    4291              :                CALL matrix_sqrt_Newton_Schulz(almo_scf_env%matrix_s_sqrt(1), &
    4292              :                                               almo_scf_env%matrix_s_sqrt_inv(1), &
    4293              :                                               almo_scf_env%matrix_s(1), &
    4294              :                                               threshold=almo_scf_env%eps_filter, &
    4295              :                                               order=almo_scf_env%order_lanczos, &
    4296              :                                               eps_lanczos=almo_scf_env%eps_lanczos, &
    4297            0 :                                               max_iter_lanczos=almo_scf_env%max_iter_lanczos)
    4298              : 
    4299              :                IF (safe_mode) THEN
    4300              :                   CALL dbcsr_create(matrix_tmp1, template=almo_scf_env%matrix_s(1), &
    4301              :                                     matrix_type=dbcsr_type_no_symmetry)
    4302              :                   CALL dbcsr_create(matrix_tmp2, template=almo_scf_env%matrix_s(1), &
    4303              :                                     matrix_type=dbcsr_type_no_symmetry)
    4304              : 
    4305              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, almo_scf_env%matrix_s_sqrt_inv(1), &
    4306              :                                       almo_scf_env%matrix_s(1), &
    4307              :                                       0.0_dp, matrix_tmp1, filter_eps=almo_scf_env%eps_filter)
    4308              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, almo_scf_env%matrix_s_sqrt_inv(1), &
    4309              :                                       0.0_dp, matrix_tmp2, filter_eps=almo_scf_env%eps_filter)
    4310              : 
    4311              :                   frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp2)
    4312              :                   CALL dbcsr_add_on_diag(matrix_tmp2, -1.0_dp)
    4313              :                   frob_matrix = dbcsr_frobenius_norm(matrix_tmp2)
    4314              :                   IF (unit_nr > 0) THEN
    4315              :                      WRITE (unit_nr, *) "Error for (inv(sqrt(S))*S*inv(sqrt(S))-I)", frob_matrix/frob_matrix_base
    4316              :                   END IF
    4317              : 
    4318              :                   CALL dbcsr_release(matrix_tmp1)
    4319              :                   CALL dbcsr_release(matrix_tmp2)
    4320              :                END IF
    4321              : 
    4322            0 :                almo_scf_env%s_sqrt_done = .TRUE.
    4323              : 
    4324              :             END IF
    4325              : 
    4326            0 :             DO ispin = 1, nspin
    4327              : 
    4328            0 :                CALL ct_step_env_init(ct_step_env)
    4329              :                CALL ct_step_env_set(ct_step_env, &
    4330              :                                     para_env=almo_scf_env%para_env, &
    4331              :                                     blacs_env=almo_scf_env%blacs_env, &
    4332              :                                     use_occ_orbs=.TRUE., &
    4333              :                                     use_virt_orbs=almo_scf_env%deloc_cayley_use_virt_orbs, &
    4334              :                                     occ_orbs_orthogonal=.FALSE., &
    4335              :                                     virt_orbs_orthogonal=almo_scf_env%orthogonal_basis, &
    4336              :                                     tensor_type=almo_scf_env%deloc_cayley_tensor_type, &
    4337              :                                     neglect_quadratic_term=almo_scf_env%deloc_cayley_linear, &
    4338              :                                     calculate_energy_corr=.TRUE., &
    4339              :                                     update_p=.TRUE., &
    4340              :                                     update_q=.FALSE., &
    4341              :                                     pp_preconditioner_full=almo_scf_env%deloc_cayley_occ_precond, &
    4342              :                                     qq_preconditioner_full=almo_scf_env%deloc_cayley_vir_precond, &
    4343              :                                     eps_convergence=almo_scf_env%deloc_cayley_eps_convergence, &
    4344              :                                     eps_filter=almo_scf_env%eps_filter, &
    4345              :                                     !nspins=almo_scf_env%nspins,&
    4346              :                                     q_index_up=almo_scf_env%matrix_s_sqrt_inv(1), &
    4347              :                                     q_index_down=almo_scf_env%matrix_s_sqrt(1), &
    4348              :                                     p_index_up=almo_scf_env%matrix_sigma_sqrt_inv(ispin), &
    4349              :                                     p_index_down=almo_scf_env%matrix_sigma_sqrt(ispin), &
    4350              :                                     matrix_ks=almo_scf_env%matrix_ks_0deloc(ispin), &
    4351              :                                     matrix_p=almo_scf_env%matrix_p(ispin), &
    4352              :                                     matrix_qp_template=almo_scf_env%matrix_t(ispin), &
    4353              :                                     matrix_pq_template=almo_scf_env%matrix_t_tr(ispin), &
    4354              :                                     matrix_t=almo_scf_env%matrix_t(ispin), &
    4355              :                                     conjugator=almo_scf_env%deloc_cayley_conjugator, &
    4356            0 :                                     max_iter=almo_scf_env%deloc_cayley_max_iter)
    4357              : 
    4358              :                ! perform calculations
    4359            0 :                CALL ct_step_execute(ct_step_env)
    4360              : 
    4361              :                ! for now we do not need the new set of orbitals
    4362              :                ! just get the energy correction
    4363              :                CALL ct_step_env_get(ct_step_env, &
    4364            0 :                                     energy_correction=energy_correction(ispin))
    4365              : 
    4366            0 :                CALL ct_step_env_clean(ct_step_env)
    4367              : 
    4368              :             END DO
    4369              : 
    4370            0 :             energy_correction(1) = energy_correction(1)*spin_factor
    4371              : 
    4372              :          END IF
    4373              : 
    4374              :          ! print the energy correction and exit
    4375            0 :          DO ispin = 1, nspin
    4376              : 
    4377            0 :             IF (unit_nr > 0) THEN
    4378            0 :                WRITE (unit_nr, *)
    4379            0 :                WRITE (unit_nr, '(T2,A,I6,F20.9)') "ECORR", ispin, &
    4380            0 :                   energy_correction(ispin)
    4381            0 :                WRITE (unit_nr, *)
    4382              :             END IF
    4383            0 :             energy_correction_final = energy_correction_final + energy_correction(ispin)
    4384              : 
    4385              :             ! obtain density matrix from updated MOs
    4386              :             ! RZK-later sigma and sigma_inv are lost here
    4387              :             CALL almo_scf_t_to_proj(t=almo_scf_env%matrix_t(ispin), &
    4388              :                                     p=almo_scf_env%matrix_p(ispin), &
    4389              :                                     eps_filter=almo_scf_env%eps_filter, &
    4390              :                                     orthog_orbs=.FALSE., &
    4391              :                                     nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
    4392              :                                     s=almo_scf_env%matrix_s(1), &
    4393              :                                     sigma=almo_scf_env%matrix_sigma(ispin), &
    4394              :                                     sigma_inv=almo_scf_env%matrix_sigma_inv(ispin), &
    4395              :                                     !use_guess=use_guess, &
    4396              :                                     algorithm=almo_scf_env%sigma_inv_algorithm, &
    4397              :                                     inverse_accelerator=almo_scf_env%order_lanczos, &
    4398              :                                     inv_eps_factor=almo_scf_env%matrix_iter_eps_error_factor, &
    4399              :                                     eps_lanczos=almo_scf_env%eps_lanczos, &
    4400              :                                     max_iter_lanczos=almo_scf_env%max_iter_lanczos, &
    4401              :                                     para_env=almo_scf_env%para_env, &
    4402            0 :                                     blacs_env=almo_scf_env%blacs_env)
    4403              : 
    4404            0 :             IF (almo_scf_env%nspins == 1) THEN
    4405              :                CALL dbcsr_scale(almo_scf_env%matrix_p(ispin), &
    4406            0 :                                 spin_factor)
    4407              :             END IF
    4408              : 
    4409              :          END DO
    4410              : 
    4411              :       CASE (dm_ls_step)
    4412              : 
    4413              :          ! compute the inverse of S
    4414            0 :          IF (.NOT. almo_scf_env%s_inv_done) THEN
    4415            0 :             IF (unit_nr > 0) THEN
    4416            0 :                WRITE (unit_nr, *) "Inverting AO overlap matrix"
    4417              :             END IF
    4418              :             CALL dbcsr_create(almo_scf_env%matrix_s_inv(1), &
    4419              :                               template=almo_scf_env%matrix_s(1), &
    4420            0 :                               matrix_type=dbcsr_type_no_symmetry)
    4421            0 :             IF (.NOT. almo_scf_env%s_sqrt_done) THEN
    4422              :                CALL invert_Hotelling(almo_scf_env%matrix_s_inv(1), &
    4423              :                                      almo_scf_env%matrix_s(1), &
    4424            0 :                                      threshold=almo_scf_env%eps_filter)
    4425              :             ELSE
    4426              :                CALL dbcsr_multiply("N", "N", 1.0_dp, almo_scf_env%matrix_s_sqrt_inv(1), &
    4427              :                                    almo_scf_env%matrix_s_sqrt_inv(1), &
    4428              :                                    0.0_dp, almo_scf_env%matrix_s_inv(1), &
    4429            0 :                                    filter_eps=almo_scf_env%eps_filter)
    4430              :             END IF
    4431              : 
    4432              :             IF (safe_mode) THEN
    4433              :                CALL dbcsr_create(matrix_tmp1, template=almo_scf_env%matrix_s(1), &
    4434              :                                  matrix_type=dbcsr_type_no_symmetry)
    4435              :                CALL dbcsr_multiply("N", "N", 1.0_dp, almo_scf_env%matrix_s_inv(1), &
    4436              :                                    almo_scf_env%matrix_s(1), &
    4437              :                                    0.0_dp, matrix_tmp1, &
    4438              :                                    filter_eps=almo_scf_env%eps_filter)
    4439              :                frob_matrix_base = dbcsr_frobenius_norm(matrix_tmp1)
    4440              :                CALL dbcsr_add_on_diag(matrix_tmp1, -1.0_dp)
    4441              :                frob_matrix = dbcsr_frobenius_norm(matrix_tmp1)
    4442              :                IF (unit_nr > 0) THEN
    4443              :                   WRITE (unit_nr, *) "Error for (inv(S)*S-I)", &
    4444              :                      frob_matrix/frob_matrix_base
    4445              :                END IF
    4446              :                CALL dbcsr_release(matrix_tmp1)
    4447              :             END IF
    4448              : 
    4449            0 :             almo_scf_env%s_inv_done = .TRUE.
    4450              : 
    4451              :          END IF
    4452              : 
    4453            0 :          ALLOCATE (matrix_p_almo_scf_converged(nspin))
    4454            0 :          DO ispin = 1, nspin
    4455              :             CALL dbcsr_create(matrix_p_almo_scf_converged(ispin), &
    4456            0 :                               template=almo_scf_env%matrix_p(ispin))
    4457              :             CALL dbcsr_copy(matrix_p_almo_scf_converged(ispin), &
    4458            0 :                             almo_scf_env%matrix_p(ispin))
    4459              :          END DO
    4460              : 
    4461              :          ! update the density matrix
    4462            0 :          DO ispin = 1, nspin
    4463              : 
    4464            0 :             nelectron_spin_real(1) = almo_scf_env%nelectrons_spin(ispin)
    4465            0 :             IF (almo_scf_env%nspins == 1) THEN
    4466            0 :                nelectron_spin_real(1) = nelectron_spin_real(1)/2
    4467              :             END IF
    4468              : 
    4469            0 :             local_mu(1) = SUM(almo_scf_env%mu_of_domain(:, ispin))/almo_scf_env%ndomains
    4470            0 :             fake(1) = 123523
    4471              : 
    4472            0 :             CPABORT("CVS only: density_matrix_sign has not been updated in SVN")
    4473              : 
    4474            0 :             IF (almo_scf_env%nspins == 1) THEN
    4475              :                CALL dbcsr_scale(almo_scf_env%matrix_p(ispin), &
    4476            0 :                                 spin_factor)
    4477              :             END IF
    4478              :             CALL dbcsr_add(matrix_p_almo_scf_converged(ispin), &
    4479            0 :                            almo_scf_env%matrix_p(ispin), -1.0_dp, 1.0_dp)
    4480              :             CALL dbcsr_dot(almo_scf_env%matrix_ks_0deloc(ispin), &
    4481              :                            matrix_p_almo_scf_converged(ispin), &
    4482            0 :                            energy_correction(ispin))
    4483              : 
    4484            0 :             energy_correction_final = energy_correction_final + energy_correction(ispin)
    4485              : 
    4486            0 :             IF (unit_nr > 0) THEN
    4487            0 :                WRITE (unit_nr, *)
    4488            0 :                WRITE (unit_nr, '(T2,A,I6,F20.9)') "ECORR", ispin, &
    4489            0 :                   energy_correction(ispin)
    4490            0 :                WRITE (unit_nr, *)
    4491              :             END IF
    4492              : 
    4493              :          END DO
    4494              : 
    4495            0 :          DO ispin = 1, nspin
    4496            0 :             CALL dbcsr_release(matrix_p_almo_scf_converged(ispin))
    4497              :          END DO
    4498            0 :          DEALLOCATE (matrix_p_almo_scf_converged)
    4499              : 
    4500              :       END SELECT ! algorithm selection
    4501              : 
    4502            0 :       t2 = m_walltime()
    4503              : 
    4504            0 :       IF (unit_nr > 0) THEN
    4505            0 :          WRITE (unit_nr, *)
    4506            0 :          WRITE (unit_nr, '(T2,A,F18.9,F18.9,F18.9,F12.6)') "ETOT", &
    4507            0 :             almo_scf_env%almo_scf_energy, &
    4508            0 :             energy_correction_final, &
    4509            0 :             almo_scf_env%almo_scf_energy + energy_correction_final, &
    4510            0 :             t2 - t1
    4511            0 :          WRITE (unit_nr, *)
    4512              :       END IF
    4513              : 
    4514            0 :       CALL timestop(handle)
    4515              : 
    4516            0 :    END SUBROUTINE harris_foulkes_correction
    4517              : 
    4518              : ! **************************************************************************************************
    4519              : !> \brief triu of a dbcsr matrix
    4520              : !> \param matrix ...
    4521              : ! **************************************************************************************************
    4522            0 :    SUBROUTINE make_triu(matrix)
    4523              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
    4524              : 
    4525              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'make_triu'
    4526              : 
    4527              :       INTEGER                                            :: col, handle, i, j, row
    4528            0 :       REAL(dp), DIMENSION(:, :), POINTER                 :: block
    4529              :       TYPE(dbcsr_iterator_type)                          :: iter
    4530              : 
    4531            0 :       CALL timeset(routineN, handle)
    4532              : 
    4533            0 :       CALL dbcsr_iterator_start(iter, matrix)
    4534            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    4535            0 :          CALL dbcsr_iterator_next_block(iter, row, col, block)
    4536            0 :          IF (row > col) block(:, :) = 0.0_dp
    4537            0 :          IF (row == col) THEN
    4538            0 :             DO j = 1, SIZE(block, 2)
    4539            0 :             DO i = j + 1, SIZE(block, 1)
    4540            0 :                block(i, j) = 0.0_dp
    4541              :             END DO
    4542              :             END DO
    4543              :          END IF
    4544              :       END DO
    4545            0 :       CALL dbcsr_iterator_stop(iter)
    4546            0 :       CALL dbcsr_filter(matrix, eps=0.0_dp)
    4547              : 
    4548            0 :       CALL timestop(handle)
    4549            0 :    END SUBROUTINE make_triu
    4550              : 
    4551              : ! **************************************************************************************************
    4552              : !> \brief Computes a diagonal preconditioner for the cg optimization of k matrix
    4553              : !> \param prec ...
    4554              : !> \param vd_prop ...
    4555              : !> \param f ...
    4556              : !> \param x ...
    4557              : !> \param oo_inv_x_tr ...
    4558              : !> \param s ...
    4559              : !> \param grad ...
    4560              : !> \param vd_blk ...
    4561              : !> \param t ...
    4562              : !> \param template_vd_vd_blk ...
    4563              : !> \param template_vr_vr_blk ...
    4564              : !> \param template_n_vr ...
    4565              : !> \param spin_factor ...
    4566              : !> \param eps_filter ...
    4567              : !> \par History
    4568              : !>       2011.09 created [Rustam Z Khaliullin]
    4569              : !> \author Rustam Z Khaliullin
    4570              : ! **************************************************************************************************
    4571            0 :    SUBROUTINE opt_k_create_preconditioner(prec, vd_prop, f, x, oo_inv_x_tr, s, grad, &
    4572              :                                           vd_blk, t, template_vd_vd_blk, template_vr_vr_blk, template_n_vr, &
    4573              :                                           spin_factor, eps_filter)
    4574              : 
    4575              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: prec
    4576              :       TYPE(dbcsr_type), INTENT(IN)                       :: vd_prop, f, x, oo_inv_x_tr, s
    4577              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: grad
    4578              :       TYPE(dbcsr_type), INTENT(IN)                       :: vd_blk, t, template_vd_vd_blk, &
    4579              :                                                             template_vr_vr_blk, template_n_vr
    4580              :       REAL(KIND=dp), INTENT(IN)                          :: spin_factor, eps_filter
    4581              : 
    4582              :       CHARACTER(len=*), PARAMETER :: routineN = 'opt_k_create_preconditioner'
    4583              : 
    4584              :       INTEGER                                            :: handle, p_nrows, q_nrows
    4585            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: p_diagonal, q_diagonal
    4586              :       TYPE(dbcsr_type)                                   :: pp_diag, qq_diag, t1, t2, tmp, &
    4587              :                                                             tmp1_n_vr, tmp2_n_vr, tmp_n_vd, &
    4588              :                                                             tmp_vd_vd_blk, tmp_vr_vr_blk
    4589              : 
    4590            0 :       CALL timeset(routineN, handle)
    4591              : 
    4592              :       ! initialize a matrix to 1.0
    4593            0 :       CALL dbcsr_create(tmp, template=prec)
    4594              :       ! in order to use dbcsr_set matrix blocks must exist
    4595            0 :       CALL dbcsr_copy(tmp, prec)
    4596            0 :       CALL dbcsr_set(tmp, 1.0_dp)
    4597              : 
    4598              :       ! compute qq = (Vd^tr)*F*Vd
    4599            0 :       CALL dbcsr_create(tmp_n_vd, template=vd_prop)
    4600              :       CALL dbcsr_multiply("N", "N", 1.0_dp, f, vd_prop, &
    4601            0 :                           0.0_dp, tmp_n_vd, filter_eps=eps_filter)
    4602              :       CALL dbcsr_create(tmp_vd_vd_blk, &
    4603            0 :                         template=template_vd_vd_blk)
    4604            0 :       CALL dbcsr_copy(tmp_vd_vd_blk, template_vd_vd_blk)
    4605              :       CALL dbcsr_multiply("T", "N", 1.0_dp, vd_prop, tmp_n_vd, &
    4606              :                           0.0_dp, tmp_vd_vd_blk, &
    4607              :                           retain_sparsity=.TRUE., &
    4608            0 :                           filter_eps=eps_filter)
    4609              :       ! copy diagonal elements of the result into rows of a matrix
    4610            0 :       CALL dbcsr_get_info(tmp_vd_vd_blk, nfullrows_total=q_nrows)
    4611            0 :       ALLOCATE (q_diagonal(q_nrows))
    4612            0 :       CALL dbcsr_get_diag(tmp_vd_vd_blk, q_diagonal)
    4613              :       CALL dbcsr_create(qq_diag, &
    4614            0 :                         template=template_vd_vd_blk)
    4615            0 :       CALL dbcsr_add_on_diag(qq_diag, 1.0_dp)
    4616            0 :       CALL dbcsr_set_diag(qq_diag, q_diagonal)
    4617            0 :       CALL dbcsr_create(t1, template=prec)
    4618              :       CALL dbcsr_multiply("N", "N", 1.0_dp, qq_diag, tmp, &
    4619            0 :                           0.0_dp, t1, filter_eps=eps_filter)
    4620              : 
    4621              :       ! compute pp = X*sigma_oo_inv*X^tr
    4622            0 :       CALL dbcsr_create(tmp_vr_vr_blk, template=template_vr_vr_blk)
    4623            0 :       CALL dbcsr_copy(tmp_vr_vr_blk, template_vr_vr_blk)
    4624              :       CALL dbcsr_multiply("N", "N", 1.0_dp, x, oo_inv_x_tr, &
    4625              :                           0.0_dp, tmp_vr_vr_blk, &
    4626              :                           retain_sparsity=.TRUE., &
    4627            0 :                           filter_eps=eps_filter)
    4628              :       ! copy diagonal elements of the result into cols of a matrix
    4629            0 :       CALL dbcsr_get_info(tmp_vr_vr_blk, nfullrows_total=p_nrows)
    4630            0 :       ALLOCATE (p_diagonal(p_nrows))
    4631            0 :       CALL dbcsr_get_diag(tmp_vr_vr_blk, p_diagonal)
    4632            0 :       CALL dbcsr_create(pp_diag, template=template_vr_vr_blk)
    4633            0 :       CALL dbcsr_add_on_diag(pp_diag, 1.0_dp)
    4634            0 :       CALL dbcsr_set_diag(pp_diag, p_diagonal)
    4635            0 :       CALL dbcsr_set(tmp, 1.0_dp)
    4636            0 :       CALL dbcsr_create(t2, template=prec)
    4637              :       CALL dbcsr_multiply("N", "N", 1.0_dp, tmp, pp_diag, &
    4638            0 :                           0.0_dp, t2, filter_eps=eps_filter)
    4639              : 
    4640            0 :       CALL dbcsr_hadamard_product(t1, t2, prec)
    4641              : 
    4642              :       ! compute qq = (Vd^tr)*S*Vd
    4643              :       CALL dbcsr_multiply("N", "N", 1.0_dp, s, vd_prop, &
    4644            0 :                           0.0_dp, tmp_n_vd, filter_eps=eps_filter)
    4645              :       CALL dbcsr_multiply("T", "N", 1.0_dp, vd_prop, tmp_n_vd, &
    4646              :                           0.0_dp, tmp_vd_vd_blk, &
    4647              :                           retain_sparsity=.TRUE., &
    4648            0 :                           filter_eps=eps_filter)
    4649              :       ! copy diagonal elements of the result into rows of a matrix
    4650            0 :       CALL dbcsr_get_diag(tmp_vd_vd_blk, q_diagonal)
    4651            0 :       CALL dbcsr_add_on_diag(qq_diag, 1.0_dp)
    4652            0 :       CALL dbcsr_set_diag(qq_diag, q_diagonal)
    4653            0 :       CALL dbcsr_set(tmp, 1.0_dp)
    4654              :       CALL dbcsr_multiply("N", "N", 1.0_dp, qq_diag, tmp, &
    4655            0 :                           0.0_dp, t1, filter_eps=eps_filter)
    4656              : 
    4657              :       ! compute pp = X*sig_oo_inv*(T^tr)*F*T*sig_oo_inv*(X^tr)
    4658            0 :       CALL dbcsr_create(tmp1_n_vr, template=template_n_vr)
    4659            0 :       CALL dbcsr_create(tmp2_n_vr, template=template_n_vr)
    4660              :       CALL dbcsr_multiply("N", "N", 1.0_dp, t, oo_inv_x_tr, &
    4661            0 :                           0.0_dp, tmp1_n_vr, filter_eps=eps_filter)
    4662              :       CALL dbcsr_multiply("N", "N", 1.0_dp, f, tmp1_n_vr, &
    4663            0 :                           0.0_dp, tmp2_n_vr, filter_eps=eps_filter)
    4664              :       CALL dbcsr_multiply("T", "N", 1.0_dp, tmp1_n_vr, tmp2_n_vr, &
    4665              :                           0.0_dp, tmp_vr_vr_blk, &
    4666              :                           retain_sparsity=.TRUE., &
    4667            0 :                           filter_eps=eps_filter)
    4668              :       ! copy diagonal elements of the result into cols of a matrix
    4669            0 :       CALL dbcsr_get_diag(tmp_vr_vr_blk, p_diagonal)
    4670            0 :       CALL dbcsr_add_on_diag(pp_diag, 1.0_dp)
    4671            0 :       CALL dbcsr_set_diag(pp_diag, p_diagonal)
    4672            0 :       CALL dbcsr_set(tmp, 1.0_dp)
    4673              :       CALL dbcsr_multiply("N", "N", 1.0_dp, tmp, pp_diag, &
    4674            0 :                           0.0_dp, t2, filter_eps=eps_filter)
    4675              : 
    4676            0 :       CALL dbcsr_hadamard_product(t1, t2, tmp)
    4677            0 :       CALL dbcsr_add(prec, tmp, 1.0_dp, -1.0_dp)
    4678            0 :       CALL dbcsr_scale(prec, 2.0_dp*spin_factor)
    4679              : 
    4680              :       ! compute qp = X*sig_oo_inv*(T^tr)*S*Vd
    4681              :       CALL dbcsr_multiply("N", "N", 1.0_dp, s, vd_blk, &
    4682            0 :                           0.0_dp, tmp_n_vd, filter_eps=eps_filter)
    4683              :       CALL dbcsr_multiply("T", "N", 1.0_dp, tmp_n_vd, tmp1_n_vr, &
    4684              :                           0.0_dp, tmp, retain_sparsity=.TRUE., &
    4685            0 :                           filter_eps=eps_filter)
    4686            0 :       CALL dbcsr_hadamard_product(grad, tmp, t1)
    4687              :       ! gradient already contains 2.0*spin_factor
    4688            0 :       CALL dbcsr_scale(t1, -2.0_dp)
    4689              : 
    4690            0 :       CALL dbcsr_add(prec, t1, 1.0_dp, 1.0_dp)
    4691              : 
    4692            0 :       CALL inverse_of_elements(prec)
    4693            0 :       CALL dbcsr_filter(prec, eps_filter)
    4694              : 
    4695            0 :       DEALLOCATE (q_diagonal)
    4696            0 :       DEALLOCATE (p_diagonal)
    4697            0 :       CALL dbcsr_release(tmp)
    4698            0 :       CALL dbcsr_release(qq_diag)
    4699            0 :       CALL dbcsr_release(t1)
    4700            0 :       CALL dbcsr_release(pp_diag)
    4701            0 :       CALL dbcsr_release(t2)
    4702            0 :       CALL dbcsr_release(tmp_n_vd)
    4703            0 :       CALL dbcsr_release(tmp_vd_vd_blk)
    4704            0 :       CALL dbcsr_release(tmp_vr_vr_blk)
    4705            0 :       CALL dbcsr_release(tmp1_n_vr)
    4706            0 :       CALL dbcsr_release(tmp2_n_vr)
    4707              : 
    4708            0 :       CALL timestop(handle)
    4709              : 
    4710            0 :    END SUBROUTINE opt_k_create_preconditioner
    4711              : 
    4712              : ! **************************************************************************************************
    4713              : !> \brief Computes a block-diagonal preconditioner for the optimization of
    4714              : !>        k matrix
    4715              : !> \param almo_scf_env ...
    4716              : !> \param vd_prop ...
    4717              : !> \param oo_inv_x_tr ...
    4718              : !> \param t_curr ...
    4719              : !> \param ispin ...
    4720              : !> \param spin_factor ...
    4721              : !> \par History
    4722              : !>       2011.10 created [Rustam Z Khaliullin]
    4723              : !> \author Rustam Z Khaliullin
    4724              : ! **************************************************************************************************
    4725            0 :    SUBROUTINE opt_k_create_preconditioner_blk(almo_scf_env, vd_prop, oo_inv_x_tr, &
    4726              :                                               t_curr, ispin, spin_factor)
    4727              : 
    4728              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
    4729              :       TYPE(dbcsr_type), INTENT(IN)                       :: vd_prop, oo_inv_x_tr, t_curr
    4730              :       INTEGER, INTENT(IN)                                :: ispin
    4731              :       REAL(KIND=dp), INTENT(IN)                          :: spin_factor
    4732              : 
    4733              :       CHARACTER(len=*), PARAMETER :: routineN = 'opt_k_create_preconditioner_blk'
    4734              : 
    4735              :       INTEGER                                            :: handle
    4736              :       REAL(KIND=dp)                                      :: eps_filter
    4737              :       TYPE(dbcsr_type)                                   :: opt_k_e_dd, opt_k_e_rr, s_dd_sqrt, &
    4738              :                                                             s_rr_sqrt, t1, tmp, tmp1_n_vr, &
    4739              :                                                             tmp2_n_vr, tmp_n_vd, tmp_vd_vd_blk, &
    4740              :                                                             tmp_vr_vr_blk
    4741              : 
    4742              : ! matrices that has been computed outside the routine already
    4743              : 
    4744            0 :       CALL timeset(routineN, handle)
    4745              : 
    4746            0 :       eps_filter = almo_scf_env%eps_filter
    4747              : 
    4748              :       ! compute S_qq = (Vd^tr)*S*Vd
    4749            0 :       CALL dbcsr_create(tmp_n_vd, template=almo_scf_env%matrix_v_disc(ispin))
    4750              :       CALL dbcsr_create(tmp_vd_vd_blk, &
    4751              :                         template=almo_scf_env%matrix_vv_disc_blk(ispin), &
    4752            0 :                         matrix_type=dbcsr_type_no_symmetry)
    4753              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4754              :                           almo_scf_env%matrix_s(1), &
    4755              :                           vd_prop, &
    4756            0 :                           0.0_dp, tmp_n_vd, filter_eps=eps_filter)
    4757              :       CALL dbcsr_copy(tmp_vd_vd_blk, &
    4758            0 :                       almo_scf_env%matrix_vv_disc_blk(ispin))
    4759              :       CALL dbcsr_multiply("T", "N", 1.0_dp, vd_prop, tmp_n_vd, &
    4760              :                           0.0_dp, tmp_vd_vd_blk, &
    4761            0 :                           retain_sparsity=.TRUE.)
    4762              : 
    4763              :       CALL dbcsr_create(s_dd_sqrt, &
    4764              :                         template=almo_scf_env%matrix_vv_disc_blk(ispin), &
    4765            0 :                         matrix_type=dbcsr_type_no_symmetry)
    4766              :       CALL matrix_sqrt_Newton_Schulz(s_dd_sqrt, &
    4767              :                                      almo_scf_env%opt_k_t_dd(ispin), &
    4768              :                                      tmp_vd_vd_blk, &
    4769              :                                      threshold=eps_filter, &
    4770              :                                      order=almo_scf_env%order_lanczos, &
    4771              :                                      eps_lanczos=almo_scf_env%eps_lanczos, &
    4772            0 :                                      max_iter_lanczos=almo_scf_env%max_iter_lanczos)
    4773              : 
    4774              :       ! compute F_qq = (Vd^tr)*F*Vd
    4775              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4776              :                           almo_scf_env%matrix_ks_0deloc(ispin), &
    4777              :                           vd_prop, &
    4778            0 :                           0.0_dp, tmp_n_vd, filter_eps=eps_filter)
    4779              :       CALL dbcsr_copy(tmp_vd_vd_blk, &
    4780            0 :                       almo_scf_env%matrix_vv_disc_blk(ispin))
    4781              :       CALL dbcsr_multiply("T", "N", 1.0_dp, vd_prop, tmp_n_vd, &
    4782              :                           0.0_dp, tmp_vd_vd_blk, &
    4783            0 :                           retain_sparsity=.TRUE.)
    4784            0 :       CALL dbcsr_release(tmp_n_vd)
    4785              : 
    4786              :       ! bring to the blocked-orthogonalized basis
    4787              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4788              :                           tmp_vd_vd_blk, &
    4789              :                           almo_scf_env%opt_k_t_dd(ispin), &
    4790            0 :                           0.0_dp, s_dd_sqrt, filter_eps=eps_filter)
    4791              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4792              :                           almo_scf_env%opt_k_t_dd(ispin), &
    4793              :                           s_dd_sqrt, &
    4794            0 :                           0.0_dp, tmp_vd_vd_blk, filter_eps=eps_filter)
    4795              : 
    4796              :       ! diagonalize the matrix
    4797              :       CALL dbcsr_create(opt_k_e_dd, &
    4798            0 :                         template=almo_scf_env%matrix_vv_disc_blk(ispin))
    4799            0 :       CALL dbcsr_release(s_dd_sqrt)
    4800              :       CALL dbcsr_create(s_dd_sqrt, &
    4801              :                         template=almo_scf_env%matrix_vv_disc_blk(ispin), &
    4802            0 :                         matrix_type=dbcsr_type_no_symmetry)
    4803              :       CALL diagonalize_diagonal_blocks(tmp_vd_vd_blk, &
    4804              :                                        s_dd_sqrt, &
    4805            0 :                                        opt_k_e_dd)
    4806              : 
    4807              :       ! obtain the transformation matrix in the discarded subspace
    4808              :       ! T = S^{-1/2}.U
    4809              :       CALL dbcsr_copy(tmp_vd_vd_blk, &
    4810            0 :                       almo_scf_env%opt_k_t_dd(ispin))
    4811              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4812              :                           tmp_vd_vd_blk, &
    4813              :                           s_dd_sqrt, &
    4814              :                           0.0_dp, almo_scf_env%opt_k_t_dd(ispin), &
    4815            0 :                           filter_eps=eps_filter)
    4816            0 :       CALL dbcsr_release(s_dd_sqrt)
    4817            0 :       CALL dbcsr_release(tmp_vd_vd_blk)
    4818              : 
    4819              :       ! copy diagonal elements of the result into rows of a matrix
    4820              :       CALL dbcsr_create(tmp, &
    4821            0 :                         template=almo_scf_env%matrix_k_blk_ones(ispin))
    4822              :       CALL dbcsr_copy(tmp, &
    4823            0 :                       almo_scf_env%matrix_k_blk_ones(ispin))
    4824              :       CALL dbcsr_create(t1, &
    4825            0 :                         template=almo_scf_env%matrix_k_blk_ones(ispin))
    4826              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4827              :                           opt_k_e_dd, tmp, &
    4828            0 :                           0.0_dp, t1, filter_eps=eps_filter)
    4829            0 :       CALL dbcsr_release(opt_k_e_dd)
    4830              : 
    4831              :       ! compute S_pp = X*sigma_oo_inv*X^tr
    4832              :       CALL dbcsr_create(tmp_vr_vr_blk, &
    4833              :                         template=almo_scf_env%matrix_sigma_vv_blk(ispin), &
    4834            0 :                         matrix_type=dbcsr_type_no_symmetry)
    4835              :       CALL dbcsr_copy(tmp_vr_vr_blk, &
    4836            0 :                       almo_scf_env%matrix_sigma_vv_blk(ispin))
    4837              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4838              :                           almo_scf_env%matrix_x(ispin), &
    4839              :                           oo_inv_x_tr, &
    4840              :                           0.0_dp, tmp_vr_vr_blk, &
    4841            0 :                           retain_sparsity=.TRUE.)
    4842              : 
    4843              :       ! obtain the orthogonalization matrix
    4844              :       CALL dbcsr_create(s_rr_sqrt, &
    4845              :                         template=almo_scf_env%matrix_sigma_vv_blk(ispin), &
    4846            0 :                         matrix_type=dbcsr_type_no_symmetry)
    4847              :       CALL matrix_sqrt_Newton_Schulz(s_rr_sqrt, &
    4848              :                                      almo_scf_env%opt_k_t_rr(ispin), &
    4849              :                                      tmp_vr_vr_blk, &
    4850              :                                      threshold=eps_filter, &
    4851              :                                      order=almo_scf_env%order_lanczos, &
    4852              :                                      eps_lanczos=almo_scf_env%eps_lanczos, &
    4853            0 :                                      max_iter_lanczos=almo_scf_env%max_iter_lanczos)
    4854              : 
    4855              :       ! compute F_pp = X*sig_oo_inv*(T^tr)*F*T*sig_oo_inv*(X^tr)
    4856              :       CALL dbcsr_create(tmp1_n_vr, &
    4857            0 :                         template=almo_scf_env%matrix_v(ispin))
    4858              :       CALL dbcsr_create(tmp2_n_vr, &
    4859            0 :                         template=almo_scf_env%matrix_v(ispin))
    4860              :       CALL dbcsr_multiply("N", "N", 1.0_dp, t_curr, oo_inv_x_tr, &
    4861            0 :                           0.0_dp, tmp1_n_vr, filter_eps=eps_filter)
    4862              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4863              :                           almo_scf_env%matrix_ks_0deloc(ispin), &
    4864              :                           tmp1_n_vr, &
    4865            0 :                           0.0_dp, tmp2_n_vr, filter_eps=eps_filter)
    4866              :       CALL dbcsr_multiply("T", "N", 1.0_dp, tmp1_n_vr, tmp2_n_vr, &
    4867              :                           0.0_dp, tmp_vr_vr_blk, &
    4868            0 :                           retain_sparsity=.TRUE.)
    4869            0 :       CALL dbcsr_release(tmp1_n_vr)
    4870            0 :       CALL dbcsr_release(tmp2_n_vr)
    4871              : 
    4872              :       ! bring to the blocked-orthogonalized basis
    4873              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4874              :                           tmp_vr_vr_blk, &
    4875              :                           almo_scf_env%opt_k_t_rr(ispin), &
    4876            0 :                           0.0_dp, s_rr_sqrt, filter_eps=eps_filter)
    4877              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4878              :                           almo_scf_env%opt_k_t_rr(ispin), &
    4879              :                           s_rr_sqrt, &
    4880            0 :                           0.0_dp, tmp_vr_vr_blk, filter_eps=eps_filter)
    4881              : 
    4882              :       ! diagonalize the matrix
    4883              :       CALL dbcsr_create(opt_k_e_rr, &
    4884            0 :                         template=almo_scf_env%matrix_sigma_vv_blk(ispin))
    4885            0 :       CALL dbcsr_release(s_rr_sqrt)
    4886              :       CALL dbcsr_create(s_rr_sqrt, &
    4887              :                         template=almo_scf_env%matrix_sigma_vv_blk(ispin), &
    4888            0 :                         matrix_type=dbcsr_type_no_symmetry)
    4889              :       CALL diagonalize_diagonal_blocks(tmp_vr_vr_blk, &
    4890              :                                        s_rr_sqrt, &
    4891            0 :                                        opt_k_e_rr)
    4892              : 
    4893              :       ! obtain the transformation matrix in the retained subspace
    4894              :       ! T = S^{-1/2}.U
    4895              :       CALL dbcsr_copy(tmp_vr_vr_blk, &
    4896            0 :                       almo_scf_env%opt_k_t_rr(ispin))
    4897              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4898              :                           tmp_vr_vr_blk, &
    4899              :                           s_rr_sqrt, &
    4900              :                           0.0_dp, almo_scf_env%opt_k_t_rr(ispin), &
    4901            0 :                           filter_eps=eps_filter)
    4902            0 :       CALL dbcsr_release(s_rr_sqrt)
    4903            0 :       CALL dbcsr_release(tmp_vr_vr_blk)
    4904              : 
    4905              :       ! copy diagonal elements of the result into cols of a matrix
    4906              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4907              :                           tmp, opt_k_e_rr, &
    4908              :                           0.0_dp, almo_scf_env%opt_k_denom(ispin), &
    4909            0 :                           filter_eps=eps_filter)
    4910            0 :       CALL dbcsr_release(opt_k_e_rr)
    4911            0 :       CALL dbcsr_release(tmp)
    4912              : 
    4913              :       ! form the denominator matrix
    4914              :       CALL dbcsr_add(almo_scf_env%opt_k_denom(ispin), t1, &
    4915            0 :                      -1.0_dp, 1.0_dp)
    4916            0 :       CALL dbcsr_release(t1)
    4917              :       CALL dbcsr_scale(almo_scf_env%opt_k_denom(ispin), &
    4918            0 :                        2.0_dp*spin_factor)
    4919              : 
    4920            0 :       CALL inverse_of_elements(almo_scf_env%opt_k_denom(ispin))
    4921              :       CALL dbcsr_filter(almo_scf_env%opt_k_denom(ispin), &
    4922            0 :                         eps_filter)
    4923              : 
    4924            0 :       CALL timestop(handle)
    4925              : 
    4926            0 :    END SUBROUTINE opt_k_create_preconditioner_blk
    4927              : 
    4928              : ! **************************************************************************************************
    4929              : !> \brief Applies a block-diagonal preconditioner for the optimization of
    4930              : !>        k matrix (preconditioner matrices must be calculated and stored
    4931              : !>        beforehand)
    4932              : !> \param almo_scf_env ...
    4933              : !> \param step ...
    4934              : !> \param grad ...
    4935              : !> \param ispin ...
    4936              : !> \par History
    4937              : !>       2011.10 created [Rustam Z Khaliullin]
    4938              : !> \author Rustam Z Khaliullin
    4939              : ! **************************************************************************************************
    4940            0 :    SUBROUTINE opt_k_apply_preconditioner_blk(almo_scf_env, step, grad, ispin)
    4941              : 
    4942              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
    4943              :       TYPE(dbcsr_type), INTENT(OUT)                      :: step
    4944              :       TYPE(dbcsr_type), INTENT(IN)                       :: grad
    4945              :       INTEGER, INTENT(IN)                                :: ispin
    4946              : 
    4947              :       CHARACTER(len=*), PARAMETER :: routineN = 'opt_k_apply_preconditioner_blk'
    4948              : 
    4949              :       INTEGER                                            :: handle
    4950              :       REAL(KIND=dp)                                      :: eps_filter
    4951              :       TYPE(dbcsr_type)                                   :: tmp_k
    4952              : 
    4953            0 :       CALL timeset(routineN, handle)
    4954              : 
    4955            0 :       eps_filter = almo_scf_env%eps_filter
    4956              : 
    4957            0 :       CALL dbcsr_create(tmp_k, template=almo_scf_env%matrix_k_blk(ispin))
    4958              : 
    4959              :       ! transform gradient to the correct "diagonal" basis
    4960              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4961              :                           grad, almo_scf_env%opt_k_t_rr(ispin), &
    4962            0 :                           0.0_dp, tmp_k, filter_eps=eps_filter)
    4963              :       CALL dbcsr_multiply("T", "N", 1.0_dp, &
    4964              :                           almo_scf_env%opt_k_t_dd(ispin), tmp_k, &
    4965            0 :                           0.0_dp, step, filter_eps=eps_filter)
    4966              : 
    4967              :       ! apply diagonal preconditioner
    4968              :       CALL dbcsr_hadamard_product(step, &
    4969            0 :                                   almo_scf_env%opt_k_denom(ispin), tmp_k)
    4970              : 
    4971              :       ! back-transform the result to the initial basis
    4972              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    4973              :                           almo_scf_env%opt_k_t_dd(ispin), tmp_k, &
    4974            0 :                           0.0_dp, step, filter_eps=eps_filter)
    4975              :       CALL dbcsr_multiply("N", "T", 1.0_dp, &
    4976              :                           step, almo_scf_env%opt_k_t_rr(ispin), &
    4977            0 :                           0.0_dp, tmp_k, filter_eps=eps_filter)
    4978              : 
    4979            0 :       CALL dbcsr_copy(step, tmp_k)
    4980              : 
    4981            0 :       CALL dbcsr_release(tmp_k)
    4982              : 
    4983            0 :       CALL timestop(handle)
    4984              : 
    4985            0 :    END SUBROUTINE opt_k_apply_preconditioner_blk
    4986              : 
    4987              : ! **************************************************************************************************
    4988              : !> \brief Compute the gradient wrt the main variable (e.g. Theta, X)
    4989              : !> \param m_grad_out ...
    4990              : !> \param m_ks ...
    4991              : !> \param m_s ...
    4992              : !> \param m_t ...
    4993              : !> \param m_t0 ...
    4994              : !> \param m_siginv ...
    4995              : !> \param m_quench_t ...
    4996              : !> \param m_FTsiginv ...
    4997              : !> \param m_siginvTFTsiginv ...
    4998              : !> \param m_ST ...
    4999              : !> \param m_STsiginv0 ...
    5000              : !> \param m_theta ...
    5001              : !> \param domain_s_inv ...
    5002              : !> \param domain_r_down ...
    5003              : !> \param cpu_of_domain ...
    5004              : !> \param domain_map ...
    5005              : !> \param assume_t0_q0x ...
    5006              : !> \param optimize_theta ...
    5007              : !> \param normalize_orbitals ...
    5008              : !> \param penalty_occ_vol ...
    5009              : !> \param penalty_occ_local ...
    5010              : !> \param penalty_occ_vol_prefactor ...
    5011              : !> \param envelope_amplitude ...
    5012              : !> \param eps_filter ...
    5013              : !> \param spin_factor ...
    5014              : !> \param special_case ...
    5015              : !> \param m_sig_sqrti_ii ...
    5016              : !> \param op_sm_set ...
    5017              : !> \param weights ...
    5018              : !> \param energy_coeff ...
    5019              : !> \param localiz_coeff ...
    5020              : !> \par History
    5021              : !>       2015.03 created [Rustam Z Khaliullin]
    5022              : !> \author Rustam Z Khaliullin
    5023              : ! **************************************************************************************************
    5024         1498 :    SUBROUTINE compute_gradient(m_grad_out, m_ks, m_s, m_t, m_t0, &
    5025              :                                m_siginv, m_quench_t, m_FTsiginv, m_siginvTFTsiginv, m_ST, m_STsiginv0, &
    5026         1498 :                                m_theta, domain_s_inv, domain_r_down, &
    5027         1498 :                                cpu_of_domain, domain_map, assume_t0_q0x, optimize_theta, &
    5028              :                                normalize_orbitals, penalty_occ_vol, penalty_occ_local, &
    5029              :                                penalty_occ_vol_prefactor, envelope_amplitude, eps_filter, spin_factor, &
    5030         1498 :                                special_case, m_sig_sqrti_ii, op_sm_set, weights, energy_coeff, &
    5031              :                                localiz_coeff)
    5032              : 
    5033              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: m_grad_out, m_ks, m_s, m_t, m_t0, &
    5034              :                                                             m_siginv, m_quench_t, m_FTsiginv, &
    5035              :                                                             m_siginvTFTsiginv, m_ST, m_STsiginv0, &
    5036              :                                                             m_theta
    5037              :       TYPE(domain_submatrix_type), DIMENSION(:), &
    5038              :          INTENT(IN)                                      :: domain_s_inv, domain_r_down
    5039              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: cpu_of_domain
    5040              :       TYPE(domain_map_type), INTENT(IN)                  :: domain_map
    5041              :       LOGICAL, INTENT(IN)                                :: assume_t0_q0x, optimize_theta, &
    5042              :                                                             normalize_orbitals, penalty_occ_vol
    5043              :       LOGICAL, INTENT(IN), OPTIONAL                      :: penalty_occ_local
    5044              :       REAL(KIND=dp), INTENT(IN)                          :: penalty_occ_vol_prefactor, &
    5045              :                                                             envelope_amplitude, eps_filter, &
    5046              :                                                             spin_factor
    5047              :       INTEGER, INTENT(IN)                                :: special_case
    5048              :       TYPE(dbcsr_type), INTENT(IN), OPTIONAL             :: m_sig_sqrti_ii
    5049              :       TYPE(dbcsr_p_type), DIMENSION(:, :), OPTIONAL, &
    5050              :          POINTER                                         :: op_sm_set
    5051              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL  :: weights
    5052              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: energy_coeff, localiz_coeff
    5053              : 
    5054              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'compute_gradient'
    5055              : 
    5056              :       INTEGER                                            :: dim0, handle, idim0, nao, reim
    5057              :       LOGICAL                                            :: my_penalty_local
    5058              :       REAL(KIND=dp)                                      :: coeff, energy_g_norm, my_energy_coeff, &
    5059              :                                                             my_localiz_coeff, &
    5060              :                                                             penalty_occ_vol_g_norm
    5061         1498 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: tg_diagonal
    5062              :       TYPE(dbcsr_type)                                   :: m_tmp_no_1, m_tmp_no_2, m_tmp_no_3, &
    5063              :                                                             m_tmp_oo_1, m_tmp_oo_2, temp1, temp2, &
    5064              :                                                             tempNOcc1, tempOccOcc1
    5065              : 
    5066         1498 :       CALL timeset(routineN, handle)
    5067              : 
    5068         1498 :       IF (normalize_orbitals .AND. (.NOT. PRESENT(m_sig_sqrti_ii))) THEN
    5069            0 :          CPABORT("Normalization matrix is required")
    5070              :       END IF
    5071              : 
    5072         1498 :       my_penalty_local = .FALSE.
    5073         1498 :       my_localiz_coeff = 1.0_dp
    5074         1498 :       my_energy_coeff = 0.0_dp
    5075         1498 :       IF (PRESENT(localiz_coeff)) THEN
    5076         1072 :          my_localiz_coeff = localiz_coeff
    5077              :       END IF
    5078         1498 :       IF (PRESENT(energy_coeff)) THEN
    5079         1072 :          my_energy_coeff = energy_coeff
    5080              :       END IF
    5081         1498 :       IF (PRESENT(penalty_occ_local)) THEN
    5082         1072 :          my_penalty_local = penalty_occ_local
    5083              :       END IF
    5084              : 
    5085              :       ! use this otherways unused variables
    5086         1498 :       CALL dbcsr_get_info(matrix=m_ks, nfullrows_total=nao)
    5087         1498 :       CALL dbcsr_get_info(matrix=m_s, nfullrows_total=nao)
    5088         1498 :       CALL dbcsr_get_info(matrix=m_t, nfullrows_total=nao)
    5089              : 
    5090              :       CALL dbcsr_create(m_tmp_no_1, &
    5091              :                         template=m_quench_t, &
    5092         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5093              :       CALL dbcsr_create(m_tmp_no_2, &
    5094              :                         template=m_quench_t, &
    5095         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5096              :       CALL dbcsr_create(m_tmp_no_3, &
    5097              :                         template=m_quench_t, &
    5098         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5099              :       CALL dbcsr_create(m_tmp_oo_1, &
    5100              :                         template=m_siginv, &
    5101         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5102              :       CALL dbcsr_create(m_tmp_oo_2, &
    5103              :                         template=m_siginv, &
    5104         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5105              :       CALL dbcsr_create(tempNOcc1, &
    5106              :                         template=m_t, &
    5107         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5108              :       CALL dbcsr_create(tempOccOcc1, &
    5109              :                         template=m_siginv, &
    5110         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5111              :       CALL dbcsr_create(temp1, &
    5112              :                         template=m_t, &
    5113         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5114              :       CALL dbcsr_create(temp2, &
    5115              :                         template=m_t, &
    5116         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5117              : 
    5118         1498 :       CALL dbcsr_copy(m_tmp_no_2, m_quench_t)
    5119         1498 :       CALL dbcsr_copy(m_tmp_no_2, m_FTsiginv, keep_sparsity=.TRUE.)
    5120              : 
    5121              :       CALL dbcsr_multiply("N", "N", -1.0_dp, &
    5122              :                           m_ST, &
    5123              :                           m_siginvTFTsiginv, &
    5124              :                           1.0_dp, m_tmp_no_2, &
    5125         1498 :                           retain_sparsity=.TRUE.)
    5126         1498 :       CALL dbcsr_scale(m_tmp_no_2, 2.0_dp*spin_factor)
    5127              : 
    5128              :       ! LzL Add gradient for Localization
    5129         1498 :       IF (my_penalty_local) THEN
    5130              : 
    5131            0 :          CALL dbcsr_set(temp2, 0.0_dp) ! accumulate the localization gradient here
    5132              : 
    5133            0 :          DO idim0 = 1, SIZE(op_sm_set, 2) ! this loop is over miller ind
    5134              : 
    5135            0 :             DO reim = 1, SIZE(op_sm_set, 1) ! this loop is over Re/Im
    5136              : 
    5137              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5138              :                                    op_sm_set(reim, idim0)%matrix, &
    5139              :                                    m_t, &
    5140              :                                    0.0_dp, tempNOcc1, &
    5141            0 :                                    filter_eps=eps_filter)
    5142              : 
    5143              :                ! warning - save time by computing only the diagonal elements
    5144              :                CALL dbcsr_multiply("T", "N", 1.0_dp, &
    5145              :                                    m_t, &
    5146              :                                    tempNOcc1, &
    5147              :                                    0.0_dp, tempOccOcc1, &
    5148            0 :                                    filter_eps=eps_filter)
    5149              : 
    5150            0 :                CALL dbcsr_get_info(tempOccOcc1, nfullrows_total=dim0)
    5151            0 :                ALLOCATE (tg_diagonal(dim0))
    5152            0 :                CALL dbcsr_get_diag(tempOccOcc1, tg_diagonal)
    5153            0 :                CALL dbcsr_set(tempOccOcc1, 0.0_dp)
    5154            0 :                CALL dbcsr_set_diag(tempOccOcc1, tg_diagonal)
    5155            0 :                DEALLOCATE (tg_diagonal)
    5156              : 
    5157              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5158              :                                    tempNOcc1, &
    5159              :                                    tempOccOcc1, &
    5160              :                                    0.0_dp, temp1, &
    5161            0 :                                    filter_eps=eps_filter)
    5162              : 
    5163              :             END DO
    5164              : 
    5165              :             SELECT CASE (2) ! allows for selection of different spread functionals
    5166              :             CASE (1) ! functional =  -W_I * log( |z_I|^2 )
    5167            0 :                CPABORT("Localization function is not implemented")
    5168              :             CASE (2) ! functional =  W_I * ( 1 - |z_I|^2 )
    5169            0 :                coeff = -weights(idim0)
    5170              :             CASE (3) ! functional =  W_I * ( 1 - |z_I| )
    5171              :                CPABORT("Localization function is not implemented")
    5172              :             END SELECT
    5173            0 :             CALL dbcsr_add(temp2, temp1, 1.0_dp, coeff)
    5174              : 
    5175              :          END DO ! end loop over idim0
    5176            0 :          CALL dbcsr_add(m_tmp_no_2, temp2, my_energy_coeff, my_localiz_coeff*4.0_dp)
    5177              :       END IF
    5178              : 
    5179              :       ! add penalty on the occupied volume: det(sigma)
    5180         1498 :       IF (penalty_occ_vol) THEN
    5181            0 :          CALL dbcsr_copy(m_tmp_no_1, m_quench_t)
    5182              :          CALL dbcsr_multiply("N", "N", &
    5183              :                              penalty_occ_vol_prefactor, &
    5184              :                              m_ST, &
    5185              :                              m_siginv, &
    5186              :                              0.0_dp, m_tmp_no_1, &
    5187            0 :                              retain_sparsity=.TRUE.)
    5188              :          ! this norm does not contain the normalization factors
    5189            0 :          penalty_occ_vol_g_norm = dbcsr_maxabs(m_tmp_no_1)
    5190            0 :          energy_g_norm = dbcsr_maxabs(m_tmp_no_2)
    5191            0 :          CALL dbcsr_add(m_tmp_no_2, m_tmp_no_1, 1.0_dp, 1.0_dp)
    5192              :       END IF
    5193              : 
    5194              :       ! take into account the factor from the normalization constraint
    5195         1498 :       IF (normalize_orbitals) THEN
    5196              : 
    5197              :          ! G = ( G - ST.[tr(T).G]_ii ) . [sig_sqrti]_ii
    5198              :          ! this expression can be simplified to
    5199              :          ! G = ( G - c0*ST ) . [sig_sqrti]_ii
    5200              :          ! where c0 = penalty_occ_vol_prefactor
    5201              :          ! This is because tr(T).G_Energy = 0 and
    5202              :          !                 tr(T).G_Penalty = c0*I
    5203              : 
    5204              :          ! slower way of taking the norm into account
    5205            0 :          CALL dbcsr_copy(m_tmp_no_1, m_quench_t)
    5206              :          CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5207              :                              m_tmp_no_2, &
    5208              :                              m_sig_sqrti_ii, &
    5209              :                              0.0_dp, m_tmp_no_1, &
    5210            0 :                              retain_sparsity=.TRUE.)
    5211              : 
    5212              :          ! get [tr(T).G]_ii
    5213            0 :          CALL dbcsr_copy(m_tmp_oo_1, m_sig_sqrti_ii)
    5214              :          CALL dbcsr_multiply("T", "N", 1.0_dp, &
    5215              :                              m_t, &
    5216              :                              m_tmp_no_2, &
    5217              :                              0.0_dp, m_tmp_oo_1, &
    5218            0 :                              retain_sparsity=.TRUE.)
    5219              : 
    5220            0 :          CALL dbcsr_get_info(m_sig_sqrti_ii, nfullrows_total=dim0)
    5221            0 :          ALLOCATE (tg_diagonal(dim0))
    5222            0 :          CALL dbcsr_get_diag(m_tmp_oo_1, tg_diagonal)
    5223            0 :          CALL dbcsr_set(m_tmp_oo_1, 0.0_dp)
    5224            0 :          CALL dbcsr_set_diag(m_tmp_oo_1, tg_diagonal)
    5225            0 :          DEALLOCATE (tg_diagonal)
    5226              : 
    5227              :          CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5228              :                              m_sig_sqrti_ii, &
    5229              :                              m_tmp_oo_1, &
    5230              :                              0.0_dp, m_tmp_oo_2, &
    5231            0 :                              filter_eps=eps_filter)
    5232              :          CALL dbcsr_multiply("N", "N", -1.0_dp, &
    5233              :                              m_ST, &
    5234              :                              m_tmp_oo_2, &
    5235              :                              1.0_dp, m_tmp_no_1, &
    5236            0 :                              retain_sparsity=.TRUE.)
    5237              : 
    5238              :       ELSE
    5239              : 
    5240         1498 :          CALL dbcsr_copy(m_tmp_no_1, m_tmp_no_2)
    5241              : 
    5242              :       END IF ! normalize_orbitals
    5243              : 
    5244              :       ! project out the occupied space from the gradient
    5245         1498 :       IF (assume_t0_q0x) THEN
    5246          466 :          IF (special_case == xalmo_case_fully_deloc) THEN
    5247          160 :             CALL dbcsr_copy(m_grad_out, m_tmp_no_1)
    5248              :             CALL dbcsr_multiply("T", "N", 1.0_dp, &
    5249              :                                 m_t0, &
    5250              :                                 m_grad_out, &
    5251              :                                 0.0_dp, m_tmp_oo_1, &
    5252          160 :                                 filter_eps=eps_filter)
    5253              :             CALL dbcsr_multiply("N", "N", -1.0_dp, &
    5254              :                                 m_STsiginv0, &
    5255              :                                 m_tmp_oo_1, &
    5256              :                                 1.0_dp, m_grad_out, &
    5257          160 :                                 filter_eps=eps_filter)
    5258          306 :          ELSE IF (special_case == xalmo_case_block_diag) THEN
    5259            0 :             CPABORT("Cannot project the zero-order space from itself")
    5260              :          ELSE
    5261              :             ! no special case: normal xALMOs
    5262              :             CALL apply_domain_operators( &
    5263              :                matrix_in=m_tmp_no_1, &
    5264              :                matrix_out=m_grad_out, &
    5265              :                operator2=domain_r_down(:), &
    5266              :                operator1=domain_s_inv(:), &
    5267              :                dpattern=m_quench_t, &
    5268              :                map=domain_map, &
    5269              :                node_of_domain=cpu_of_domain, &
    5270              :                my_action=1, &
    5271              :                filter_eps=eps_filter, &
    5272              :                !matrix_trimmer=,&
    5273          306 :                use_trimmer=.FALSE.)
    5274              :          END IF ! my_special_case
    5275          466 :          CALL dbcsr_copy(m_tmp_no_1, m_grad_out)
    5276              :       END IF
    5277              : 
    5278              :       ! transform d_E/d_T to d_E/d_theta
    5279         1498 :       IF (optimize_theta) THEN
    5280            0 :          CALL dbcsr_copy(m_tmp_no_2, m_theta)
    5281            0 :          CALL dtanh_of_elements(m_tmp_no_2, alpha=1.0_dp/envelope_amplitude)
    5282            0 :          CALL dbcsr_scale(m_tmp_no_2, envelope_amplitude)
    5283            0 :          CALL dbcsr_set(m_tmp_no_3, 0.0_dp)
    5284            0 :          CALL dbcsr_filter(m_tmp_no_3, eps_filter)
    5285              :          CALL dbcsr_hadamard_product(m_tmp_no_1, &
    5286              :                                      m_tmp_no_2, &
    5287            0 :                                      m_tmp_no_3)
    5288              :          CALL dbcsr_hadamard_product(m_tmp_no_3, &
    5289              :                                      m_quench_t, &
    5290            0 :                                      m_grad_out)
    5291              :       ELSE ! simply copy
    5292              :          CALL dbcsr_hadamard_product(m_tmp_no_1, &
    5293              :                                      m_quench_t, &
    5294         1498 :                                      m_grad_out)
    5295              :       END IF
    5296         1498 :       CALL dbcsr_filter(m_grad_out, eps_filter)
    5297              : 
    5298         1498 :       CALL dbcsr_release(m_tmp_no_1)
    5299         1498 :       CALL dbcsr_release(m_tmp_no_2)
    5300         1498 :       CALL dbcsr_release(m_tmp_no_3)
    5301         1498 :       CALL dbcsr_release(m_tmp_oo_1)
    5302         1498 :       CALL dbcsr_release(m_tmp_oo_2)
    5303         1498 :       CALL dbcsr_release(tempNOcc1)
    5304         1498 :       CALL dbcsr_release(tempOccOcc1)
    5305         1498 :       CALL dbcsr_release(temp1)
    5306         1498 :       CALL dbcsr_release(temp2)
    5307              : 
    5308         1498 :       CALL timestop(handle)
    5309              : 
    5310         2996 :    END SUBROUTINE compute_gradient
    5311              : 
    5312              : ! **************************************************************************************************
    5313              : !> \brief Serial code that prints matrices readable by Mathematica
    5314              : !> \param matrix - matrix to print
    5315              : !> \param filename ...
    5316              : !> \par History
    5317              : !>       2015.05 created [Rustam Z. Khaliullin]
    5318              : !> \author Rustam Z. Khaliullin
    5319              : ! **************************************************************************************************
    5320            0 :    SUBROUTINE print_mathematica_matrix(matrix, filename)
    5321              : 
    5322              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
    5323              :       CHARACTER(len=*), INTENT(IN)                       :: filename
    5324              : 
    5325              :       CHARACTER(len=*), PARAMETER :: routineN = 'print_mathematica_matrix'
    5326              : 
    5327              :       CHARACTER(LEN=20)                                  :: formatstr, Scols
    5328              :       INTEGER                                            :: col, fiunit, handle, hori_offset, jj, &
    5329              :                                                             nblkcols_tot, nblkrows_tot, Ncols, &
    5330              :                                                             ncores, Nrows, row, unit_nr, &
    5331              :                                                             vert_offset
    5332            0 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ao_block_sizes, mo_block_sizes
    5333            0 :       INTEGER, DIMENSION(:), POINTER                     :: ao_blk_sizes, mo_blk_sizes
    5334              :       LOGICAL                                            :: found
    5335            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: H
    5336            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block_p
    5337              :       TYPE(cp_logger_type), POINTER                      :: logger
    5338              :       TYPE(dbcsr_distribution_type)                      :: dist
    5339              :       TYPE(dbcsr_type)                                   :: matrix_asym
    5340              : 
    5341            0 :       CALL timeset(routineN, handle)
    5342              : 
    5343              :       ! get a useful output_unit
    5344            0 :       logger => cp_get_default_logger()
    5345            0 :       IF (logger%para_env%is_source()) THEN
    5346            0 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    5347              :       ELSE
    5348              :          unit_nr = -1
    5349              :       END IF
    5350              : 
    5351              :       ! serial code only
    5352            0 :       CALL dbcsr_get_info(matrix, distribution=dist)
    5353            0 :       CALL dbcsr_distribution_get(dist, numnodes=ncores)
    5354            0 :       IF (ncores > 1) THEN
    5355            0 :          CPABORT("mathematica files: serial code only")
    5356              :       END IF
    5357              : 
    5358              :       CALL dbcsr_get_info(matrix, row_blk_size=ao_blk_sizes, col_blk_size=mo_blk_sizes, &
    5359            0 :                           nblkrows_total=nblkrows_tot, nblkcols_total=nblkcols_tot)
    5360            0 :       CPASSERT(nblkrows_tot == nblkcols_tot)
    5361            0 :       ALLOCATE (mo_block_sizes(nblkcols_tot), ao_block_sizes(nblkcols_tot))
    5362            0 :       mo_block_sizes(:) = mo_blk_sizes(:)
    5363            0 :       ao_block_sizes(:) = ao_blk_sizes(:)
    5364              : 
    5365              :       CALL dbcsr_create(matrix_asym, &
    5366              :                         template=matrix, &
    5367            0 :                         matrix_type=dbcsr_type_no_symmetry)
    5368            0 :       CALL dbcsr_desymmetrize(matrix, matrix_asym)
    5369              : 
    5370            0 :       Ncols = SUM(mo_block_sizes)
    5371            0 :       Nrows = SUM(ao_block_sizes)
    5372            0 :       ALLOCATE (H(Nrows, Ncols))
    5373            0 :       H(:, :) = 0.0_dp
    5374              : 
    5375            0 :       hori_offset = 0
    5376            0 :       DO col = 1, nblkcols_tot
    5377              : 
    5378            0 :          vert_offset = 0
    5379            0 :          DO row = 1, nblkrows_tot
    5380              : 
    5381            0 :             CALL dbcsr_get_block_p(matrix_asym, row, col, block_p, found)
    5382            0 :             IF (found) THEN
    5383              : 
    5384              :                H(vert_offset + 1:vert_offset + ao_block_sizes(row), &
    5385              :                  hori_offset + 1:hori_offset + mo_block_sizes(col)) &
    5386            0 :                   = block_p(:, :)
    5387              : 
    5388              :             END IF
    5389              : 
    5390            0 :             vert_offset = vert_offset + ao_block_sizes(row)
    5391              : 
    5392              :          END DO
    5393              : 
    5394            0 :          hori_offset = hori_offset + mo_block_sizes(col)
    5395              : 
    5396              :       END DO ! loop over electron blocks
    5397              : 
    5398            0 :       CALL dbcsr_release(matrix_asym)
    5399              : 
    5400            0 :       IF (unit_nr > 0) THEN
    5401            0 :          CALL open_file(filename, unit_number=fiunit, file_status='REPLACE')
    5402            0 :          WRITE (Scols, "(I10)") Ncols
    5403            0 :          formatstr = "("//TRIM(Scols)//"E27.17)"
    5404            0 :          DO jj = 1, Nrows
    5405            0 :             WRITE (fiunit, formatstr) H(jj, :)
    5406              :          END DO
    5407            0 :          CALL close_file(fiunit)
    5408              :       END IF
    5409              : 
    5410            0 :       DEALLOCATE (mo_block_sizes)
    5411            0 :       DEALLOCATE (ao_block_sizes)
    5412            0 :       DEALLOCATE (H)
    5413              : 
    5414            0 :       CALL timestop(handle)
    5415              : 
    5416            0 :    END SUBROUTINE print_mathematica_matrix
    5417              : 
    5418              : ! **************************************************************************************************
    5419              : !> \brief Compute the objective functional of NLMOs
    5420              : !> \param localization_obj_function_ispin ...
    5421              : !> \param penalty_func_ispin ...
    5422              : !> \param penalty_vol_prefactor ...
    5423              : !> \param overlap_determinant ...
    5424              : !> \param m_sigma ...
    5425              : !> \param nocc ...
    5426              : !> \param m_B0 ...
    5427              : !> \param m_theta_normalized ...
    5428              : !> \param template_matrix_mo ...
    5429              : !> \param weights ...
    5430              : !> \param m_S0 ...
    5431              : !> \param just_started ...
    5432              : !> \param penalty_amplitude ...
    5433              : !> \param eps_filter ...
    5434              : !> \par History
    5435              : !>       2020.01 created [Ziling Luo]
    5436              : !> \author Ziling Luo
    5437              : ! **************************************************************************************************
    5438           82 :    SUBROUTINE compute_obj_nlmos(localization_obj_function_ispin, penalty_func_ispin, &
    5439           82 :                                 penalty_vol_prefactor, overlap_determinant, m_sigma, nocc, m_B0, &
    5440           82 :                                 m_theta_normalized, template_matrix_mo, weights, m_S0, just_started, &
    5441              :                                 penalty_amplitude, eps_filter)
    5442              : 
    5443              :       REAL(KIND=dp), INTENT(INOUT) :: localization_obj_function_ispin, penalty_func_ispin, &
    5444              :          penalty_vol_prefactor, overlap_determinant
    5445              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: m_sigma
    5446              :       INTEGER, INTENT(IN)                                :: nocc
    5447              :       TYPE(dbcsr_type), DIMENSION(:, :), INTENT(IN)      :: m_B0
    5448              :       TYPE(dbcsr_type), INTENT(IN)                       :: m_theta_normalized, template_matrix_mo
    5449              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: weights
    5450              :       TYPE(dbcsr_type), INTENT(IN)                       :: m_S0
    5451              :       LOGICAL, INTENT(IN)                                :: just_started
    5452              :       REAL(KIND=dp), INTENT(IN)                          :: penalty_amplitude, eps_filter
    5453              : 
    5454              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'compute_obj_nlmos'
    5455              : 
    5456              :       INTEGER                                            :: handle, idim0, ielem, reim
    5457              :       REAL(KIND=dp)                                      :: det1, fval
    5458           82 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: reim_diag, z2
    5459              :       TYPE(dbcsr_type)                                   :: tempNOcc1, tempOccOcc1, tempOccOcc2
    5460              :       TYPE(mp_comm_type)                                 :: group
    5461              : 
    5462           82 :       CALL timeset(routineN, handle)
    5463              : 
    5464              :       CALL dbcsr_create(tempNOcc1, &
    5465              :                         template=template_matrix_mo, &
    5466           82 :                         matrix_type=dbcsr_type_no_symmetry)
    5467              :       CALL dbcsr_create(tempOccOcc1, &
    5468              :                         template=m_theta_normalized, &
    5469           82 :                         matrix_type=dbcsr_type_no_symmetry)
    5470              :       CALL dbcsr_create(tempOccOcc2, &
    5471              :                         template=m_theta_normalized, &
    5472           82 :                         matrix_type=dbcsr_type_no_symmetry)
    5473              : 
    5474           82 :       localization_obj_function_ispin = 0.0_dp
    5475           82 :       penalty_func_ispin = 0.0_dp
    5476          246 :       ALLOCATE (z2(nocc))
    5477          164 :       ALLOCATE (reim_diag(nocc))
    5478              : 
    5479           82 :       CALL dbcsr_get_info(tempOccOcc2, group=group)
    5480              : 
    5481          842 :       DO idim0 = 1, SIZE(m_B0, 2) ! this loop is over miller ind
    5482              : 
    5483          760 :          z2(:) = 0.0_dp
    5484              : 
    5485         1520 :          DO reim = 1, SIZE(m_B0, 1) ! this loop is over Re/Im
    5486              : 
    5487              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5488              :                                 m_B0(reim, idim0), &
    5489              :                                 m_theta_normalized, &
    5490              :                                 0.0_dp, tempOccOcc1, &
    5491          760 :                                 filter_eps=eps_filter)
    5492          760 :             CALL dbcsr_set(tempOccOcc2, 0.0_dp)
    5493          760 :             CALL dbcsr_add_on_diag(tempOccOcc2, 1.0_dp)
    5494              :             CALL dbcsr_multiply("T", "N", 1.0_dp, &
    5495              :                                 m_theta_normalized, &
    5496              :                                 tempOccOcc1, &
    5497              :                                 0.0_dp, tempOccOcc2, &
    5498          760 :                                 retain_sparsity=.TRUE.)
    5499              : 
    5500          760 :             reim_diag = 0.0_dp
    5501          760 :             CALL dbcsr_get_diag(tempOccOcc2, reim_diag)
    5502          760 :             CALL group%sum(reim_diag)
    5503        13368 :             z2(:) = z2(:) + reim_diag(:)*reim_diag(:)
    5504              : 
    5505              :          END DO
    5506              : 
    5507        12690 :          DO ielem = 1, nocc
    5508              :             SELECT CASE (2) ! allows for selection of different spread functionals
    5509              :             CASE (1) ! functional =  -W_I * log( |z_I|^2 )
    5510        11848 :                fval = -weights(idim0)*LOG(ABS(z2(ielem)))
    5511              :             CASE (2) ! functional =  W_I * ( 1 - |z_I|^2 )
    5512        11848 :                fval = weights(idim0) - weights(idim0)*ABS(z2(ielem))
    5513              :             CASE (3) ! functional =  W_I * ( 1 - |z_I| )
    5514              :                fval = weights(idim0) - weights(idim0)*SQRT(ABS(z2(ielem)))
    5515              :             END SELECT
    5516        12608 :             localization_obj_function_ispin = localization_obj_function_ispin + fval
    5517              :          END DO
    5518              : 
    5519              :       END DO ! end loop over idim0
    5520              : 
    5521           82 :       DEALLOCATE (z2)
    5522           82 :       DEALLOCATE (reim_diag)
    5523              : 
    5524              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5525              :                           m_S0, &
    5526              :                           m_theta_normalized, &
    5527              :                           0.0_dp, tempOccOcc1, &
    5528           82 :                           filter_eps=eps_filter)
    5529              :       ! compute current sigma
    5530              :       CALL dbcsr_multiply("T", "N", 1.0_dp, &
    5531              :                           m_theta_normalized, &
    5532              :                           tempOccOcc1, &
    5533              :                           0.0_dp, m_sigma, &
    5534           82 :                           filter_eps=eps_filter)
    5535              : 
    5536              :       CALL determinant(m_sigma, det1, &
    5537           82 :                        eps_filter)
    5538              :       ! save the current determinant
    5539           82 :       overlap_determinant = det1
    5540              : 
    5541           82 :       IF (just_started .AND. penalty_amplitude < 0.0_dp) THEN
    5542            4 :          penalty_vol_prefactor = -(-penalty_amplitude)*localization_obj_function_ispin
    5543              :       END IF
    5544           82 :       penalty_func_ispin = penalty_func_ispin + penalty_vol_prefactor*LOG(det1)
    5545              : 
    5546           82 :       CALL dbcsr_release(tempNOcc1)
    5547           82 :       CALL dbcsr_release(tempOccOcc1)
    5548           82 :       CALL dbcsr_release(tempOccOcc2)
    5549              : 
    5550           82 :       CALL timestop(handle)
    5551              : 
    5552          164 :    END SUBROUTINE compute_obj_nlmos
    5553              : 
    5554              : ! **************************************************************************************************
    5555              : !> \brief Compute the gradient wrt the main variable
    5556              : !> \param m_grad_out ...
    5557              : !> \param m_B0 ...
    5558              : !> \param weights ...
    5559              : !> \param m_S0 ...
    5560              : !> \param m_theta_normalized ...
    5561              : !> \param m_siginv ...
    5562              : !> \param m_sig_sqrti_ii ...
    5563              : !> \param penalty_vol_prefactor ...
    5564              : !> \param eps_filter ...
    5565              : !> \param suggested_vol_penalty ...
    5566              : !> \par History
    5567              : !>       2018.10 created [Ziling Luo]
    5568              : !> \author Ziling Luo
    5569              : ! **************************************************************************************************
    5570           82 :    SUBROUTINE compute_gradient_nlmos(m_grad_out, m_B0, weights, &
    5571              :                                      m_S0, m_theta_normalized, m_siginv, m_sig_sqrti_ii, &
    5572              :                                      penalty_vol_prefactor, eps_filter, suggested_vol_penalty)
    5573              : 
    5574              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: m_grad_out
    5575              :       TYPE(dbcsr_type), DIMENSION(:, :), INTENT(IN)      :: m_B0
    5576              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: weights
    5577              :       TYPE(dbcsr_type), INTENT(IN)                       :: m_S0, m_theta_normalized, m_siginv, &
    5578              :                                                             m_sig_sqrti_ii
    5579              :       REAL(KIND=dp), INTENT(IN)                          :: penalty_vol_prefactor, eps_filter
    5580              :       REAL(KIND=dp), INTENT(INOUT)                       :: suggested_vol_penalty
    5581              : 
    5582              :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_gradient_nlmos'
    5583              : 
    5584              :       INTEGER                                            :: dim0, handle, idim0, reim
    5585              :       REAL(KIND=dp)                                      :: norm_loc, norm_vol
    5586              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: tg_diagonal, z2
    5587              :       TYPE(dbcsr_type)                                   :: m_temp_oo_1, m_temp_oo_2, m_temp_oo_3, &
    5588              :                                                             m_temp_oo_4
    5589              : 
    5590           82 :       CALL timeset(routineN, handle)
    5591              : 
    5592              :       CALL dbcsr_create(m_temp_oo_1, &
    5593              :                         template=m_theta_normalized, &
    5594           82 :                         matrix_type=dbcsr_type_no_symmetry)
    5595              :       CALL dbcsr_create(m_temp_oo_2, &
    5596              :                         template=m_theta_normalized, &
    5597           82 :                         matrix_type=dbcsr_type_no_symmetry)
    5598              :       CALL dbcsr_create(m_temp_oo_3, &
    5599              :                         template=m_theta_normalized, &
    5600           82 :                         matrix_type=dbcsr_type_no_symmetry)
    5601              :       CALL dbcsr_create(m_temp_oo_4, &
    5602              :                         template=m_theta_normalized, &
    5603           82 :                         matrix_type=dbcsr_type_no_symmetry)
    5604              : 
    5605           82 :       CALL dbcsr_get_info(m_siginv, nfullrows_total=dim0)
    5606          246 :       ALLOCATE (tg_diagonal(dim0))
    5607          164 :       ALLOCATE (z2(dim0))
    5608           82 :       CALL dbcsr_set(m_temp_oo_1, 0.0_dp) ! accumulate the gradient wrt a_norm here
    5609              : 
    5610              :       ! do d_Omega/d_a_normalized first
    5611          842 :       DO idim0 = 1, SIZE(m_B0, 2) ! this loop is over miller ind
    5612              : 
    5613          760 :          z2(:) = 0.0_dp
    5614          760 :          CALL dbcsr_set(m_temp_oo_2, 0.0_dp) ! accumulate index gradient here
    5615         1520 :          DO reim = 1, SIZE(m_B0, 1) ! this loop is over Re/Im
    5616              : 
    5617              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5618              :                                 m_B0(reim, idim0), &
    5619              :                                 m_theta_normalized, &
    5620              :                                 0.0_dp, m_temp_oo_3, &
    5621          760 :                                 filter_eps=eps_filter)
    5622              : 
    5623              :             ! result contain Re/Im part of Z for the current Miller index
    5624              :             ! warning - save time by computing only the diagonal elements
    5625              :             CALL dbcsr_multiply("T", "N", 1.0_dp, &
    5626              :                                 m_theta_normalized, &
    5627              :                                 m_temp_oo_3, &
    5628              :                                 0.0_dp, m_temp_oo_4, &
    5629          760 :                                 filter_eps=eps_filter)
    5630              : 
    5631          760 :             tg_diagonal(:) = 0.0_dp
    5632          760 :             CALL dbcsr_get_diag(m_temp_oo_4, tg_diagonal)
    5633          760 :             CALL dbcsr_set(m_temp_oo_4, 0.0_dp)
    5634          760 :             CALL dbcsr_set_diag(m_temp_oo_4, tg_diagonal)
    5635        12608 :             z2(:) = z2(:) + tg_diagonal(:)*tg_diagonal(:)
    5636              : 
    5637              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5638              :                                 m_temp_oo_3, &
    5639              :                                 m_temp_oo_4, &
    5640              :                                 1.0_dp, m_temp_oo_2, &
    5641         1520 :                                 filter_eps=eps_filter)
    5642              : 
    5643              :          END DO
    5644              : 
    5645              :          ! TODO: because some elements are zeros on some MPI tasks the
    5646              :          ! gradient evaluation will fail for CASE 1 and 3
    5647              :          SELECT CASE (2) ! allows for selection of different spread functionals
    5648              :          CASE (1) ! functional =  -W_I * log( |z_I|^2 )
    5649              :             z2(:) = -weights(idim0)/z2(:)
    5650              :          CASE (2) ! functional =  W_I * ( 1 - |z_I|^2 )
    5651        12608 :             z2(:) = -weights(idim0)
    5652              :          CASE (3) ! functional =  W_I * ( 1 - |z_I| )
    5653              :             z2(:) = -weights(idim0)/(2*SQRT(z2(:)))
    5654              :          END SELECT
    5655          760 :          CALL dbcsr_set(m_temp_oo_3, 0.0_dp)
    5656          760 :          CALL dbcsr_set_diag(m_temp_oo_3, z2)
    5657              :          ! TODO: print this matrix to make sure its block structure is fine
    5658              :          ! and there are no unecessary elements
    5659              : 
    5660              :          CALL dbcsr_multiply("N", "N", 4.0_dp, &
    5661              :                              m_temp_oo_2, &
    5662              :                              m_temp_oo_3, &
    5663              :                              1.0_dp, m_temp_oo_1, &
    5664          842 :                              filter_eps=eps_filter)
    5665              : 
    5666              :       END DO ! end loop over idim0
    5667           82 :       DEALLOCATE (z2)
    5668              : 
    5669              :       ! sigma0.a_norm is necessary for the volume penalty and normalization
    5670              :       CALL dbcsr_multiply("N", "N", &
    5671              :                           1.0_dp, &
    5672              :                           m_S0, &
    5673              :                           m_theta_normalized, &
    5674              :                           0.0_dp, m_temp_oo_2, &
    5675           82 :                           filter_eps=eps_filter)
    5676              : 
    5677              :       ! add gradient of the penalty functional log[det(sigma)]
    5678              :       ! G = 2*prefactor*sigma0.a_norm.sigma_inv
    5679              :       CALL dbcsr_multiply("N", "N", &
    5680              :                           1.0_dp, &
    5681              :                           m_temp_oo_2, &
    5682              :                           m_siginv, &
    5683              :                           0.0_dp, m_temp_oo_3, &
    5684           82 :                           filter_eps=eps_filter)
    5685           82 :       norm_vol = dbcsr_maxabs(m_temp_oo_3)
    5686           82 :       norm_loc = dbcsr_maxabs(m_temp_oo_1)
    5687           82 :       suggested_vol_penalty = norm_loc/norm_vol
    5688              :       CALL dbcsr_add(m_temp_oo_1, m_temp_oo_3, &
    5689           82 :                      1.0_dp, 2.0_dp*penalty_vol_prefactor)
    5690              : 
    5691              :       ! take into account the factor from the normalization constraint
    5692              :       ! G = ( G - sigma0.a_norm.[tr(a_norm).G]_ii ) . [sig_sqrti]_ii
    5693              :       ! 1. get G.[sig_sqrti]_ii
    5694              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5695              :                           m_temp_oo_1, &
    5696              :                           m_sig_sqrti_ii, &
    5697              :                           0.0_dp, m_grad_out, &
    5698           82 :                           filter_eps=eps_filter)
    5699              : 
    5700              :       ! 2. get [tr(a_norm).G]_ii
    5701              :       ! it is possible to save time by computing only the diagonal elements
    5702              :       CALL dbcsr_multiply("T", "N", 1.0_dp, &
    5703              :                           m_theta_normalized, &
    5704              :                           m_temp_oo_1, &
    5705              :                           0.0_dp, m_temp_oo_3, &
    5706           82 :                           filter_eps=eps_filter)
    5707           82 :       CALL dbcsr_get_diag(m_temp_oo_3, tg_diagonal)
    5708           82 :       CALL dbcsr_set(m_temp_oo_3, 0.0_dp)
    5709           82 :       CALL dbcsr_set_diag(m_temp_oo_3, tg_diagonal)
    5710              : 
    5711              :       ! 3. [X]_ii . [sig_sqrti]_ii
    5712              :       ! it is possible to save time by computing only the diagonal elements
    5713              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5714              :                           m_sig_sqrti_ii, &
    5715              :                           m_temp_oo_3, &
    5716              :                           0.0_dp, m_temp_oo_1, &
    5717           82 :                           filter_eps=eps_filter)
    5718              :       ! 4. (sigma0*a_norm) .[X]_ii
    5719              :       CALL dbcsr_multiply("N", "N", -1.0_dp, &
    5720              :                           m_temp_oo_2, &
    5721              :                           m_temp_oo_1, &
    5722              :                           1.0_dp, m_grad_out, &
    5723           82 :                           filter_eps=eps_filter)
    5724              : 
    5725           82 :       DEALLOCATE (tg_diagonal)
    5726           82 :       CALL dbcsr_release(m_temp_oo_1)
    5727           82 :       CALL dbcsr_release(m_temp_oo_2)
    5728           82 :       CALL dbcsr_release(m_temp_oo_3)
    5729           82 :       CALL dbcsr_release(m_temp_oo_4)
    5730              : 
    5731           82 :       CALL timestop(handle)
    5732              : 
    5733          164 :    END SUBROUTINE compute_gradient_nlmos
    5734              : 
    5735              : ! **************************************************************************************************
    5736              : !> \brief Compute MO coeffs from the main optimized variable (e.g. Theta, X)
    5737              : !> \param m_var_in ...
    5738              : !> \param m_t_out ...
    5739              : !> \param m_quench_t ...
    5740              : !> \param m_t0 ...
    5741              : !> \param m_oo_template ...
    5742              : !> \param m_STsiginv0 ...
    5743              : !> \param m_s ...
    5744              : !> \param m_sig_sqrti_ii_out ...
    5745              : !> \param domain_r_down ...
    5746              : !> \param domain_s_inv ...
    5747              : !> \param domain_map ...
    5748              : !> \param cpu_of_domain ...
    5749              : !> \param assume_t0_q0x ...
    5750              : !> \param just_started ...
    5751              : !> \param optimize_theta ...
    5752              : !> \param normalize_orbitals ...
    5753              : !> \param envelope_amplitude ...
    5754              : !> \param eps_filter ...
    5755              : !> \param special_case ...
    5756              : !> \param nocc_of_domain ...
    5757              : !> \param order_lanczos ...
    5758              : !> \param eps_lanczos ...
    5759              : !> \param max_iter_lanczos ...
    5760              : !> \par History
    5761              : !>       2015.03 created [Rustam Z Khaliullin]
    5762              : !> \author Rustam Z Khaliullin
    5763              : ! **************************************************************************************************
    5764         2996 :    SUBROUTINE compute_xalmos_from_main_var(m_var_in, m_t_out, m_quench_t, &
    5765         1498 :                                            m_t0, m_oo_template, m_STsiginv0, m_s, m_sig_sqrti_ii_out, domain_r_down, &
    5766         1498 :                                            domain_s_inv, domain_map, cpu_of_domain, assume_t0_q0x, just_started, &
    5767              :                                            optimize_theta, normalize_orbitals, envelope_amplitude, eps_filter, &
    5768         1498 :                                            special_case, nocc_of_domain, order_lanczos, eps_lanczos, max_iter_lanczos)
    5769              : 
    5770              :       TYPE(dbcsr_type), INTENT(IN)                       :: m_var_in
    5771              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: m_t_out, m_quench_t, m_t0, &
    5772              :                                                             m_oo_template, m_STsiginv0, m_s, &
    5773              :                                                             m_sig_sqrti_ii_out
    5774              :       TYPE(domain_submatrix_type), DIMENSION(:), &
    5775              :          INTENT(IN)                                      :: domain_r_down, domain_s_inv
    5776              :       TYPE(domain_map_type), INTENT(IN)                  :: domain_map
    5777              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: cpu_of_domain
    5778              :       LOGICAL, INTENT(IN)                                :: assume_t0_q0x, just_started, &
    5779              :                                                             optimize_theta, normalize_orbitals
    5780              :       REAL(KIND=dp), INTENT(IN)                          :: envelope_amplitude, eps_filter
    5781              :       INTEGER, INTENT(IN)                                :: special_case
    5782              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: nocc_of_domain
    5783              :       INTEGER, INTENT(IN)                                :: order_lanczos
    5784              :       REAL(KIND=dp), INTENT(IN)                          :: eps_lanczos
    5785              :       INTEGER, INTENT(IN)                                :: max_iter_lanczos
    5786              : 
    5787              :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_xalmos_from_main_var'
    5788              : 
    5789              :       INTEGER                                            :: handle, unit_nr
    5790              :       REAL(KIND=dp)                                      :: t_norm
    5791              :       TYPE(cp_logger_type), POINTER                      :: logger
    5792              :       TYPE(dbcsr_type)                                   :: m_tmp_no_1, m_tmp_oo_1
    5793              : 
    5794         1498 :       CALL timeset(routineN, handle)
    5795              : 
    5796              :       ! get a useful output_unit
    5797         1498 :       logger => cp_get_default_logger()
    5798         1498 :       IF (logger%para_env%is_source()) THEN
    5799          749 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    5800              :       ELSE
    5801              :          unit_nr = -1
    5802              :       END IF
    5803              : 
    5804              :       CALL dbcsr_create(m_tmp_no_1, &
    5805              :                         template=m_quench_t, &
    5806         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5807              :       CALL dbcsr_create(m_tmp_oo_1, &
    5808              :                         template=m_oo_template, &
    5809         1498 :                         matrix_type=dbcsr_type_no_symmetry)
    5810              : 
    5811         1498 :       CALL dbcsr_copy(m_tmp_no_1, m_var_in)
    5812         1498 :       IF (optimize_theta) THEN
    5813              :          ! check that all MO coefficients of the guess are less
    5814              :          ! than the maximum allowed amplitude
    5815            0 :          t_norm = dbcsr_maxabs(m_tmp_no_1)
    5816            0 :          IF (unit_nr > 0) THEN
    5817            0 :             WRITE (unit_nr, *) "Maximum norm of the initial guess: ", t_norm
    5818            0 :             WRITE (unit_nr, *) "Maximum allowed amplitude: ", &
    5819            0 :                envelope_amplitude
    5820              :          END IF
    5821            0 :          IF (t_norm > envelope_amplitude .AND. just_started) THEN
    5822            0 :             CPABORT("Max norm of the initial guess is too large")
    5823              :          END IF
    5824              :          ! use artanh to tame MOs
    5825            0 :          CALL tanh_of_elements(m_tmp_no_1, alpha=1.0_dp/envelope_amplitude)
    5826            0 :          CALL dbcsr_scale(m_tmp_no_1, envelope_amplitude)
    5827              :       END IF
    5828              :       CALL dbcsr_hadamard_product(m_tmp_no_1, m_quench_t, &
    5829         1498 :                                   m_t_out)
    5830              : 
    5831              :       ! project out R_0
    5832         1498 :       IF (assume_t0_q0x) THEN
    5833          466 :          IF (special_case == xalmo_case_fully_deloc) THEN
    5834              :             CALL dbcsr_multiply("T", "N", 1.0_dp, &
    5835              :                                 m_STsiginv0, &
    5836              :                                 m_t_out, &
    5837              :                                 0.0_dp, m_tmp_oo_1, &
    5838          160 :                                 filter_eps=eps_filter)
    5839              :             CALL dbcsr_multiply("N", "N", -1.0_dp, &
    5840              :                                 m_t0, &
    5841              :                                 m_tmp_oo_1, &
    5842              :                                 1.0_dp, m_t_out, &
    5843          160 :                                 filter_eps=eps_filter)
    5844          306 :          ELSE IF (special_case == xalmo_case_block_diag) THEN
    5845            0 :             CPABORT("cannot use projector with block-daigonal ALMOs")
    5846              :          ELSE
    5847              :             ! no special case
    5848              :             CALL apply_domain_operators( &
    5849              :                matrix_in=m_t_out, &
    5850              :                matrix_out=m_tmp_no_1, &
    5851              :                operator1=domain_r_down, &
    5852              :                operator2=domain_s_inv, &
    5853              :                dpattern=m_quench_t, &
    5854              :                map=domain_map, &
    5855              :                node_of_domain=cpu_of_domain, &
    5856              :                my_action=1, &
    5857              :                filter_eps=eps_filter, &
    5858          306 :                use_trimmer=.FALSE.)
    5859              :             CALL dbcsr_copy(m_t_out, &
    5860          306 :                             m_tmp_no_1)
    5861              :          END IF ! special case
    5862              :          CALL dbcsr_add(m_t_out, &
    5863          466 :                         m_t0, 1.0_dp, 1.0_dp)
    5864              :       END IF
    5865              : 
    5866         1498 :       IF (normalize_orbitals) THEN
    5867              :          CALL orthogonalize_mos( &
    5868              :             ket=m_t_out, &
    5869              :             overlap=m_tmp_oo_1, &
    5870              :             metric=m_s, &
    5871              :             retain_locality=.TRUE., &
    5872              :             only_normalize=.TRUE., &
    5873              :             nocc_of_domain=nocc_of_domain(:), &
    5874              :             eps_filter=eps_filter, &
    5875              :             order_lanczos=order_lanczos, &
    5876              :             eps_lanczos=eps_lanczos, &
    5877              :             max_iter_lanczos=max_iter_lanczos, &
    5878            0 :             overlap_sqrti=m_sig_sqrti_ii_out)
    5879              :       END IF
    5880              : 
    5881         1498 :       CALL dbcsr_filter(m_t_out, eps_filter)
    5882              : 
    5883         1498 :       CALL dbcsr_release(m_tmp_no_1)
    5884         1498 :       CALL dbcsr_release(m_tmp_oo_1)
    5885              : 
    5886         1498 :       CALL timestop(handle)
    5887              : 
    5888         1498 :    END SUBROUTINE compute_xalmos_from_main_var
    5889              : 
    5890              : ! **************************************************************************************************
    5891              : !> \brief Compute the preconditioner matrices and invert them if necessary
    5892              : !> \param domain_prec_out ...
    5893              : !> \param m_prec_out ...
    5894              : !> \param m_ks ...
    5895              : !> \param m_s ...
    5896              : !> \param m_siginv ...
    5897              : !> \param m_quench_t ...
    5898              : !> \param m_FTsiginv ...
    5899              : !> \param m_siginvTFTsiginv ...
    5900              : !> \param m_ST ...
    5901              : !> \param m_STsiginv_out ...
    5902              : !> \param m_s_vv_out ...
    5903              : !> \param m_f_vv_out ...
    5904              : !> \param para_env ...
    5905              : !> \param blacs_env ...
    5906              : !> \param nocc_of_domain ...
    5907              : !> \param domain_s_inv ...
    5908              : !> \param domain_s_inv_half ...
    5909              : !> \param domain_s_half ...
    5910              : !> \param domain_r_down ...
    5911              : !> \param cpu_of_domain ...
    5912              : !> \param domain_map ...
    5913              : !> \param assume_t0_q0x ...
    5914              : !> \param penalty_occ_vol ...
    5915              : !> \param penalty_occ_vol_prefactor ...
    5916              : !> \param eps_filter ...
    5917              : !> \param neg_thr ...
    5918              : !> \param spin_factor ...
    5919              : !> \param special_case ...
    5920              : !> \param bad_modes_projector_down_out ...
    5921              : !> \param skip_inversion ...
    5922              : !> \par History
    5923              : !>       2015.03 created [Rustam Z Khaliullin]
    5924              : !> \author Rustam Z Khaliullin
    5925              : ! **************************************************************************************************
    5926         1524 :    SUBROUTINE compute_preconditioner(domain_prec_out, m_prec_out, m_ks, m_s, &
    5927              :                                      m_siginv, m_quench_t, m_FTsiginv, m_siginvTFTsiginv, m_ST, &
    5928              :                                      m_STsiginv_out, m_s_vv_out, m_f_vv_out, para_env, &
    5929         1016 :                                      blacs_env, nocc_of_domain, domain_s_inv, domain_s_inv_half, domain_s_half, &
    5930          508 :                                      domain_r_down, cpu_of_domain, &
    5931              :                                      domain_map, assume_t0_q0x, penalty_occ_vol, penalty_occ_vol_prefactor, &
    5932          508 :                                      eps_filter, neg_thr, spin_factor, special_case, bad_modes_projector_down_out, &
    5933              :                                      skip_inversion)
    5934              : 
    5935              :       TYPE(domain_submatrix_type), DIMENSION(:), &
    5936              :          INTENT(INOUT)                                   :: domain_prec_out
    5937              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: m_prec_out, m_ks, m_s
    5938              :       TYPE(dbcsr_type), INTENT(IN)                       :: m_siginv, m_quench_t, m_FTsiginv, &
    5939              :                                                             m_siginvTFTsiginv, m_ST
    5940              :       TYPE(dbcsr_type), INTENT(INOUT), OPTIONAL          :: m_STsiginv_out, m_s_vv_out, m_f_vv_out
    5941              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    5942              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    5943              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: nocc_of_domain
    5944              :       TYPE(domain_submatrix_type), DIMENSION(:), &
    5945              :          INTENT(IN)                                      :: domain_s_inv
    5946              :       TYPE(domain_submatrix_type), DIMENSION(:), &
    5947              :          INTENT(IN), OPTIONAL                            :: domain_s_inv_half, domain_s_half
    5948              :       TYPE(domain_submatrix_type), DIMENSION(:), &
    5949              :          INTENT(IN)                                      :: domain_r_down
    5950              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: cpu_of_domain
    5951              :       TYPE(domain_map_type), INTENT(IN)                  :: domain_map
    5952              :       LOGICAL, INTENT(IN)                                :: assume_t0_q0x, penalty_occ_vol
    5953              :       REAL(KIND=dp), INTENT(IN)                          :: penalty_occ_vol_prefactor, eps_filter, &
    5954              :                                                             neg_thr, spin_factor
    5955              :       INTEGER, INTENT(IN)                                :: special_case
    5956              :       TYPE(domain_submatrix_type), DIMENSION(:), &
    5957              :          INTENT(INOUT), OPTIONAL                         :: bad_modes_projector_down_out
    5958              :       LOGICAL, INTENT(IN)                                :: skip_inversion
    5959              : 
    5960              :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_preconditioner'
    5961              : 
    5962              :       INTEGER                                            :: handle, ndim, precond_domain_projector
    5963          508 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: nn_diagonal
    5964              :       TYPE(dbcsr_type)                                   :: m_tmp_nn_1, m_tmp_no_3
    5965              : 
    5966          508 :       CALL timeset(routineN, handle)
    5967              : 
    5968              :       CALL dbcsr_create(m_tmp_nn_1, &
    5969              :                         template=m_s, &
    5970          508 :                         matrix_type=dbcsr_type_no_symmetry)
    5971              :       CALL dbcsr_create(m_tmp_no_3, &
    5972              :                         template=m_quench_t, &
    5973          508 :                         matrix_type=dbcsr_type_no_symmetry)
    5974              : 
    5975              :       ! calculate (1-R)F(1-R) and S-SRS
    5976              :       ! RZK-warning take advantage: some elements will be removed by the quencher
    5977              :       ! RZK-warning S operations can be performed outside the spin loop to save time
    5978              :       ! IT IS REQUIRED THAT PRECONDITIONER DOES NOT BREAK THE LOCALITY!!!!
    5979              :       ! RZK-warning: further optimization is ABSOLUTELY NECESSARY
    5980              : 
    5981              :       ! First S-SRS
    5982              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    5983              :                           m_ST, &
    5984              :                           m_siginv, &
    5985              :                           0.0_dp, m_tmp_no_3, &
    5986          508 :                           filter_eps=eps_filter)
    5987          508 :       CALL dbcsr_desymmetrize(m_s, m_tmp_nn_1)
    5988              :       ! return STsiginv if necessary
    5989          508 :       IF (PRESENT(m_STsiginv_out)) THEN
    5990            0 :          CALL dbcsr_copy(m_STsiginv_out, m_tmp_no_3)
    5991              :       END IF
    5992          508 :       IF (special_case == xalmo_case_fully_deloc) THEN
    5993              :          ! use S instead of S-SRS
    5994              :       ELSE
    5995              :          CALL dbcsr_multiply("N", "T", -1.0_dp, &
    5996              :                              m_ST, &
    5997              :                              m_tmp_no_3, &
    5998              :                              1.0_dp, m_tmp_nn_1, &
    5999          464 :                              filter_eps=eps_filter)
    6000              :       END IF
    6001              :       ! return S_vv = (S or S-SRS) if necessary
    6002          508 :       IF (PRESENT(m_s_vv_out)) THEN
    6003            0 :          CALL dbcsr_copy(m_s_vv_out, m_tmp_nn_1)
    6004              :       END IF
    6005              : 
    6006              :       ! Second (1-R)F(1-R)
    6007              :       ! re-create matrix because desymmetrize is buggy -
    6008              :       ! it will create multiple copies of blocks
    6009          508 :       CALL dbcsr_desymmetrize(m_ks, m_prec_out)
    6010              :       CALL dbcsr_multiply("N", "T", -1.0_dp, &
    6011              :                           m_FTsiginv, &
    6012              :                           m_ST, &
    6013              :                           1.0_dp, m_prec_out, &
    6014          508 :                           filter_eps=eps_filter)
    6015              :       CALL dbcsr_multiply("N", "T", -1.0_dp, &
    6016              :                           m_ST, &
    6017              :                           m_FTsiginv, &
    6018              :                           1.0_dp, m_prec_out, &
    6019          508 :                           filter_eps=eps_filter)
    6020              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    6021              :                           m_ST, &
    6022              :                           m_siginvTFTsiginv, &
    6023              :                           0.0_dp, m_tmp_no_3, &
    6024          508 :                           filter_eps=eps_filter)
    6025              :       CALL dbcsr_multiply("N", "T", 1.0_dp, &
    6026              :                           m_tmp_no_3, &
    6027              :                           m_ST, &
    6028              :                           1.0_dp, m_prec_out, &
    6029          508 :                           filter_eps=eps_filter)
    6030              :       ! return F_vv = (I-SR)F(I-RS) if necessary
    6031          508 :       IF (PRESENT(m_f_vv_out)) THEN
    6032            0 :          CALL dbcsr_copy(m_f_vv_out, m_prec_out)
    6033              :       END IF
    6034              : 
    6035              :       ! sum up the F_vv and S_vv terms
    6036              :       CALL dbcsr_add(m_prec_out, m_tmp_nn_1, &
    6037          508 :                      1.0_dp, 1.0_dp)
    6038              :       ! Scale to obtain unit step length
    6039          508 :       CALL dbcsr_scale(m_prec_out, 2.0_dp*spin_factor)
    6040              : 
    6041              :       ! add the contribution from the penalty on the occupied volume
    6042          508 :       IF (penalty_occ_vol) THEN
    6043              :          CALL dbcsr_add(m_prec_out, m_tmp_nn_1, &
    6044            0 :                         1.0_dp, penalty_occ_vol_prefactor)
    6045              :       END IF
    6046              : 
    6047          508 :       CALL dbcsr_copy(m_tmp_nn_1, m_prec_out)
    6048              : 
    6049              :       ! invert using various algorithms
    6050          508 :       IF (special_case == xalmo_case_block_diag) THEN ! non-overlapping diagonal blocks
    6051              : 
    6052          104 :          IF (skip_inversion) THEN
    6053              : 
    6054              :             ! impose block-diagonal structure
    6055           92 :             CALL dbcsr_get_info(m_s, nfullrows_total=ndim)
    6056          276 :             ALLOCATE (nn_diagonal(ndim))
    6057           92 :             CALL dbcsr_get_diag(m_s, nn_diagonal)
    6058           92 :             CALL dbcsr_set(m_prec_out, 0.0_dp)
    6059           92 :             CALL dbcsr_set_diag(m_prec_out, nn_diagonal)
    6060           92 :             CALL dbcsr_filter(m_prec_out, eps_filter)
    6061           92 :             DEALLOCATE (nn_diagonal)
    6062              : 
    6063          184 :             CALL dbcsr_copy(m_prec_out, m_tmp_nn_1, keep_sparsity=.TRUE.)
    6064              : 
    6065              :          ELSE
    6066              : 
    6067              :             CALL pseudo_invert_diagonal_blk( &
    6068              :                matrix_in=m_tmp_nn_1, &
    6069              :                matrix_out=m_prec_out, &
    6070              :                nocc=nocc_of_domain(:) &
    6071           12 :                )
    6072              : 
    6073              :          END IF
    6074              : 
    6075          404 :       ELSE IF (special_case == xalmo_case_fully_deloc) THEN ! the entire system is a block
    6076              : 
    6077           44 :          IF (skip_inversion) THEN
    6078            0 :             CALL dbcsr_copy(m_prec_out, m_tmp_nn_1)
    6079              :          ELSE
    6080              : 
    6081              :             ! invert using cholesky (works with S matrix, will not work with S-SRS matrix)
    6082              :             CALL cp_dbcsr_cholesky_decompose(m_prec_out, &
    6083              :                                              para_env=para_env, &
    6084           44 :                                              blacs_env=blacs_env)
    6085              :             CALL cp_dbcsr_cholesky_invert(m_prec_out, &
    6086              :                                           para_env=para_env, &
    6087              :                                           blacs_env=blacs_env, &
    6088           44 :                                           uplo_to_full=.TRUE.)
    6089              :          END IF !skip_inversion
    6090              : 
    6091           44 :          CALL dbcsr_filter(m_prec_out, eps_filter)
    6092              : 
    6093              :       ELSE
    6094              : 
    6095              :          !!! use a true domain preconditioner with overlapping domains
    6096          360 :          IF (assume_t0_q0x) THEN
    6097           26 :             precond_domain_projector = -1
    6098              :          ELSE
    6099          334 :             precond_domain_projector = 0
    6100              :          END IF
    6101              :          !! RZK-warning: use PRESENT to make two nearly-identical calls
    6102              :          !! this is done because intel compiler does not seem to conform
    6103              :          !! to the FORTRAN standard for passing through optional arguments
    6104          360 :          IF (PRESENT(bad_modes_projector_down_out)) THEN
    6105              :             CALL construct_domain_preconditioner( &
    6106              :                matrix_main=m_tmp_nn_1, &
    6107              :                subm_s_inv=domain_s_inv(:), &
    6108              :                subm_s_inv_half=domain_s_inv_half(:), &
    6109              :                subm_s_half=domain_s_half(:), &
    6110              :                subm_r_down=domain_r_down(:), &
    6111              :                matrix_trimmer=m_quench_t, &
    6112              :                dpattern=m_quench_t, &
    6113              :                map=domain_map, &
    6114              :                node_of_domain=cpu_of_domain, &
    6115              :                preconditioner=domain_prec_out(:), &
    6116              :                use_trimmer=.FALSE., &
    6117              :                bad_modes_projector_down=bad_modes_projector_down_out(:), &
    6118              :                eps_zero_eigenvalues=neg_thr, &
    6119              :                my_action=precond_domain_projector, &
    6120              :                skip_inversion=skip_inversion &
    6121           18 :                )
    6122              :          ELSE
    6123              :             CALL construct_domain_preconditioner( &
    6124              :                matrix_main=m_tmp_nn_1, &
    6125              :                subm_s_inv=domain_s_inv(:), &
    6126              :                subm_r_down=domain_r_down(:), &
    6127              :                matrix_trimmer=m_quench_t, &
    6128              :                dpattern=m_quench_t, &
    6129              :                map=domain_map, &
    6130              :                node_of_domain=cpu_of_domain, &
    6131              :                preconditioner=domain_prec_out(:), &
    6132              :                use_trimmer=.FALSE., &
    6133              :                !eps_zero_eigenvalues=neg_thr,&
    6134              :                my_action=precond_domain_projector, &
    6135              :                skip_inversion=skip_inversion &
    6136          342 :                )
    6137              :          END IF
    6138              : 
    6139              :       END IF ! special_case
    6140              : 
    6141          508 :       CALL dbcsr_release(m_tmp_nn_1)
    6142          508 :       CALL dbcsr_release(m_tmp_no_3)
    6143              : 
    6144          508 :       CALL timestop(handle)
    6145              : 
    6146         1016 :    END SUBROUTINE compute_preconditioner
    6147              : 
    6148              : ! **************************************************************************************************
    6149              : !> \brief Compute beta for conjugate gradient algorithms
    6150              : !> \param beta ...
    6151              : !> \param numer ...
    6152              : !> \param denom ...
    6153              : !> \param reset_conjugator ...
    6154              : !> \param conjugator ...
    6155              : !> \param grad ...
    6156              : !> \param prev_grad ...
    6157              : !> \param step ...
    6158              : !> \param prev_step ...
    6159              : !> \param prev_minus_prec_grad ...
    6160              : !> \par History
    6161              : !>       2015.04 created [Rustam Z Khaliullin]
    6162              : !> \author Rustam Z Khaliullin
    6163              : ! **************************************************************************************************
    6164         1016 :    SUBROUTINE compute_cg_beta(beta, numer, denom, reset_conjugator, conjugator, &
    6165          508 :                               grad, prev_grad, step, prev_step, prev_minus_prec_grad)
    6166              : 
    6167              :       REAL(KIND=dp), INTENT(INOUT)                       :: beta
    6168              :       REAL(KIND=dp), INTENT(INOUT), OPTIONAL             :: numer, denom
    6169              :       LOGICAL, INTENT(INOUT)                             :: reset_conjugator
    6170              :       INTEGER, INTENT(IN)                                :: conjugator
    6171              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT)      :: grad, prev_grad, step, prev_step
    6172              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT), &
    6173              :          OPTIONAL                                        :: prev_minus_prec_grad
    6174              : 
    6175              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'compute_cg_beta'
    6176              : 
    6177              :       INTEGER                                            :: handle, i, nsize, unit_nr
    6178              :       REAL(KIND=dp)                                      :: den, kappa, my_denom, my_numer, &
    6179              :                                                             my_numer2, my_numer3, num, num2, num3, &
    6180              :                                                             tau
    6181              :       TYPE(cp_logger_type), POINTER                      :: logger
    6182              :       TYPE(dbcsr_type)                                   :: m_tmp_no_1
    6183              : 
    6184          508 :       CALL timeset(routineN, handle)
    6185              : 
    6186              :       ! get a useful output_unit
    6187          508 :       logger => cp_get_default_logger()
    6188          508 :       IF (logger%para_env%is_source()) THEN
    6189          254 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    6190              :       ELSE
    6191              :          unit_nr = -1
    6192              :       END IF
    6193              : 
    6194          508 :       IF (.NOT. PRESENT(prev_minus_prec_grad)) THEN
    6195              :          IF (conjugator == cg_fletcher_reeves .OR. &
    6196           82 :              conjugator == cg_polak_ribiere .OR. &
    6197              :              conjugator == cg_hager_zhang) THEN
    6198            0 :             CPABORT("conjugator needs more input")
    6199              :          END IF
    6200              :       END IF
    6201              : 
    6202              :       ! return num denom so beta can be calculated spin-by-spin
    6203          508 :       IF (PRESENT(numer) .OR. PRESENT(denom)) THEN
    6204              :          IF (conjugator == cg_hestenes_stiefel .OR. &
    6205            0 :              conjugator == cg_dai_yuan .OR. &
    6206              :              conjugator == cg_hager_zhang) THEN
    6207            0 :             CPABORT("cannot return numer/denom")
    6208              :          END IF
    6209              :       END IF
    6210              : 
    6211          508 :       nsize = SIZE(grad)
    6212              : 
    6213          508 :       my_numer = 0.0_dp
    6214          508 :       my_numer2 = 0.0_dp
    6215          508 :       my_numer3 = 0.0_dp
    6216          508 :       my_denom = 0.0_dp
    6217              : 
    6218         1016 :       DO i = 1, nsize
    6219              : 
    6220              :          CALL dbcsr_create(m_tmp_no_1, &
    6221              :                            template=grad(i), &
    6222          508 :                            matrix_type=dbcsr_type_no_symmetry)
    6223              : 
    6224          570 :          SELECT CASE (conjugator)
    6225              :          CASE (cg_hestenes_stiefel)
    6226           62 :             CALL dbcsr_copy(m_tmp_no_1, grad(i))
    6227              :             CALL dbcsr_add(m_tmp_no_1, prev_grad(i), &
    6228           62 :                            1.0_dp, -1.0_dp)
    6229           62 :             CALL dbcsr_dot(m_tmp_no_1, step(i), num)
    6230          156 :             CALL dbcsr_dot(m_tmp_no_1, prev_step(i), den)
    6231              :          CASE (cg_fletcher_reeves)
    6232           94 :             CALL dbcsr_dot(grad(i), step(i), num)
    6233          124 :             CALL dbcsr_dot(prev_grad(i), prev_minus_prec_grad(i), den)
    6234              :          CASE (cg_polak_ribiere)
    6235           30 :             CALL dbcsr_dot(prev_grad(i), prev_minus_prec_grad(i), den)
    6236           30 :             CALL dbcsr_copy(m_tmp_no_1, grad(i))
    6237           30 :             CALL dbcsr_add(m_tmp_no_1, prev_grad(i), 1.0_dp, -1.0_dp)
    6238          202 :             CALL dbcsr_dot(m_tmp_no_1, step(i), num)
    6239              :          CASE (cg_fletcher)
    6240          172 :             CALL dbcsr_dot(grad(i), step(i), num)
    6241          192 :             CALL dbcsr_dot(prev_grad(i), prev_step(i), den)
    6242              :          CASE (cg_liu_storey)
    6243           20 :             CALL dbcsr_dot(prev_grad(i), prev_step(i), den)
    6244           20 :             CALL dbcsr_copy(m_tmp_no_1, grad(i))
    6245           20 :             CALL dbcsr_add(m_tmp_no_1, prev_grad(i), 1.0_dp, -1.0_dp)
    6246           54 :             CALL dbcsr_dot(m_tmp_no_1, step(i), num)
    6247              :          CASE (cg_dai_yuan)
    6248           34 :             CALL dbcsr_dot(grad(i), step(i), num)
    6249           34 :             CALL dbcsr_copy(m_tmp_no_1, grad(i))
    6250           34 :             CALL dbcsr_add(m_tmp_no_1, prev_grad(i), 1.0_dp, -1.0_dp)
    6251          106 :             CALL dbcsr_dot(m_tmp_no_1, prev_step(i), den)
    6252              :          CASE (cg_hager_zhang)
    6253           72 :             CALL dbcsr_copy(m_tmp_no_1, grad(i))
    6254           72 :             CALL dbcsr_add(m_tmp_no_1, prev_grad(i), 1.0_dp, -1.0_dp)
    6255           72 :             CALL dbcsr_dot(m_tmp_no_1, prev_step(i), den)
    6256           72 :             CALL dbcsr_dot(m_tmp_no_1, prev_minus_prec_grad(i), num)
    6257           72 :             CALL dbcsr_dot(m_tmp_no_1, step(i), num2)
    6258           72 :             CALL dbcsr_dot(prev_step(i), grad(i), num3)
    6259           72 :             my_numer2 = my_numer2 + num2
    6260           72 :             my_numer3 = my_numer3 + num3
    6261              :          CASE (cg_zero)
    6262           24 :             num = 0.0_dp
    6263           24 :             den = 1.0_dp
    6264              :          CASE DEFAULT
    6265          726 :             CPABORT("illegal conjugator")
    6266              :          END SELECT
    6267          508 :          my_numer = my_numer + num
    6268          508 :          my_denom = my_denom + den
    6269              : 
    6270         1016 :          CALL dbcsr_release(m_tmp_no_1)
    6271              : 
    6272              :       END DO ! i - nsize
    6273              : 
    6274         1016 :       DO i = 1, nsize
    6275              : 
    6276          508 :          SELECT CASE (conjugator)
    6277              :          CASE (cg_hestenes_stiefel, cg_dai_yuan)
    6278           96 :             beta = -1.0_dp*my_numer/my_denom
    6279              :          CASE (cg_fletcher_reeves, cg_polak_ribiere, cg_fletcher, cg_liu_storey)
    6280          316 :             beta = my_numer/my_denom
    6281              :          CASE (cg_hager_zhang)
    6282           72 :             kappa = -2.0_dp*my_numer/my_denom
    6283           72 :             tau = -1.0_dp*my_numer2/my_denom
    6284           72 :             beta = tau - kappa*my_numer3/my_denom
    6285              :          CASE (cg_zero)
    6286           24 :             beta = 0.0_dp
    6287              :          CASE DEFAULT
    6288          508 :             CPABORT("illegal conjugator")
    6289              :          END SELECT
    6290              : 
    6291              :       END DO ! i - nsize
    6292              : 
    6293          508 :       IF (beta < 0.0_dp) THEN
    6294            0 :          IF (unit_nr > 0) THEN
    6295            0 :             WRITE (unit_nr, *) " Resetting conjugator because beta is negative: ", beta
    6296              :          END IF
    6297            0 :          reset_conjugator = .TRUE.
    6298              :       END IF
    6299              : 
    6300          508 :       IF (PRESENT(numer)) THEN
    6301            0 :          numer = my_numer
    6302              :       END IF
    6303          508 :       IF (PRESENT(denom)) THEN
    6304            0 :          denom = my_denom
    6305              :       END IF
    6306              : 
    6307          508 :       CALL timestop(handle)
    6308              : 
    6309          508 :    END SUBROUTINE compute_cg_beta
    6310              : 
    6311              : ! **************************************************************************************************
    6312              : !> \brief computes the step matrix from the gradient and Hessian using the Newton-Raphson method
    6313              : !> \param optimizer ...
    6314              : !> \param m_grad ...
    6315              : !> \param m_delta ...
    6316              : !> \param m_s ...
    6317              : !> \param m_ks ...
    6318              : !> \param m_siginv ...
    6319              : !> \param m_quench_t ...
    6320              : !> \param m_FTsiginv ...
    6321              : !> \param m_siginvTFTsiginv ...
    6322              : !> \param m_ST ...
    6323              : !> \param m_t ...
    6324              : !> \param m_sig_sqrti_ii ...
    6325              : !> \param domain_s_inv ...
    6326              : !> \param domain_r_down ...
    6327              : !> \param domain_map ...
    6328              : !> \param cpu_of_domain ...
    6329              : !> \param nocc_of_domain ...
    6330              : !> \param para_env ...
    6331              : !> \param blacs_env ...
    6332              : !> \param eps_filter ...
    6333              : !> \param optimize_theta ...
    6334              : !> \param penalty_occ_vol ...
    6335              : !> \param normalize_orbitals ...
    6336              : !> \param penalty_occ_vol_prefactor ...
    6337              : !> \param penalty_occ_vol_pf2 ...
    6338              : !> \param special_case ...
    6339              : !> \par History
    6340              : !>       2015.04 created [Rustam Z. Khaliullin]
    6341              : !> \author Rustam Z. Khaliullin
    6342              : ! **************************************************************************************************
    6343            0 :    SUBROUTINE newton_grad_to_step(optimizer, m_grad, m_delta, m_s, m_ks, &
    6344            0 :                                   m_siginv, m_quench_t, m_FTsiginv, m_siginvTFTsiginv, m_ST, m_t, &
    6345            0 :                                   m_sig_sqrti_ii, domain_s_inv, domain_r_down, domain_map, cpu_of_domain, &
    6346            0 :                                   nocc_of_domain, para_env, blacs_env, eps_filter, optimize_theta, &
    6347            0 :                                   penalty_occ_vol, normalize_orbitals, penalty_occ_vol_prefactor, &
    6348            0 :                                   penalty_occ_vol_pf2, special_case)
    6349              : 
    6350              :       TYPE(optimizer_options_type), INTENT(IN)           :: optimizer
    6351              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: m_grad
    6352              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT)      :: m_delta, m_s, m_ks, m_siginv, m_quench_t
    6353              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: m_FTsiginv, m_siginvTFTsiginv, m_ST, &
    6354              :                                                             m_t, m_sig_sqrti_ii
    6355              :       TYPE(domain_submatrix_type), DIMENSION(:, :), &
    6356              :          INTENT(IN)                                      :: domain_s_inv, domain_r_down
    6357              :       TYPE(domain_map_type), DIMENSION(:), INTENT(IN)    :: domain_map
    6358              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: cpu_of_domain
    6359              :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: nocc_of_domain
    6360              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    6361              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    6362              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    6363              :       LOGICAL, INTENT(IN)                                :: optimize_theta, penalty_occ_vol, &
    6364              :                                                             normalize_orbitals
    6365              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: penalty_occ_vol_prefactor, &
    6366              :                                                             penalty_occ_vol_pf2
    6367              :       INTEGER, INTENT(IN)                                :: special_case
    6368              : 
    6369              :       CHARACTER(len=*), PARAMETER :: routineN = 'newton_grad_to_step'
    6370              : 
    6371              :       CHARACTER(LEN=20)                                  :: iter_type
    6372              :       INTEGER                                            :: handle, ispin, iteration, max_iter, &
    6373              :                                                             ndomains, nspins, outer_iteration, &
    6374              :                                                             outer_max_iter, unit_nr
    6375              :       LOGICAL :: converged, do_exact_inversion, outer_prepare_to_exit, prepare_to_exit, &
    6376              :          reset_conjugator, use_preconditioner
    6377              :       REAL(KIND=dp)                                      :: alpha, beta, denom, denom_ispin, &
    6378              :                                                             eps_error_target, numer, numer_ispin, &
    6379              :                                                             residue_norm, spin_factor, t1, t2
    6380            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: residue_max_norm
    6381              :       TYPE(cp_logger_type), POINTER                      :: logger
    6382              :       TYPE(dbcsr_type)                                   :: m_tmp_oo_1, m_tmp_oo_2
    6383            0 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: m_f_vo, m_f_vv, m_Hstep, m_prec, &
    6384            0 :                                                             m_residue, m_residue_prev, m_s_vv, &
    6385            0 :                                                             m_step, m_STsiginv, m_zet, m_zet_prev
    6386              :       TYPE(domain_submatrix_type), ALLOCATABLE, &
    6387              :          DIMENSION(:, :)                                 :: domain_prec
    6388              : 
    6389            0 :       CALL timeset(routineN, handle)
    6390              : 
    6391              :       ! get a useful output_unit
    6392            0 :       logger => cp_get_default_logger()
    6393            0 :       IF (logger%para_env%is_source()) THEN
    6394            0 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    6395              :       ELSE
    6396              :          unit_nr = -1
    6397              :       END IF
    6398              : 
    6399              :       !!! Currently for non-theta only
    6400            0 :       IF (optimize_theta) THEN
    6401            0 :          CPABORT("theta is NYI")
    6402              :       END IF
    6403              : 
    6404              :       ! set optimizer options
    6405            0 :       use_preconditioner = (optimizer%preconditioner /= xalmo_prec_zero)
    6406            0 :       outer_max_iter = optimizer%max_iter_outer_loop
    6407            0 :       max_iter = optimizer%max_iter
    6408            0 :       eps_error_target = optimizer%eps_error
    6409              : 
    6410              :       ! set key dimensions
    6411            0 :       nspins = SIZE(m_ks)
    6412            0 :       ndomains = SIZE(domain_s_inv, 1)
    6413              : 
    6414            0 :       IF (nspins == 1) THEN
    6415            0 :          spin_factor = 2.0_dp
    6416              :       ELSE
    6417            0 :          spin_factor = 1.0_dp
    6418              :       END IF
    6419              : 
    6420            0 :       ALLOCATE (domain_prec(ndomains, nspins))
    6421            0 :       CALL init_submatrices(domain_prec)
    6422              : 
    6423              :       ! allocate matrices
    6424            0 :       ALLOCATE (m_residue(nspins))
    6425            0 :       ALLOCATE (m_residue_prev(nspins))
    6426            0 :       ALLOCATE (m_step(nspins))
    6427            0 :       ALLOCATE (m_zet(nspins))
    6428            0 :       ALLOCATE (m_zet_prev(nspins))
    6429            0 :       ALLOCATE (m_Hstep(nspins))
    6430            0 :       ALLOCATE (m_prec(nspins))
    6431            0 :       ALLOCATE (m_s_vv(nspins))
    6432            0 :       ALLOCATE (m_f_vv(nspins))
    6433            0 :       ALLOCATE (m_f_vo(nspins))
    6434            0 :       ALLOCATE (m_STsiginv(nspins))
    6435              : 
    6436            0 :       ALLOCATE (residue_max_norm(nspins))
    6437              : 
    6438              :       ! initiate objects before iterations
    6439            0 :       DO ispin = 1, nspins
    6440              : 
    6441              :          ! init matrices
    6442              :          CALL dbcsr_create(m_residue(ispin), &
    6443              :                            template=m_quench_t(ispin), &
    6444            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6445              :          CALL dbcsr_create(m_residue_prev(ispin), &
    6446              :                            template=m_quench_t(ispin), &
    6447            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6448              :          CALL dbcsr_create(m_step(ispin), &
    6449              :                            template=m_quench_t(ispin), &
    6450            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6451              :          CALL dbcsr_create(m_zet_prev(ispin), &
    6452              :                            template=m_quench_t(ispin), &
    6453            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6454              :          CALL dbcsr_create(m_zet(ispin), &
    6455              :                            template=m_quench_t(ispin), &
    6456            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6457              :          CALL dbcsr_create(m_Hstep(ispin), &
    6458              :                            template=m_quench_t(ispin), &
    6459            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6460              :          CALL dbcsr_create(m_f_vo(ispin), &
    6461              :                            template=m_quench_t(ispin), &
    6462            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6463              :          CALL dbcsr_create(m_STsiginv(ispin), &
    6464              :                            template=m_quench_t(ispin), &
    6465            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6466              :          CALL dbcsr_create(m_f_vv(ispin), &
    6467              :                            template=m_ks(ispin), &
    6468            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6469              :          CALL dbcsr_create(m_s_vv(ispin), &
    6470              :                            template=m_s(1), &
    6471            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6472              :          CALL dbcsr_create(m_prec(ispin), &
    6473              :                            template=m_ks(ispin), &
    6474            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6475              : 
    6476              :          ! compute the full "gradient" - it is necessary to
    6477              :          ! evaluate Hessian.X
    6478            0 :          CALL dbcsr_copy(m_f_vo(ispin), m_FTsiginv(ispin))
    6479              :          CALL dbcsr_multiply("N", "N", -1.0_dp, &
    6480              :                              m_ST(ispin), &
    6481              :                              m_siginvTFTsiginv(ispin), &
    6482              :                              1.0_dp, m_f_vo(ispin), &
    6483            0 :                              filter_eps=eps_filter)
    6484              : 
    6485              : ! RZK-warning
    6486              : 
    6487              : ! domain_s_inv and domain_r_down are never used with assume_t0_q0x=FALSE
    6488              :          CALL compute_preconditioner( &
    6489              :             domain_prec_out=domain_prec(:, ispin), &
    6490              :             m_prec_out=m_prec(ispin), &
    6491              :             m_ks=m_ks(ispin), &
    6492              :             m_s=m_s(1), &
    6493              :             m_siginv=m_siginv(ispin), &
    6494              :             m_quench_t=m_quench_t(ispin), &
    6495              :             m_FTsiginv=m_FTsiginv(ispin), &
    6496              :             m_siginvTFTsiginv=m_siginvTFTsiginv(ispin), &
    6497              :             m_ST=m_ST(ispin), &
    6498              :             m_STsiginv_out=m_STsiginv(ispin), &
    6499              :             m_s_vv_out=m_s_vv(ispin), &
    6500              :             m_f_vv_out=m_f_vv(ispin), &
    6501              :             para_env=para_env, &
    6502              :             blacs_env=blacs_env, &
    6503              :             nocc_of_domain=nocc_of_domain(:, ispin), &
    6504              :             domain_s_inv=domain_s_inv(:, ispin), &
    6505              :             domain_r_down=domain_r_down(:, ispin), &
    6506              :             cpu_of_domain=cpu_of_domain(:), &
    6507              :             domain_map=domain_map(ispin), &
    6508              :             assume_t0_q0x=.FALSE., &
    6509              :             penalty_occ_vol=penalty_occ_vol, &
    6510              :             penalty_occ_vol_prefactor=penalty_occ_vol_prefactor(ispin), &
    6511              :             eps_filter=eps_filter, &
    6512              :             neg_thr=0.5_dp, &
    6513              :             spin_factor=spin_factor, &
    6514              :             special_case=special_case, &
    6515              :             skip_inversion=.FALSE. &
    6516            0 :             )
    6517              : 
    6518              :          ! initial guess
    6519            0 :          CALL dbcsr_copy(m_delta(ispin), m_quench_t(ispin))
    6520              :          ! in order to use dbcsr_set matrix blocks must exist
    6521            0 :          CALL dbcsr_set(m_delta(ispin), 0.0_dp)
    6522            0 :          CALL dbcsr_copy(m_residue(ispin), m_grad(ispin))
    6523            0 :          CALL dbcsr_scale(m_residue(ispin), -1.0_dp)
    6524              : 
    6525            0 :          do_exact_inversion = .FALSE.
    6526              :          IF (do_exact_inversion) THEN
    6527              : 
    6528              :             ! copy grad to m_step temporarily
    6529              :             ! use m_step as input to the inversion routine
    6530              :             CALL dbcsr_copy(m_step(ispin), m_grad(ispin))
    6531              : 
    6532              :             ! expensive "exact" inversion of the "nearly-exact" Hessian
    6533              :             ! hopefully returns Z=-H^(-1).G
    6534              :             CALL hessian_diag_apply( &
    6535              :                matrix_grad=m_step(ispin), &
    6536              :                matrix_step=m_zet(ispin), &
    6537              :                matrix_S_ao=m_s_vv(ispin), &
    6538              :                matrix_F_ao=m_f_vv(ispin), &
    6539              :                !matrix_S_ao=m_s(ispin),&
    6540              :                !matrix_F_ao=m_ks(ispin),&
    6541              :                matrix_S_mo=m_siginv(ispin), &
    6542              :                matrix_F_mo=m_siginvTFTsiginv(ispin), &
    6543              :                matrix_S_vo=m_STsiginv(ispin), &
    6544              :                matrix_F_vo=m_f_vo(ispin), &
    6545              :                quench_t=m_quench_t(ispin), &
    6546              :                spin_factor=spin_factor, &
    6547              :                eps_zero=eps_filter*10.0_dp, &
    6548              :                penalty_occ_vol=penalty_occ_vol, &
    6549              :                penalty_occ_vol_prefactor=penalty_occ_vol_prefactor(ispin), &
    6550              :                penalty_occ_vol_pf2=penalty_occ_vol_pf2(ispin), &
    6551              :                m_s=m_s(1), &
    6552              :                para_env=para_env, &
    6553              :                blacs_env=blacs_env)
    6554              : 
    6555              :          ELSE ! use PCG to solve H.D=-G
    6556              : 
    6557            0 :             IF (use_preconditioner) THEN
    6558              : 
    6559            0 :                IF (special_case == xalmo_case_block_diag .OR. &
    6560              :                    special_case == xalmo_case_fully_deloc) THEN
    6561              : 
    6562              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, &
    6563              :                                       m_prec(ispin), &
    6564              :                                       m_residue(ispin), &
    6565              :                                       0.0_dp, m_zet(ispin), &
    6566            0 :                                       filter_eps=eps_filter)
    6567              : 
    6568              :                ELSE
    6569              : 
    6570              :                   CALL apply_domain_operators( &
    6571              :                      matrix_in=m_residue(ispin), &
    6572              :                      matrix_out=m_zet(ispin), &
    6573              :                      operator1=domain_prec(:, ispin), &
    6574              :                      dpattern=m_quench_t(ispin), &
    6575              :                      map=domain_map(ispin), &
    6576              :                      node_of_domain=cpu_of_domain(:), &
    6577              :                      my_action=0, &
    6578            0 :                      filter_eps=eps_filter)
    6579              : 
    6580              :                END IF ! special_case
    6581              : 
    6582              :             ELSE ! do not use preconditioner
    6583              : 
    6584            0 :                CALL dbcsr_copy(m_zet(ispin), m_residue(ispin))
    6585              : 
    6586              :             END IF ! use_preconditioner
    6587              : 
    6588              :          END IF ! do_exact_inversion
    6589              : 
    6590            0 :          CALL dbcsr_copy(m_step(ispin), m_zet(ispin))
    6591              : 
    6592              :       END DO !ispin
    6593              : 
    6594              :       ! start the outer SCF loop
    6595              :       outer_prepare_to_exit = .FALSE.
    6596              :       outer_iteration = 0
    6597              :       residue_norm = 0.0_dp
    6598              : 
    6599              :       DO
    6600              : 
    6601              :          ! start the inner SCF loop
    6602            0 :          prepare_to_exit = .FALSE.
    6603            0 :          converged = .FALSE.
    6604            0 :          iteration = 0
    6605            0 :          t1 = m_walltime()
    6606              : 
    6607              :          DO
    6608              : 
    6609              :             ! apply hessian to the step matrix
    6610              :             CALL apply_hessian( &
    6611              :                m_x_in=m_step, &
    6612              :                m_x_out=m_Hstep, &
    6613              :                m_ks=m_ks, &
    6614              :                m_s=m_s, &
    6615              :                m_siginv=m_siginv, &
    6616              :                m_quench_t=m_quench_t, &
    6617              :                m_FTsiginv=m_FTsiginv, &
    6618              :                m_siginvTFTsiginv=m_siginvTFTsiginv, &
    6619              :                m_ST=m_ST, &
    6620              :                m_STsiginv=m_STsiginv, &
    6621              :                m_s_vv=m_s_vv, &
    6622              :                m_ks_vv=m_f_vv, &
    6623              :                !m_s_vv=m_s,&
    6624              :                !m_ks_vv=m_ks,&
    6625              :                m_g_full=m_f_vo, &
    6626              :                m_t=m_t, &
    6627              :                m_sig_sqrti_ii=m_sig_sqrti_ii, &
    6628              :                penalty_occ_vol=penalty_occ_vol, &
    6629              :                normalize_orbitals=normalize_orbitals, &
    6630              :                penalty_occ_vol_prefactor=penalty_occ_vol_prefactor, &
    6631              :                eps_filter=eps_filter, &
    6632            0 :                path_num=hessian_path_reuse)
    6633              : 
    6634              :             ! alpha is computed outside the spin loop
    6635            0 :             numer = 0.0_dp
    6636            0 :             denom = 0.0_dp
    6637            0 :             DO ispin = 1, nspins
    6638              : 
    6639            0 :                CALL dbcsr_dot(m_residue(ispin), m_zet(ispin), numer_ispin)
    6640            0 :                CALL dbcsr_dot(m_step(ispin), m_Hstep(ispin), denom_ispin)
    6641              : 
    6642            0 :                numer = numer + numer_ispin
    6643            0 :                denom = denom + denom_ispin
    6644              : 
    6645              :             END DO !ispin
    6646              : 
    6647            0 :             alpha = numer/denom
    6648              : 
    6649            0 :             DO ispin = 1, nspins
    6650              : 
    6651              :                ! update the variable
    6652            0 :                CALL dbcsr_add(m_delta(ispin), m_step(ispin), 1.0_dp, alpha)
    6653            0 :                CALL dbcsr_copy(m_residue_prev(ispin), m_residue(ispin))
    6654              :                CALL dbcsr_add(m_residue(ispin), m_Hstep(ispin), &
    6655            0 :                               1.0_dp, -1.0_dp*alpha)
    6656            0 :                residue_max_norm(ispin) = dbcsr_maxabs(m_residue(ispin))
    6657              : 
    6658              :             END DO ! ispin
    6659              : 
    6660              :             ! check convergence and other exit criteria
    6661            0 :             residue_norm = MAXVAL(residue_max_norm)
    6662            0 :             converged = (residue_norm < eps_error_target)
    6663            0 :             IF (converged .OR. (iteration >= max_iter)) THEN
    6664              :                prepare_to_exit = .TRUE.
    6665              :             END IF
    6666              : 
    6667            0 :             IF (.NOT. prepare_to_exit) THEN
    6668              : 
    6669            0 :                DO ispin = 1, nspins
    6670              : 
    6671              :                   ! save current z before the update
    6672            0 :                   CALL dbcsr_copy(m_zet_prev(ispin), m_zet(ispin))
    6673              : 
    6674              :                   ! compute the new step (apply preconditioner if available)
    6675            0 :                   IF (use_preconditioner) THEN
    6676              : 
    6677            0 :                      IF (special_case == xalmo_case_block_diag .OR. &
    6678              :                          special_case == xalmo_case_fully_deloc) THEN
    6679              : 
    6680              :                         CALL dbcsr_multiply("N", "N", 1.0_dp, &
    6681              :                                             m_prec(ispin), &
    6682              :                                             m_residue(ispin), &
    6683              :                                             0.0_dp, m_zet(ispin), &
    6684            0 :                                             filter_eps=eps_filter)
    6685              : 
    6686              :                      ELSE
    6687              : 
    6688              :                         CALL apply_domain_operators( &
    6689              :                            matrix_in=m_residue(ispin), &
    6690              :                            matrix_out=m_zet(ispin), &
    6691              :                            operator1=domain_prec(:, ispin), &
    6692              :                            dpattern=m_quench_t(ispin), &
    6693              :                            map=domain_map(ispin), &
    6694              :                            node_of_domain=cpu_of_domain(:), &
    6695              :                            my_action=0, &
    6696            0 :                            filter_eps=eps_filter)
    6697              : 
    6698              :                      END IF ! special case
    6699              : 
    6700              :                   ELSE
    6701              : 
    6702            0 :                      CALL dbcsr_copy(m_zet(ispin), m_residue(ispin))
    6703              : 
    6704              :                   END IF
    6705              : 
    6706              :                END DO !ispin
    6707              : 
    6708              :                ! compute the conjugation coefficient - beta
    6709              :                CALL compute_cg_beta( &
    6710              :                   beta=beta, &
    6711              :                   reset_conjugator=reset_conjugator, &
    6712              :                   conjugator=cg_fletcher, &
    6713              :                   grad=m_residue, &
    6714              :                   prev_grad=m_residue_prev, &
    6715              :                   step=m_zet, &
    6716            0 :                   prev_step=m_zet_prev)
    6717              : 
    6718            0 :                DO ispin = 1, nspins
    6719              : 
    6720              :                   ! conjugate the step direction
    6721            0 :                   CALL dbcsr_add(m_step(ispin), m_zet(ispin), beta, 1.0_dp)
    6722              : 
    6723              :                END DO !ispin
    6724              : 
    6725              :             END IF ! not.prepare_to_exit
    6726              : 
    6727            0 :             t2 = m_walltime()
    6728            0 :             IF (unit_nr > 0) THEN
    6729            0 :                iter_type = TRIM("NR STEP")
    6730              :                WRITE (unit_nr, '(T6,A9,I6,F14.5,F14.5,F15.10,F9.2)') &
    6731            0 :                   iter_type, iteration, &
    6732            0 :                   alpha, beta, residue_norm, &
    6733            0 :                   t2 - t1
    6734              :             END IF
    6735            0 :             t1 = m_walltime()
    6736              : 
    6737            0 :             iteration = iteration + 1
    6738            0 :             IF (prepare_to_exit) EXIT
    6739              : 
    6740              :          END DO ! inner loop
    6741              : 
    6742            0 :          IF (converged .OR. (outer_iteration >= outer_max_iter)) THEN
    6743            0 :             outer_prepare_to_exit = .TRUE.
    6744              :          END IF
    6745              : 
    6746            0 :          outer_iteration = outer_iteration + 1
    6747            0 :          IF (outer_prepare_to_exit) EXIT
    6748              : 
    6749              :       END DO ! outer loop
    6750              : 
    6751            0 :       DO ispin = 1, nspins
    6752              : 
    6753              :          ! check whether the step lies entirely in R or Q
    6754              :          CALL dbcsr_create(m_tmp_oo_1, &
    6755              :                            template=m_siginv(ispin), &
    6756            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6757              :          CALL dbcsr_create(m_tmp_oo_2, &
    6758              :                            template=m_siginv(ispin), &
    6759            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6760              :          CALL dbcsr_multiply("T", "N", 1.0_dp, &
    6761              :                              m_ST(ispin), &
    6762              :                              m_delta(ispin), &
    6763              :                              0.0_dp, m_tmp_oo_1, &
    6764            0 :                              filter_eps=eps_filter)
    6765              :          CALL dbcsr_multiply("N", "N", 1.0_dp, &
    6766              :                              m_siginv(ispin), &
    6767              :                              m_tmp_oo_1, &
    6768              :                              0.0_dp, m_tmp_oo_2, &
    6769            0 :                              filter_eps=eps_filter)
    6770            0 :          CALL dbcsr_copy(m_zet(ispin), m_quench_t(ispin))
    6771              :          CALL dbcsr_multiply("N", "N", 1.0_dp, &
    6772              :                              m_t(ispin), &
    6773              :                              m_tmp_oo_2, &
    6774              :                              0.0_dp, m_zet(ispin), &
    6775            0 :                              retain_sparsity=.TRUE.)
    6776            0 :          alpha = dbcsr_maxabs(m_zet(ispin))
    6777            0 :          WRITE (unit_nr, "(A50,2F20.10)") "Occupied-space projection of the step", alpha
    6778            0 :          CALL dbcsr_add(m_zet(ispin), m_delta(ispin), -1.0_dp, 1.0_dp)
    6779            0 :          alpha = dbcsr_maxabs(m_zet(ispin))
    6780            0 :          WRITE (unit_nr, "(A50,2F20.10)") "Virtual-space projection of the step", alpha
    6781            0 :          alpha = dbcsr_maxabs(m_delta(ispin))
    6782            0 :          WRITE (unit_nr, "(A50,2F20.10)") "Full step", alpha
    6783            0 :          CALL dbcsr_release(m_tmp_oo_1)
    6784            0 :          CALL dbcsr_release(m_tmp_oo_2)
    6785              : 
    6786              :       END DO
    6787              : 
    6788              :       ! clean up
    6789            0 :       DO ispin = 1, nspins
    6790            0 :          CALL release_submatrices(domain_prec(:, ispin))
    6791            0 :          CALL dbcsr_release(m_residue(ispin))
    6792            0 :          CALL dbcsr_release(m_residue_prev(ispin))
    6793            0 :          CALL dbcsr_release(m_step(ispin))
    6794            0 :          CALL dbcsr_release(m_zet(ispin))
    6795            0 :          CALL dbcsr_release(m_zet_prev(ispin))
    6796            0 :          CALL dbcsr_release(m_Hstep(ispin))
    6797            0 :          CALL dbcsr_release(m_f_vo(ispin))
    6798            0 :          CALL dbcsr_release(m_f_vv(ispin))
    6799            0 :          CALL dbcsr_release(m_s_vv(ispin))
    6800            0 :          CALL dbcsr_release(m_prec(ispin))
    6801            0 :          CALL dbcsr_release(m_STsiginv(ispin))
    6802              :       END DO !ispin
    6803            0 :       DEALLOCATE (domain_prec)
    6804            0 :       DEALLOCATE (m_residue)
    6805            0 :       DEALLOCATE (m_residue_prev)
    6806            0 :       DEALLOCATE (m_step)
    6807            0 :       DEALLOCATE (m_zet)
    6808            0 :       DEALLOCATE (m_zet_prev)
    6809            0 :       DEALLOCATE (m_prec)
    6810            0 :       DEALLOCATE (m_Hstep)
    6811            0 :       DEALLOCATE (m_s_vv)
    6812            0 :       DEALLOCATE (m_f_vv)
    6813            0 :       DEALLOCATE (m_f_vo)
    6814            0 :       DEALLOCATE (m_STsiginv)
    6815            0 :       DEALLOCATE (residue_max_norm)
    6816              : 
    6817            0 :       IF (.NOT. converged) THEN
    6818            0 :          CPABORT("Optimization not converged!")
    6819              :       END IF
    6820              : 
    6821              :       ! check that the step satisfies H.step=-grad
    6822              : 
    6823            0 :       CALL timestop(handle)
    6824              : 
    6825            0 :    END SUBROUTINE newton_grad_to_step
    6826              : 
    6827              : ! *****************************************************************************
    6828              : !> \brief Computes Hessian.X
    6829              : !> \param m_x_in ...
    6830              : !> \param m_x_out ...
    6831              : !> \param m_ks ...
    6832              : !> \param m_s ...
    6833              : !> \param m_siginv ...
    6834              : !> \param m_quench_t ...
    6835              : !> \param m_FTsiginv ...
    6836              : !> \param m_siginvTFTsiginv ...
    6837              : !> \param m_ST ...
    6838              : !> \param m_STsiginv ...
    6839              : !> \param m_s_vv ...
    6840              : !> \param m_ks_vv ...
    6841              : !> \param m_g_full ...
    6842              : !> \param m_t ...
    6843              : !> \param m_sig_sqrti_ii ...
    6844              : !> \param penalty_occ_vol ...
    6845              : !> \param normalize_orbitals ...
    6846              : !> \param penalty_occ_vol_prefactor ...
    6847              : !> \param eps_filter ...
    6848              : !> \param path_num ...
    6849              : !> \par History
    6850              : !>       2015.04 created [Rustam Z Khaliullin]
    6851              : !> \author Rustam Z Khaliullin
    6852              : ! **************************************************************************************************
    6853            0 :    SUBROUTINE apply_hessian(m_x_in, m_x_out, m_ks, m_s, m_siginv, &
    6854            0 :                             m_quench_t, m_FTsiginv, m_siginvTFTsiginv, m_ST, m_STsiginv, m_s_vv, &
    6855            0 :                             m_ks_vv, m_g_full, m_t, m_sig_sqrti_ii, penalty_occ_vol, &
    6856            0 :                             normalize_orbitals, penalty_occ_vol_prefactor, eps_filter, path_num)
    6857              : 
    6858              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT)      :: m_x_in, m_x_out, m_ks, m_s
    6859              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: m_siginv, m_quench_t, m_FTsiginv, &
    6860              :                                                             m_siginvTFTsiginv, m_ST, m_STsiginv
    6861              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT)      :: m_s_vv, m_ks_vv, m_g_full
    6862              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: m_t, m_sig_sqrti_ii
    6863              :       LOGICAL, INTENT(IN)                                :: penalty_occ_vol, normalize_orbitals
    6864              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: penalty_occ_vol_prefactor
    6865              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    6866              :       INTEGER, INTENT(IN)                                :: path_num
    6867              : 
    6868              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'apply_hessian'
    6869              : 
    6870              :       INTEGER                                            :: dim0, handle, ispin, nspins
    6871              :       REAL(KIND=dp)                                      :: penalty_prefactor_local, spin_factor
    6872            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: tg_diagonal
    6873              :       TYPE(dbcsr_type)                                   :: m_tmp_no_1, m_tmp_no_2, m_tmp_oo_1, &
    6874              :                                                             m_tmp_x_in
    6875              : 
    6876            0 :       CALL timeset(routineN, handle)
    6877              : 
    6878              :       !JHU: test and use for unused debug variables
    6879            0 :       IF (penalty_occ_vol) penalty_prefactor_local = 1._dp
    6880            0 :       CPASSERT(SIZE(m_STsiginv) >= 0)
    6881            0 :       CPASSERT(SIZE(m_siginvTFTsiginv) >= 0)
    6882            0 :       CPASSERT(SIZE(m_s) >= 0)
    6883            0 :       CPASSERT(SIZE(m_g_full) >= 0)
    6884            0 :       CPASSERT(SIZE(m_FTsiginv) >= 0)
    6885              :       MARK_USED(m_siginvTFTsiginv)
    6886              :       MARK_USED(m_STsiginv)
    6887              :       MARK_USED(m_FTsiginv)
    6888              :       MARK_USED(m_g_full)
    6889              :       MARK_USED(m_s)
    6890              : 
    6891            0 :       nspins = SIZE(m_ks)
    6892              : 
    6893            0 :       IF (nspins == 1) THEN
    6894              :          spin_factor = 2.0_dp
    6895              :       ELSE
    6896            0 :          spin_factor = 1.0_dp
    6897              :       END IF
    6898              : 
    6899            0 :       DO ispin = 1, nspins
    6900              : 
    6901            0 :          penalty_prefactor_local = penalty_occ_vol_prefactor(ispin)/(2.0_dp*spin_factor)
    6902              : 
    6903              :          CALL dbcsr_create(m_tmp_oo_1, &
    6904              :                            template=m_siginv(ispin), &
    6905            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6906              :          CALL dbcsr_create(m_tmp_no_1, &
    6907              :                            template=m_quench_t(ispin), &
    6908            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6909              :          CALL dbcsr_create(m_tmp_no_2, &
    6910              :                            template=m_quench_t(ispin), &
    6911            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6912              :          CALL dbcsr_create(m_tmp_x_in, &
    6913              :                            template=m_quench_t(ispin), &
    6914            0 :                            matrix_type=dbcsr_type_no_symmetry)
    6915              : 
    6916              :          ! transform the input X to take into account the normalization constraint
    6917            0 :          IF (normalize_orbitals) THEN
    6918              : 
    6919              :             ! H.D = ( (H.D) - ST.[tr(T).(H.D)]_ii ) . [sig_sqrti]_ii
    6920              : 
    6921              :             ! get [tr(T).HD]_ii
    6922            0 :             CALL dbcsr_copy(m_tmp_oo_1, m_sig_sqrti_ii(ispin))
    6923              :             CALL dbcsr_multiply("T", "N", 1.0_dp, &
    6924              :                                 m_x_in(ispin), &
    6925              :                                 m_ST(ispin), &
    6926              :                                 0.0_dp, m_tmp_oo_1, &
    6927            0 :                                 retain_sparsity=.TRUE.)
    6928            0 :             CALL dbcsr_get_info(m_sig_sqrti_ii(ispin), nfullrows_total=dim0)
    6929            0 :             ALLOCATE (tg_diagonal(dim0))
    6930            0 :             CALL dbcsr_get_diag(m_tmp_oo_1, tg_diagonal)
    6931            0 :             CALL dbcsr_set(m_tmp_oo_1, 0.0_dp)
    6932            0 :             CALL dbcsr_set_diag(m_tmp_oo_1, tg_diagonal)
    6933            0 :             DEALLOCATE (tg_diagonal)
    6934              : 
    6935            0 :             CALL dbcsr_copy(m_tmp_no_1, m_x_in(ispin))
    6936              :             CALL dbcsr_multiply("N", "N", -1.0_dp, &
    6937              :                                 m_t(ispin), &
    6938              :                                 m_tmp_oo_1, &
    6939              :                                 1.0_dp, m_tmp_no_1, &
    6940            0 :                                 filter_eps=eps_filter)
    6941              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    6942              :                                 m_tmp_no_1, &
    6943              :                                 m_sig_sqrti_ii(ispin), &
    6944              :                                 0.0_dp, m_tmp_x_in, &
    6945            0 :                                 filter_eps=eps_filter)
    6946              : 
    6947              :          ELSE
    6948              : 
    6949            0 :             CALL dbcsr_copy(m_tmp_x_in, m_x_in(ispin))
    6950              : 
    6951              :          END IF ! normalize_orbitals
    6952              : 
    6953            0 :          IF (path_num == hessian_path_reuse) THEN
    6954              : 
    6955              :             ! apply pre-computed F_vv and S_vv to X
    6956              : 
    6957              :             ! debugging: only vv matrices, oo matrices are kronecker
    6958            0 :             CALL dbcsr_copy(m_x_out(ispin), m_quench_t(ispin))
    6959              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    6960              :                                 m_ks_vv(ispin), &
    6961              :                                 m_tmp_x_in, &
    6962              :                                 0.0_dp, m_x_out(ispin), &
    6963            0 :                                 retain_sparsity=.TRUE.)
    6964              : 
    6965            0 :             CALL dbcsr_copy(m_tmp_no_2, m_quench_t(ispin))
    6966              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    6967              :                                 m_s_vv(ispin), &
    6968              :                                 m_tmp_x_in, &
    6969              :                                 0.0_dp, m_tmp_no_2, &
    6970            0 :                                 retain_sparsity=.TRUE.)
    6971              :             CALL dbcsr_add(m_x_out(ispin), m_tmp_no_2, &
    6972            0 :                            1.0_dp, -4.0_dp*penalty_prefactor_local + 1.0_dp)
    6973              : 
    6974            0 :          ELSE IF (path_num == hessian_path_assemble) THEN
    6975              : 
    6976              :             ! compute F_vv.X and S_vv.X directly
    6977              :             ! this path will be advantageous if the number
    6978              :             ! of PCG iterations is small
    6979            0 :             CPABORT("path is NYI")
    6980              : 
    6981              :          ELSE
    6982            0 :             CPABORT("illegal path")
    6983              :          END IF ! path
    6984              : 
    6985              :          ! transform the output to take into account the normalization constraint
    6986            0 :          IF (normalize_orbitals) THEN
    6987              : 
    6988              :             ! H.D = ( (H.D) - ST.[tr(T).(H.D)]_ii ) . [sig_sqrti]_ii
    6989              : 
    6990              :             ! get [tr(T).HD]_ii
    6991            0 :             CALL dbcsr_copy(m_tmp_oo_1, m_sig_sqrti_ii(ispin))
    6992              :             CALL dbcsr_multiply("T", "N", 1.0_dp, &
    6993              :                                 m_t(ispin), &
    6994              :                                 m_x_out(ispin), &
    6995              :                                 0.0_dp, m_tmp_oo_1, &
    6996            0 :                                 retain_sparsity=.TRUE.)
    6997            0 :             CALL dbcsr_get_info(m_sig_sqrti_ii(ispin), nfullrows_total=dim0)
    6998            0 :             ALLOCATE (tg_diagonal(dim0))
    6999            0 :             CALL dbcsr_get_diag(m_tmp_oo_1, tg_diagonal)
    7000            0 :             CALL dbcsr_set(m_tmp_oo_1, 0.0_dp)
    7001            0 :             CALL dbcsr_set_diag(m_tmp_oo_1, tg_diagonal)
    7002            0 :             DEALLOCATE (tg_diagonal)
    7003              : 
    7004              :             CALL dbcsr_multiply("N", "N", -1.0_dp, &
    7005              :                                 m_ST(ispin), &
    7006              :                                 m_tmp_oo_1, &
    7007              :                                 1.0_dp, m_x_out(ispin), &
    7008            0 :                                 retain_sparsity=.TRUE.)
    7009            0 :             CALL dbcsr_copy(m_tmp_no_1, m_x_out(ispin))
    7010              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    7011              :                                 m_tmp_no_1, &
    7012              :                                 m_sig_sqrti_ii(ispin), &
    7013              :                                 0.0_dp, m_x_out(ispin), &
    7014            0 :                                 retain_sparsity=.TRUE.)
    7015              : 
    7016              :          END IF ! normalize_orbitals
    7017              : 
    7018              :          CALL dbcsr_scale(m_x_out(ispin), &
    7019            0 :                           2.0_dp*spin_factor)
    7020              : 
    7021            0 :          CALL dbcsr_release(m_tmp_oo_1)
    7022            0 :          CALL dbcsr_release(m_tmp_no_1)
    7023            0 :          CALL dbcsr_release(m_tmp_no_2)
    7024            0 :          CALL dbcsr_release(m_tmp_x_in)
    7025              : 
    7026              :       END DO !ispin
    7027              : 
    7028              :       ! there is one more part of the hessian that comes
    7029              :       ! from T-dependence of the KS matrix
    7030              :       ! it is neglected here
    7031              : 
    7032            0 :       CALL timestop(handle)
    7033              : 
    7034            0 :    END SUBROUTINE apply_hessian
    7035              : 
    7036              : ! *****************************************************************************
    7037              : !> \brief Serial code that constructs an approximate Hessian
    7038              : !> \param matrix_grad ...
    7039              : !> \param matrix_step ...
    7040              : !> \param matrix_S_ao ...
    7041              : !> \param matrix_F_ao ...
    7042              : !> \param matrix_S_mo ...
    7043              : !> \param matrix_F_mo ...
    7044              : !> \param matrix_S_vo ...
    7045              : !> \param matrix_F_vo ...
    7046              : !> \param quench_t ...
    7047              : !> \param penalty_occ_vol ...
    7048              : !> \param penalty_occ_vol_prefactor ...
    7049              : !> \param penalty_occ_vol_pf2 ...
    7050              : !> \param spin_factor ...
    7051              : !> \param eps_zero ...
    7052              : !> \param m_s ...
    7053              : !> \param para_env ...
    7054              : !> \param blacs_env ...
    7055              : !> \par History
    7056              : !>       2012.02 created [Rustam Z. Khaliullin]
    7057              : !> \author Rustam Z. Khaliullin
    7058              : ! **************************************************************************************************
    7059            0 :    SUBROUTINE hessian_diag_apply(matrix_grad, matrix_step, matrix_S_ao, &
    7060              :                                  matrix_F_ao, matrix_S_mo, matrix_F_mo, matrix_S_vo, matrix_F_vo, quench_t, &
    7061              :                                  penalty_occ_vol, penalty_occ_vol_prefactor, penalty_occ_vol_pf2, &
    7062              :                                  spin_factor, eps_zero, m_s, para_env, blacs_env)
    7063              : 
    7064              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix_grad, matrix_step, matrix_S_ao, &
    7065              :                                                             matrix_F_ao, matrix_S_mo
    7066              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix_F_mo
    7067              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix_S_vo, matrix_F_vo, quench_t
    7068              :       LOGICAL, INTENT(IN)                                :: penalty_occ_vol
    7069              :       REAL(KIND=dp), INTENT(IN)                          :: penalty_occ_vol_prefactor, &
    7070              :                                                             penalty_occ_vol_pf2, spin_factor, &
    7071              :                                                             eps_zero
    7072              :       TYPE(dbcsr_type), INTENT(IN)                       :: m_s
    7073              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    7074              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    7075              : 
    7076              :       CHARACTER(len=*), PARAMETER :: routineN = 'hessian_diag_apply'
    7077              : 
    7078              :       INTEGER :: ao_hori_offset, ao_vert_offset, block_col, block_row, col, H_size, handle, ii, &
    7079              :          INFO, jj, lev1_hori_offset, lev1_vert_offset, lev2_hori_offset, lev2_vert_offset, LWORK, &
    7080              :          nblkcols_tot, nblkrows_tot, ncores, orb_i, orb_j, row, unit_nr, zero_neg_eiv
    7081            0 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ao_block_sizes, ao_domain_sizes, &
    7082            0 :                                                             mo_block_sizes
    7083            0 :       INTEGER, DIMENSION(:), POINTER                     :: ao_blk_sizes, mo_blk_sizes
    7084              :       LOGICAL                                            :: found, found_col, found_row
    7085              :       REAL(KIND=dp)                                      :: penalty_prefactor_local, test_error
    7086            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenvalues, Grad_vec, Step_vec, tmp, &
    7087            0 :                                                             tmpr, work
    7088            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: F_ao_block, F_mo_block, H, Hinv, &
    7089            0 :                                                             new_block, S_ao_block, S_mo_block, &
    7090            0 :                                                             test, test2
    7091            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block_p
    7092              :       TYPE(cp_logger_type), POINTER                      :: logger
    7093              :       TYPE(dbcsr_distribution_type)                      :: main_dist
    7094              :       TYPE(dbcsr_type)                                   :: matrix_F_ao_sym, matrix_F_mo_sym, &
    7095              :                                                             matrix_S_ao_sym, matrix_S_mo_sym
    7096              : 
    7097            0 :       CALL timeset(routineN, handle)
    7098              : 
    7099              :       ! get a useful output_unit
    7100            0 :       logger => cp_get_default_logger()
    7101            0 :       IF (logger%para_env%is_source()) THEN
    7102            0 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    7103              :       ELSE
    7104              :          unit_nr = -1
    7105              :       END IF
    7106              : 
    7107              :       !JHU use and test for unused debug variables
    7108            0 :       CPASSERT(ASSOCIATED(blacs_env))
    7109            0 :       CPASSERT(ASSOCIATED(para_env))
    7110              :       MARK_USED(blacs_env)
    7111              :       MARK_USED(para_env)
    7112              : 
    7113            0 :       CALL dbcsr_get_info(m_s, row_blk_size=ao_blk_sizes)
    7114            0 :       CALL dbcsr_get_info(matrix_S_vo, row_blk_size=ao_blk_sizes)
    7115            0 :       CALL dbcsr_get_info(matrix_F_vo, row_blk_size=ao_blk_sizes)
    7116              : 
    7117              :       ! serial code only
    7118            0 :       CALL dbcsr_get_info(matrix=matrix_S_ao, distribution=main_dist)
    7119            0 :       CALL dbcsr_distribution_get(main_dist, numnodes=ncores)
    7120            0 :       IF (ncores > 1) THEN
    7121            0 :          CPABORT("serial code only")
    7122              :       END IF
    7123              : 
    7124              :       CALL dbcsr_get_info(quench_t, row_blk_size=ao_blk_sizes, col_blk_size=mo_blk_sizes, &
    7125            0 :                           nblkrows_total=nblkrows_tot, nblkcols_total=nblkcols_tot)
    7126            0 :       CPASSERT(nblkrows_tot == nblkcols_tot)
    7127            0 :       ALLOCATE (mo_block_sizes(nblkcols_tot), ao_block_sizes(nblkcols_tot))
    7128            0 :       ALLOCATE (ao_domain_sizes(nblkcols_tot))
    7129            0 :       mo_block_sizes(:) = mo_blk_sizes(:)
    7130            0 :       ao_block_sizes(:) = ao_blk_sizes(:)
    7131            0 :       ao_domain_sizes(:) = 0
    7132              : 
    7133              :       CALL dbcsr_create(matrix_S_ao_sym, &
    7134              :                         template=matrix_S_ao, &
    7135            0 :                         matrix_type=dbcsr_type_no_symmetry)
    7136            0 :       CALL dbcsr_desymmetrize(matrix_S_ao, matrix_S_ao_sym)
    7137            0 :       CALL dbcsr_scale(matrix_S_ao_sym, 2.0_dp*spin_factor)
    7138              : 
    7139              :       CALL dbcsr_create(matrix_F_ao_sym, &
    7140              :                         template=matrix_F_ao, &
    7141            0 :                         matrix_type=dbcsr_type_no_symmetry)
    7142            0 :       CALL dbcsr_desymmetrize(matrix_F_ao, matrix_F_ao_sym)
    7143            0 :       CALL dbcsr_scale(matrix_F_ao_sym, 2.0_dp*spin_factor)
    7144              : 
    7145              :       CALL dbcsr_create(matrix_S_mo_sym, &
    7146              :                         template=matrix_S_mo, &
    7147            0 :                         matrix_type=dbcsr_type_no_symmetry)
    7148            0 :       CALL dbcsr_desymmetrize(matrix_S_mo, matrix_S_mo_sym)
    7149              : 
    7150              :       CALL dbcsr_create(matrix_F_mo_sym, &
    7151              :                         template=matrix_F_mo, &
    7152            0 :                         matrix_type=dbcsr_type_no_symmetry)
    7153            0 :       CALL dbcsr_desymmetrize(matrix_F_mo, matrix_F_mo_sym)
    7154              : 
    7155            0 :       IF (penalty_occ_vol) THEN
    7156            0 :          penalty_prefactor_local = penalty_occ_vol_prefactor/(2.0_dp*spin_factor)
    7157              :       ELSE
    7158            0 :          penalty_prefactor_local = 0.0_dp
    7159              :       END IF
    7160              : 
    7161            0 :       WRITE (unit_nr, *) "penalty_prefactor_local: ", penalty_prefactor_local
    7162            0 :       WRITE (unit_nr, *) "penalty_prefactor_2: ", penalty_occ_vol_pf2
    7163              : 
    7164              :       ! loop over domains to find the size of the Hessian
    7165            0 :       H_size = 0
    7166            0 :       DO col = 1, nblkcols_tot
    7167              : 
    7168              :          ! find sizes of AO submatrices
    7169            0 :          DO row = 1, nblkrows_tot
    7170              : 
    7171              :             CALL dbcsr_get_block_p(quench_t, &
    7172            0 :                                    row, col, block_p, found)
    7173            0 :             IF (found) THEN
    7174            0 :                ao_domain_sizes(col) = ao_domain_sizes(col) + ao_blk_sizes(row)
    7175              :             END IF
    7176              : 
    7177              :          END DO
    7178              : 
    7179            0 :          H_size = H_size + ao_domain_sizes(col)*mo_block_sizes(col)
    7180              : 
    7181              :       END DO
    7182              : 
    7183            0 :       ALLOCATE (H(H_size, H_size))
    7184            0 :       H(:, :) = 0.0_dp
    7185              : 
    7186              :       ! fill the Hessian matrix
    7187            0 :       lev1_vert_offset = 0
    7188              :       ! loop over all pairs of fragments
    7189            0 :       DO row = 1, nblkcols_tot
    7190              : 
    7191            0 :          lev1_hori_offset = 0
    7192            0 :          DO col = 1, nblkcols_tot
    7193              : 
    7194              :             ! prepare blocks for the current row-column fragment pair
    7195            0 :             ALLOCATE (F_ao_block(ao_domain_sizes(row), ao_domain_sizes(col)))
    7196            0 :             ALLOCATE (S_ao_block(ao_domain_sizes(row), ao_domain_sizes(col)))
    7197            0 :             ALLOCATE (F_mo_block(mo_block_sizes(row), mo_block_sizes(col)))
    7198            0 :             ALLOCATE (S_mo_block(mo_block_sizes(row), mo_block_sizes(col)))
    7199              : 
    7200            0 :             F_ao_block(:, :) = 0.0_dp
    7201            0 :             S_ao_block(:, :) = 0.0_dp
    7202              :             F_mo_block(:, :) = 0.0_dp
    7203              :             S_mo_block(:, :) = 0.0_dp
    7204              : 
    7205              :             ! fill AO submatrices
    7206              :             ! loop over all blocks of the AO dbcsr matrix
    7207            0 :             ao_vert_offset = 0
    7208            0 :             DO block_row = 1, nblkcols_tot
    7209              : 
    7210              :                CALL dbcsr_get_block_p(quench_t, &
    7211            0 :                                       block_row, row, block_p, found_row)
    7212            0 :                IF (found_row) THEN
    7213              : 
    7214            0 :                   ao_hori_offset = 0
    7215            0 :                   DO block_col = 1, nblkcols_tot
    7216              : 
    7217              :                      CALL dbcsr_get_block_p(quench_t, &
    7218            0 :                                             block_col, col, block_p, found_col)
    7219            0 :                      IF (found_col) THEN
    7220              : 
    7221              :                         CALL dbcsr_get_block_p(matrix_F_ao_sym, &
    7222            0 :                                                block_row, block_col, block_p, found)
    7223            0 :                         IF (found) THEN
    7224              :                            ! copy the block into the submatrix
    7225              :                            F_ao_block(ao_vert_offset + 1:ao_vert_offset + ao_block_sizes(block_row), &
    7226              :                                       ao_hori_offset + 1:ao_hori_offset + ao_block_sizes(block_col)) &
    7227            0 :                               = block_p(:, :)
    7228              :                         END IF
    7229              : 
    7230              :                         CALL dbcsr_get_block_p(matrix_S_ao_sym, &
    7231            0 :                                                block_row, block_col, block_p, found)
    7232            0 :                         IF (found) THEN
    7233              :                            ! copy the block into the submatrix
    7234              :                            S_ao_block(ao_vert_offset + 1:ao_vert_offset + ao_block_sizes(block_row), &
    7235              :                                       ao_hori_offset + 1:ao_hori_offset + ao_block_sizes(block_col)) &
    7236            0 :                               = block_p(:, :)
    7237              :                         END IF
    7238              : 
    7239            0 :                         ao_hori_offset = ao_hori_offset + ao_block_sizes(block_col)
    7240              : 
    7241              :                      END IF
    7242              : 
    7243              :                   END DO
    7244              : 
    7245            0 :                   ao_vert_offset = ao_vert_offset + ao_block_sizes(block_row)
    7246              : 
    7247              :                END IF
    7248              : 
    7249              :             END DO
    7250              : 
    7251              :             ! fill MO submatrices
    7252            0 :             CALL dbcsr_get_block_p(matrix_F_mo_sym, row, col, block_p, found)
    7253            0 :             IF (found) THEN
    7254              :                ! copy the block into the submatrix
    7255            0 :                F_mo_block(1:mo_block_sizes(row), 1:mo_block_sizes(col)) = block_p(:, :)
    7256              :             END IF
    7257            0 :             CALL dbcsr_get_block_p(matrix_S_mo_sym, row, col, block_p, found)
    7258            0 :             IF (found) THEN
    7259              :                ! copy the block into the submatrix
    7260            0 :                S_mo_block(1:mo_block_sizes(row), 1:mo_block_sizes(col)) = block_p(:, :)
    7261              :             END IF
    7262              : 
    7263              :             ! construct tensor products for the current row-column fragment pair
    7264              :             lev2_vert_offset = 0
    7265            0 :             DO orb_j = 1, mo_block_sizes(row)
    7266              : 
    7267              :                lev2_hori_offset = 0
    7268            0 :                DO orb_i = 1, mo_block_sizes(col)
    7269            0 :                   IF (orb_i == orb_j .AND. row == col) THEN
    7270              :                      H(lev1_vert_offset + lev2_vert_offset + 1:lev1_vert_offset + lev2_vert_offset + ao_domain_sizes(row), &
    7271              :                        lev1_hori_offset + lev2_hori_offset + 1:lev1_hori_offset + lev2_hori_offset + ao_domain_sizes(col)) &
    7272            0 :                         = F_ao_block(:, :) + S_ao_block(:, :)
    7273              :                   END IF
    7274              : 
    7275            0 :                   lev2_hori_offset = lev2_hori_offset + ao_domain_sizes(col)
    7276              : 
    7277              :                END DO
    7278              : 
    7279            0 :                lev2_vert_offset = lev2_vert_offset + ao_domain_sizes(row)
    7280              : 
    7281              :             END DO
    7282              : 
    7283            0 :             lev1_hori_offset = lev1_hori_offset + ao_domain_sizes(col)*mo_block_sizes(col)
    7284              : 
    7285            0 :             DEALLOCATE (F_ao_block)
    7286            0 :             DEALLOCATE (S_ao_block)
    7287            0 :             DEALLOCATE (F_mo_block)
    7288            0 :             DEALLOCATE (S_mo_block)
    7289              : 
    7290              :          END DO ! col fragment
    7291              : 
    7292            0 :          lev1_vert_offset = lev1_vert_offset + ao_domain_sizes(row)*mo_block_sizes(row)
    7293              : 
    7294              :       END DO ! row fragment
    7295              : 
    7296            0 :       CALL dbcsr_release(matrix_S_ao_sym)
    7297            0 :       CALL dbcsr_release(matrix_F_ao_sym)
    7298            0 :       CALL dbcsr_release(matrix_S_mo_sym)
    7299            0 :       CALL dbcsr_release(matrix_F_mo_sym)
    7300              : 
    7301              :       ! convert gradient from the dbcsr matrix to the vector form
    7302            0 :       ALLOCATE (Grad_vec(H_size))
    7303            0 :       Grad_vec(:) = 0.0_dp
    7304            0 :       lev1_vert_offset = 0
    7305              :       ! loop over all electron blocks
    7306            0 :       DO col = 1, nblkcols_tot
    7307              : 
    7308              :          ! loop over AO-rows of the dbcsr matrix
    7309            0 :          lev2_vert_offset = 0
    7310            0 :          DO row = 1, nblkrows_tot
    7311              : 
    7312              :             CALL dbcsr_get_block_p(quench_t, &
    7313            0 :                                    row, col, block_p, found_row)
    7314            0 :             IF (found_row) THEN
    7315              : 
    7316              :                CALL dbcsr_get_block_p(matrix_grad, &
    7317            0 :                                       row, col, block_p, found)
    7318            0 :                IF (found) THEN
    7319              :                   ! copy the data into the vector, column by column
    7320            0 :                   DO orb_i = 1, mo_block_sizes(col)
    7321              :                      Grad_vec(lev1_vert_offset + ao_domain_sizes(col)*(orb_i - 1) + lev2_vert_offset + 1: &
    7322              :                               lev1_vert_offset + ao_domain_sizes(col)*(orb_i - 1) + lev2_vert_offset + ao_block_sizes(row)) &
    7323            0 :                         = block_p(:, orb_i)
    7324              :                   END DO
    7325              : 
    7326              :                END IF
    7327              : 
    7328            0 :                lev2_vert_offset = lev2_vert_offset + ao_block_sizes(row)
    7329              : 
    7330              :             END IF
    7331              : 
    7332              :          END DO
    7333              : 
    7334            0 :          lev1_vert_offset = lev1_vert_offset + ao_domain_sizes(col)*mo_block_sizes(col)
    7335              : 
    7336              :       END DO ! loop over electron blocks
    7337              : 
    7338              :       ! invert the Hessian
    7339            0 :       INFO = 0
    7340            0 :       ALLOCATE (Hinv(H_size, H_size))
    7341            0 :       Hinv(:, :) = H(:, :)
    7342              : 
    7343              :       ! before inverting diagonalize
    7344            0 :       ALLOCATE (eigenvalues(H_size))
    7345              :       ! Query the optimal workspace for dsyev
    7346            0 :       LWORK = -1
    7347            0 :       ALLOCATE (WORK(MAX(1, LWORK)))
    7348            0 :       CALL dsyev('V', 'L', H_size, Hinv, H_size, eigenvalues, WORK, LWORK, INFO)
    7349            0 :       LWORK = INT(WORK(1))
    7350            0 :       DEALLOCATE (WORK)
    7351              :       ! Allocate the workspace and solve the eigenproblem
    7352            0 :       ALLOCATE (WORK(MAX(1, LWORK)))
    7353            0 :       CALL dsyev('V', 'L', H_size, Hinv, H_size, eigenvalues, WORK, LWORK, INFO)
    7354            0 :       IF (INFO /= 0) THEN
    7355            0 :          WRITE (unit_nr, *) 'DSYEV ERROR MESSAGE: ', INFO
    7356            0 :          CPABORT("DSYEV failed")
    7357              :       END IF
    7358            0 :       DEALLOCATE (WORK)
    7359              : 
    7360              :       ! compute grad vector in the basis of Hessian eigenvectors
    7361            0 :       ALLOCATE (Step_vec(H_size))
    7362              :       ! Step_vec contains Grad_vec here
    7363            0 :       Step_vec(:) = MATMUL(TRANSPOSE(Hinv), Grad_vec)
    7364              : 
    7365              :       ! invert eigenvalues and use eigenvectors to compute the Hessian inverse
    7366              :       ! project out zero-eigenvalue directions
    7367            0 :       ALLOCATE (test(H_size, H_size))
    7368            0 :       zero_neg_eiv = 0
    7369            0 :       DO jj = 1, H_size
    7370            0 :          WRITE (unit_nr, "(I10,F20.10,F20.10)") jj, eigenvalues(jj), Step_vec(jj)
    7371            0 :          IF (eigenvalues(jj) > eps_zero) THEN
    7372            0 :             test(jj, :) = Hinv(:, jj)/eigenvalues(jj)
    7373              :          ELSE
    7374            0 :             test(jj, :) = Hinv(:, jj)*0.0_dp
    7375            0 :             zero_neg_eiv = zero_neg_eiv + 1
    7376              :          END IF
    7377              :       END DO
    7378            0 :       WRITE (unit_nr, *) 'ZERO OR NEGATIVE EIGENVALUES: ', zero_neg_eiv
    7379            0 :       DEALLOCATE (Step_vec)
    7380              : 
    7381            0 :       ALLOCATE (test2(H_size, H_size))
    7382            0 :       test2(:, :) = MATMUL(Hinv, test)
    7383            0 :       Hinv(:, :) = test2(:, :)
    7384            0 :       DEALLOCATE (test, test2)
    7385              : 
    7386            0 :       DEALLOCATE (eigenvalues)
    7387              : 
    7388              :       ! compute the inversion error
    7389            0 :       ALLOCATE (test(H_size, H_size))
    7390            0 :       test(:, :) = MATMUL(Hinv, H)
    7391            0 :       DO ii = 1, H_size
    7392            0 :          test(ii, ii) = test(ii, ii) - 1.0_dp
    7393              :       END DO
    7394            0 :       test_error = 0.0_dp
    7395            0 :       DO ii = 1, H_size
    7396            0 :          DO jj = 1, H_size
    7397            0 :             test_error = test_error + test(jj, ii)*test(jj, ii)
    7398              :          END DO
    7399              :       END DO
    7400            0 :       WRITE (unit_nr, *) "Hessian inversion error: ", SQRT(test_error)
    7401            0 :       DEALLOCATE (test)
    7402              : 
    7403              :       ! prepare the output vector
    7404            0 :       ALLOCATE (Step_vec(H_size))
    7405            0 :       ALLOCATE (tmp(H_size))
    7406            0 :       tmp(:) = MATMUL(Hinv, Grad_vec)
    7407            0 :       Step_vec(:) = -1.0_dp*tmp(:)
    7408              : 
    7409            0 :       ALLOCATE (tmpr(H_size))
    7410            0 :       tmpr(:) = MATMUL(H, Step_vec)
    7411            0 :       tmp(:) = tmpr(:) + Grad_vec(:)
    7412            0 :       DEALLOCATE (tmpr)
    7413            0 :       WRITE (unit_nr, *) "NEWTOV step error: ", MAXVAL(ABS(tmp))
    7414              : 
    7415            0 :       DEALLOCATE (tmp)
    7416              : 
    7417            0 :       DEALLOCATE (H)
    7418            0 :       DEALLOCATE (Hinv)
    7419            0 :       DEALLOCATE (Grad_vec)
    7420              : 
    7421              : !S-1.G DEALLOCATE(test3)
    7422              : 
    7423              :       ! copy the step from the vector into the dbcsr matrix
    7424              : 
    7425              :       ! re-create the step matrix to remove all blocks
    7426              :       CALL dbcsr_create(matrix_step, &
    7427              :                         template=matrix_grad, &
    7428            0 :                         matrix_type=dbcsr_type_no_symmetry)
    7429            0 :       CALL dbcsr_work_create(matrix_step, work_mutable=.TRUE.)
    7430              : 
    7431            0 :       lev1_vert_offset = 0
    7432              :       ! loop over all electron blocks
    7433            0 :       DO col = 1, nblkcols_tot
    7434              : 
    7435              :          ! loop over AO-rows of the dbcsr matrix
    7436            0 :          lev2_vert_offset = 0
    7437            0 :          DO row = 1, nblkrows_tot
    7438              : 
    7439              :             CALL dbcsr_get_block_p(quench_t, &
    7440            0 :                                    row, col, block_p, found_row)
    7441            0 :             IF (found_row) THEN
    7442              :                ! copy the data column by column
    7443            0 :                ALLOCATE (new_block(ao_block_sizes(row), mo_block_sizes(col)))
    7444            0 :                DO orb_i = 1, mo_block_sizes(col)
    7445              :                   new_block(:, orb_i) = &
    7446              :                      Step_vec(lev1_vert_offset + ao_domain_sizes(col)*(orb_i - 1) + lev2_vert_offset + 1: &
    7447            0 :                               lev1_vert_offset + ao_domain_sizes(col)*(orb_i - 1) + lev2_vert_offset + ao_block_sizes(row))
    7448              :                END DO
    7449            0 :                CALL dbcsr_put_block(matrix_step, row, col, new_block)
    7450            0 :                DEALLOCATE (new_block)
    7451            0 :                lev2_vert_offset = lev2_vert_offset + ao_block_sizes(row)
    7452              :             END IF
    7453              : 
    7454              :          END DO
    7455              : 
    7456            0 :          lev1_vert_offset = lev1_vert_offset + ao_domain_sizes(col)*mo_block_sizes(col)
    7457              : 
    7458              :       END DO ! loop over electron blocks
    7459              : 
    7460            0 :       DEALLOCATE (Step_vec)
    7461              : 
    7462            0 :       CALL dbcsr_finalize(matrix_step)
    7463              : 
    7464            0 :       DEALLOCATE (mo_block_sizes, ao_block_sizes)
    7465            0 :       DEALLOCATE (ao_domain_sizes)
    7466              : 
    7467              :       CALL dbcsr_create(matrix_S_ao_sym, &
    7468              :                         template=quench_t, &
    7469            0 :                         matrix_type=dbcsr_type_no_symmetry)
    7470            0 :       CALL dbcsr_copy(matrix_S_ao_sym, quench_t)
    7471              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    7472              :                           matrix_F_ao, &
    7473              :                           matrix_step, &
    7474              :                           0.0_dp, matrix_S_ao_sym, &
    7475            0 :                           retain_sparsity=.TRUE.)
    7476              :       CALL dbcsr_create(matrix_F_ao_sym, &
    7477              :                         template=quench_t, &
    7478            0 :                         matrix_type=dbcsr_type_no_symmetry)
    7479            0 :       CALL dbcsr_copy(matrix_F_ao_sym, quench_t)
    7480              :       CALL dbcsr_multiply("N", "N", 1.0_dp, &
    7481              :                           matrix_S_ao, &
    7482              :                           matrix_step, &
    7483              :                           0.0_dp, matrix_F_ao_sym, &
    7484            0 :                           retain_sparsity=.TRUE.)
    7485              :       CALL dbcsr_add(matrix_S_ao_sym, matrix_F_ao_sym, &
    7486            0 :                      1.0_dp, 1.0_dp)
    7487            0 :       CALL dbcsr_scale(matrix_S_ao_sym, 2.0_dp*spin_factor)
    7488              :       CALL dbcsr_add(matrix_S_ao_sym, matrix_grad, &
    7489            0 :                      1.0_dp, 1.0_dp)
    7490            0 :       test_error = dbcsr_maxabs(matrix_S_ao_sym)
    7491            0 :       WRITE (unit_nr, *) "NEWTOL step error: ", test_error
    7492            0 :       CALL dbcsr_release(matrix_S_ao_sym)
    7493            0 :       CALL dbcsr_release(matrix_F_ao_sym)
    7494              : 
    7495            0 :       CALL timestop(handle)
    7496              : 
    7497            0 :    END SUBROUTINE hessian_diag_apply
    7498              : 
    7499              : ! **************************************************************************************************
    7500              : !> \brief Optimization of ALMOs using trust region minimizers
    7501              : !> \param qs_env ...
    7502              : !> \param almo_scf_env ...
    7503              : !> \param optimizer   controls the optimization algorithm
    7504              : !> \param quench_t ...
    7505              : !> \param matrix_t_in ...
    7506              : !> \param matrix_t_out ...
    7507              : !> \param perturbation_only - perturbative (do not update Hamiltonian)
    7508              : !> \param special_case   to reduce the overhead special cases are implemented:
    7509              : !>                       xalmo_case_normal - no special case (i.e. xALMOs)
    7510              : !>                       xalmo_case_block_diag
    7511              : !>                       xalmo_case_fully_deloc
    7512              : !> \par History
    7513              : !>       2020.01 created [Rustam Z Khaliullin]
    7514              : !> \author Rustam Z Khaliullin
    7515              : ! **************************************************************************************************
    7516           18 :    SUBROUTINE almo_scf_xalmo_trustr(qs_env, almo_scf_env, optimizer, quench_t, &
    7517              :                                     matrix_t_in, matrix_t_out, perturbation_only, &
    7518              :                                     special_case)
    7519              : 
    7520              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    7521              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
    7522              :       TYPE(optimizer_options_type), INTENT(IN)           :: optimizer
    7523              :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: quench_t, matrix_t_in, matrix_t_out
    7524              :       LOGICAL, INTENT(IN)                                :: perturbation_only
    7525              :       INTEGER, INTENT(IN), OPTIONAL                      :: special_case
    7526              : 
    7527              :       CHARACTER(len=*), PARAMETER :: routineN = 'almo_scf_xalmo_trustr'
    7528              : 
    7529              :       INTEGER :: handle, ispin, iteration, iteration_type_to_report, my_special_case, ndomains, &
    7530              :          nspins, outer_iteration, prec_type, unit_nr
    7531           18 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nocc
    7532              :       LOGICAL :: assume_t0_q0x, border_reached, inner_loop_success, normalize_orbitals, &
    7533              :          optimize_theta, penalty_occ_vol, reset_conjugator, same_position, scf_converged
    7534              :       REAL(kind=dp) :: beta, energy_start, energy_trial, eta, expected_reduction, &
    7535              :          fake_step_size_to_report, grad_norm_ratio, grad_norm_ref, loss_change_to_report, &
    7536              :          loss_start, loss_trial, model_grad_norm, penalty_amplitude, penalty_start, penalty_trial, &
    7537              :          radius_current, radius_max, real_temp, rho, spin_factor, step_norm, step_size, t1, &
    7538              :          t1outer, t2, t2outer, y_scalar
    7539           18 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: grad_norm_spin, &
    7540           18 :                                                             penalty_occ_vol_g_prefactor, &
    7541           18 :                                                             penalty_occ_vol_h_prefactor
    7542              :       TYPE(cp_logger_type), POINTER                      :: logger
    7543              :       TYPE(dbcsr_type)                                   :: m_s_inv
    7544           18 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:) :: FTsiginv, grad, m_model_Bd, m_model_d, &
    7545           18 :          m_model_hessian, m_model_hessian_inv, m_model_r, m_model_r_prev, m_model_rt, &
    7546           18 :          m_model_rt_prev, m_sig_sqrti_ii, m_theta, m_theta_trial, prev_step, siginvTFTsiginv, ST, &
    7547           18 :          step, STsiginv_0
    7548              :       TYPE(domain_submatrix_type), ALLOCATABLE, &
    7549           18 :          DIMENSION(:, :)                                 :: domain_model_hessian_inv, domain_r_down
    7550              : 
    7551              :       ! RZK-warning: number of temporary storage matrices can be reduced
    7552           18 :       CALL timeset(routineN, handle)
    7553              : 
    7554           18 :       t1outer = m_walltime()
    7555              : 
    7556           18 :       my_special_case = xalmo_case_normal
    7557           18 :       IF (PRESENT(special_case)) my_special_case = special_case
    7558              : 
    7559              :       ! get a useful output_unit
    7560           18 :       logger => cp_get_default_logger()
    7561           18 :       IF (logger%para_env%is_source()) THEN
    7562            9 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    7563              :       ELSE
    7564            9 :          unit_nr = -1
    7565              :       END IF
    7566              : 
    7567              :       ! Trust radius code is written to obviate the need in projected orbitals
    7568           18 :       assume_t0_q0x = .FALSE.
    7569              :       ! Smoothing of the orbitals have not been implemented
    7570           18 :       optimize_theta = .FALSE.
    7571              : 
    7572           18 :       nspins = almo_scf_env%nspins
    7573           18 :       IF (nspins == 1) THEN
    7574           18 :          spin_factor = 2.0_dp
    7575              :       ELSE
    7576            0 :          spin_factor = 1.0_dp
    7577              :       END IF
    7578              : 
    7579           18 :       IF (unit_nr > 0) THEN
    7580            9 :          WRITE (unit_nr, *)
    7581            1 :          SELECT CASE (my_special_case)
    7582              :          CASE (xalmo_case_block_diag)
    7583            1 :             WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 20), &
    7584            2 :                " Optimization of block-diagonal ALMOs ", REPEAT("-", 21)
    7585              :          CASE (xalmo_case_fully_deloc)
    7586            0 :             WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 20), &
    7587            0 :                " Optimization of fully delocalized MOs ", REPEAT("-", 20)
    7588              :          CASE (xalmo_case_normal)
    7589            8 :             WRITE (unit_nr, '(T2,A,A,A)') REPEAT("-", 27), &
    7590           17 :                " Optimization of XALMOs ", REPEAT("-", 28)
    7591              :          END SELECT
    7592            9 :          WRITE (unit_nr, *)
    7593              :          CALL trust_r_report(unit_nr, &
    7594              :                              iter_type=0, & ! print header, all values are ignored
    7595              :                              iteration=0, &
    7596              :                              radius=0.0_dp, &
    7597              :                              loss=0.0_dp, &
    7598              :                              delta_loss=0.0_dp, &
    7599              :                              grad_norm=0.0_dp, &
    7600              :                              predicted_reduction=0.0_dp, &
    7601              :                              rho=0.0_dp, &
    7602              :                              new=.TRUE., &
    7603            9 :                              time=0.0_dp)
    7604            9 :          WRITE (unit_nr, '(T2,A)') REPEAT("-", 79)
    7605              :       END IF
    7606              : 
    7607              :       ! penalty amplitude adjusts the strength of volume conservation
    7608           18 :       penalty_occ_vol = .FALSE.
    7609           18 :       normalize_orbitals = penalty_occ_vol
    7610           18 :       penalty_amplitude = 0.0_dp !almo_scf_env%penalty%occ_vol_coeff
    7611           54 :       ALLOCATE (penalty_occ_vol_g_prefactor(nspins))
    7612           36 :       ALLOCATE (penalty_occ_vol_h_prefactor(nspins))
    7613           18 :       penalty_occ_vol_g_prefactor(:) = 0.0_dp
    7614           18 :       penalty_occ_vol_h_prefactor(:) = 0.0_dp
    7615              : 
    7616              :       ! here preconditioner is the Hessian of model function
    7617           18 :       prec_type = optimizer%preconditioner
    7618              : 
    7619           36 :       ALLOCATE (grad_norm_spin(nspins))
    7620           54 :       ALLOCATE (nocc(nspins))
    7621              : 
    7622              :       ! m_theta contains a set of variational parameters
    7623              :       ! that define one-electron orbitals (simple, projected, etc.)
    7624           72 :       ALLOCATE (m_theta(nspins))
    7625           36 :       DO ispin = 1, nspins
    7626              :          CALL dbcsr_create(m_theta(ispin), &
    7627              :                            template=matrix_t_out(ispin), &
    7628           36 :                            matrix_type=dbcsr_type_no_symmetry)
    7629              :       END DO
    7630              : 
    7631              :       ! create initial guess from the initial orbitals
    7632              :       CALL xalmo_initial_guess(m_guess=m_theta, &
    7633              :                                m_t_in=matrix_t_in, &
    7634              :                                m_t0=almo_scf_env%matrix_t_blk, &
    7635              :                                m_quench_t=quench_t, &
    7636              :                                m_overlap=almo_scf_env%matrix_s(1), &
    7637              :                                m_sigma_tmpl=almo_scf_env%matrix_sigma_inv, &
    7638              :                                nspins=nspins, &
    7639              :                                xalmo_history=almo_scf_env%xalmo_history, &
    7640              :                                assume_t0_q0x=assume_t0_q0x, &
    7641              :                                optimize_theta=optimize_theta, &
    7642              :                                envelope_amplitude=almo_scf_env%envelope_amplitude, &
    7643              :                                eps_filter=almo_scf_env%eps_filter, &
    7644              :                                order_lanczos=almo_scf_env%order_lanczos, &
    7645              :                                eps_lanczos=almo_scf_env%eps_lanczos, &
    7646              :                                max_iter_lanczos=almo_scf_env%max_iter_lanczos, &
    7647           18 :                                nocc_of_domain=almo_scf_env%nocc_of_domain)
    7648              : 
    7649           18 :       ndomains = almo_scf_env%ndomains
    7650          218 :       ALLOCATE (domain_r_down(ndomains, nspins))
    7651           18 :       CALL init_submatrices(domain_r_down)
    7652          200 :       ALLOCATE (domain_model_hessian_inv(ndomains, nspins))
    7653           18 :       CALL init_submatrices(domain_model_hessian_inv)
    7654              : 
    7655           54 :       ALLOCATE (m_model_hessian(nspins))
    7656           54 :       ALLOCATE (m_model_hessian_inv(nspins))
    7657           54 :       ALLOCATE (siginvTFTsiginv(nspins))
    7658           54 :       ALLOCATE (STsiginv_0(nspins))
    7659           54 :       ALLOCATE (FTsiginv(nspins))
    7660           54 :       ALLOCATE (ST(nspins))
    7661           54 :       ALLOCATE (grad(nspins))
    7662           72 :       ALLOCATE (prev_step(nspins))
    7663           54 :       ALLOCATE (step(nspins))
    7664           54 :       ALLOCATE (m_sig_sqrti_ii(nspins))
    7665           54 :       ALLOCATE (m_model_r(nspins))
    7666           54 :       ALLOCATE (m_model_rt(nspins))
    7667           54 :       ALLOCATE (m_model_d(nspins))
    7668           54 :       ALLOCATE (m_model_Bd(nspins))
    7669           54 :       ALLOCATE (m_model_r_prev(nspins))
    7670           54 :       ALLOCATE (m_model_rt_prev(nspins))
    7671           54 :       ALLOCATE (m_theta_trial(nspins))
    7672              : 
    7673           36 :       DO ispin = 1, nspins
    7674              : 
    7675              :          ! init temporary storage
    7676              :          CALL dbcsr_create(m_model_hessian_inv(ispin), &
    7677              :                            template=almo_scf_env%matrix_ks(ispin), &
    7678           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7679              :          CALL dbcsr_create(m_model_hessian(ispin), &
    7680              :                            template=almo_scf_env%matrix_ks(ispin), &
    7681           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7682              :          CALL dbcsr_create(siginvTFTsiginv(ispin), &
    7683              :                            template=almo_scf_env%matrix_sigma(ispin), &
    7684           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7685              :          CALL dbcsr_create(STsiginv_0(ispin), &
    7686              :                            template=matrix_t_out(ispin), &
    7687           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7688              :          CALL dbcsr_create(FTsiginv(ispin), &
    7689              :                            template=matrix_t_out(ispin), &
    7690           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7691              :          CALL dbcsr_create(ST(ispin), &
    7692              :                            template=matrix_t_out(ispin), &
    7693           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7694              :          CALL dbcsr_create(grad(ispin), &
    7695              :                            template=matrix_t_out(ispin), &
    7696           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7697              :          CALL dbcsr_create(prev_step(ispin), &
    7698              :                            template=matrix_t_out(ispin), &
    7699           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7700              :          CALL dbcsr_create(step(ispin), &
    7701              :                            template=matrix_t_out(ispin), &
    7702           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7703              :          CALL dbcsr_create(m_sig_sqrti_ii(ispin), &
    7704              :                            template=almo_scf_env%matrix_sigma_inv(ispin), &
    7705           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7706              :          CALL dbcsr_create(m_model_r(ispin), &
    7707              :                            template=matrix_t_out(ispin), &
    7708           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7709              :          CALL dbcsr_create(m_model_rt(ispin), &
    7710              :                            template=matrix_t_out(ispin), &
    7711           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7712              :          CALL dbcsr_create(m_model_d(ispin), &
    7713              :                            template=matrix_t_out(ispin), &
    7714           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7715              :          CALL dbcsr_create(m_model_Bd(ispin), &
    7716              :                            template=matrix_t_out(ispin), &
    7717           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7718              :          CALL dbcsr_create(m_model_r_prev(ispin), &
    7719              :                            template=matrix_t_out(ispin), &
    7720           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7721              :          CALL dbcsr_create(m_model_rt_prev(ispin), &
    7722              :                            template=matrix_t_out(ispin), &
    7723           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7724              :          CALL dbcsr_create(m_theta_trial(ispin), &
    7725              :                            template=matrix_t_out(ispin), &
    7726           18 :                            matrix_type=dbcsr_type_no_symmetry)
    7727              : 
    7728           18 :          CALL dbcsr_set(step(ispin), 0.0_dp)
    7729           18 :          CALL dbcsr_set(prev_step(ispin), 0.0_dp)
    7730              : 
    7731              :          CALL dbcsr_get_info(almo_scf_env%matrix_sigma_inv(ispin), &
    7732           18 :                              nfullrows_total=nocc(ispin))
    7733              : 
    7734              :          ! invert S domains if necessary
    7735              :          ! Note: domains for alpha and beta electrons might be different
    7736              :          ! that is why the inversion of the AO overlap is inside the spin loop
    7737           36 :          IF (my_special_case == xalmo_case_normal) THEN
    7738              : 
    7739              :             CALL construct_domain_s_inv( &
    7740              :                matrix_s=almo_scf_env%matrix_s(1), &
    7741              :                subm_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    7742              :                dpattern=quench_t(ispin), &
    7743              :                map=almo_scf_env%domain_map(ispin), &
    7744           16 :                node_of_domain=almo_scf_env%cpu_of_domain)
    7745              : 
    7746              :          END IF
    7747              : 
    7748              :       END DO ! ispin
    7749              : 
    7750              :       ! invert metric for special case where metric is spin independent
    7751           18 :       IF (my_special_case == xalmo_case_block_diag) THEN
    7752              : 
    7753              :          CALL dbcsr_create(m_s_inv, &
    7754              :                            template=almo_scf_env%matrix_s(1), &
    7755            2 :                            matrix_type=dbcsr_type_no_symmetry)
    7756              :          CALL invert_Hotelling(m_s_inv, &
    7757              :                                almo_scf_env%matrix_s_blk(1), &
    7758              :                                threshold=almo_scf_env%eps_filter, &
    7759            2 :                                filter_eps=almo_scf_env%eps_filter)
    7760              : 
    7761           16 :       ELSE IF (my_special_case == xalmo_case_fully_deloc) THEN
    7762              : 
    7763              :          ! invert S using cholesky
    7764              :          CALL dbcsr_create(m_s_inv, &
    7765              :                            template=almo_scf_env%matrix_s(1), &
    7766            0 :                            matrix_type=dbcsr_type_no_symmetry)
    7767            0 :          CALL dbcsr_desymmetrize(almo_scf_env%matrix_s(1), m_s_inv)
    7768              :          CALL cp_dbcsr_cholesky_decompose(m_s_inv, &
    7769              :                                           para_env=almo_scf_env%para_env, &
    7770            0 :                                           blacs_env=almo_scf_env%blacs_env)
    7771              :          CALL cp_dbcsr_cholesky_invert(m_s_inv, &
    7772              :                                        para_env=almo_scf_env%para_env, &
    7773              :                                        blacs_env=almo_scf_env%blacs_env, &
    7774            0 :                                        uplo_to_full=.TRUE.)
    7775            0 :          CALL dbcsr_filter(m_s_inv, almo_scf_env%eps_filter)
    7776              : 
    7777              :       END IF ! s_inv
    7778              : 
    7779           18 :       radius_max = optimizer%max_trust_radius
    7780           18 :       radius_current = MIN(optimizer%initial_trust_radius, radius_max)
    7781              :       ! eta must be between 0 and 0.25
    7782           18 :       eta = MIN(MAX(optimizer%rho_do_not_update, 0.0_dp), 0.25_dp)
    7783              :       energy_start = 0.0_dp
    7784           18 :       energy_trial = 0.0_dp
    7785              :       penalty_start = 0.0_dp
    7786           18 :       penalty_trial = 0.0_dp
    7787              :       loss_start = 0.0_dp ! sum of the energy and penalty
    7788           18 :       loss_trial = 0.0_dp
    7789              : 
    7790           18 :       same_position = .FALSE.
    7791              : 
    7792              :       ! compute the energy
    7793              :       CALL main_var_to_xalmos_and_loss_func( &
    7794              :          almo_scf_env=almo_scf_env, &
    7795              :          qs_env=qs_env, &
    7796              :          m_main_var_in=m_theta, &
    7797              :          m_t_out=matrix_t_out, &
    7798              :          m_sig_sqrti_ii_out=m_sig_sqrti_ii, &
    7799              :          energy_out=energy_start, &
    7800              :          penalty_out=penalty_start, &
    7801              :          m_FTsiginv_out=FTsiginv, &
    7802              :          m_siginvTFTsiginv_out=siginvTFTsiginv, &
    7803              :          m_ST_out=ST, &
    7804              :          m_STsiginv0_in=STsiginv_0, &
    7805              :          m_quench_t_in=quench_t, &
    7806              :          domain_r_down_in=domain_r_down, &
    7807              :          assume_t0_q0x=assume_t0_q0x, &
    7808              :          just_started=.TRUE., &
    7809              :          optimize_theta=optimize_theta, &
    7810              :          normalize_orbitals=normalize_orbitals, &
    7811              :          perturbation_only=perturbation_only, &
    7812              :          do_penalty=penalty_occ_vol, &
    7813           18 :          special_case=my_special_case)
    7814           18 :       loss_start = energy_start + penalty_start
    7815           18 :       IF (my_special_case == xalmo_case_block_diag) THEN
    7816            2 :          almo_scf_env%almo_scf_energy = energy_start
    7817              :       END IF
    7818           36 :       DO ispin = 1, nspins
    7819           36 :          IF (penalty_occ_vol) THEN
    7820              :             penalty_occ_vol_g_prefactor(ispin) = &
    7821            0 :                -2.0_dp*penalty_amplitude*spin_factor*nocc(ispin)
    7822            0 :             penalty_occ_vol_h_prefactor(ispin) = 0.0_dp
    7823              :          END IF
    7824              :       END DO ! ispin
    7825              : 
    7826              :       ! start the outer step-size-adjustment loop
    7827           18 :       scf_converged = .FALSE.
    7828          426 :       adjust_r_loop: DO outer_iteration = 1, optimizer%max_iter_outer_loop
    7829              : 
    7830              :          ! start the inner fixed-radius loop
    7831          426 :          border_reached = .FALSE.
    7832              : 
    7833          852 :          DO ispin = 1, nspins
    7834          426 :             CALL dbcsr_set(step(ispin), 0.0_dp)
    7835          852 :             CALL dbcsr_filter(step(ispin), almo_scf_env%eps_filter)
    7836              :          END DO
    7837              : 
    7838          426 :          IF (.NOT. same_position) THEN
    7839              : 
    7840          852 :             DO ispin = 1, nspins
    7841              : 
    7842              :                IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Compute model gradient"
    7843              :                CALL compute_gradient( &
    7844              :                   m_grad_out=grad(ispin), &
    7845              :                   m_ks=almo_scf_env%matrix_ks(ispin), &
    7846              :                   m_s=almo_scf_env%matrix_s(1), &
    7847              :                   m_t=matrix_t_out(ispin), &
    7848              :                   m_t0=almo_scf_env%matrix_t_blk(ispin), &
    7849              :                   m_siginv=almo_scf_env%matrix_sigma_inv(ispin), &
    7850              :                   m_quench_t=quench_t(ispin), &
    7851              :                   m_FTsiginv=FTsiginv(ispin), &
    7852              :                   m_siginvTFTsiginv=siginvTFTsiginv(ispin), &
    7853              :                   m_ST=ST(ispin), &
    7854              :                   m_STsiginv0=STsiginv_0(ispin), &
    7855              :                   m_theta=m_theta(ispin), &
    7856              :                   m_sig_sqrti_ii=m_sig_sqrti_ii(ispin), &
    7857              :                   domain_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    7858              :                   domain_r_down=domain_r_down(:, ispin), &
    7859              :                   cpu_of_domain=almo_scf_env%cpu_of_domain, &
    7860              :                   domain_map=almo_scf_env%domain_map(ispin), &
    7861              :                   assume_t0_q0x=assume_t0_q0x, &
    7862              :                   optimize_theta=optimize_theta, &
    7863              :                   normalize_orbitals=normalize_orbitals, &
    7864              :                   penalty_occ_vol=penalty_occ_vol, &
    7865              :                   penalty_occ_vol_prefactor=penalty_occ_vol_g_prefactor(ispin), &
    7866              :                   envelope_amplitude=almo_scf_env%envelope_amplitude, &
    7867              :                   eps_filter=almo_scf_env%eps_filter, &
    7868              :                   spin_factor=spin_factor, &
    7869          852 :                   special_case=my_special_case)
    7870              : 
    7871              :             END DO ! ispin
    7872              : 
    7873              :          END IF ! skip_grad
    7874              : 
    7875              :          ! check convergence and other exit criteria
    7876          852 :          DO ispin = 1, nspins
    7877          852 :             grad_norm_spin(ispin) = dbcsr_maxabs(grad(ispin))
    7878              :          END DO ! ispin
    7879          852 :          grad_norm_ref = MAXVAL(grad_norm_spin)
    7880              : 
    7881          426 :          t2outer = m_walltime()
    7882              :          CALL trust_r_report(unit_nr, &
    7883              :                              iter_type=1, & ! only some data is important
    7884              :                              iteration=outer_iteration, &
    7885              :                              loss=loss_start, &
    7886              :                              delta_loss=0.0_dp, &
    7887              :                              grad_norm=grad_norm_ref, &
    7888              :                              predicted_reduction=0.0_dp, &
    7889              :                              rho=0.0_dp, &
    7890              :                              radius=radius_current, &
    7891              :                              new=.NOT. same_position, &
    7892          426 :                              time=t2outer - t1outer)
    7893          426 :          t1outer = m_walltime()
    7894              : 
    7895          426 :          IF (grad_norm_ref <= optimizer%eps_error) THEN
    7896           18 :             scf_converged = .TRUE.
    7897           18 :             border_reached = .FALSE.
    7898           18 :             expected_reduction = 0.0_dp
    7899           18 :             IF (.NOT. (optimizer%early_stopping_on .AND. outer_iteration == 1)) THEN
    7900              :                EXIT adjust_r_loop
    7901              :             END IF
    7902              :          ELSE
    7903              :             scf_converged = .FALSE.
    7904              :          END IF
    7905              : 
    7906          816 :          DO ispin = 1, nspins
    7907              : 
    7908          408 :             CALL dbcsr_copy(m_model_r(ispin), grad(ispin))
    7909          408 :             CALL dbcsr_scale(m_model_r(ispin), -1.0_dp)
    7910              : 
    7911          408 :             IF (my_special_case == xalmo_case_block_diag .OR. &
    7912              :                 my_special_case == xalmo_case_fully_deloc) THEN
    7913              : 
    7914              :                IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Multiply Sinv.r"
    7915              :                CALL dbcsr_multiply("N", "N", 1.0_dp, &
    7916              :                                    m_s_inv, &
    7917              :                                    m_model_r(ispin), &
    7918              :                                    0.0_dp, m_model_rt(ispin), &
    7919           92 :                                    filter_eps=almo_scf_env%eps_filter)
    7920              : 
    7921          316 :             ELSE IF (my_special_case == xalmo_case_normal) THEN
    7922              : 
    7923              :                IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Multiply Sinv_xx.r"
    7924              :                CALL apply_domain_operators( &
    7925              :                   matrix_in=m_model_r(ispin), &
    7926              :                   matrix_out=m_model_rt(ispin), &
    7927              :                   operator1=almo_scf_env%domain_s_inv(:, ispin), &
    7928              :                   dpattern=quench_t(ispin), &
    7929              :                   map=almo_scf_env%domain_map(ispin), &
    7930              :                   node_of_domain=almo_scf_env%cpu_of_domain, &
    7931              :                   my_action=0, &
    7932          316 :                   filter_eps=almo_scf_env%eps_filter)
    7933              : 
    7934              :             ELSE
    7935            0 :                CPABORT("Unknown XALMO special case")
    7936              :             END IF
    7937              : 
    7938          816 :             CALL dbcsr_copy(m_model_d(ispin), m_model_rt(ispin))
    7939              : 
    7940              :          END DO ! ispin
    7941              : 
    7942              :          ! compute model Hessian
    7943          408 :          IF (.NOT. same_position) THEN
    7944              : 
    7945              :             SELECT CASE (prec_type)
    7946              :             CASE (xalmo_prec_domain)
    7947              : 
    7948              :                IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Compute model Hessian"
    7949          816 :                DO ispin = 1, nspins
    7950              :                   CALL compute_preconditioner( &
    7951              :                      domain_prec_out=almo_scf_env%domain_preconditioner(:, ispin), &
    7952              :                      m_prec_out=m_model_hessian(ispin), &
    7953              :                      m_ks=almo_scf_env%matrix_ks(ispin), &
    7954              :                      m_s=almo_scf_env%matrix_s(1), &
    7955              :                      m_siginv=almo_scf_env%matrix_sigma_inv(ispin), &
    7956              :                      m_quench_t=quench_t(ispin), &
    7957              :                      m_FTsiginv=FTsiginv(ispin), &
    7958              :                      m_siginvTFTsiginv=siginvTFTsiginv(ispin), &
    7959              :                      m_ST=ST(ispin), &
    7960              :                      para_env=almo_scf_env%para_env, &
    7961              :                      blacs_env=almo_scf_env%blacs_env, &
    7962              :                      nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
    7963              :                      domain_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    7964              :                      domain_r_down=domain_r_down(:, ispin), &
    7965              :                      cpu_of_domain=almo_scf_env%cpu_of_domain, &
    7966              :                      domain_map=almo_scf_env%domain_map(ispin), &
    7967              :                      assume_t0_q0x=.FALSE., &
    7968              :                      penalty_occ_vol=penalty_occ_vol, &
    7969              :                      penalty_occ_vol_prefactor=penalty_occ_vol_g_prefactor(ispin), &
    7970              :                      eps_filter=almo_scf_env%eps_filter, &
    7971              :                      neg_thr=0.5_dp, &
    7972              :                      spin_factor=spin_factor, &
    7973              :                      skip_inversion=.TRUE., &
    7974          816 :                      special_case=my_special_case)
    7975              :                END DO ! ispin
    7976              : 
    7977              :             CASE DEFAULT
    7978              : 
    7979          408 :                CPABORT("Unknown preconditioner")
    7980              : 
    7981              :             END SELECT ! preconditioner type fork
    7982              : 
    7983              :          END IF  ! not same position
    7984              : 
    7985              :          ! print the header (argument values are ignored)
    7986              :          CALL fixed_r_report(unit_nr, &
    7987              :                              iter_type=0, &
    7988              :                              iteration=0, &
    7989              :                              step_size=0.0_dp, &
    7990              :                              border_reached=.FALSE., &
    7991              :                              curvature=0.0_dp, &
    7992              :                              grad_norm_ratio=0.0_dp, &
    7993          408 :                              time=0.0_dp)
    7994              : 
    7995              :          IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Start inner loop"
    7996              : 
    7997          408 :          t1 = m_walltime()
    7998          408 :          inner_loop_success = .FALSE.
    7999              :          ! trustr_steihaug, trustr_cauchy, trustr_dogleg
    8000          490 :          fixed_r_loop: DO iteration = 1, optimizer%max_iter
    8001              : 
    8002              :             ! Step 2. Get curvature. If negative, step to the border
    8003          490 :             y_scalar = 0.0_dp
    8004          980 :             DO ispin = 1, nspins
    8005              : 
    8006              :                ! Get B.d
    8007          490 :                IF (my_special_case == xalmo_case_block_diag .OR. &
    8008              :                    my_special_case == xalmo_case_fully_deloc) THEN
    8009              : 
    8010              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, &
    8011              :                                       m_model_hessian(ispin), &
    8012              :                                       m_model_d(ispin), &
    8013              :                                       0.0_dp, m_model_Bd(ispin), &
    8014           92 :                                       filter_eps=almo_scf_env%eps_filter)
    8015              : 
    8016              :                ELSE
    8017              : 
    8018              :                   CALL apply_domain_operators( &
    8019              :                      matrix_in=m_model_d(ispin), &
    8020              :                      matrix_out=m_model_Bd(ispin), &
    8021              :                      operator1=almo_scf_env%domain_preconditioner(:, ispin), &
    8022              :                      dpattern=quench_t(ispin), &
    8023              :                      map=almo_scf_env%domain_map(ispin), &
    8024              :                      node_of_domain=almo_scf_env%cpu_of_domain, &
    8025              :                      my_action=0, &
    8026          398 :                      filter_eps=almo_scf_env%eps_filter)
    8027              : 
    8028              :                END IF ! special case
    8029              : 
    8030              :                ! Get y=d^T.B.d
    8031          490 :                CALL dbcsr_dot(m_model_d(ispin), m_model_Bd(ispin), real_temp)
    8032          980 :                y_scalar = y_scalar + real_temp
    8033              : 
    8034              :             END DO ! ispin
    8035              :             IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Curvature: ", y_scalar
    8036              : 
    8037              :             ! step to the border
    8038          490 :             IF (y_scalar < 0.0_dp) THEN
    8039              : 
    8040              :                CALL step_size_to_border( &
    8041              :                   step_size_out=step_size, &
    8042              :                   metric_in=almo_scf_env%matrix_s, &
    8043              :                   position_in=step, &
    8044              :                   direction_in=m_model_d, &
    8045              :                   trust_radius_in=radius_current, &
    8046              :                   quench_t_in=quench_t, &
    8047              :                   eps_filter_in=almo_scf_env%eps_filter &
    8048            0 :                   )
    8049              : 
    8050            0 :                DO ispin = 1, nspins
    8051            0 :                   CALL dbcsr_add(step(ispin), m_model_d(ispin), 1.0_dp, step_size)
    8052              :                END DO
    8053              : 
    8054            0 :                border_reached = .TRUE.
    8055            0 :                inner_loop_success = .TRUE.
    8056              : 
    8057              :                CALL predicted_reduction( &
    8058              :                   reduction_out=expected_reduction, &
    8059              :                   grad_in=grad, &
    8060              :                   step_in=step, &
    8061              :                   hess_in=m_model_hessian, &
    8062              :                   hess_submatrix_in=almo_scf_env%domain_preconditioner, &
    8063              :                   quench_t_in=quench_t, &
    8064              :                   special_case=my_special_case, &
    8065              :                   eps_filter=almo_scf_env%eps_filter, &
    8066              :                   domain_map=almo_scf_env%domain_map, &
    8067              :                   cpu_of_domain=almo_scf_env%cpu_of_domain &
    8068            0 :                   )
    8069              : 
    8070            0 :                t2 = m_walltime()
    8071              :                CALL fixed_r_report(unit_nr, &
    8072              :                                    iter_type=2, &
    8073              :                                    iteration=iteration, &
    8074              :                                    step_size=step_size, &
    8075              :                                    border_reached=border_reached, &
    8076              :                                    curvature=y_scalar, &
    8077              :                                    grad_norm_ratio=expected_reduction, &
    8078            0 :                                    time=t2 - t1)
    8079              : 
    8080              :                EXIT fixed_r_loop ! the inner loop
    8081              : 
    8082              :             END IF ! y is negative
    8083              : 
    8084              :             ! Step 3. Compute the step size along the direction
    8085          490 :             step_size = 0.0_dp
    8086          980 :             DO ispin = 1, nspins
    8087          490 :                CALL dbcsr_dot(m_model_r(ispin), m_model_rt(ispin), real_temp)
    8088          980 :                step_size = step_size + real_temp
    8089              :             END DO ! ispin
    8090          490 :             step_size = step_size/y_scalar
    8091              :             IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Proposed step size: ", step_size
    8092              : 
    8093              :             ! Update the step matrix
    8094          980 :             DO ispin = 1, nspins
    8095          490 :                CALL dbcsr_copy(prev_step(ispin), step(ispin))
    8096          980 :                CALL dbcsr_add(step(ispin), m_model_d(ispin), 1.0_dp, step_size)
    8097              :             END DO
    8098              : 
    8099              :             ! Compute step norm
    8100              :             CALL contravariant_matrix_norm( &
    8101              :                norm_out=step_norm, &
    8102              :                matrix_in=step, &
    8103              :                metric_in=almo_scf_env%matrix_s, &
    8104              :                quench_t_in=quench_t, &
    8105              :                eps_filter_in=almo_scf_env%eps_filter &
    8106          490 :                )
    8107              :             IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Step norm: ", step_norm
    8108              : 
    8109              :             ! Do not step beyond the trust radius
    8110          490 :             IF (step_norm > radius_current) THEN
    8111              : 
    8112              :                IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Norm is too large"
    8113              :                CALL step_size_to_border( &
    8114              :                   step_size_out=step_size, &
    8115              :                   metric_in=almo_scf_env%matrix_s, &
    8116              :                   position_in=prev_step, &
    8117              :                   direction_in=m_model_d, &
    8118              :                   trust_radius_in=radius_current, &
    8119              :                   quench_t_in=quench_t, &
    8120              :                   eps_filter_in=almo_scf_env%eps_filter &
    8121           34 :                   )
    8122              :                IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Step size to border: ", step_size
    8123              : 
    8124           68 :                DO ispin = 1, nspins
    8125           34 :                   CALL dbcsr_copy(step(ispin), prev_step(ispin))
    8126           68 :                   CALL dbcsr_add(step(ispin), m_model_d(ispin), 1.0_dp, step_size)
    8127              :                END DO
    8128              : 
    8129              :                IF (debug_mode) THEN
    8130              :                   ! Compute step norm
    8131              :                   IF (unit_nr > 0) WRITE (unit_nr, *) "...Extra norm evaluation"
    8132              :                   CALL contravariant_matrix_norm( &
    8133              :                      norm_out=step_norm, &
    8134              :                      matrix_in=step, &
    8135              :                      metric_in=almo_scf_env%matrix_s, &
    8136              :                      quench_t_in=quench_t, &
    8137              :                      eps_filter_in=almo_scf_env%eps_filter &
    8138              :                      )
    8139              :                   IF (unit_nr > 0) WRITE (unit_nr, *) "...Step norm: ", step_norm
    8140              :                   IF (unit_nr > 0) WRITE (unit_nr, *) "...Current radius: ", radius_current
    8141              :                END IF
    8142              : 
    8143           34 :                border_reached = .TRUE.
    8144           34 :                inner_loop_success = .TRUE.
    8145              : 
    8146              :                CALL predicted_reduction( &
    8147              :                   reduction_out=expected_reduction, &
    8148              :                   grad_in=grad, &
    8149              :                   step_in=step, &
    8150              :                   hess_in=m_model_hessian, &
    8151              :                   hess_submatrix_in=almo_scf_env%domain_preconditioner, &
    8152              :                   quench_t_in=quench_t, &
    8153              :                   special_case=my_special_case, &
    8154              :                   eps_filter=almo_scf_env%eps_filter, &
    8155              :                   domain_map=almo_scf_env%domain_map, &
    8156              :                   cpu_of_domain=almo_scf_env%cpu_of_domain &
    8157           34 :                   )
    8158              : 
    8159           34 :                t2 = m_walltime()
    8160              :                CALL fixed_r_report(unit_nr, &
    8161              :                                    iter_type=3, &
    8162              :                                    iteration=iteration, &
    8163              :                                    step_size=step_size, &
    8164              :                                    border_reached=border_reached, &
    8165              :                                    curvature=y_scalar, &
    8166              :                                    grad_norm_ratio=expected_reduction, &
    8167           34 :                                    time=t2 - t1)
    8168              : 
    8169              :                EXIT fixed_r_loop ! the inner loop
    8170              : 
    8171              :             END IF
    8172              : 
    8173          456 :             IF (optimizer%trustr_algorithm == trustr_cauchy) THEN
    8174              :                ! trustr_steihaug, trustr_cauchy, trustr_dogleg
    8175              : 
    8176           80 :                border_reached = .FALSE.
    8177           80 :                inner_loop_success = .TRUE.
    8178              : 
    8179              :                CALL predicted_reduction( &
    8180              :                   reduction_out=expected_reduction, &
    8181              :                   grad_in=grad, &
    8182              :                   step_in=step, &
    8183              :                   hess_in=m_model_hessian, &
    8184              :                   hess_submatrix_in=almo_scf_env%domain_preconditioner, &
    8185              :                   quench_t_in=quench_t, &
    8186              :                   special_case=my_special_case, &
    8187              :                   eps_filter=almo_scf_env%eps_filter, &
    8188              :                   domain_map=almo_scf_env%domain_map, &
    8189              :                   cpu_of_domain=almo_scf_env%cpu_of_domain &
    8190           80 :                   )
    8191              : 
    8192           80 :                t2 = m_walltime()
    8193              :                CALL fixed_r_report(unit_nr, &
    8194              :                                    iter_type=5, & ! Cauchy point
    8195              :                                    iteration=iteration, &
    8196              :                                    step_size=step_size, &
    8197              :                                    border_reached=border_reached, &
    8198              :                                    curvature=y_scalar, &
    8199              :                                    grad_norm_ratio=expected_reduction, &
    8200           80 :                                    time=t2 - t1)
    8201              : 
    8202              :                EXIT fixed_r_loop ! the inner loop
    8203              : 
    8204          376 :             ELSE IF (optimizer%trustr_algorithm == trustr_dogleg) THEN
    8205              : 
    8206              :                ! invert or pseudo-invert B
    8207          268 :                SELECT CASE (prec_type)
    8208              :                CASE (xalmo_prec_domain)
    8209              : 
    8210              :                   IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Pseudo-invert model Hessian"
    8211          268 :                   IF (special_case == xalmo_case_block_diag) THEN ! non-overlapping diagonal blocks
    8212              : 
    8213          156 :                      DO ispin = 1, nspins
    8214              :                         CALL pseudo_invert_diagonal_blk( &
    8215              :                            matrix_in=m_model_hessian(ispin), &
    8216              :                            matrix_out=m_model_hessian_inv(ispin), &
    8217              :                            nocc=almo_scf_env%nocc_of_domain(:, ispin) &
    8218          156 :                            )
    8219              :                      END DO
    8220              : 
    8221          190 :                   ELSE IF (special_case == xalmo_case_fully_deloc) THEN ! the entire system is a block
    8222              : 
    8223              :                      ! invert using cholesky decomposition
    8224            0 :                      DO ispin = 1, nspins
    8225              :                         CALL dbcsr_copy(m_model_hessian_inv(ispin), &
    8226            0 :                                         m_model_hessian(ispin))
    8227              :                         CALL cp_dbcsr_cholesky_decompose(m_model_hessian_inv(ispin), &
    8228              :                                                          para_env=almo_scf_env%para_env, &
    8229            0 :                                                          blacs_env=almo_scf_env%blacs_env)
    8230              :                         CALL cp_dbcsr_cholesky_invert(m_model_hessian_inv(ispin), &
    8231              :                                                       para_env=almo_scf_env%para_env, &
    8232              :                                                       blacs_env=almo_scf_env%blacs_env, &
    8233            0 :                                                       uplo_to_full=.TRUE.)
    8234              :                         CALL dbcsr_filter(m_model_hessian_inv(ispin), &
    8235            0 :                                           almo_scf_env%eps_filter)
    8236              :                      END DO
    8237              : 
    8238              :                   ELSE
    8239              : 
    8240          380 :                      DO ispin = 1, nspins
    8241              :                         CALL construct_domain_preconditioner( &
    8242              :                            matrix_main=m_model_hessian(ispin), &
    8243              :                            subm_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    8244              :                            subm_r_down=domain_r_down(:, ispin), &
    8245              :                            matrix_trimmer=quench_t(ispin), &
    8246              :                            dpattern=quench_t(ispin), &
    8247              :                            map=almo_scf_env%domain_map(ispin), &
    8248              :                            node_of_domain=almo_scf_env%cpu_of_domain, &
    8249              :                            preconditioner=domain_model_hessian_inv(:, ispin), &
    8250              :                            use_trimmer=.FALSE., &
    8251              :                            my_action=0, & ! do not do domain (1-r0) projection
    8252              :                            skip_inversion=.FALSE. &
    8253          380 :                            )
    8254              :                      END DO
    8255              : 
    8256              :                   END IF ! special_case
    8257              : 
    8258              :                CASE DEFAULT
    8259              : 
    8260          268 :                   CPABORT("Unknown preconditioner")
    8261              : 
    8262              :                END SELECT ! preconditioner type fork
    8263              : 
    8264              :                ! get pB = Binv.m_model_r = -Binv.grad
    8265          536 :                DO ispin = 1, nspins
    8266              : 
    8267              :                   ! Get B.d
    8268          268 :                   IF (my_special_case == xalmo_case_block_diag .OR. &
    8269          268 :                       my_special_case == xalmo_case_fully_deloc) THEN
    8270              : 
    8271              :                      CALL dbcsr_multiply("N", "N", 1.0_dp, &
    8272              :                                          m_model_hessian_inv(ispin), &
    8273              :                                          m_model_r(ispin), &
    8274              :                                          0.0_dp, m_model_Bd(ispin), &
    8275           78 :                                          filter_eps=almo_scf_env%eps_filter)
    8276              : 
    8277              :                   ELSE
    8278              : 
    8279              :                      CALL apply_domain_operators( &
    8280              :                         matrix_in=m_model_r(ispin), &
    8281              :                         matrix_out=m_model_Bd(ispin), &
    8282              :                         operator1=domain_model_hessian_inv(:, ispin), &
    8283              :                         dpattern=quench_t(ispin), &
    8284              :                         map=almo_scf_env%domain_map(ispin), &
    8285              :                         node_of_domain=almo_scf_env%cpu_of_domain, &
    8286              :                         my_action=0, &
    8287          190 :                         filter_eps=almo_scf_env%eps_filter)
    8288              : 
    8289              :                   END IF ! special case
    8290              : 
    8291              :                END DO ! ispin
    8292              : 
    8293              :                ! Compute norm of pB
    8294              :                CALL contravariant_matrix_norm( &
    8295              :                   norm_out=step_norm, &
    8296              :                   matrix_in=m_model_Bd, &
    8297              :                   metric_in=almo_scf_env%matrix_s, &
    8298              :                   quench_t_in=quench_t, &
    8299              :                   eps_filter_in=almo_scf_env%eps_filter &
    8300          268 :                   )
    8301              :                IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...pB norm: ", step_norm
    8302              : 
    8303              :                ! Do not step beyond the trust radius
    8304          268 :                IF (step_norm <= radius_current) THEN
    8305              : 
    8306              :                   IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Full dogleg"
    8307              : 
    8308          266 :                   border_reached = .FALSE.
    8309              : 
    8310          532 :                   DO ispin = 1, nspins
    8311          532 :                      CALL dbcsr_copy(step(ispin), m_model_Bd(ispin))
    8312              :                   END DO
    8313              : 
    8314          266 :                   fake_step_size_to_report = 2.0_dp
    8315          266 :                   iteration_type_to_report = 6
    8316              : 
    8317              :                ELSE ! take a shorter dogleg step
    8318              : 
    8319              :                   IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...pB norm is too large"
    8320              : 
    8321            2 :                   border_reached = .TRUE.
    8322              : 
    8323              :                   ! compute the dogleg vector = pB - pU
    8324              :                   ! this destroys -Binv.grad content
    8325            4 :                   DO ispin = 1, nspins
    8326            4 :                      CALL dbcsr_add(m_model_Bd(ispin), step(ispin), 1.0_dp, -1.0_dp)
    8327              :                   END DO
    8328              : 
    8329              :                   CALL step_size_to_border( &
    8330              :                      step_size_out=step_size, &
    8331              :                      metric_in=almo_scf_env%matrix_s, &
    8332              :                      position_in=step, &
    8333              :                      direction_in=m_model_Bd, &
    8334              :                      trust_radius_in=radius_current, &
    8335              :                      quench_t_in=quench_t, &
    8336              :                      eps_filter_in=almo_scf_env%eps_filter &
    8337            2 :                      )
    8338              :                   IF (unit_nr > 0 .AND. debug_mode) WRITE (unit_nr, *) "...Step size to border: ", step_size
    8339            2 :                   IF (step_size > 1.0_dp .OR. step_size < 0.0_dp) THEN
    8340            0 :                      IF (unit_nr > 0) THEN
    8341            0 :                         WRITE (unit_nr, *) "Step size (", step_size, ") must lie inside (0,1)"
    8342              :                      END IF
    8343            0 :                      CPABORT("Wrong dog leg step. We should never end up here.")
    8344              :                   END IF
    8345              : 
    8346            4 :                   DO ispin = 1, nspins
    8347            4 :                      CALL dbcsr_add(step(ispin), m_model_Bd(ispin), 1.0_dp, step_size)
    8348              :                   END DO
    8349              : 
    8350            2 :                   fake_step_size_to_report = 1.0_dp + step_size
    8351            2 :                   iteration_type_to_report = 7
    8352              : 
    8353              :                END IF ! full or partial dogleg?
    8354              : 
    8355              :                IF (debug_mode) THEN
    8356              :                   ! Compute step norm
    8357              :                   IF (unit_nr > 0) WRITE (unit_nr, *) "...Extra norm evaluation"
    8358              :                   CALL contravariant_matrix_norm( &
    8359              :                      norm_out=step_norm, &
    8360              :                      matrix_in=step, &
    8361              :                      metric_in=almo_scf_env%matrix_s, &
    8362              :                      quench_t_in=quench_t, &
    8363              :                      eps_filter_in=almo_scf_env%eps_filter &
    8364              :                      )
    8365              :                   IF (unit_nr > 0) WRITE (unit_nr, *) "...Step norm: ", step_norm
    8366              :                   IF (unit_nr > 0) WRITE (unit_nr, *) "...Current radius: ", radius_current
    8367              :                END IF
    8368              : 
    8369              :                CALL predicted_reduction( &
    8370              :                   reduction_out=expected_reduction, &
    8371              :                   grad_in=grad, &
    8372              :                   step_in=step, &
    8373              :                   hess_in=m_model_hessian, &
    8374              :                   hess_submatrix_in=almo_scf_env%domain_preconditioner, &
    8375              :                   quench_t_in=quench_t, &
    8376              :                   special_case=my_special_case, &
    8377              :                   eps_filter=almo_scf_env%eps_filter, &
    8378              :                   domain_map=almo_scf_env%domain_map, &
    8379              :                   cpu_of_domain=almo_scf_env%cpu_of_domain &
    8380          268 :                   )
    8381              : 
    8382          268 :                inner_loop_success = .TRUE.
    8383              : 
    8384          268 :                t2 = m_walltime()
    8385              :                CALL fixed_r_report(unit_nr, &
    8386              :                                    iter_type=iteration_type_to_report, &
    8387              :                                    iteration=iteration, &
    8388              :                                    step_size=fake_step_size_to_report, &
    8389              :                                    border_reached=border_reached, &
    8390              :                                    curvature=y_scalar, &
    8391              :                                    grad_norm_ratio=expected_reduction, &
    8392          268 :                                    time=t2 - t1)
    8393              : 
    8394              :                EXIT fixed_r_loop ! the inner loop
    8395              : 
    8396              :             END IF ! Non-iterative subproblem methods exit here
    8397              : 
    8398              :             ! Step 4: update model gradient
    8399          216 :             DO ispin = 1, nspins
    8400              :                ! save previous data
    8401          108 :                CALL dbcsr_copy(m_model_r_prev(ispin), m_model_r(ispin))
    8402              :                CALL dbcsr_add(m_model_r(ispin), m_model_Bd(ispin), &
    8403          216 :                               1.0_dp, -step_size)
    8404              :             END DO ! ispin
    8405              : 
    8406              :             ! Model grad norm
    8407          216 :             DO ispin = 1, nspins
    8408          216 :                grad_norm_spin(ispin) = dbcsr_maxabs(m_model_r(ispin))
    8409              :             END DO ! ispin
    8410          216 :             model_grad_norm = MAXVAL(grad_norm_spin)
    8411              : 
    8412              :             ! Check norm reduction
    8413          108 :             grad_norm_ratio = model_grad_norm/grad_norm_ref
    8414          108 :             IF (grad_norm_ratio < optimizer%model_grad_norm_ratio) THEN
    8415              : 
    8416           26 :                border_reached = .FALSE.
    8417           26 :                inner_loop_success = .TRUE.
    8418              : 
    8419              :                CALL predicted_reduction( &
    8420              :                   reduction_out=expected_reduction, &
    8421              :                   grad_in=grad, &
    8422              :                   step_in=step, &
    8423              :                   hess_in=m_model_hessian, &
    8424              :                   hess_submatrix_in=almo_scf_env%domain_preconditioner, &
    8425              :                   quench_t_in=quench_t, &
    8426              :                   special_case=my_special_case, &
    8427              :                   eps_filter=almo_scf_env%eps_filter, &
    8428              :                   domain_map=almo_scf_env%domain_map, &
    8429              :                   cpu_of_domain=almo_scf_env%cpu_of_domain &
    8430           26 :                   )
    8431              : 
    8432           26 :                t2 = m_walltime()
    8433              :                CALL fixed_r_report(unit_nr, &
    8434              :                                    iter_type=4, &
    8435              :                                    iteration=iteration, &
    8436              :                                    step_size=step_size, &
    8437              :                                    border_reached=border_reached, &
    8438              :                                    curvature=y_scalar, &
    8439              :                                    grad_norm_ratio=expected_reduction, &
    8440           26 :                                    time=t2 - t1)
    8441              : 
    8442              :                EXIT fixed_r_loop ! the inner loop
    8443              : 
    8444              :             END IF
    8445              : 
    8446              :             ! Step 5: update model direction
    8447          164 :             DO ispin = 1, nspins
    8448              :                ! save previous data
    8449          164 :                CALL dbcsr_copy(m_model_rt_prev(ispin), m_model_rt(ispin))
    8450              :             END DO ! ispin
    8451              : 
    8452          164 :             DO ispin = 1, nspins
    8453              : 
    8454           82 :                IF (my_special_case == xalmo_case_block_diag .OR. &
    8455           82 :                    my_special_case == xalmo_case_fully_deloc) THEN
    8456              : 
    8457              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, &
    8458              :                                       m_s_inv, &
    8459              :                                       m_model_r(ispin), &
    8460              :                                       0.0_dp, m_model_rt(ispin), &
    8461            0 :                                       filter_eps=almo_scf_env%eps_filter)
    8462              : 
    8463           82 :                ELSE IF (my_special_case == xalmo_case_normal) THEN
    8464              : 
    8465              :                   CALL apply_domain_operators( &
    8466              :                      matrix_in=m_model_r(ispin), &
    8467              :                      matrix_out=m_model_rt(ispin), &
    8468              :                      operator1=almo_scf_env%domain_s_inv(:, ispin), &
    8469              :                      dpattern=quench_t(ispin), &
    8470              :                      map=almo_scf_env%domain_map(ispin), &
    8471              :                      node_of_domain=almo_scf_env%cpu_of_domain, &
    8472              :                      my_action=0, &
    8473           82 :                      filter_eps=almo_scf_env%eps_filter)
    8474              : 
    8475              :                END IF
    8476              : 
    8477              :             END DO ! ispin
    8478              : 
    8479              :             CALL compute_cg_beta( &
    8480              :                beta=beta, &
    8481              :                reset_conjugator=reset_conjugator, &
    8482              :                conjugator=optimizer%conjugator, &
    8483              :                grad=m_model_r(:), &
    8484              :                prev_grad=m_model_r_prev(:), &
    8485              :                step=m_model_rt(:), &
    8486              :                prev_step=m_model_rt_prev(:) &
    8487           82 :                )
    8488              : 
    8489          164 :             DO ispin = 1, nspins
    8490              :                ! update direction
    8491          164 :                CALL dbcsr_add(m_model_d(ispin), m_model_rt(ispin), beta, 1.0_dp)
    8492              :             END DO ! ispin
    8493              : 
    8494           82 :             t2 = m_walltime()
    8495              :             CALL fixed_r_report(unit_nr, &
    8496              :                                 iter_type=1, &
    8497              :                                 iteration=iteration, &
    8498              :                                 step_size=step_size, &
    8499              :                                 border_reached=border_reached, &
    8500              :                                 curvature=y_scalar, &
    8501              :                                 grad_norm_ratio=grad_norm_ratio, &
    8502           82 :                                 time=t2 - t1)
    8503           82 :             t1 = m_walltime()
    8504              : 
    8505              :          END DO fixed_r_loop
    8506              :          !!!! done with the inner loop
    8507              :          ! the inner loop must return: step, predicted reduction,
    8508              :          ! whether it reached the border and completed successfully
    8509              : 
    8510              :          IF (.NOT. inner_loop_success) THEN
    8511            0 :             CPABORT("Inner loop did not produce solution")
    8512              :          END IF
    8513              : 
    8514          816 :          DO ispin = 1, nspins
    8515              : 
    8516          408 :             CALL dbcsr_copy(m_theta_trial(ispin), m_theta(ispin))
    8517          816 :             CALL dbcsr_add(m_theta_trial(ispin), step(ispin), 1.0_dp, 1.0_dp)
    8518              : 
    8519              :          END DO ! ispin
    8520              : 
    8521              :          ! compute the energy
    8522              :          CALL main_var_to_xalmos_and_loss_func( &
    8523              :             almo_scf_env=almo_scf_env, &
    8524              :             qs_env=qs_env, &
    8525              :             m_main_var_in=m_theta_trial, &
    8526              :             m_t_out=matrix_t_out, &
    8527              :             m_sig_sqrti_ii_out=m_sig_sqrti_ii, &
    8528              :             energy_out=energy_trial, &
    8529              :             penalty_out=penalty_trial, &
    8530              :             m_FTsiginv_out=FTsiginv, &
    8531              :             m_siginvTFTsiginv_out=siginvTFTsiginv, &
    8532              :             m_ST_out=ST, &
    8533              :             m_STsiginv0_in=STsiginv_0, &
    8534              :             m_quench_t_in=quench_t, &
    8535              :             domain_r_down_in=domain_r_down, &
    8536              :             assume_t0_q0x=assume_t0_q0x, &
    8537              :             just_started=.FALSE., &
    8538              :             optimize_theta=optimize_theta, &
    8539              :             normalize_orbitals=normalize_orbitals, &
    8540              :             perturbation_only=perturbation_only, &
    8541              :             do_penalty=penalty_occ_vol, &
    8542          408 :             special_case=my_special_case)
    8543          408 :          loss_trial = energy_trial + penalty_trial
    8544              : 
    8545          408 :          rho = (loss_trial - loss_start)/expected_reduction
    8546          408 :          loss_change_to_report = loss_trial - loss_start
    8547              : 
    8548          408 :          IF (rho < 0.25_dp) THEN
    8549            0 :             radius_current = 0.25_dp*radius_current
    8550              :          ELSE
    8551          408 :             IF (rho > 0.75_dp .AND. border_reached) THEN
    8552            2 :                radius_current = MIN(2.0_dp*radius_current, radius_max)
    8553              :             END IF
    8554              :          END IF ! radius adjustment
    8555              : 
    8556          408 :          IF (rho > eta) THEN
    8557          816 :             DO ispin = 1, nspins
    8558          816 :                CALL dbcsr_copy(m_theta(ispin), m_theta_trial(ispin))
    8559              :             END DO ! ispin
    8560          408 :             loss_start = loss_trial
    8561          408 :             energy_start = energy_trial
    8562          408 :             penalty_start = penalty_trial
    8563          408 :             same_position = .FALSE.
    8564          408 :             IF (my_special_case == xalmo_case_block_diag) THEN
    8565           92 :                almo_scf_env%almo_scf_energy = energy_trial
    8566              :             END IF
    8567              :          ELSE
    8568            0 :             same_position = .TRUE.
    8569            0 :             IF (my_special_case == xalmo_case_block_diag) THEN
    8570            0 :                almo_scf_env%almo_scf_energy = energy_start
    8571              :             END IF
    8572              :          END IF ! finalize step
    8573              : 
    8574          408 :          t2outer = m_walltime()
    8575              :          CALL trust_r_report(unit_nr, &
    8576              :                              iter_type=2, &
    8577              :                              iteration=outer_iteration, &
    8578              :                              loss=loss_trial, &
    8579              :                              delta_loss=loss_change_to_report, &
    8580              :                              grad_norm=0.0_dp, &
    8581              :                              predicted_reduction=expected_reduction, &
    8582              :                              rho=rho, &
    8583              :                              radius=radius_current, &
    8584              :                              new=.NOT. same_position, &
    8585          408 :                              time=t2outer - t1outer)
    8586          426 :          t1outer = m_walltime()
    8587              : 
    8588              :       END DO adjust_r_loop
    8589              : 
    8590              :       ! post SCF-loop calculations
    8591           18 :       IF (scf_converged) THEN
    8592              : 
    8593              :          CALL wrap_up_xalmo_scf( &
    8594              :             qs_env=qs_env, &
    8595              :             almo_scf_env=almo_scf_env, &
    8596              :             perturbation_in=perturbation_only, &
    8597              :             m_xalmo_in=matrix_t_out, &
    8598              :             m_quench_in=quench_t, &
    8599           18 :             energy_inout=energy_start)
    8600              : 
    8601              :       END IF ! if converged
    8602              : 
    8603           36 :       DO ispin = 1, nspins
    8604           18 :          CALL dbcsr_release(m_model_hessian_inv(ispin))
    8605           18 :          CALL dbcsr_release(m_model_hessian(ispin))
    8606           18 :          CALL dbcsr_release(STsiginv_0(ispin))
    8607           18 :          CALL dbcsr_release(ST(ispin))
    8608           18 :          CALL dbcsr_release(FTsiginv(ispin))
    8609           18 :          CALL dbcsr_release(siginvTFTsiginv(ispin))
    8610           18 :          CALL dbcsr_release(prev_step(ispin))
    8611           18 :          CALL dbcsr_release(grad(ispin))
    8612           18 :          CALL dbcsr_release(step(ispin))
    8613           18 :          CALL dbcsr_release(m_theta(ispin))
    8614           18 :          CALL dbcsr_release(m_sig_sqrti_ii(ispin))
    8615           18 :          CALL dbcsr_release(m_model_r(ispin))
    8616           18 :          CALL dbcsr_release(m_model_rt(ispin))
    8617           18 :          CALL dbcsr_release(m_model_d(ispin))
    8618           18 :          CALL dbcsr_release(m_model_Bd(ispin))
    8619           18 :          CALL dbcsr_release(m_model_r_prev(ispin))
    8620           18 :          CALL dbcsr_release(m_model_rt_prev(ispin))
    8621           18 :          CALL dbcsr_release(m_theta_trial(ispin))
    8622           18 :          CALL release_submatrices(domain_r_down(:, ispin))
    8623           36 :          CALL release_submatrices(domain_model_hessian_inv(:, ispin))
    8624              :       END DO ! ispin
    8625              : 
    8626           18 :       IF (my_special_case == xalmo_case_block_diag .OR. &
    8627              :           my_special_case == xalmo_case_fully_deloc) THEN
    8628            2 :          CALL dbcsr_release(m_s_inv)
    8629              :       END IF
    8630              : 
    8631           18 :       DEALLOCATE (m_model_hessian)
    8632           18 :       DEALLOCATE (m_model_hessian_inv)
    8633           18 :       DEALLOCATE (siginvTFTsiginv)
    8634           18 :       DEALLOCATE (STsiginv_0)
    8635           18 :       DEALLOCATE (FTsiginv)
    8636           18 :       DEALLOCATE (ST)
    8637           18 :       DEALLOCATE (grad)
    8638           18 :       DEALLOCATE (prev_step)
    8639           18 :       DEALLOCATE (step)
    8640           18 :       DEALLOCATE (m_sig_sqrti_ii)
    8641           18 :       DEALLOCATE (m_model_r)
    8642           18 :       DEALLOCATE (m_model_rt)
    8643           18 :       DEALLOCATE (m_model_d)
    8644           18 :       DEALLOCATE (m_model_Bd)
    8645           18 :       DEALLOCATE (m_model_r_prev)
    8646           18 :       DEALLOCATE (m_model_rt_prev)
    8647           18 :       DEALLOCATE (m_theta_trial)
    8648              : 
    8649          146 :       DEALLOCATE (domain_r_down)
    8650          146 :       DEALLOCATE (domain_model_hessian_inv)
    8651              : 
    8652           18 :       DEALLOCATE (penalty_occ_vol_g_prefactor)
    8653           18 :       DEALLOCATE (penalty_occ_vol_h_prefactor)
    8654           18 :       DEALLOCATE (grad_norm_spin)
    8655           18 :       DEALLOCATE (nocc)
    8656              : 
    8657           18 :       DEALLOCATE (m_theta)
    8658              : 
    8659           18 :       IF (.NOT. scf_converged .AND. .NOT. optimizer%early_stopping_on) THEN
    8660            0 :          CPABORT("Optimization not converged! ")
    8661              :       END IF
    8662              : 
    8663           18 :       CALL timestop(handle)
    8664              : 
    8665           36 :    END SUBROUTINE almo_scf_xalmo_trustr
    8666              : 
    8667              : ! **************************************************************************************************
    8668              : !> \brief Computes molecular orbitals and the objective (loss) function from the main variables
    8669              : !>        Most important input and output variables are given as arguments explicitly.
    8670              : !>        Some variables inside almo_scf_env (KS, DM) and qs_env are also updated but are not
    8671              : !>        listed as arguments for brevity
    8672              : !> \param almo_scf_env ...
    8673              : !> \param qs_env ...
    8674              : !> \param m_main_var_in ...
    8675              : !> \param m_t_out ...
    8676              : !> \param energy_out ...
    8677              : !> \param penalty_out ...
    8678              : !> \param m_sig_sqrti_ii_out ...
    8679              : !> \param m_FTsiginv_out ...
    8680              : !> \param m_siginvTFTsiginv_out ...
    8681              : !> \param m_ST_out ...
    8682              : !> \param m_STsiginv0_in ...
    8683              : !> \param m_quench_t_in ...
    8684              : !> \param domain_r_down_in ...
    8685              : !> \param assume_t0_q0x ...
    8686              : !> \param just_started ...
    8687              : !> \param optimize_theta ...
    8688              : !> \param normalize_orbitals ...
    8689              : !> \param perturbation_only ...
    8690              : !> \param do_penalty ...
    8691              : !> \param special_case ...
    8692              : !> \par History
    8693              : !>       2019.12 created [Rustam Z Khaliullin]
    8694              : !> \author Rustam Z Khaliullin
    8695              : ! **************************************************************************************************
    8696         1486 :    SUBROUTINE main_var_to_xalmos_and_loss_func(almo_scf_env, qs_env, m_main_var_in, &
    8697         1486 :                                                m_t_out, energy_out, penalty_out, m_sig_sqrti_ii_out, m_FTsiginv_out, &
    8698         1486 :                                                m_siginvTFTsiginv_out, m_ST_out, m_STsiginv0_in, m_quench_t_in, domain_r_down_in, &
    8699              :                                                assume_t0_q0x, just_started, optimize_theta, normalize_orbitals, perturbation_only, &
    8700              :                                                do_penalty, special_case)
    8701              : 
    8702              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
    8703              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    8704              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: m_main_var_in
    8705              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT)      :: m_t_out
    8706              :       REAL(KIND=dp), INTENT(OUT)                         :: energy_out, penalty_out
    8707              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT)      :: m_sig_sqrti_ii_out, m_FTsiginv_out, &
    8708              :                                                             m_siginvTFTsiginv_out, m_ST_out, &
    8709              :                                                             m_STsiginv0_in, m_quench_t_in
    8710              :       TYPE(domain_submatrix_type), DIMENSION(:, :), &
    8711              :          INTENT(IN)                                      :: domain_r_down_in
    8712              :       LOGICAL, INTENT(IN)                                :: assume_t0_q0x, just_started, &
    8713              :                                                             optimize_theta, normalize_orbitals, &
    8714              :                                                             perturbation_only, do_penalty
    8715              :       INTEGER, INTENT(IN)                                :: special_case
    8716              : 
    8717              :       CHARACTER(len=*), PARAMETER :: routineN = 'main_var_to_xalmos_and_loss_func'
    8718              : 
    8719              :       INTEGER                                            :: handle, ispin, nspins
    8720         1486 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nocc
    8721              :       REAL(KIND=dp)                                      :: det1, energy_ispin, penalty_amplitude, &
    8722              :                                                             spin_factor
    8723              : 
    8724         1486 :       CALL timeset(routineN, handle)
    8725              : 
    8726         1486 :       energy_out = 0.0_dp
    8727         1486 :       penalty_out = 0.0_dp
    8728              : 
    8729         1486 :       nspins = SIZE(m_main_var_in)
    8730         1486 :       IF (nspins == 1) THEN
    8731         1474 :          spin_factor = 2.0_dp
    8732              :       ELSE
    8733           12 :          spin_factor = 1.0_dp
    8734              :       END IF
    8735              : 
    8736         1486 :       penalty_amplitude = 0.0_dp !almo_scf_env%penalty%occ_vol_coeff
    8737              : 
    8738         4458 :       ALLOCATE (nocc(nspins))
    8739         2984 :       DO ispin = 1, nspins
    8740              :          CALL dbcsr_get_info(almo_scf_env%matrix_sigma_inv(ispin), &
    8741         2984 :                              nfullrows_total=nocc(ispin))
    8742              :       END DO
    8743              : 
    8744         2984 :       DO ispin = 1, nspins
    8745              : 
    8746              :          ! compute MO coefficients from the main variable
    8747              :          CALL compute_xalmos_from_main_var( &
    8748              :             m_var_in=m_main_var_in(ispin), &
    8749              :             m_t_out=m_t_out(ispin), &
    8750              :             m_quench_t=m_quench_t_in(ispin), &
    8751              :             m_t0=almo_scf_env%matrix_t_blk(ispin), &
    8752              :             m_oo_template=almo_scf_env%matrix_sigma_inv(ispin), &
    8753              :             m_STsiginv0=m_STsiginv0_in(ispin), &
    8754              :             m_s=almo_scf_env%matrix_s(1), &
    8755              :             m_sig_sqrti_ii_out=m_sig_sqrti_ii_out(ispin), &
    8756              :             domain_r_down=domain_r_down_in(:, ispin), &
    8757              :             domain_s_inv=almo_scf_env%domain_s_inv(:, ispin), &
    8758              :             domain_map=almo_scf_env%domain_map(ispin), &
    8759              :             cpu_of_domain=almo_scf_env%cpu_of_domain, &
    8760              :             assume_t0_q0x=assume_t0_q0x, &
    8761              :             just_started=just_started, &
    8762              :             optimize_theta=optimize_theta, &
    8763              :             normalize_orbitals=normalize_orbitals, &
    8764              :             envelope_amplitude=almo_scf_env%envelope_amplitude, &
    8765              :             eps_filter=almo_scf_env%eps_filter, &
    8766              :             special_case=special_case, &
    8767              :             nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
    8768              :             order_lanczos=almo_scf_env%order_lanczos, &
    8769              :             eps_lanczos=almo_scf_env%eps_lanczos, &
    8770         1498 :             max_iter_lanczos=almo_scf_env%max_iter_lanczos)
    8771              : 
    8772              :          ! compute the global projectors (for the density matrix)
    8773              :          CALL almo_scf_t_to_proj( &
    8774              :             t=m_t_out(ispin), &
    8775              :             p=almo_scf_env%matrix_p(ispin), &
    8776              :             eps_filter=almo_scf_env%eps_filter, &
    8777              :             orthog_orbs=.FALSE., &
    8778              :             nocc_of_domain=almo_scf_env%nocc_of_domain(:, ispin), &
    8779              :             s=almo_scf_env%matrix_s(1), &
    8780              :             sigma=almo_scf_env%matrix_sigma(ispin), &
    8781              :             sigma_inv=almo_scf_env%matrix_sigma_inv(ispin), &
    8782              :             use_guess=.FALSE., &
    8783              :             algorithm=almo_scf_env%sigma_inv_algorithm, &
    8784              :             inv_eps_factor=almo_scf_env%matrix_iter_eps_error_factor, &
    8785              :             inverse_accelerator=almo_scf_env%order_lanczos, &
    8786              :             eps_lanczos=almo_scf_env%eps_lanczos, &
    8787              :             max_iter_lanczos=almo_scf_env%max_iter_lanczos, &
    8788              :             para_env=almo_scf_env%para_env, &
    8789         1498 :             blacs_env=almo_scf_env%blacs_env)
    8790              : 
    8791              :          ! compute dm from the projector(s)
    8792              :          CALL dbcsr_scale(almo_scf_env%matrix_p(ispin), &
    8793         2984 :                           spin_factor)
    8794              : 
    8795              :       END DO ! ispin
    8796              : 
    8797              :       ! update the KS matrix and energy if necessary
    8798         1486 :       IF (perturbation_only) THEN
    8799              :          ! note: do not combine the two IF statements
    8800          212 :          IF (just_started) THEN
    8801           48 :             DO ispin = 1, nspins
    8802              :                CALL dbcsr_copy(almo_scf_env%matrix_ks(ispin), &
    8803           48 :                                almo_scf_env%matrix_ks_0deloc(ispin))
    8804              :             END DO
    8805              :          END IF
    8806              :       ELSE
    8807              :          ! the KS matrix is updated outside the spin loop
    8808              :          CALL almo_dm_to_almo_ks(qs_env, &
    8809              :                                  almo_scf_env%matrix_p, &
    8810              :                                  almo_scf_env%matrix_ks, &
    8811              :                                  energy_out, &
    8812              :                                  almo_scf_env%eps_filter, &
    8813         1274 :                                  almo_scf_env%mat_distr_aos)
    8814              :       END IF
    8815              : 
    8816         1486 :       penalty_out = 0.0_dp
    8817         2984 :       DO ispin = 1, nspins
    8818              : 
    8819              :          CALL compute_frequently_used_matrices( &
    8820              :             filter_eps=almo_scf_env%eps_filter, &
    8821              :             m_T_in=m_t_out(ispin), &
    8822              :             m_siginv_in=almo_scf_env%matrix_sigma_inv(ispin), &
    8823              :             m_S_in=almo_scf_env%matrix_s(1), &
    8824              :             m_F_in=almo_scf_env%matrix_ks(ispin), &
    8825              :             m_FTsiginv_out=m_FTsiginv_out(ispin), &
    8826              :             m_siginvTFTsiginv_out=m_siginvTFTsiginv_out(ispin), &
    8827         1498 :             m_ST_out=m_ST_out(ispin))
    8828              : 
    8829         1498 :          IF (perturbation_only) THEN
    8830              :             ! calculate objective function Tr(F_0 R)
    8831          212 :             IF (ispin == 1) energy_out = 0.0_dp
    8832          212 :             CALL dbcsr_dot(m_t_out(ispin), m_FTsiginv_out(ispin), energy_ispin)
    8833          212 :             energy_out = energy_out + energy_ispin*spin_factor
    8834              :          END IF
    8835              : 
    8836         2984 :          IF (do_penalty) THEN
    8837              : 
    8838              :             CALL determinant(almo_scf_env%matrix_sigma(ispin), det1, &
    8839            0 :                              almo_scf_env%eps_filter)
    8840              :             penalty_out = penalty_out - &
    8841            0 :                           penalty_amplitude*spin_factor*nocc(ispin)*LOG(det1)
    8842              : 
    8843              :          END IF
    8844              : 
    8845              :       END DO ! ispin
    8846              : 
    8847         1486 :       DEALLOCATE (nocc)
    8848              : 
    8849         1486 :       CALL timestop(handle)
    8850              : 
    8851         1486 :    END SUBROUTINE main_var_to_xalmos_and_loss_func
    8852              : 
    8853              : ! **************************************************************************************************
    8854              : !> \brief Computes the step size required to reach the trust-radius border,
    8855              : !>        measured from the origin,
    8856              : !>        given the current position (position) in the direction (direction)
    8857              : !> \param step_size_out ...
    8858              : !> \param metric_in ...
    8859              : !> \param position_in ...
    8860              : !> \param direction_in ...
    8861              : !> \param trust_radius_in ...
    8862              : !> \param quench_t_in ...
    8863              : !> \param eps_filter_in ...
    8864              : !> \par History
    8865              : !>       2019.12 created [Rustam Z Khaliullin]
    8866              : !> \author Rustam Z Khaliullin
    8867              : ! **************************************************************************************************
    8868           36 :    SUBROUTINE step_size_to_border(step_size_out, metric_in, position_in, &
    8869           36 :                                   direction_in, trust_radius_in, quench_t_in, eps_filter_in)
    8870              : 
    8871              :       REAL(KIND=dp), INTENT(INOUT)                       :: step_size_out
    8872              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: metric_in, position_in, direction_in
    8873              :       REAL(KIND=dp), INTENT(IN)                          :: trust_radius_in
    8874              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: quench_t_in
    8875              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter_in
    8876              : 
    8877              :       INTEGER                                            :: isol, ispin, nsolutions, &
    8878              :                                                             nsolutions_found, nspins
    8879           36 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nocc
    8880              :       REAL(KIND=dp)                                      :: discrim_sign, discriminant, solution, &
    8881              :                                                             spin_factor, temp_real
    8882              :       REAL(KIND=dp), DIMENSION(3)                        :: coef
    8883           36 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: m_temp_no
    8884              : 
    8885           36 :       step_size_out = 0.0_dp
    8886              : 
    8887           36 :       nspins = SIZE(position_in)
    8888           36 :       IF (nspins == 1) THEN
    8889              :          spin_factor = 2.0_dp
    8890              :       ELSE
    8891            0 :          spin_factor = 1.0_dp
    8892              :       END IF
    8893              : 
    8894          108 :       ALLOCATE (nocc(nspins))
    8895          144 :       ALLOCATE (m_temp_no(nspins))
    8896              : 
    8897           36 :       coef(:) = 0.0_dp
    8898           72 :       DO ispin = 1, nspins
    8899              : 
    8900              :          CALL dbcsr_create(m_temp_no(ispin), &
    8901           36 :                            template=direction_in(ispin))
    8902              : 
    8903              :          CALL dbcsr_get_info(direction_in(ispin), &
    8904           36 :                              nfullcols_total=nocc(ispin))
    8905              : 
    8906           36 :          CALL dbcsr_copy(m_temp_no(ispin), quench_t_in(ispin))
    8907              :          CALL dbcsr_multiply("N", "N", 1.0_dp, &
    8908              :                              metric_in(1), &
    8909              :                              position_in(ispin), &
    8910              :                              0.0_dp, m_temp_no(ispin), &
    8911           36 :                              retain_sparsity=.TRUE.)
    8912           36 :          CALL dbcsr_filter(m_temp_no(ispin), eps_filter_in)
    8913           36 :          CALL dbcsr_dot(position_in(ispin), m_temp_no(ispin), temp_real)
    8914           36 :          coef(3) = coef(3) + temp_real/nocc(ispin)
    8915           36 :          CALL dbcsr_dot(direction_in(ispin), m_temp_no(ispin), temp_real)
    8916           36 :          coef(2) = coef(2) + 2.0_dp*temp_real/nocc(ispin)
    8917           36 :          CALL dbcsr_copy(m_temp_no(ispin), quench_t_in(ispin))
    8918              :          CALL dbcsr_multiply("N", "N", 1.0_dp, &
    8919              :                              metric_in(1), &
    8920              :                              direction_in(ispin), &
    8921              :                              0.0_dp, m_temp_no(ispin), &
    8922           36 :                              retain_sparsity=.TRUE.)
    8923           36 :          CALL dbcsr_filter(m_temp_no(ispin), eps_filter_in)
    8924           36 :          CALL dbcsr_dot(direction_in(ispin), m_temp_no(ispin), temp_real)
    8925           36 :          coef(1) = coef(1) + temp_real/nocc(ispin)
    8926              : 
    8927          108 :          CALL dbcsr_release(m_temp_no(ispin))
    8928              : 
    8929              :       END DO !ispin
    8930              : 
    8931           36 :       DEALLOCATE (nocc)
    8932           36 :       DEALLOCATE (m_temp_no)
    8933              : 
    8934          144 :       coef(:) = coef(:)*spin_factor
    8935           36 :       coef(3) = coef(3) - trust_radius_in*trust_radius_in
    8936              : 
    8937              :       ! solve the quadratic equation
    8938           36 :       discriminant = coef(2)*coef(2) - 4.0_dp*coef(1)*coef(3)
    8939           36 :       IF (discriminant > TINY(discriminant)) THEN
    8940              :          nsolutions = 2
    8941            0 :       ELSE IF (discriminant < 0.0_dp) THEN
    8942            0 :          nsolutions = 0
    8943            0 :          CPABORT("Step to border: no solutions")
    8944              :       ELSE
    8945              :          nsolutions = 1
    8946              :       END IF
    8947              : 
    8948           36 :       discrim_sign = 1.0_dp
    8949           36 :       nsolutions_found = 0
    8950          108 :       DO isol = 1, nsolutions
    8951           72 :          solution = (-coef(2) + discrim_sign*SQRT(discriminant))/(2.0_dp*coef(1))
    8952           72 :          IF (solution > 0.0_dp) THEN
    8953           36 :             nsolutions_found = nsolutions_found + 1
    8954           36 :             step_size_out = solution
    8955              :          END IF
    8956          108 :          discrim_sign = -discrim_sign
    8957              :       END DO
    8958              : 
    8959           36 :       IF (nsolutions_found == 0) THEN
    8960            0 :          CPABORT("Step to border: no positive solutions")
    8961           36 :       ELSE IF (nsolutions_found == 2) THEN
    8962            0 :          CPABORT("Two positive border steps possible!")
    8963              :       END IF
    8964              : 
    8965           36 :    END SUBROUTINE step_size_to_border
    8966              : 
    8967              : ! **************************************************************************************************
    8968              : !> \brief Computes a norm of a contravariant NBasis x Occ matrix using proper metric
    8969              : !> \param norm_out ...
    8970              : !> \param matrix_in ...
    8971              : !> \param metric_in ...
    8972              : !> \param quench_t_in ...
    8973              : !> \param eps_filter_in ...
    8974              : !> \par History
    8975              : !>       2019.12 created [Rustam Z Khaliullin]
    8976              : !> \author Rustam Z Khaliullin
    8977              : ! **************************************************************************************************
    8978          758 :    SUBROUTINE contravariant_matrix_norm(norm_out, matrix_in, metric_in, &
    8979          758 :                                         quench_t_in, eps_filter_in)
    8980              : 
    8981              :       REAL(KIND=dp), INTENT(OUT)                         :: norm_out
    8982              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: matrix_in, metric_in, quench_t_in
    8983              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter_in
    8984              : 
    8985              :       INTEGER                                            :: ispin, nspins
    8986          758 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nocc
    8987              :       REAL(KIND=dp)                                      :: my_norm, spin_factor, temp_real
    8988          758 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: m_temp_no
    8989              : 
    8990              :       ! Frist thing: assign the output value to avoid norms being undefined
    8991          758 :       norm_out = 0.0_dp
    8992              : 
    8993          758 :       nspins = SIZE(matrix_in)
    8994          758 :       IF (nspins == 1) THEN
    8995              :          spin_factor = 2.0_dp
    8996              :       ELSE
    8997            0 :          spin_factor = 1.0_dp
    8998              :       END IF
    8999              : 
    9000         2274 :       ALLOCATE (nocc(nspins))
    9001         3032 :       ALLOCATE (m_temp_no(nspins))
    9002              : 
    9003          758 :       my_norm = 0.0_dp
    9004         1516 :       DO ispin = 1, nspins
    9005              : 
    9006          758 :          CALL dbcsr_create(m_temp_no(ispin), template=matrix_in(ispin))
    9007              : 
    9008              :          CALL dbcsr_get_info(matrix_in(ispin), &
    9009          758 :                              nfullcols_total=nocc(ispin))
    9010              : 
    9011          758 :          CALL dbcsr_copy(m_temp_no(ispin), quench_t_in(ispin))
    9012              :          CALL dbcsr_multiply("N", "N", 1.0_dp, &
    9013              :                              metric_in(1), &
    9014              :                              matrix_in(ispin), &
    9015              :                              0.0_dp, m_temp_no(ispin), &
    9016          758 :                              retain_sparsity=.TRUE.)
    9017          758 :          CALL dbcsr_filter(m_temp_no(ispin), eps_filter_in)
    9018          758 :          CALL dbcsr_dot(matrix_in(ispin), m_temp_no(ispin), temp_real)
    9019              : 
    9020          758 :          my_norm = my_norm + temp_real/nocc(ispin)
    9021              : 
    9022         1516 :          CALL dbcsr_release(m_temp_no(ispin))
    9023              : 
    9024              :       END DO !ispin
    9025              : 
    9026          758 :       DEALLOCATE (nocc)
    9027          758 :       DEALLOCATE (m_temp_no)
    9028              : 
    9029          758 :       my_norm = my_norm*spin_factor
    9030          758 :       norm_out = SQRT(my_norm)
    9031              : 
    9032          758 :    END SUBROUTINE contravariant_matrix_norm
    9033              : 
    9034              : ! **************************************************************************************************
    9035              : !> \brief Loss reduction for a given step is estimated using
    9036              : !>        gradient and hessian
    9037              : !> \param reduction_out ...
    9038              : !> \param grad_in ...
    9039              : !> \param step_in ...
    9040              : !> \param hess_in ...
    9041              : !> \param hess_submatrix_in ...
    9042              : !> \param quench_t_in ...
    9043              : !> \param special_case ...
    9044              : !> \param eps_filter ...
    9045              : !> \param domain_map ...
    9046              : !> \param cpu_of_domain ...
    9047              : !> \par History
    9048              : !>       2019.12 created [Rustam Z Khaliullin]
    9049              : !> \author Rustam Z Khaliullin
    9050              : ! **************************************************************************************************
    9051          408 :    SUBROUTINE predicted_reduction(reduction_out, grad_in, step_in, hess_in, &
    9052          408 :                                   hess_submatrix_in, quench_t_in, special_case, eps_filter, domain_map, &
    9053          408 :                                   cpu_of_domain)
    9054              : 
    9055              :       !RZK-noncritical: can be formulated without submatrices
    9056              :       REAL(KIND=dp), INTENT(INOUT)                       :: reduction_out
    9057              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(INOUT)      :: grad_in, step_in, hess_in
    9058              :       TYPE(domain_submatrix_type), DIMENSION(:, :), &
    9059              :          INTENT(IN)                                      :: hess_submatrix_in
    9060              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: quench_t_in
    9061              :       INTEGER, INTENT(IN)                                :: special_case
    9062              :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    9063              :       TYPE(domain_map_type), DIMENSION(:), INTENT(IN)    :: domain_map
    9064              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: cpu_of_domain
    9065              : 
    9066              :       INTEGER                                            :: ispin, nspins
    9067              :       REAL(KIND=dp)                                      :: my_reduction, spin_factor, temp_real
    9068          408 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: m_temp_no
    9069              : 
    9070          408 :       reduction_out = 0.0_dp
    9071              : 
    9072          408 :       nspins = SIZE(grad_in)
    9073          408 :       IF (nspins == 1) THEN
    9074              :          spin_factor = 2.0_dp
    9075              :       ELSE
    9076            0 :          spin_factor = 1.0_dp
    9077              :       END IF
    9078              : 
    9079         1632 :       ALLOCATE (m_temp_no(nspins))
    9080              : 
    9081          408 :       my_reduction = 0.0_dp
    9082          816 :       DO ispin = 1, nspins
    9083              : 
    9084          408 :          CALL dbcsr_create(m_temp_no(ispin), template=grad_in(ispin))
    9085              : 
    9086          408 :          CALL dbcsr_dot(step_in(ispin), grad_in(ispin), temp_real)
    9087          408 :          my_reduction = my_reduction + temp_real
    9088              : 
    9089              :          ! Get Hess.step
    9090          408 :          IF (special_case == xalmo_case_block_diag .OR. &
    9091              :              special_case == xalmo_case_fully_deloc) THEN
    9092              : 
    9093              :             CALL dbcsr_multiply("N", "N", 1.0_dp, &
    9094              :                                 hess_in(ispin), &
    9095              :                                 step_in(ispin), &
    9096              :                                 0.0_dp, m_temp_no(ispin), &
    9097           92 :                                 filter_eps=eps_filter)
    9098              : 
    9099              :          ELSE
    9100              : 
    9101              :             CALL apply_domain_operators( &
    9102              :                matrix_in=step_in(ispin), &
    9103              :                matrix_out=m_temp_no(ispin), &
    9104              :                operator1=hess_submatrix_in(:, ispin), &
    9105              :                dpattern=quench_t_in(ispin), &
    9106              :                map=domain_map(ispin), &
    9107              :                node_of_domain=cpu_of_domain, &
    9108              :                my_action=0, &
    9109          316 :                filter_eps=eps_filter)
    9110              : 
    9111              :          END IF ! special case
    9112              : 
    9113              :          ! Get y=step^T.Hess.step
    9114          408 :          CALL dbcsr_dot(step_in(ispin), m_temp_no(ispin), temp_real)
    9115          408 :          my_reduction = my_reduction + 0.5_dp*temp_real
    9116              : 
    9117         1224 :          CALL dbcsr_release(m_temp_no(ispin))
    9118              : 
    9119              :       END DO ! ispin
    9120              : 
    9121              :       !RZK-critical: do we need to multiply by the spin factor?
    9122          408 :       my_reduction = spin_factor*my_reduction
    9123              : 
    9124          408 :       reduction_out = my_reduction
    9125              : 
    9126          408 :       DEALLOCATE (m_temp_no)
    9127              : 
    9128          408 :    END SUBROUTINE predicted_reduction
    9129              : 
    9130              : ! **************************************************************************************************
    9131              : !> \brief Prints key quantities from the fixed-radius minimizer
    9132              : !> \param unit_nr ...
    9133              : !> \param iter_type ...
    9134              : !> \param iteration ...
    9135              : !> \param step_size ...
    9136              : !> \param border_reached ...
    9137              : !> \param curvature ...
    9138              : !> \param grad_norm_ratio ...
    9139              : !> \param predicted_reduction ...
    9140              : !> \param time ...
    9141              : !> \par History
    9142              : !>       2019.12 created [Rustam Z Khaliullin]
    9143              : !> \author Rustam Z Khaliullin
    9144              : ! **************************************************************************************************
    9145          898 :    SUBROUTINE fixed_r_report(unit_nr, iter_type, iteration, step_size, &
    9146              :                              border_reached, curvature, grad_norm_ratio, predicted_reduction, time)
    9147              : 
    9148              :       INTEGER, INTENT(IN)                                :: unit_nr, iter_type, iteration
    9149              :       REAL(KIND=dp), INTENT(IN)                          :: step_size
    9150              :       LOGICAL, INTENT(IN)                                :: border_reached
    9151              :       REAL(KIND=dp), INTENT(IN)                          :: curvature
    9152              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: grad_norm_ratio, predicted_reduction
    9153              :       REAL(KIND=dp), INTENT(IN)                          :: time
    9154              : 
    9155              :       CHARACTER(LEN=20)                                  :: iter_type_str
    9156              :       REAL(KIND=dp)                                      :: loss_or_grad_change
    9157              : 
    9158          898 :       loss_or_grad_change = 0.0_dp
    9159          898 :       IF (PRESENT(grad_norm_ratio)) THEN
    9160          898 :          loss_or_grad_change = grad_norm_ratio
    9161            0 :       ELSE IF (PRESENT(predicted_reduction)) THEN
    9162            0 :          loss_or_grad_change = predicted_reduction
    9163              :       ELSE
    9164            0 :          CPABORT("one argument is missing")
    9165              :       END IF
    9166              : 
    9167         1306 :       SELECT CASE (iter_type)
    9168              :       CASE (0)
    9169          408 :          iter_type_str = TRIM("Ignored")
    9170              :       CASE (1)
    9171           82 :          iter_type_str = TRIM("PCG")
    9172              :       CASE (2)
    9173            0 :          iter_type_str = TRIM("Neg. curvatr.")
    9174              :       CASE (3)
    9175           34 :          iter_type_str = TRIM("Step too long")
    9176              :       CASE (4)
    9177           26 :          iter_type_str = TRIM("Grad. reduced")
    9178              :       CASE (5)
    9179           80 :          iter_type_str = TRIM("Cauchy point")
    9180              :       CASE (6)
    9181          266 :          iter_type_str = TRIM("Full dogleg")
    9182              :       CASE (7)
    9183            2 :          iter_type_str = TRIM("Part. dogleg")
    9184              :       CASE DEFAULT
    9185          898 :          CPABORT("unknown report type")
    9186              :       END SELECT
    9187              : 
    9188          898 :       IF (unit_nr > 0) THEN
    9189              : 
    9190          204 :          SELECT CASE (iter_type)
    9191              :          CASE (0)
    9192              : 
    9193          204 :             WRITE (unit_nr, *)
    9194              :             WRITE (unit_nr, '(T4,A15,A6,A10,A10,A7,A20,A8)') &
    9195          204 :                "Action", &
    9196          204 :                "Iter", &
    9197          204 :                "Curv", &
    9198          204 :                "Step", &
    9199          204 :                "Edge?", &
    9200          204 :                "Grad/o.f. reduc", &
    9201          408 :                "Time"
    9202              : 
    9203              :          CASE DEFAULT
    9204              : 
    9205              :             WRITE (unit_nr, '(T4,A15,I6,F10.5,F10.5,L7,F20.10,F8.2)') &
    9206          245 :                iter_type_str, &
    9207          245 :                iteration, &
    9208          245 :                curvature, step_size, border_reached, &
    9209          245 :                loss_or_grad_change, &
    9210          694 :                time
    9211              : 
    9212              :          END SELECT
    9213              : 
    9214              :          ! epilogue
    9215          204 :          SELECT CASE (iter_type)
    9216              :          CASE (2, 3, 4, 5, 6, 7)
    9217              : 
    9218          449 :             WRITE (unit_nr, *)
    9219              : 
    9220              :          END SELECT
    9221              : 
    9222              :       END IF
    9223              : 
    9224          898 :    END SUBROUTINE fixed_r_report
    9225              : 
    9226              : ! **************************************************************************************************
    9227              : !> \brief Prints key quantities from the loop that tunes trust radius
    9228              : !> \param unit_nr ...
    9229              : !> \param iter_type ...
    9230              : !> \param iteration ...
    9231              : !> \param radius ...
    9232              : !> \param loss ...
    9233              : !> \param delta_loss ...
    9234              : !> \param grad_norm ...
    9235              : !> \param predicted_reduction ...
    9236              : !> \param rho ...
    9237              : !> \param new ...
    9238              : !> \param time ...
    9239              : !> \par History
    9240              : !>       2019.12 created [Rustam Z Khaliullin]
    9241              : !> \author Rustam Z Khaliullin
    9242              : ! **************************************************************************************************
    9243          843 :    SUBROUTINE trust_r_report(unit_nr, iter_type, iteration, radius, &
    9244              :                              loss, delta_loss, grad_norm, predicted_reduction, rho, new, time)
    9245              : 
    9246              :       INTEGER, INTENT(IN)                                :: unit_nr, iter_type, iteration
    9247              :       REAL(KIND=dp), INTENT(IN)                          :: radius, loss, delta_loss, grad_norm, &
    9248              :                                                             predicted_reduction, rho
    9249              :       LOGICAL, INTENT(IN)                                :: new
    9250              :       REAL(KIND=dp), INTENT(IN)                          :: time
    9251              : 
    9252              :       CHARACTER(LEN=20)                                  :: iter_status, iter_type_str
    9253              : 
    9254          852 :       SELECT CASE (iter_type)
    9255              :       CASE (0) ! header
    9256            9 :          iter_type_str = TRIM("Iter")
    9257            9 :          iter_status = TRIM("Stat")
    9258              :       CASE (1) ! first iteration, not all data is available yet
    9259          426 :          iter_type_str = TRIM("TR INI")
    9260          426 :          IF (new) THEN
    9261          426 :             iter_status = "  New" ! new point
    9262              :          ELSE
    9263            0 :             iter_status = " Redo" ! restarted
    9264              :          END IF
    9265              :       CASE (2) ! typical
    9266          408 :          iter_type_str = TRIM("TR FIN")
    9267          408 :          IF (new) THEN
    9268          408 :             iter_status = "  Acc" ! accepted
    9269              :          ELSE
    9270            0 :             iter_status = "  Rej" ! rejected
    9271              :          END IF
    9272              :       CASE DEFAULT
    9273          843 :          CPABORT("unknown report type")
    9274              :       END SELECT
    9275              : 
    9276          843 :       IF (unit_nr > 0) THEN
    9277              : 
    9278            9 :          SELECT CASE (iter_type)
    9279              :          CASE (0)
    9280              : 
    9281              :             WRITE (unit_nr, '(T2,A6,A5,A6,A22,A10,T67,A7,A6)') &
    9282            9 :                "Method", &
    9283            9 :                "Stat", &
    9284            9 :                "Iter", &
    9285            9 :                "Objective Function", &
    9286            9 :                "Conver", &!"Model Change", "Rho", &
    9287            9 :                "Radius", &
    9288           18 :                "Time"
    9289              :             WRITE (unit_nr, '(T41,A10,A10,A6)') &
    9290              :                !"Method", &
    9291              :                !"Iter", &
    9292              :                !"Objective Function", &
    9293            9 :                "Change", "Expct.", "Rho"
    9294              :             !"Radius", &
    9295              :             !"Time"
    9296              : 
    9297              :          CASE (1)
    9298              : 
    9299              :             WRITE (unit_nr, '(T2,A6,A5,I6,F22.10,ES10.2,T67,ES7.0,F6.1)') &
    9300          213 :                iter_type_str, &
    9301          213 :                iter_status, &
    9302          213 :                iteration, &
    9303          213 :                loss, &
    9304          213 :                grad_norm, & ! distinct
    9305          213 :                radius, &
    9306          426 :                time
    9307              : 
    9308              :          CASE (2)
    9309              : 
    9310              :             WRITE (unit_nr, '(T2,A6,A5,I6,F22.10,ES10.2,ES10.2,F6.1,ES7.0,F6.1)') &
    9311          204 :                iter_type_str, &
    9312          204 :                iter_status, &
    9313          204 :                iteration, &
    9314          204 :                loss, &
    9315          204 :                delta_loss, predicted_reduction, rho, & ! distinct
    9316          204 :                radius, &
    9317          630 :                time
    9318              : 
    9319              :          END SELECT
    9320              :       END IF
    9321              : 
    9322          843 :    END SUBROUTINE trust_r_report
    9323              : 
    9324              : ! **************************************************************************************************
    9325              : !> \brief ...
    9326              : !> \param unit_nr ...
    9327              : !> \param ref_energy ...
    9328              : !> \param energy_lowering ...
    9329              : ! **************************************************************************************************
    9330           26 :    SUBROUTINE energy_lowering_report(unit_nr, ref_energy, energy_lowering)
    9331              : 
    9332              :       INTEGER, INTENT(IN)                                :: unit_nr
    9333              :       REAL(KIND=dp), INTENT(IN)                          :: ref_energy, energy_lowering
    9334              : 
    9335              :       ! print out the energy lowering
    9336           26 :       IF (unit_nr > 0) THEN
    9337           13 :          WRITE (unit_nr, *)
    9338           13 :          WRITE (unit_nr, '(T2,A35,F25.10)') "ENERGY OF BLOCK-DIAGONAL ALMOs:", &
    9339           26 :             ref_energy
    9340           13 :          WRITE (unit_nr, '(T2,A35,F25.10)') "ENERGY LOWERING:", &
    9341           26 :             energy_lowering
    9342           13 :          WRITE (unit_nr, '(T2,A35,F25.10)') "CORRECTED ENERGY:", &
    9343           26 :             ref_energy + energy_lowering
    9344           13 :          WRITE (unit_nr, *)
    9345              :       END IF
    9346              : 
    9347           26 :    END SUBROUTINE energy_lowering_report
    9348              : 
    9349              :    ! post SCF-loop calculations
    9350              : ! **************************************************************************************************
    9351              : !> \brief ...
    9352              : !> \param qs_env ...
    9353              : !> \param almo_scf_env ...
    9354              : !> \param perturbation_in ...
    9355              : !> \param m_xalmo_in ...
    9356              : !> \param m_quench_in ...
    9357              : !> \param energy_inout ...
    9358              : ! **************************************************************************************************
    9359          110 :    SUBROUTINE wrap_up_xalmo_scf(qs_env, almo_scf_env, perturbation_in, &
    9360          110 :                                 m_xalmo_in, m_quench_in, energy_inout)
    9361              : 
    9362              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    9363              :       TYPE(almo_scf_env_type), INTENT(INOUT)             :: almo_scf_env
    9364              :       LOGICAL, INTENT(IN)                                :: perturbation_in
    9365              :       TYPE(dbcsr_type), DIMENSION(:), INTENT(IN)         :: m_xalmo_in, m_quench_in
    9366              :       REAL(KIND=dp), INTENT(INOUT)                       :: energy_inout
    9367              : 
    9368              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'wrap_up_xalmo_scf'
    9369              : 
    9370              :       INTEGER                                            :: eda_unit, handle, ispin, nspins, unit_nr
    9371              :       TYPE(cp_logger_type), POINTER                      :: logger
    9372          110 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: m_temp_no1, m_temp_no2
    9373              :       TYPE(section_vals_type), POINTER                   :: almo_print_section, input
    9374              : 
    9375          110 :       CALL timeset(routineN, handle)
    9376              : 
    9377              :       ! get a useful output_unit
    9378          110 :       logger => cp_get_default_logger()
    9379          110 :       IF (logger%para_env%is_source()) THEN
    9380           55 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    9381              :       ELSE
    9382           55 :          unit_nr = -1
    9383              :       END IF
    9384              : 
    9385          110 :       nspins = almo_scf_env%nspins
    9386              : 
    9387              :       ! RZK-warning: must obtain MO coefficients from final theta
    9388              : 
    9389          110 :       IF (perturbation_in) THEN
    9390              : 
    9391           96 :          ALLOCATE (m_temp_no1(nspins))
    9392           72 :          ALLOCATE (m_temp_no2(nspins))
    9393              : 
    9394           48 :          DO ispin = 1, nspins
    9395           24 :             CALL dbcsr_create(m_temp_no1(ispin), template=m_xalmo_in(ispin))
    9396           48 :             CALL dbcsr_create(m_temp_no2(ispin), template=m_xalmo_in(ispin))
    9397              :          END DO
    9398              : 
    9399              :          ! return perturbed density to qs_env
    9400              :          CALL almo_dm_to_qs_env(qs_env, almo_scf_env%matrix_p, &
    9401           24 :                                 almo_scf_env%mat_distr_aos)
    9402              : 
    9403              :          ! compute energy correction and perform
    9404              :          ! detailed decomposition analysis (if requested)
    9405              :          ! reuse step and grad matrices to store decomposition results
    9406              :          CALL xalmo_analysis( &
    9407              :             detailed_analysis=almo_scf_env%almo_analysis%do_analysis, &
    9408              :             eps_filter=almo_scf_env%eps_filter, &
    9409              :             m_T_in=m_xalmo_in, &
    9410              :             m_T0_in=almo_scf_env%matrix_t_blk, &
    9411              :             m_siginv_in=almo_scf_env%matrix_sigma_inv, &
    9412              :             m_siginv0_in=almo_scf_env%matrix_sigma_inv_0deloc, &
    9413              :             m_S_in=almo_scf_env%matrix_s, &
    9414              :             m_KS0_in=almo_scf_env%matrix_ks_0deloc, &
    9415              :             m_quench_t_in=m_quench_in, &
    9416              :             energy_out=energy_inout, & ! get energy loewring
    9417              :             m_eda_out=m_temp_no1, &
    9418              :             m_cta_out=m_temp_no2 &
    9419           24 :             )
    9420              : 
    9421           24 :          IF (almo_scf_env%almo_analysis%do_analysis) THEN
    9422              : 
    9423            4 :             DO ispin = 1, nspins
    9424              : 
    9425              :                ! energy decomposition analysis (EDA)
    9426            2 :                IF (unit_nr > 0) THEN
    9427            1 :                   WRITE (unit_nr, '(T2,A)') "DECOMPOSITION OF THE DELOCALIZATION ENERGY"
    9428              :                END IF
    9429              : 
    9430              :                ! open the output file, print and close
    9431            2 :                CALL get_qs_env(qs_env, input=input)
    9432            2 :                almo_print_section => section_vals_get_subs_vals(input, "DFT%ALMO_SCF%ANALYSIS%PRINT")
    9433              :                eda_unit = cp_print_key_unit_nr(logger, almo_print_section, &
    9434            2 :                                                "ALMO_EDA_CT", extension=".dat", local=.TRUE.)
    9435            2 :                CALL print_block_sum(m_temp_no1(ispin), eda_unit)
    9436              :                CALL cp_print_key_finished_output(eda_unit, logger, almo_print_section, &
    9437            2 :                                                  "ALMO_EDA_CT", local=.TRUE.)
    9438              : 
    9439              :                ! charge transfer analysis (CTA)
    9440            2 :                IF (unit_nr > 0) THEN
    9441            1 :                   WRITE (unit_nr, '(T2,A)') "DECOMPOSITION OF CHARGE TRANSFER TERMS"
    9442              :                END IF
    9443              : 
    9444              :                eda_unit = cp_print_key_unit_nr(logger, almo_print_section, &
    9445            2 :                                                "ALMO_CTA", extension=".dat", local=.TRUE.)
    9446            2 :                CALL print_block_sum(m_temp_no2(ispin), eda_unit)
    9447              :                CALL cp_print_key_finished_output(eda_unit, logger, almo_print_section, &
    9448            4 :                                                  "ALMO_CTA", local=.TRUE.)
    9449              : 
    9450              :             END DO ! ispin
    9451              : 
    9452              :          END IF ! do ALMO EDA/CTA
    9453              : 
    9454              :          CALL energy_lowering_report( &
    9455              :             unit_nr=unit_nr, &
    9456              :             ref_energy=almo_scf_env%almo_scf_energy, &
    9457           24 :             energy_lowering=energy_inout)
    9458              :          CALL almo_scf_update_ks_energy(qs_env, &
    9459              :                                         energy=almo_scf_env%almo_scf_energy, &
    9460           24 :                                         energy_singles_corr=energy_inout)
    9461              : 
    9462           48 :          DO ispin = 1, nspins
    9463           24 :             CALL dbcsr_release(m_temp_no1(ispin))
    9464           48 :             CALL dbcsr_release(m_temp_no2(ispin))
    9465              :          END DO
    9466              : 
    9467           24 :          DEALLOCATE (m_temp_no1)
    9468           24 :          DEALLOCATE (m_temp_no2)
    9469              : 
    9470              :       ELSE ! non-perturbative
    9471              : 
    9472              :          CALL almo_scf_update_ks_energy(qs_env, &
    9473           86 :                                         energy=energy_inout)
    9474              : 
    9475              :       END IF ! if perturbation only
    9476              : 
    9477          110 :       CALL timestop(handle)
    9478              : 
    9479          110 :    END SUBROUTINE wrap_up_xalmo_scf
    9480              : 
    9481              : ! **************************************************************************************************
    9482              : !> \brief Computes tanh(alpha*x) of the matrix elements. Fails if |alpha*x| >= 1.
    9483              : !> \param matrix ...
    9484              : !> \param alpha ...
    9485              : !> \author Ole Schuett
    9486              : ! **************************************************************************************************
    9487            0 :    SUBROUTINE tanh_of_elements(matrix, alpha)
    9488              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
    9489              :       REAL(kind=dp), INTENT(IN)                          :: alpha
    9490              : 
    9491              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'tanh_of_elements'
    9492              : 
    9493              :       INTEGER                                            :: handle
    9494            0 :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: block
    9495              :       TYPE(dbcsr_iterator_type)                          :: iter
    9496              : 
    9497            0 :       CALL timeset(routineN, handle)
    9498            0 :       CALL dbcsr_iterator_start(iter, matrix)
    9499            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    9500            0 :          CALL dbcsr_iterator_next_block(iter, block=block)
    9501            0 :          block = TANH(alpha*block)
    9502              :       END DO
    9503            0 :       CALL dbcsr_iterator_stop(iter)
    9504            0 :       CALL timestop(handle)
    9505              : 
    9506            0 :    END SUBROUTINE tanh_of_elements
    9507              : 
    9508              : ! **************************************************************************************************
    9509              : !> \brief Computes d(tanh(alpha*x)) / dx of the matrix elements. Fails if |alpha*x| >= 1.
    9510              : !> \param matrix ...
    9511              : !> \param alpha ...
    9512              : !> \author Ole Schuett
    9513              : ! **************************************************************************************************
    9514            0 :    SUBROUTINE dtanh_of_elements(matrix, alpha)
    9515              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
    9516              :       REAL(kind=dp), INTENT(IN)                          :: alpha
    9517              : 
    9518              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'dtanh_of_elements'
    9519              : 
    9520              :       INTEGER                                            :: handle
    9521            0 :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: block
    9522              :       TYPE(dbcsr_iterator_type)                          :: iter
    9523              : 
    9524            0 :       CALL timeset(routineN, handle)
    9525            0 :       CALL dbcsr_iterator_start(iter, matrix)
    9526            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    9527            0 :          CALL dbcsr_iterator_next_block(iter, block=block)
    9528            0 :          block = alpha*(1.0_dp - TANH(block)**2)
    9529              :       END DO
    9530            0 :       CALL dbcsr_iterator_stop(iter)
    9531            0 :       CALL timestop(handle)
    9532              : 
    9533            0 :    END SUBROUTINE dtanh_of_elements
    9534              : 
    9535              : ! **************************************************************************************************
    9536              : !> \brief Computes 1/x of the matrix elements.
    9537              : !> \param matrix ...
    9538              : !> \author Ole Schuett
    9539              : ! **************************************************************************************************
    9540            0 :    SUBROUTINE inverse_of_elements(matrix)
    9541              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
    9542              : 
    9543              :       CHARACTER(len=*), PARAMETER :: routineN = 'inverse_of_elements'
    9544              : 
    9545              :       INTEGER                                            :: handle
    9546            0 :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: block
    9547              :       TYPE(dbcsr_iterator_type)                          :: iter
    9548              : 
    9549            0 :       CALL timeset(routineN, handle)
    9550            0 :       CALL dbcsr_iterator_start(iter, matrix)
    9551            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    9552            0 :          CALL dbcsr_iterator_next_block(iter, block=block)
    9553            0 :          block = 1.0_dp/block
    9554              :       END DO
    9555            0 :       CALL dbcsr_iterator_stop(iter)
    9556            0 :       CALL timestop(handle)
    9557              : 
    9558            0 :    END SUBROUTINE inverse_of_elements
    9559              : 
    9560              : ! **************************************************************************************************
    9561              : !> \brief Prints the sum of the elements for each block.
    9562              : !> \param matrix ...
    9563              : !> \param unit_nr ...
    9564              : ! **************************************************************************************************
    9565            4 :    SUBROUTINE print_block_sum(matrix, unit_nr)
    9566              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
    9567              :       INTEGER, INTENT(IN)                                :: unit_nr
    9568              : 
    9569              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'print_block_sum'
    9570              : 
    9571              :       INTEGER                                            :: col, handle, row
    9572            4 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: block
    9573              :       TYPE(dbcsr_iterator_type)                          :: iter
    9574              : 
    9575            4 :       CALL timeset(routineN, handle)
    9576              : 
    9577            4 :       IF (unit_nr > 0) THEN
    9578            4 :          CALL dbcsr_iterator_readonly_start(iter, matrix)
    9579           34 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
    9580           30 :             CALL dbcsr_iterator_next_block(iter, row, col, block)
    9581         2914 :             WRITE (unit_nr, '(I6,I6,ES18.9)') row, col, SUM(block)
    9582              :          END DO
    9583            4 :          CALL dbcsr_iterator_stop(iter)
    9584              :       END IF
    9585              : 
    9586            4 :       CALL timestop(handle)
    9587            4 :    END SUBROUTINE print_block_sum
    9588              : 
    9589              : END MODULE almo_scf_optimizer
    9590              : 
        

Generated by: LCOV version 2.0-1