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

Generated by: LCOV version 2.0-1