LCOV - code coverage report
Current view: top level - src - qs_scf_loop_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 94.7 % 1460 1383
Test Date: 2026-09-03 07:32:15 Functions: 100.0 % 30 30

            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              : !> \brief Utility routines for qs_scf
       9              : ! **************************************************************************************************
      10              : MODULE qs_scf_loop_utils
      11              :    USE cp_control_types,                ONLY: dft_control_type,&
      12              :                                               hairy_probes_type
      13              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      14              :                                               dbcsr_get_info,&
      15              :                                               dbcsr_p_type,&
      16              :                                               dbcsr_release,&
      17              :                                               dbcsr_release_p,&
      18              :                                               dbcsr_scale,&
      19              :                                               dbcsr_set,&
      20              :                                               dbcsr_type
      21              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_dot,&
      22              :                                               dbcsr_get_diag,&
      23              :                                               dbcsr_scale_by_vector
      24              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      25              :                                               copy_fm_to_dbcsr,&
      26              :                                               cp_dbcsr_sm_fm_multiply,&
      27              :                                               dbcsr_allocate_matrix_set,&
      28              :                                               dbcsr_deallocate_matrix_set
      29              :    USE cp_external_control,             ONLY: external_control
      30              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      31              :                                               cp_fm_gemm,&
      32              :                                               cp_fm_scale_and_add
      33              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      34              :                                               cp_fm_struct_release,&
      35              :                                               cp_fm_struct_type
      36              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      37              :                                               cp_fm_get_info,&
      38              :                                               cp_fm_get_submatrix,&
      39              :                                               cp_fm_release,&
      40              :                                               cp_fm_set_submatrix,&
      41              :                                               cp_fm_to_fm,&
      42              :                                               cp_fm_type
      43              :    USE cp_log_handling,                 ONLY: cp_to_string
      44              :    USE ieee_arithmetic,                 ONLY: ieee_is_finite
      45              :    USE input_constants,                 ONLY: diag_update_method_adiis,&
      46              :                                               smear_fermi_dirac,&
      47              :                                               smear_gaussian,&
      48              :                                               smear_mp,&
      49              :                                               smear_mv
      50              :    USE input_section_types,             ONLY: section_vals_get,&
      51              :                                               section_vals_get_subs_vals,&
      52              :                                               section_vals_type
      53              :    USE kinds,                           ONLY: default_string_length,&
      54              :                                               dp
      55              :    USE kpoint_methods,                  ONLY: kpoint_density_matrices,&
      56              :                                               kpoint_density_transform,&
      57              :                                               kpoint_set_mo_occupation
      58              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      59              :                                               kpoint_env_type,&
      60              :                                               kpoint_type
      61              :    USE message_passing,                 ONLY: mp_para_env_type
      62              :    USE qs_density_matrices,             ONLY: calculate_density_matrix
      63              :    USE qs_density_mixing_types,         ONLY: broyden_mixing_nr,&
      64              :                                               direct_mixing_nr,&
      65              :                                               gspace_mixing_nr,&
      66              :                                               modified_broyden_mixing_nr,&
      67              :                                               multisecant_mixing_nr,&
      68              :                                               new_pulay_mixing_nr,&
      69              :                                               no_mixing_nr,&
      70              :                                               pulay_mixing_nr
      71              :    USE qs_energy_types,                 ONLY: qs_energy_type
      72              :    USE qs_environment_types,            ONLY: get_qs_env,&
      73              :                                               qs_environment_type
      74              :    USE qs_fb_env_methods,               ONLY: fb_env_do_diag
      75              :    USE qs_gspace_mixing,                ONLY: gspace_mixing
      76              :    USE qs_kpp1_env_types,               ONLY: kpp1_release,&
      77              :                                               qs_kpp1_env_type
      78              :    USE qs_ks_types,                     ONLY: qs_ks_did_change,&
      79              :                                               qs_ks_env_type
      80              :    USE qs_linres_kernel,                ONLY: apply_hxc_kernel_kp
      81              :    USE qs_mixing_utils,                 ONLY: self_consistency_check
      82              :    USE qs_mo_occupation,                ONLY: set_mo_occupation
      83              :    USE qs_mo_types,                     ONLY: get_mo_set,&
      84              :                                               mo_set_type
      85              :    USE qs_mom_methods,                  ONLY: do_mom_diag
      86              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      87              :    USE qs_ot,                           ONLY: &
      88              :         qs_ot_antihermitian_spectral_norm, qs_ot_density_secant_orbital_overlaps, &
      89              :         qs_ot_density_secant_projected_hessian, qs_ot_density_tangent, &
      90              :         qs_ot_finite_rotation_response, qs_ot_fixed_n_energy_gradient, qs_ot_fixed_n_schur_block, &
      91              :         qs_ot_get_orbitals_complex, qs_ot_get_orbitals_ref_complex, &
      92              :         qs_ot_projected_response_update, qs_ot_symmetric_abs_solve
      93              :    USE qs_ot_minimizer,                 ONLY: ot_mermin_response_preparation_needed,&
      94              :                                               ot_mermin_secant_curvature,&
      95              :                                               ot_mini,&
      96              :                                               ot_mini_prepare_gradient
      97              :    USE qs_ot_scf,                       ONLY: ot_scf_destroy,&
      98              :                                               ot_scf_mini
      99              :    USE qs_ot_types,                     ONLY: qs_ot_channel_index,&
     100              :                                               qs_ot_check_channel_context,&
     101              :                                               qs_ot_type
     102              :    USE qs_outer_scf,                    ONLY: outer_loop_gradient
     103              :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
     104              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     105              :                                               qs_rho_type
     106              :    USE qs_scf_diagonalization,          ONLY: &
     107              :         do_block_davidson_diag, do_block_davidson_diag_kp, do_block_krylov_diag, do_general_diag, &
     108              :         do_general_diag_kp, do_ot_diag, do_ot_diag_kp, do_roks_diag, do_scf_diag_subspace, &
     109              :         do_special_diag, qs_scf_distribute_kpoint_operator, qs_scf_get_ot_kpoint_operator
     110              :    USE qs_scf_methods,                  ONLY: cp_sm_mix,&
     111              :                                               scf_env_density_mixing
     112              :    USE qs_scf_output,                   ONLY: qs_scf_print_summary
     113              :    USE qs_scf_types,                    ONLY: &
     114              :         block_davidson_diag_method_nr, block_krylov_diag_method_nr, filter_matrix_diag_method_nr, &
     115              :         general_diag_method_nr, ot_diag_method_nr, ot_method_nr, qs_scf_env_type, &
     116              :         smeagol_method_nr, special_diag_method_nr
     117              :    USE scf_control_types,               ONLY: scf_control_type,&
     118              :                                               smear_type
     119              :    USE smeagol_interface,               ONLY: run_smeagol_emtrans
     120              :    USE smearing_utils,                  ONLY: Smearkp,&
     121              :                                               Smearkp2,&
     122              :                                               smearing_response_weight
     123              :    USE tblite_interface,                ONLY: tb_native_scc_mixer_active
     124              : #include "./base/base_uses.f90"
     125              : 
     126              :    IMPLICIT NONE
     127              : 
     128              :    PRIVATE
     129              : 
     130              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_loop_utils'
     131              : 
     132              :    PUBLIC :: qs_scf_set_loop_flags, &
     133              :              qs_scf_new_mos, qs_scf_new_mos_kp, &
     134              :              qs_scf_kp_ref_refresh_ready, qs_scf_kp_search_endpoint, &
     135              :              qs_scf_candidate_density_delta, qs_scf_commit_density_candidate, &
     136              :              qs_scf_density_mixing, qs_scf_check_inner_exit, &
     137              :              qs_scf_check_outer_exit, qs_scf_inner_finalize, qs_scf_rho_update
     138              : 
     139              : CONTAINS
     140              : 
     141              : ! **************************************************************************************************
     142              : !> \brief identify an accepted OT search endpoint from its iteration label
     143              : !> \param method OT iteration label
     144              : !> \return true for the primary endpoint of every supported minimizer
     145              : ! **************************************************************************************************
     146         2614 :    PURE FUNCTION qs_scf_kp_search_endpoint(method) RESULT(endpoint)
     147              : 
     148              :       CHARACTER(LEN=*), INTENT(IN)                       :: method
     149              :       LOGICAL                                            :: endpoint
     150              : 
     151         2614 :       SELECT CASE (TRIM(method))
     152              :       CASE ("OT CG", "OT SD", "OT DIIS", "OT BROY", "OT LBFGS")
     153         1178 :          endpoint = .TRUE.
     154              :       CASE DEFAULT
     155         2614 :          endpoint = .FALSE.
     156              :       END SELECT
     157              : 
     158         2614 :    END FUNCTION qs_scf_kp_search_endpoint
     159              : 
     160              : ! **************************************************************************************************
     161              : !> \brief decide whether a mature variable-occupation REF chart should be rebuilt
     162              : !> \param accepted_searches accepted search directions in the current REF chart
     163              : !> \param residual current OT residual
     164              : !> \param eps_scf requested SCF threshold
     165              : !> \param base_state whether the current point can start a new search direction
     166              : !> \param allow_exit_window whether a prior physical REF rebuild permits an exit-only rebuild
     167              : !> \return true inside the asymptotic residual window after sufficient accepted history
     168              : ! **************************************************************************************************
     169         1388 :    PURE FUNCTION qs_scf_kp_ref_refresh_ready( &
     170              :       accepted_searches, residual, eps_scf, base_state, allow_exit_window) &
     171              :       RESULT(refresh)
     172              : 
     173              :       INTEGER, INTENT(IN)                                :: accepted_searches
     174              :       REAL(KIND=dp), INTENT(IN)                          :: residual, eps_scf
     175              :       LOGICAL, INTENT(IN)                                :: base_state
     176              :       LOGICAL, INTENT(IN), OPTIONAL                      :: allow_exit_window
     177              :       LOGICAL                                            :: refresh
     178              : 
     179              :       INTEGER, PARAMETER                                 :: min_accepted_searches = 12
     180              : 
     181              :       LOGICAL                                            :: exit_window
     182              :       REAL(KIND=dp)                                      :: eps
     183              : 
     184         1388 :       eps = MAX(eps_scf, EPSILON(1.0_dp))
     185         1388 :       exit_window = .FALSE.
     186         1388 :       IF (PRESENT(allow_exit_window)) exit_window = allow_exit_window
     187              :       refresh = base_state .AND. accepted_searches >= min_accepted_searches .AND. &
     188              :                 ((residual > 10.0_dp*eps .AND. residual <= 0.2_dp*SQRT(eps)) .OR. &
     189         1388 :                  (exit_window .AND. residual > 0.25_dp*eps .AND. residual <= 10.0_dp*eps))
     190              : 
     191         1388 :    END FUNCTION qs_scf_kp_ref_refresh_ready
     192              : 
     193              : ! **************************************************************************************************
     194              : !> \brief computes properties for a given hamiltonian using the current wfn
     195              : !> \param scf_env ...
     196              : !> \param diis_step ...
     197              : !> \param energy_only ...
     198              : !> \param just_energy ...
     199              : !> \param exit_inner_loop ...
     200              : ! **************************************************************************************************
     201        25073 :    SUBROUTINE qs_scf_set_loop_flags(scf_env, diis_step, &
     202              :                                     energy_only, just_energy, exit_inner_loop)
     203              : 
     204              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     205              :       LOGICAL                                            :: diis_step, energy_only, just_energy, &
     206              :                                                             exit_inner_loop
     207              : 
     208              : ! Some flags needed to be set at the beginning of the loop
     209              : 
     210        25073 :       diis_step = .FALSE.
     211        25073 :       energy_only = .FALSE.
     212        25073 :       just_energy = .FALSE.
     213              : 
     214              :       ! SCF loop, optimisation of the wfn coefficients
     215              :       ! qs_env%rho%rho_r and qs_env%rho%rho_g should be up to date here
     216              : 
     217        25073 :       scf_env%iter_count = 0
     218        25073 :       scf_env%adiis_check_next = .FALSE.
     219        25073 :       scf_env%adiis_validated = .FALSE.
     220        25073 :       scf_env%step_norm = 0.0_dp
     221        25073 :       scf_env%raw_map_delta = 0.0_dp
     222        25073 :       scf_env%oda_lambda = 0.0_dp
     223        25073 :       scf_env%oda_energy = 0.0_dp
     224        25073 :       scf_env%oda_gradient0 = 0.0_dp
     225        25073 :       scf_env%oda_gradient1 = 0.0_dp
     226        25073 :       scf_env%oda_evaluations = 0
     227        25073 :       scf_env%oda_status = ""
     228        25073 :       scf_env%raw_map_delta_valid = .FALSE.
     229        25073 :       exit_inner_loop = .FALSE.
     230              : 
     231        25073 :    END SUBROUTINE qs_scf_set_loop_flags
     232              : 
     233              : ! **************************************************************************************************
     234              : !> \brief takes known energy and derivatives and produces new wfns
     235              : !>        and or density matrix
     236              : !> \param qs_env ...
     237              : !> \param scf_env ...
     238              : !> \param scf_control ...
     239              : !> \param scf_section ...
     240              : !> \param diis_step ...
     241              : !> \param energy_only ...
     242              : !> \param probe ...
     243              : ! **************************************************************************************************
     244       197115 :    SUBROUTINE qs_scf_new_mos(qs_env, scf_env, scf_control, scf_section, diis_step, &
     245              :                              energy_only, probe)
     246              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     247              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     248              :       TYPE(scf_control_type), POINTER                    :: scf_control
     249              :       TYPE(section_vals_type), POINTER                   :: scf_section
     250              :       LOGICAL                                            :: diis_step, energy_only
     251              :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     252              :          POINTER                                         :: probe
     253              : 
     254              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_scf_new_mos'
     255              : 
     256              :       INTEGER                                            :: handle, ispin
     257              :       LOGICAL                                            :: disable_diis, has_unit_metric, &
     258              :                                                             skip_diag_sub
     259              :       REAL(KIND=dp)                                      :: saved_eps_diis
     260       197115 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     261              :       TYPE(dft_control_type), POINTER                    :: dft_control
     262       197115 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     263              :       TYPE(qs_energy_type), POINTER                      :: energy
     264              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     265              :       TYPE(qs_rho_type), POINTER                         :: rho
     266              : 
     267       197115 :       CALL timeset(routineN, handle)
     268              : 
     269       197115 :       NULLIFY (energy, ks_env, matrix_ks, matrix_s, rho, mos, dft_control)
     270              : 
     271              :       CALL get_qs_env(qs_env=qs_env, &
     272              :                       matrix_s=matrix_s, energy=energy, &
     273              :                       ks_env=ks_env, &
     274              :                       matrix_ks=matrix_ks, rho=rho, mos=mos, &
     275              :                       dft_control=dft_control, &
     276       197115 :                       has_unit_metric=has_unit_metric)
     277       197115 :       scf_env%iter_param = 0.0_dp
     278              : 
     279              :       disable_diis = dft_control%qs_control%xtb_control%do_tblite .AND. &
     280       197115 :                      tb_native_scc_mixer_active(dft_control)
     281              :       IF (disable_diis) THEN
     282        12006 :          saved_eps_diis = scf_control%eps_diis
     283        12006 :          scf_control%eps_diis = 0.0_dp
     284              :       END IF
     285              : 
     286              :       ! transfer total_zeff_corr from qs_env to scf_env only if
     287              :       ! correct_el_density_dip is switched on [SGh]
     288       197115 :       IF (dft_control%correct_el_density_dip) THEN
     289           40 :          scf_env%sum_zeff_corr = qs_env%total_zeff_corr
     290           40 :          IF (ABS(qs_env%total_zeff_corr) > 0.0_dp) THEN
     291           40 :             IF (scf_env%method /= general_diag_method_nr) THEN
     292              :                CALL cp_abort(__LOCATION__, &
     293              :                              "Please use ALGORITHM STANDARD in "// &
     294              :                              "SCF%DIAGONALIZATION if "// &
     295              :                              "CORE_CORRECTION /= 0.0 and "// &
     296            0 :                              "SURFACE_DIPOLE_CORRECTION TRUE ")
     297           40 :             ELSE IF (dft_control%roks) THEN
     298              :                CALL cp_abort(__LOCATION__, &
     299              :                              "Combination of "// &
     300              :                              "CORE_CORRECTION /= 0.0 and "// &
     301              :                              "SURFACE_DIPOLE_CORRECTION TRUE "// &
     302            0 :                              "is not implemented with ROKS")
     303           40 :             ELSE IF (scf_control%diagonalization%mom) THEN
     304              :                CALL cp_abort(__LOCATION__, &
     305              :                              "Combination of "// &
     306              :                              "CORE_CORRECTION /= 0.0 and "// &
     307              :                              "SURFACE_DIPOLE_CORRECTION TRUE "// &
     308            0 :                              "is not implemented with SCF%MOM")
     309              :             END IF
     310              :          END IF
     311              :       END IF
     312              : 
     313       197115 :       SELECT CASE (scf_env%method)
     314              :       CASE DEFAULT
     315              :          CALL cp_abort(__LOCATION__, &
     316              :                        "unknown scf method: "// &
     317            0 :                        cp_to_string(scf_env%method))
     318              : 
     319              :          ! *************************************************************************
     320              :          ! Filter matrix diagonalisation: ugly implementation at this point of time
     321              :          ! *************************************************************************
     322              :       CASE (filter_matrix_diag_method_nr)
     323              : 
     324           80 :          IF (ABS(qs_env%total_zeff_corr) > 0.0_dp) THEN
     325              :             CALL cp_abort(__LOCATION__, &
     326              :                           "CORE_CORRECTION /= 0.0 plus SURFACE_DIPOLE_CORRECTION TRUE "// &
     327            0 :                           "requires SCF%DIAGONALIZATION: ALGORITHM STANDARD")
     328              :          END IF
     329              :          CALL fb_env_do_diag(scf_env%filter_matrix_env, qs_env, &
     330           80 :                              matrix_ks, matrix_s, scf_section, diis_step)
     331              : 
     332              :          ! Diagonlization in non orthonormal case
     333              :       CASE (general_diag_method_nr)
     334        99521 :          IF (dft_control%roks) THEN
     335              :             CALL do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
     336              :                               scf_control, scf_section, diis_step, &
     337          610 :                               has_unit_metric)
     338              :          ELSE
     339        98911 :             IF (scf_control%diagonalization%mom) THEN
     340              :                CALL do_mom_diag(scf_env, mos, matrix_ks, &
     341              :                                 matrix_s, scf_control, scf_section, &
     342          324 :                                 diis_step)
     343              :             ELSE
     344        98587 :                IF (dft_control%hairy_probes .EQV. .TRUE.) THEN
     345              :                   CALL do_general_diag(scf_env, mos, matrix_ks, &
     346              :                                        matrix_s, scf_control, scf_section, &
     347              :                                        diis_step, &
     348           14 :                                        probe)
     349              :                ELSE
     350              :                   CALL do_general_diag(scf_env, mos, matrix_ks, &
     351              :                                        matrix_s, scf_control, scf_section, &
     352        98573 :                                        diis_step)
     353              :                END IF
     354              :             END IF
     355        98911 :             IF (scf_control%do_diag_sub) THEN
     356              :                skip_diag_sub = (scf_env%subspace_env%eps_diag_sub > 0.0_dp) .AND. &
     357           10 :                                (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%subspace_env%eps_diag_sub)
     358              :                IF (.NOT. skip_diag_sub) THEN
     359              :                   CALL do_scf_diag_subspace(qs_env, scf_env, scf_env%subspace_env, mos, rho, &
     360           10 :                                             ks_env, scf_section, scf_control)
     361              :                END IF
     362              :             END IF
     363              :          END IF
     364              :          ! Diagonlization in orthonormal case
     365              :       CASE (special_diag_method_nr)
     366        18398 :          IF (dft_control%roks) THEN
     367              :             CALL do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
     368              :                               scf_control, scf_section, diis_step, &
     369          522 :                               has_unit_metric)
     370              :          ELSE
     371              :             CALL do_special_diag(scf_env, mos, matrix_ks, &
     372              :                                  scf_control, scf_section, &
     373        17876 :                                  diis_step)
     374              :          END IF
     375              :          ! OT diagonalization
     376              :       CASE (ot_diag_method_nr)
     377              :          CALL do_ot_diag(scf_env, mos, matrix_ks, matrix_s, &
     378          202 :                          scf_control, scf_section, diis_step)
     379              :          ! Block Krylov diagonlization
     380              :       CASE (block_krylov_diag_method_nr)
     381           40 :          IF ((scf_env%krylov_space%eps_std_diag > 0.0_dp) .AND. &
     382              :              (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%krylov_space%eps_std_diag)) THEN
     383            2 :             IF (scf_env%krylov_space%always_check_conv) THEN
     384              :                CALL do_block_krylov_diag(scf_env, mos, matrix_ks, &
     385            0 :                                          scf_control, scf_section, check_moconv_only=.TRUE.)
     386              :             END IF
     387              :             CALL do_general_diag(scf_env, mos, matrix_ks, &
     388            2 :                                  matrix_s, scf_control, scf_section, diis_step)
     389              :          ELSE
     390              :             CALL do_block_krylov_diag(scf_env, mos, matrix_ks, &
     391           38 :                                       scf_control, scf_section)
     392              :          END IF
     393           40 :          IF (scf_control%do_diag_sub) THEN
     394              :             skip_diag_sub = (scf_env%subspace_env%eps_diag_sub > 0.0_dp) .AND. &
     395            0 :                             (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%subspace_env%eps_diag_sub)
     396              :             IF (.NOT. skip_diag_sub) THEN
     397              :                CALL do_scf_diag_subspace(qs_env, scf_env, scf_env%subspace_env, mos, rho, &
     398            0 :                                          ks_env, scf_section, scf_control)
     399              :             END IF
     400              :          END IF
     401              :          ! Block Davidson diagonlization
     402              :       CASE (block_davidson_diag_method_nr)
     403              :          CALL do_block_davidson_diag(qs_env, scf_env, mos, matrix_ks, matrix_s, scf_control, &
     404           94 :                                      scf_section, .FALSE.)
     405              :          ! OT without diagonlization. Needs special treatment for SCP runs
     406              :       CASE (ot_method_nr)
     407              :          CALL qs_scf_loop_do_ot(qs_env, scf_env, scf_control%smear, mos, rho, &
     408              :                                 qs_env%mo_derivs, energy%total, &
     409       197115 :                                 matrix_s, energy_only=energy_only, has_unit_metric=has_unit_metric)
     410              :       END SELECT
     411       197115 :       IF (disable_diis) scf_control%eps_diis = saved_eps_diis
     412              : 
     413       197115 :       energy%kTS = 0.0_dp
     414       197115 :       energy%efermi = 0.0_dp
     415       197115 :       CALL get_qs_env(qs_env, mos=mos)
     416       427297 :       DO ispin = 1, SIZE(mos)
     417       230182 :          energy%kTS = energy%kTS + mos(ispin)%kTS
     418       427297 :          energy%efermi = energy%efermi + mos(ispin)%mu
     419              :       END DO
     420       197115 :       energy%efermi = energy%efermi/REAL(SIZE(mos), KIND=dp)
     421              : 
     422       197115 :       CALL timestop(handle)
     423              : 
     424       197115 :    END SUBROUTINE qs_scf_new_mos
     425              : 
     426              : ! **************************************************************************************************
     427              : !> \brief Updates MOs and density matrix using diagonalization
     428              : !>        Kpoint code
     429              : !> \param qs_env ...
     430              : !> \param scf_env ...
     431              : !> \param scf_control ...
     432              : !> \param diis_step ...
     433              : !> \param probe ...
     434              : !> \param ot_kp_subspace_refresh ...
     435              : !> \param allow_ot_kp_subspace_refresh ...
     436              : !> \param allow_ot_kp_exit_refresh ...
     437              : !> \param accepted_ot_kp_searches ...
     438              : !> \param added_mos_auto_grow ...
     439              : !> \param energy_only ...
     440              : ! **************************************************************************************************
     441        36614 :    SUBROUTINE qs_scf_new_mos_kp(qs_env, scf_env, scf_control, diis_step, probe, &
     442              :                                 ot_kp_subspace_refresh, allow_ot_kp_subspace_refresh, &
     443              :                                 allow_ot_kp_exit_refresh, accepted_ot_kp_searches, &
     444              :                                 added_mos_auto_grow, energy_only)
     445              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     446              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     447              :       TYPE(scf_control_type), POINTER                    :: scf_control
     448              :       LOGICAL                                            :: diis_step
     449              :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     450              :          POINTER                                         :: probe
     451              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: ot_kp_subspace_refresh
     452              :       LOGICAL, INTENT(IN), OPTIONAL                      :: allow_ot_kp_subspace_refresh, &
     453              :                                                             allow_ot_kp_exit_refresh
     454              :       INTEGER, INTENT(IN), OPTIONAL                      :: accepted_ot_kp_searches
     455              :       LOGICAL, INTENT(OUT), OPTIONAL                     :: added_mos_auto_grow, energy_only
     456              : 
     457              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_scf_new_mos_kp'
     458              : 
     459              :       INTEGER                                            :: accepted_searches, handle, ispin, &
     460              :                                                             refresh_count
     461              :       LOGICAL :: allow_exit_refresh, allow_refresh, base_state, disable_diis, has_unit_metric, &
     462              :          my_added_mos_auto_grow, ot_energy_only, refresh
     463              :       REAL(dp)                                           :: diis_error, residual, saved_eps_diis
     464        36614 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s, matrix_t
     465              :       TYPE(dft_control_type), POINTER                    :: dft_control
     466              :       TYPE(kpoint_type), POINTER                         :: kpoints
     467        36614 :       TYPE(mo_set_type), DIMENSION(:, :), POINTER        :: mos
     468              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     469              :       TYPE(qs_energy_type), POINTER                      :: energy
     470              : 
     471        36614 :       CALL timeset(routineN, handle)
     472              : 
     473        36614 :       allow_refresh = .FALSE.
     474        36614 :       allow_exit_refresh = .FALSE.
     475        36614 :       accepted_searches = 0
     476        36614 :       my_added_mos_auto_grow = .FALSE.
     477        36614 :       refresh = .FALSE.
     478        36614 :       IF (PRESENT(allow_ot_kp_subspace_refresh)) allow_refresh = allow_ot_kp_subspace_refresh
     479        36614 :       IF (PRESENT(allow_ot_kp_exit_refresh)) allow_exit_refresh = allow_ot_kp_exit_refresh
     480        36614 :       IF (PRESENT(accepted_ot_kp_searches)) accepted_searches = accepted_ot_kp_searches
     481        36614 :       IF (PRESENT(ot_kp_subspace_refresh)) ot_kp_subspace_refresh = .FALSE.
     482        36614 :       IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .FALSE.
     483        36614 :       IF (PRESENT(energy_only)) energy_only = .FALSE.
     484              : 
     485        36614 :       NULLIFY (dft_control, energy, kpoints, matrix_ks, matrix_s, matrix_t, para_env)
     486              : 
     487        36614 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, energy=energy, kpoints=kpoints)
     488        36614 :       CALL get_kpoint_info(kpoints, para_env=para_env)
     489        36614 :       CPASSERT(ASSOCIATED(para_env))
     490        36614 :       scf_env%iter_param = 0.0_dp
     491              :       disable_diis = dft_control%qs_control%xtb_control%do_tblite .AND. &
     492        36614 :                      tb_native_scc_mixer_active(dft_control)
     493              :       IF (disable_diis) THEN
     494        10420 :          saved_eps_diis = scf_control%eps_diis
     495        10420 :          scf_control%eps_diis = 0.0_dp
     496              :       END IF
     497              : 
     498        36614 :       IF (dft_control%roks .AND. scf_env%method /= ot_method_nr) THEN
     499            0 :          CPABORT("KP code: ROKS method not available: ")
     500              :       END IF
     501              : 
     502        36614 :       SELECT CASE (scf_env%method)
     503              :       CASE DEFAULT
     504              :          CALL cp_abort(__LOCATION__, &
     505              :                        "KP code: Unknown scf method: "// &
     506            0 :                        cp_to_string(scf_env%method))
     507              :       CASE (general_diag_method_nr)
     508              :          ! Diagonlization in non orthonormal case
     509        33008 :          CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s)
     510        33008 :          IF (scf_control%diagonalization%update_method == diag_update_method_adiis) THEN
     511          122 :             CPASSERT(ASSOCIATED(scf_env%scf_subspace_buffer))
     512          122 :             diis_error = scf_env%scf_subspace_buffer%last_old_fock_weight
     513              :          END IF
     514        33008 :          IF (dft_control%hairy_probes .EQV. .TRUE.) THEN
     515            0 :             scf_control%smear%do_smear = .FALSE.
     516              :             CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, .TRUE., &
     517            0 :                                     diis_step, diis_error, qs_env, probe)
     518              :          ELSE
     519              :             CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, .TRUE., &
     520              :                                     diis_step, diis_error, qs_env, &
     521        33008 :                                     added_mos_auto_grow=my_added_mos_auto_grow)
     522              :          END IF
     523        33008 :          IF (my_added_mos_auto_grow) THEN
     524            0 :             IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
     525            0 :             IF (disable_diis) scf_control%eps_diis = saved_eps_diis
     526            0 :             CALL timestop(handle)
     527            6 :             RETURN
     528              :          END IF
     529        33008 :          IF (scf_control%diagonalization%update_method == diag_update_method_adiis .AND. &
     530            0 :              .NOT. diis_step) THEN
     531           74 :             scf_env%iter_param = diis_error
     532           74 :             IF (scf_env%scf_subspace_buffer%last_restart) THEN
     533            0 :                scf_env%iter_method = "ADIIS/Rst."
     534              :             ELSE
     535           74 :                scf_env%iter_method = "ADIIS/Diag."
     536              :             END IF
     537        32934 :          ELSE IF (diis_step) THEN
     538        10308 :             scf_env%iter_param = diis_error
     539        10308 :             scf_env%iter_method = "DIIS/Diag."
     540              :          ELSE
     541        22626 :             IF (scf_env%mixing_method == 0) THEN
     542            0 :                scf_env%iter_method = "NoMix/Diag."
     543        22626 :             ELSE IF (scf_env%mixing_method == 1) THEN
     544        20082 :                scf_env%iter_param = scf_env%p_mix_alpha
     545        20082 :                scf_env%iter_method = "P_Mix/Diag."
     546         2544 :             ELSE IF (scf_env%mixing_method > 1) THEN
     547         2544 :                scf_env%iter_param = scf_env%mixing_store%alpha
     548         2544 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
     549              :             END IF
     550              :          END IF
     551              :       CASE (special_diag_method_nr)
     552            0 :          CALL get_qs_env(qs_env=qs_env, has_unit_metric=has_unit_metric)
     553            0 :          CPASSERT(has_unit_metric)
     554              :          ! Diagonlization in orthonormal case
     555              :          CALL cp_abort(__LOCATION__, &
     556              :                        "KP code: Scf method not available: "// &
     557            0 :                        cp_to_string(scf_env%method))
     558              :       CASE (ot_diag_method_nr)
     559           58 :          CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s, kinetic_kp=matrix_t)
     560              :          CALL do_ot_diag_kp(matrix_ks, matrix_s, matrix_t, kpoints, scf_env, scf_control, &
     561           58 :                             diis_step, my_added_mos_auto_grow)
     562           58 :          IF (my_added_mos_auto_grow) THEN
     563            0 :             IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
     564            0 :             IF (disable_diis) scf_control%eps_diis = saved_eps_diis
     565            0 :             CALL timestop(handle)
     566            0 :             RETURN
     567              :          END IF
     568              :       CASE (block_krylov_diag_method_nr)
     569              :          CALL cp_abort(__LOCATION__, &
     570              :                        "KP code: Scf method not available: "// &
     571            0 :                        cp_to_string(scf_env%method))
     572              :       CASE (block_davidson_diag_method_nr)
     573          932 :          CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s)
     574              :          CALL do_block_davidson_diag_kp(qs_env, scf_env, matrix_ks, matrix_s, kpoints, &
     575          932 :                                         scf_control)
     576              :       CASE (ot_method_nr)
     577         2616 :          CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s)
     578              :          base_state = .NOT. scf_env%qs_ot_env(1)%energy_only .AND. &
     579              :                       (scf_env%qs_ot_env(1)%line_search_count == 0 .OR. &
     580         2616 :                        scf_env%qs_ot_env(1)%line_search_might_be_done)
     581         2616 :          residual = MAX(scf_env%iter_delta, scf_env%qs_ot_env(1)%delta)
     582              :          refresh = (allow_refresh .OR. allow_exit_refresh) .AND. &
     583              :                    scf_env%qs_ot_env(1)%settings%do_ener .AND. &
     584              :                    scf_env%qs_ot_env(1)%settings%occupation_preconditioner .AND. &
     585              :                    (dft_control%smear .OR. scf_control%smear%do_smear) .AND. &
     586              :                    qs_scf_kp_ref_refresh_ready(accepted_searches, residual, &
     587         2616 :                                                scf_control%eps_scf, base_state, allow_exit_refresh)
     588         2616 :          refresh_count = MERGE(1, 0, refresh)
     589         2616 :          CALL para_env%sum(refresh_count)
     590         2616 :          refresh = refresh_count > 0
     591         2616 :          IF (refresh) THEN
     592           26 :             IF (PRESENT(ot_kp_subspace_refresh)) ot_kp_subspace_refresh = .TRUE.
     593              :          ELSE
     594              :             CALL qs_scf_loop_do_ot_kp(qs_env, scf_env, matrix_ks, matrix_s, &
     595         2590 :                                       my_added_mos_auto_grow, ot_energy_only)
     596         2590 :             IF (PRESENT(energy_only)) energy_only = ot_energy_only
     597         2590 :             IF (my_added_mos_auto_grow) THEN
     598            6 :                IF (PRESENT(added_mos_auto_grow)) added_mos_auto_grow = .TRUE.
     599            6 :                IF (disable_diis) scf_control%eps_diis = saved_eps_diis
     600            6 :                CALL timestop(handle)
     601            6 :                RETURN
     602              :             END IF
     603         2584 :             IF (allow_exit_refresh .AND. scf_env%iter_delta <= scf_control%eps_scf) THEN
     604           16 :                base_state = qs_scf_kp_search_endpoint(scf_env%iter_method)
     605              :                refresh = qs_scf_kp_ref_refresh_ready( &
     606              :                          accepted_searches, scf_env%iter_delta, scf_control%eps_scf, &
     607           16 :                          base_state, allow_exit_window=.TRUE.)
     608           16 :                IF (refresh .AND. PRESENT(ot_kp_subspace_refresh)) THEN
     609            0 :                   ot_kp_subspace_refresh = .TRUE.
     610              :                END IF
     611              :             END IF
     612         2584 :             refresh_count = MERGE(1, 0, refresh)
     613         2584 :             CALL para_env%sum(refresh_count)
     614         2584 :             refresh = refresh_count > 0
     615         2584 :             IF (refresh .AND. PRESENT(ot_kp_subspace_refresh)) THEN
     616            0 :                ot_kp_subspace_refresh = .TRUE.
     617              :             END IF
     618              :          END IF
     619              :       CASE (smeagol_method_nr)
     620              :          ! SMEAGOL interface
     621            0 :          diis_step = .FALSE.
     622            0 :          IF (scf_env%mixing_method == 0) THEN
     623            0 :             scf_env%iter_method = "NoMix/SMGL"
     624            0 :          ELSE IF (scf_env%mixing_method == 1) THEN
     625            0 :             scf_env%iter_param = scf_env%p_mix_alpha
     626            0 :             scf_env%iter_method = "P_Mix/SMGL"
     627            0 :          ELSE IF (scf_env%mixing_method > 1) THEN
     628            0 :             scf_env%iter_param = scf_env%mixing_store%alpha
     629            0 :             scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/SMGL"
     630              :          END IF
     631        36672 :          CALL run_smeagol_emtrans(qs_env, last=.FALSE., iter=scf_env%iter_count, rho_ao_kp=scf_env%p_mix_new)
     632              :       END SELECT
     633        36608 :       IF (disable_diis) scf_control%eps_diis = saved_eps_diis
     634              : 
     635        36608 :       CALL get_qs_env(qs_env=qs_env, energy=energy)
     636        36608 :       energy%kTS = 0.0_dp
     637        36608 :       energy%efermi = 0.0_dp
     638        36608 :       mos => kpoints%kp_env(1)%kpoint_env%mos
     639        75518 :       DO ispin = 1, SIZE(mos, 2)
     640        38910 :          energy%kTS = energy%kTS + mos(1, ispin)%kTS
     641        75518 :          energy%efermi = energy%efermi + mos(1, ispin)%mu
     642              :       END DO
     643        36608 :       energy%efermi = energy%efermi/REAL(SIZE(mos, 2), KIND=dp)
     644              : 
     645        36608 :       CALL timestop(handle)
     646              : 
     647        36614 :    END SUBROUTINE qs_scf_new_mos_kp
     648              : 
     649              : ! **************************************************************************************************
     650              : !> \brief K-point OT driver for local complex spin/k-point channels
     651              : !> \param qs_env ...
     652              : !> \param scf_env ...
     653              : !> \param matrix_ks ...
     654              : !> \param matrix_s ...
     655              : !> \param added_mos_auto_grow ...
     656              : !> \param energy_only ...
     657              : ! **************************************************************************************************
     658         2590 :    SUBROUTINE qs_scf_loop_do_ot_kp(qs_env, scf_env, matrix_ks, matrix_s, added_mos_auto_grow, energy_only)
     659              : 
     660              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     661              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     662              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s
     663              :       LOGICAL, INTENT(OUT)                               :: added_mos_auto_grow, energy_only
     664              : 
     665              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_scf_loop_do_ot_kp'
     666              : 
     667              :       INTEGER :: energy_spin, energy_start, first_channel, handle, homo, icomponent, ikpoint, &
     668              :          ispin, local_channel, local_kpoint, nao, nkp_groups, nkpoint, nlocal_channels, nmo, &
     669              :          nspin_energy, nspin_ot
     670              :       INTEGER, DIMENSION(2)                              :: kp_range
     671              :       LOGICAL                                            :: ot_gradient_prepared, &
     672              :                                                             physical_base_state, restricted_roks, &
     673              :                                                             transfer_step, use_real_wfn
     674              :       REAL(KIND=dp)                                      :: trial_kTS
     675         2590 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: orbital_scaling_factor, roks_occupation, &
     676         2590 :                                                             trial_mu
     677         2590 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: trial_eigenvalues, trial_occupation
     678         2590 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation_numbers, wkp
     679              :       TYPE(cp_fm_struct_type), POINTER                   :: active_mo_struct, chc_struct
     680              :       TYPE(cp_fm_type)                                   :: active_mo_coeff, active_mo_coeff_im, &
     681              :                                                             chc_im, chc_re, hc_im, hc_re, &
     682              :                                                             hc_roks_im, hc_roks_re
     683         2590 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
     684              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_coeff_im, mo_coeff_target
     685         2590 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_hc, matrix_hc_im, &
     686         2590 :                                                             matrix_hc_physical, &
     687         2590 :                                                             matrix_hc_physical_im
     688         2590 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: density_target, rho_ao_kp
     689              :       TYPE(dbcsr_type), POINTER                          :: matrix_k_im, matrix_k_re, matrix_s_im, &
     690              :                                                             matrix_s_re
     691              :       TYPE(dft_control_type), POINTER                    :: dft_control
     692              :       TYPE(kpoint_env_type), POINTER                     :: kp
     693              :       TYPE(kpoint_type), POINTER                         :: kpoints
     694              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
     695              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     696         2590 :          POINTER                                         :: sab_nl
     697              :       TYPE(qs_energy_type), POINTER                      :: energy
     698         2590 :       TYPE(qs_ot_type), DIMENSION(:), POINTER            :: local_ot_env
     699              :       TYPE(qs_rho_type), POINTER                         :: rho
     700              :       TYPE(scf_control_type), POINTER                    :: scf_control
     701              : 
     702         2590 :       CALL timeset(routineN, handle)
     703         2590 :       added_mos_auto_grow = .FALSE.
     704         2590 :       ot_gradient_prepared = .FALSE.
     705              : 
     706         2590 :       NULLIFY (active_mo_struct, chc_struct, density_target, dft_control, energy, fmwork, kpoints, &
     707         2590 :                local_ot_env, matrix_hc, matrix_hc_im, matrix_k_im, matrix_k_re, matrix_s_im, &
     708         2590 :                matrix_hc_physical, matrix_hc_physical_im, matrix_s_re, mo_coeff, mo_coeff_im, &
     709         2590 :                occupation_numbers, para_env_inter_kp, rho, &
     710         2590 :                rho_ao_kp, sab_nl, scf_control, wkp)
     711              : 
     712         2590 :       CPASSERT(ASSOCIATED(scf_env%qs_ot_env))
     713              :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, energy=energy, kpoints=kpoints, rho=rho, &
     714         2590 :                       scf_control=scf_control)
     715              :       CALL get_kpoint_info(kpoints, nkp=nkpoint, wkp=wkp, use_real_wfn=use_real_wfn, &
     716              :                            kp_range=kp_range, nkp_groups=nkp_groups, para_env_inter_kp=para_env_inter_kp, &
     717         2590 :                            sab_nl=sab_nl)
     718         2590 :       fmwork => scf_env%scf_work1
     719         2590 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
     720         2590 :       CPASSERT(ASSOCIATED(sab_nl))
     721         2590 :       CPASSERT(ASSOCIATED(matrix_ks))
     722         2590 :       CPASSERT(ASSOCIATED(matrix_s))
     723              : 
     724         2590 :       IF (use_real_wfn) THEN
     725              :          CALL cp_abort(__LOCATION__, &
     726            0 :                        "K-point OT driver currently supports complex k-point wavefunctions only.")
     727              :       END IF
     728         2590 :       IF (scf_env%qs_ot_env(1)%settings%ot_algorithm /= "TOD" .AND. &
     729              :           scf_env%qs_ot_env(1)%settings%ot_algorithm /= "REF") THEN
     730              :          CALL cp_abort(__LOCATION__, &
     731            0 :                        "K-point OT driver supports OT%ALGORITHM STRICT or IRAC.")
     732              :       END IF
     733         2590 :       kp => kpoints%kp_env(1)%kpoint_env
     734         2590 :       restricted_roks = dft_control%restricted
     735         2590 :       nspin_ot = MERGE(1, SIZE(kp%mos, 2), restricted_roks)
     736         2590 :       nspin_energy = MERGE(SIZE(kp%mos, 2), nspin_ot, restricted_roks)
     737              :       CALL qs_ot_check_channel_context(scf_env%qs_ot_env, nspin_ot, &
     738              :                                        nkpoint=nkpoint, &
     739              :                                        restricted=ANY(scf_env%qs_ot_env(:)%restricted), &
     740              :                                        require_kpoint=.TRUE., &
     741              :                                        kp_range=kp_range, &
     742              :                                        wkp=wkp, &
     743              :                                        require_local_state=.TRUE., &
     744         8000 :                                        require_complex_state=.TRUE.)
     745              : 
     746         2590 :       IF (nkp_groups > 1) THEN
     747          868 :          transfer_step = .FALSE.
     748              :          CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, .FALSE., &
     749          868 :                                  transfer_step, store_ot_matrices=.TRUE., transfer_only=.TRUE.)
     750              :       END IF
     751              : 
     752         2590 :       first_channel = qs_ot_channel_index(1, kp_range(1), nspin_ot)
     753         2590 :       nlocal_channels = SIZE(kpoints%kp_env)*nspin_ot
     754         2590 :       local_ot_env => scf_env%qs_ot_env(first_channel:first_channel + nlocal_channels - 1)
     755         2590 :       local_ot_env(1)%etotal = energy%total
     756              :       physical_base_state = local_ot_env(1)%settings%do_ener .AND. &
     757              :                             .NOT. local_ot_env(1)%energy_only .AND. &
     758              :                             (local_ot_env(1)%line_search_count == 0 .OR. &
     759         2590 :                              local_ot_env(1)%line_search_might_be_done)
     760              : 
     761        12066 :       ALLOCATE (matrix_hc(nlocal_channels))
     762         9476 :       ALLOCATE (matrix_hc_im(nlocal_channels))
     763         2590 :       IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
     764         4536 :          ALLOCATE (matrix_hc_physical(nlocal_channels))
     765         4536 :          ALLOCATE (matrix_hc_physical_im(nlocal_channels))
     766              :       END IF
     767         6886 :       DO local_channel = 1, nlocal_channels
     768         4296 :          NULLIFY (matrix_hc(local_channel)%matrix)
     769         4296 :          NULLIFY (matrix_hc_im(local_channel)%matrix)
     770         4296 :          ALLOCATE (matrix_hc(local_channel)%matrix)
     771         4296 :          ALLOCATE (matrix_hc_im(local_channel)%matrix)
     772         4296 :          CALL dbcsr_copy(matrix_hc(local_channel)%matrix, local_ot_env(local_channel)%matrix_x, name="matrix_hc")
     773              :          CALL dbcsr_copy(matrix_hc_im(local_channel)%matrix, local_ot_env(local_channel)%matrix_x_im, &
     774         4296 :                          name="matrix_hc_im")
     775         4296 :          CALL dbcsr_set(matrix_hc(local_channel)%matrix, 0.0_dp)
     776         4296 :          CALL dbcsr_set(matrix_hc_im(local_channel)%matrix, 0.0_dp)
     777         6886 :          IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
     778         1880 :             NULLIFY (matrix_hc_physical(local_channel)%matrix)
     779         1880 :             NULLIFY (matrix_hc_physical_im(local_channel)%matrix)
     780         1880 :             ALLOCATE (matrix_hc_physical(local_channel)%matrix)
     781         1880 :             ALLOCATE (matrix_hc_physical_im(local_channel)%matrix)
     782              :             CALL dbcsr_copy(matrix_hc_physical(local_channel)%matrix, &
     783         1880 :                             local_ot_env(local_channel)%matrix_x, name="matrix_hc_physical")
     784              :             CALL dbcsr_copy(matrix_hc_physical_im(local_channel)%matrix, &
     785         1880 :                             local_ot_env(local_channel)%matrix_x_im, name="matrix_hc_physical_im")
     786         1880 :             CALL dbcsr_set(matrix_hc_physical(local_channel)%matrix, 0.0_dp)
     787         1880 :             CALL dbcsr_set(matrix_hc_physical_im(local_channel)%matrix, 0.0_dp)
     788              :          END IF
     789              :       END DO
     790              : 
     791         6586 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
     792         3996 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
     793         3996 :          ikpoint = kp%nkpoint
     794         3996 :          CPASSERT(ASSOCIATED(kp%ot_hmat))
     795         3996 :          CPASSERT(SIZE(kp%ot_hmat, 1) >= 2)
     796        10882 :          DO ispin = 1, nspin_ot
     797         4296 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
     798              :             CALL qs_scf_get_ot_kpoint_operator( &
     799              :                matrix_ks, kpoints, kp, MIN(ispin, SIZE(matrix_ks, 1)), &
     800              :                kp%ot_hmat(1, MIN(ispin, SIZE(kp%ot_hmat, 2))), &
     801         4296 :                kp%ot_hmat(2, MIN(ispin, SIZE(kp%ot_hmat, 2))), matrix_k_re, matrix_k_im)
     802         4296 :             IF (physical_base_state .AND. nkp_groups == 1) THEN
     803              :                ! The direct single-group transform bypasses the full-matrix cache.  Synchronize it
     804              :                ! at accepted endpoints so the physical Mermin history sees the H(k) used for H(k)C(k).
     805              :                CALL copy_dbcsr_to_fm( &
     806          874 :                   matrix_k_re, kp%ot_hmat(1, MIN(ispin, SIZE(kp%ot_hmat, 2))))
     807              :                CALL copy_dbcsr_to_fm( &
     808          874 :                   matrix_k_im, kp%ot_hmat(2, MIN(ispin, SIZE(kp%ot_hmat, 2))))
     809              :             END IF
     810              : 
     811              :             CALL get_mo_set(kp%mos(1, ispin), homo=homo, mo_coeff=mo_coeff, nao=nao, nmo=nmo, &
     812         4296 :                             occupation_numbers=occupation_numbers)
     813         4296 :             CALL get_mo_set(kp%mos(2, ispin), mo_coeff=mo_coeff_im)
     814         4296 :             IF (local_ot_env(local_channel)%settings%do_ener) homo = nmo
     815         4296 :             CPASSERT(homo >= 1 .AND. homo <= nmo)
     816         4296 :             IF (.NOT. local_ot_env(local_channel)%settings%do_ener) THEN
     817        21042 :                IF (MAXVAL(ABS(occupation_numbers(1:homo) - occupation_numbers(1))) > &
     818              :                    100.0_dp*EPSILON(1.0_dp)) THEN
     819              :                   CALL cp_abort(__LOCATION__, &
     820            0 :                                 "Fixed-occupation K-point OT requires uniform occupations within each channel.")
     821              :                END IF
     822         2218 :                IF (occupation_numbers(1) <= 100.0_dp*EPSILON(1.0_dp)) THEN
     823              :                   CALL cp_abort(__LOCATION__, &
     824            0 :                                 "Fixed-occupation K-point OT encountered an empty active orbital block.")
     825              :                END IF
     826         2218 :                IF (homo < nmo) THEN
     827          128 :                   IF (MAXVAL(ABS(occupation_numbers(homo + 1:nmo))) > 100.0_dp*EPSILON(1.0_dp)) THEN
     828              :                      CALL cp_abort(__LOCATION__, &
     829            0 :                                    "Fixed-occupation K-point OT cannot optimize occupied padded MO columns.")
     830              :                   END IF
     831              :                END IF
     832              :             END IF
     833              :             CALL cp_fm_struct_create(active_mo_struct, template_fmstruct=mo_coeff%matrix_struct, &
     834         4296 :                                      ncol_global=homo)
     835         4296 :             CALL cp_fm_create(active_mo_coeff, active_mo_struct)
     836         4296 :             CALL cp_fm_create(active_mo_coeff_im, active_mo_struct)
     837         4296 :             CALL cp_fm_to_fm(mo_coeff, active_mo_coeff, homo)
     838         4296 :             CALL cp_fm_to_fm(mo_coeff_im, active_mo_coeff_im, homo)
     839         4296 :             CALL cp_fm_create(hc_re, active_mo_struct)
     840         4296 :             CALL cp_fm_create(hc_im, active_mo_struct)
     841              : 
     842         4296 :             CALL cp_dbcsr_sm_fm_multiply(matrix_k_re, active_mo_coeff, hc_re, homo)
     843              :             CALL cp_dbcsr_sm_fm_multiply(matrix_k_im, active_mo_coeff_im, hc_re, homo, &
     844         4296 :                                          alpha=-1.0_dp, beta=1.0_dp)
     845         4296 :             CALL cp_dbcsr_sm_fm_multiply(matrix_k_re, active_mo_coeff_im, hc_im, homo)
     846              :             CALL cp_dbcsr_sm_fm_multiply(matrix_k_im, active_mo_coeff, hc_im, homo, &
     847         4296 :                                          alpha=1.0_dp, beta=1.0_dp)
     848              : 
     849         4296 :             IF (restricted_roks) THEN
     850              :                ! ROKS has one complex orbital variable but two spin densities. Form the exact
     851              :                ! shared-orbital derivative before handing it to the one-channel OT minimizer.
     852          206 :                IF (local_ot_env(local_channel)%settings%do_ener) THEN
     853              :                   CALL cp_fm_struct_create(chc_struct, template_fmstruct=active_mo_struct, &
     854           32 :                                            nrow_global=homo, ncol_global=homo)
     855           32 :                   CALL cp_fm_create(chc_re, chc_struct)
     856           32 :                   CALL cp_fm_create(chc_im, chc_struct)
     857              :                   CALL multiply_complex_fm_adjoint( &
     858              :                      active_mo_coeff, active_mo_coeff_im, hc_re, hc_im, &
     859           32 :                      chc_re, chc_im, 1.0_dp, 0.0_dp)
     860           32 :                   CALL copy_fm_to_dbcsr(chc_re, local_ot_env(local_channel)%rot_mat_chc)
     861              :                   CALL dbcsr_get_diag(local_ot_env(local_channel)%rot_mat_chc, &
     862           32 :                                       local_ot_env(local_channel)%ener_rayleigh(1:homo))
     863              :                   CALL local_ot_env(local_channel)%para_env%sum( &
     864          640 :                      local_ot_env(local_channel)%ener_rayleigh(1:homo))
     865           32 :                   CALL cp_fm_release(chc_im)
     866           32 :                   CALL cp_fm_release(chc_re)
     867           32 :                   CALL cp_fm_struct_release(chc_struct)
     868              :                END IF
     869          206 :                CALL cp_fm_column_scale(hc_re, occupation_numbers(1:homo))
     870          206 :                CALL cp_fm_column_scale(hc_im, occupation_numbers(1:homo))
     871          206 :                CALL dbcsr_release_p(matrix_k_re)
     872          206 :                CALL dbcsr_release_p(matrix_k_im)
     873              : 
     874              :                CALL qs_scf_get_ot_kpoint_operator( &
     875              :                   matrix_ks, kpoints, kp, 2, kp%ot_hmat(1, 2), kp%ot_hmat(2, 2), &
     876          206 :                   matrix_k_re, matrix_k_im)
     877          206 :                CALL get_mo_set(kp%mos(1, 2), occupation_numbers=occupation_numbers, nmo=nmo)
     878          618 :                ALLOCATE (roks_occupation(homo))
     879          206 :                roks_occupation(:) = 0.0_dp
     880          858 :                roks_occupation(1:MIN(homo, nmo)) = occupation_numbers(1:MIN(homo, nmo))
     881              : 
     882          206 :                CALL cp_fm_create(hc_roks_re, active_mo_struct)
     883          206 :                CALL cp_fm_create(hc_roks_im, active_mo_struct)
     884          206 :                CALL cp_dbcsr_sm_fm_multiply(matrix_k_re, active_mo_coeff, hc_roks_re, homo)
     885              :                CALL cp_dbcsr_sm_fm_multiply(matrix_k_im, active_mo_coeff_im, hc_roks_re, homo, &
     886          206 :                                             alpha=-1.0_dp, beta=1.0_dp)
     887          206 :                CALL cp_dbcsr_sm_fm_multiply(matrix_k_re, active_mo_coeff_im, hc_roks_im, homo)
     888              :                CALL cp_dbcsr_sm_fm_multiply(matrix_k_im, active_mo_coeff, hc_roks_im, homo, &
     889          206 :                                             alpha=1.0_dp, beta=1.0_dp)
     890          206 :                IF (local_ot_env(local_channel)%settings%do_ener) THEN
     891              :                   CALL cp_fm_struct_create(chc_struct, template_fmstruct=active_mo_struct, &
     892           32 :                                            nrow_global=homo, ncol_global=homo)
     893           32 :                   CALL cp_fm_create(chc_re, chc_struct)
     894           32 :                   CALL cp_fm_create(chc_im, chc_struct)
     895              :                   CALL multiply_complex_fm_adjoint( &
     896              :                      active_mo_coeff, active_mo_coeff_im, hc_roks_re, hc_roks_im, &
     897           32 :                      chc_re, chc_im, 1.0_dp, 0.0_dp)
     898           32 :                   CALL copy_fm_to_dbcsr(chc_re, local_ot_env(local_channel)%rot_mat_chc)
     899              :                   CALL dbcsr_get_diag(local_ot_env(local_channel)%rot_mat_chc, &
     900           32 :                                       local_ot_env(local_channel)%ener_rayleigh(homo + 1:2*homo))
     901              :                   CALL local_ot_env(local_channel)%para_env%sum( &
     902          640 :                      local_ot_env(local_channel)%ener_rayleigh(homo + 1:2*homo))
     903           32 :                   CALL cp_fm_release(chc_im)
     904           32 :                   CALL cp_fm_release(chc_re)
     905           32 :                   CALL cp_fm_struct_release(chc_struct)
     906              :                END IF
     907          206 :                CALL cp_fm_column_scale(hc_roks_re, roks_occupation)
     908          206 :                CALL cp_fm_column_scale(hc_roks_im, roks_occupation)
     909          206 :                CALL cp_fm_scale_and_add(1.0_dp, hc_re, 1.0_dp, hc_roks_re)
     910          206 :                CALL cp_fm_scale_and_add(1.0_dp, hc_im, 1.0_dp, hc_roks_im)
     911          206 :                CALL cp_fm_release(hc_roks_re)
     912          206 :                CALL cp_fm_release(hc_roks_im)
     913          618 :                DEALLOCATE (roks_occupation)
     914              :             END IF
     915              : 
     916         4296 :             IF (local_ot_env(local_channel)%settings%do_ener) THEN
     917              :                CALL cp_fm_struct_create(chc_struct, template_fmstruct=active_mo_struct, &
     918         2078 :                                         nrow_global=homo, ncol_global=homo)
     919         2078 :                CALL cp_fm_create(chc_re, chc_struct)
     920         2078 :                CALL cp_fm_create(chc_im, chc_struct)
     921              :                CALL multiply_complex_fm_adjoint( &
     922              :                   active_mo_coeff, active_mo_coeff_im, hc_re, hc_im, &
     923         2078 :                   chc_re, chc_im, 1.0_dp, 0.0_dp)
     924         2078 :                CALL copy_fm_to_dbcsr(chc_re, local_ot_env(local_channel)%rot_mat_chc)
     925         2078 :                CPASSERT(ASSOCIATED(local_ot_env(local_channel)%rot_mat_chc_im))
     926         2078 :                CALL copy_fm_to_dbcsr(chc_im, local_ot_env(local_channel)%rot_mat_chc_im)
     927         2078 :                IF (.NOT. restricted_roks) THEN
     928              :                   CALL dbcsr_get_diag(local_ot_env(local_channel)%rot_mat_chc, &
     929         2046 :                                       local_ot_env(local_channel)%ener_rayleigh)
     930         2046 :                   CPASSERT(ASSOCIATED(local_ot_env(local_channel)%para_env))
     931              :                   CALL local_ot_env(local_channel)%para_env%sum( &
     932        29750 :                      local_ot_env(local_channel)%ener_rayleigh)
     933              :                END IF
     934         2078 :                CALL cp_fm_release(chc_im)
     935         2078 :                CALL cp_fm_release(chc_re)
     936         2078 :                CALL cp_fm_struct_release(chc_struct)
     937              :             END IF
     938              : 
     939         4296 :             CALL copy_fm_to_dbcsr(hc_re, matrix_hc(local_channel)%matrix)
     940         4296 :             CALL copy_fm_to_dbcsr(hc_im, matrix_hc_im(local_channel)%matrix)
     941              : 
     942         4296 :             CALL cp_fm_release(active_mo_coeff)
     943         4296 :             CALL cp_fm_release(active_mo_coeff_im)
     944         4296 :             CALL cp_fm_release(hc_re)
     945         4296 :             CALL cp_fm_release(hc_im)
     946         4296 :             CALL cp_fm_struct_release(active_mo_struct)
     947         4296 :             CALL dbcsr_release_p(matrix_k_re)
     948        21180 :             CALL dbcsr_release_p(matrix_k_im)
     949              :          END DO
     950              :       END DO
     951              : 
     952         2590 :       IF (local_ot_env(1)%settings%do_ener) THEN
     953              :          CALL qs_scf_loop_collect_ot_kp_trial_smearing( &
     954              :             kpoints, local_ot_env, first_channel, nspin_ot, nspin_energy, restricted_roks, &
     955              :             kp_range, wkp, para_env_inter_kp, scf_control%smear, &
     956         1526 :             trial_eigenvalues, trial_occupation, trial_mu, trial_kTS)
     957              :       END IF
     958              : 
     959         6586 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
     960         3996 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
     961         3996 :          ikpoint = kp%nkpoint
     962        10882 :          DO ispin = 1, nspin_ot
     963         4296 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
     964              :             CALL get_mo_set(kp%mos(1, ispin), homo=homo, mo_coeff=mo_coeff, nmo=nmo, &
     965         4296 :                             occupation_numbers=occupation_numbers)
     966         4296 :             CALL get_mo_set(kp%mos(2, ispin), mo_coeff=mo_coeff_im)
     967         4296 :             IF (local_ot_env(local_channel)%settings%do_ener) homo = nmo
     968         4296 :             IF (physical_base_state .AND. .NOT. restricted_roks .AND. &
     969              :                 local_ot_env(local_channel)%settings%occupation_preconditioner) THEN
     970              :                CALL qs_scf_kp_roll_physical_secant( &
     971              :                   local_ot_env(local_channel), mo_coeff, mo_coeff_im, &
     972              :                   kp%ot_hmat(1, MIN(ispin, SIZE(kp%ot_hmat, 2))), &
     973              :                   kp%ot_hmat(2, MIN(ispin, SIZE(kp%ot_hmat, 2))), &
     974          932 :                   trial_occupation(:, ikpoint, ispin))
     975              :             END IF
     976         4296 :             IF (local_ot_env(local_channel)%settings%occupation_preconditioner) THEN
     977              :                CALL dbcsr_copy(matrix_hc_physical(local_channel)%matrix, &
     978         1880 :                                matrix_hc(local_channel)%matrix)
     979              :                CALL dbcsr_copy(matrix_hc_physical_im(local_channel)%matrix, &
     980         1880 :                                matrix_hc_im(local_channel)%matrix)
     981         5640 :                ALLOCATE (orbital_scaling_factor(homo))
     982         1880 :                IF (restricted_roks) THEN
     983          336 :                   orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)
     984              :                ELSE
     985              :                   orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)* &
     986        11344 :                                               trial_occupation(1:homo, ikpoint, ispin)
     987              :                END IF
     988              :                CALL dbcsr_scale_by_vector(matrix_hc_physical(local_channel)%matrix, &
     989         1880 :                                           alpha=orbital_scaling_factor, side='right')
     990              :                CALL dbcsr_scale_by_vector(matrix_hc_physical_im(local_channel)%matrix, &
     991         1880 :                                           alpha=orbital_scaling_factor, side='right')
     992         1880 :                DEALLOCATE (orbital_scaling_factor)
     993              :             END IF
     994        12888 :             ALLOCATE (orbital_scaling_factor(homo))
     995         4296 :             IF (local_ot_env(local_channel)%settings%occupation_preconditioner) THEN
     996        11680 :                orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)
     997         2416 :             ELSE IF (restricted_roks) THEN
     998          522 :                orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)
     999         2242 :             ELSE IF (local_ot_env(local_channel)%settings%do_ener) THEN
    1000              :                orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)* &
    1001         4554 :                                            trial_occupation(1:homo, ikpoint, ispin)
    1002              :             ELSE
    1003        20520 :                orbital_scaling_factor(:) = 2.0_dp*wkp(ikpoint)*occupation_numbers(1:homo)
    1004              :             END IF
    1005              :             CALL dbcsr_scale_by_vector(matrix_hc(local_channel)%matrix, &
    1006         4296 :                                        alpha=orbital_scaling_factor, side='right')
    1007              :             CALL dbcsr_scale_by_vector(matrix_hc_im(local_channel)%matrix, &
    1008         4296 :                                        alpha=orbital_scaling_factor, side='right')
    1009        12588 :             DEALLOCATE (orbital_scaling_factor)
    1010              :          END DO
    1011              :       END DO
    1012              : 
    1013         2590 :       IF (local_ot_env(1)%settings%do_ener) THEN
    1014         1526 :          local_ot_env(1)%etotal = energy%total - energy%kTS + trial_kTS
    1015              :          CALL qs_scf_loop_prepare_ot_kp_energy_gradient( &
    1016              :             kpoints, local_ot_env, first_channel, nspin_ot, nspin_energy, restricted_roks, &
    1017              :             wkp, para_env_inter_kp, scf_control%smear, &
    1018         1526 :             trial_eigenvalues, trial_occupation, trial_mu)
    1019         1526 :          IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
    1020              :             CALL ot_mini_prepare_gradient( &
    1021              :                local_ot_env, matrix_hc, matrix_hc_im=matrix_hc_im, &
    1022              :                matrix_hc_physical=matrix_hc_physical, &
    1023              :                matrix_hc_physical_im=matrix_hc_physical_im, &
    1024         1328 :                para_env_inter_kp=para_env_inter_kp)
    1025              :          ELSE
    1026              :             CALL ot_mini_prepare_gradient( &
    1027              :                local_ot_env, matrix_hc, matrix_hc_im=matrix_hc_im, &
    1028          198 :                para_env_inter_kp=para_env_inter_kp)
    1029              :          END IF
    1030         1526 :          ot_gradient_prepared = .TRUE.
    1031              :          ! A coupled response direction is consumed only when the minimizer starts a new
    1032              :          ! search.  Line-search trial points still need their physical gradient, but rebuilding
    1033              :          ! the dense finite-rotation Hessian there cannot affect the accepted direction.
    1034         1526 :          IF (physical_base_state) THEN
    1035              :             CALL qs_scf_loop_prepare_ot_kp_rotation_response( &
    1036              :                qs_env, kpoints, local_ot_env, first_channel, nspin_ot, restricted_roks, &
    1037              :                wkp, para_env_inter_kp, sab_nl, fmwork, rho_ao_kp, &
    1038          812 :                scf_control%smear, trial_eigenvalues, trial_occupation, trial_mu)
    1039              :          END IF
    1040              :          IF (physical_base_state .AND. &
    1041          812 :              local_ot_env(1)%settings%occupation_preconditioner .AND. &
    1042              :              (local_ot_env(1)%settings%ot_method == "CG" .OR. &
    1043              :               local_ot_env(1)%settings%ot_method == "LBFG")) THEN
    1044          790 :             DO local_channel = 1, nlocal_channels
    1045         1284 :                CALL qs_scf_kp_store_mermin_gradient(local_ot_env(local_channel))
    1046              :             END DO
    1047              :          END IF
    1048              :       END IF
    1049         2590 :       IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
    1050              :          CALL ot_mini(local_ot_env, matrix_hc, matrix_hc_im=matrix_hc_im, &
    1051              :                       matrix_hc_physical=matrix_hc_physical, &
    1052              :                       matrix_hc_physical_im=matrix_hc_physical_im, &
    1053              :                       para_env_inter_kp=para_env_inter_kp, &
    1054         1328 :                       gradient_prepared=ot_gradient_prepared)
    1055              :       ELSE
    1056              :          CALL ot_mini(local_ot_env, matrix_hc, matrix_hc_im=matrix_hc_im, &
    1057              :                       para_env_inter_kp=para_env_inter_kp, &
    1058         1262 :                       gradient_prepared=ot_gradient_prepared)
    1059              :       END IF
    1060         2590 :       scf_env%iter_delta = local_ot_env(1)%delta
    1061         2590 :       energy_only = local_ot_env(1)%energy_only
    1062              : 
    1063         6586 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    1064         3996 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    1065         3996 :          ikpoint = kp%nkpoint
    1066         3996 :          CPASSERT(ASSOCIATED(kp%ot_smat))
    1067         3996 :          CPASSERT(SIZE(kp%ot_smat) >= 2)
    1068              :          CALL qs_scf_get_ot_kpoint_operator(matrix_s, kpoints, kp, 1, &
    1069              :                                             kp%ot_smat(1), kp%ot_smat(2), &
    1070         3996 :                                             matrix_s_re, matrix_s_im)
    1071         8292 :          DO ispin = 1, nspin_ot
    1072         4296 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    1073              :             CALL get_mo_set(kp%mos(1, ispin), homo=homo, mo_coeff=mo_coeff, eigenvalues=eigenvalues, &
    1074         4296 :                             nao=nao, nmo=nmo)
    1075         4296 :             CALL get_mo_set(kp%mos(2, ispin), mo_coeff=mo_coeff_im)
    1076         4296 :             IF (local_ot_env(local_channel)%settings%do_ener) homo = nmo
    1077         1408 :             SELECT CASE (local_ot_env(local_channel)%settings%ot_algorithm)
    1078              :             CASE ("TOD")
    1079              :                CALL qs_ot_get_orbitals_complex(matrix_hc(local_channel)%matrix, &
    1080              :                                                matrix_hc_im(local_channel)%matrix, &
    1081              :                                                matrix_s_re, matrix_s_im, &
    1082         1408 :                                                local_ot_env(local_channel))
    1083              :             CASE ("REF")
    1084              :                CALL qs_ot_get_orbitals_ref_complex(matrix_hc(local_channel)%matrix, &
    1085              :                                                    matrix_hc_im(local_channel)%matrix, &
    1086              :                                                    matrix_s_re, matrix_s_im, &
    1087         2888 :                                                    local_ot_env(local_channel), local_ot_env(1))
    1088              :             CASE DEFAULT
    1089         4296 :                CPABORT("K-point OT orbital update requires ALGORITHM STRICT or IRAC")
    1090              :             END SELECT
    1091              :             CALL cp_fm_struct_create(active_mo_struct, template_fmstruct=mo_coeff%matrix_struct, &
    1092         4296 :                                      ncol_global=homo)
    1093         4296 :             CALL cp_fm_create(active_mo_coeff, active_mo_struct)
    1094         4296 :             CALL cp_fm_create(active_mo_coeff_im, active_mo_struct)
    1095         4296 :             CALL copy_dbcsr_to_fm(matrix_hc(local_channel)%matrix, active_mo_coeff)
    1096         4296 :             CALL copy_dbcsr_to_fm(matrix_hc_im(local_channel)%matrix, active_mo_coeff_im)
    1097         4296 :             CALL cp_fm_to_fm(active_mo_coeff, mo_coeff, homo)
    1098         4296 :             CALL cp_fm_to_fm(active_mo_coeff_im, mo_coeff_im, homo)
    1099         4296 :             IF (local_ot_env(local_channel)%settings%do_ener .AND. .NOT. restricted_roks) THEN
    1100        15898 :                eigenvalues(1:homo) = local_ot_env(local_channel)%ener_x(:)
    1101        29750 :                kp%mos(2, ispin)%eigenvalues(1:homo) = local_ot_env(local_channel)%ener_x(:)
    1102              :             END IF
    1103         4296 :             CALL cp_fm_release(active_mo_coeff)
    1104         4296 :             CALL cp_fm_release(active_mo_coeff_im)
    1105        16884 :             CALL cp_fm_struct_release(active_mo_struct)
    1106              :          END DO
    1107         3996 :          IF (restricted_roks) THEN
    1108          206 :             CPASSERT(SIZE(kp%mos, 2) == 2)
    1109          618 :             DO icomponent = 1, 2
    1110          412 :                CALL get_mo_set(kp%mos(icomponent, 1), mo_coeff=mo_coeff)
    1111          412 :                CALL get_mo_set(kp%mos(icomponent, 2), mo_coeff=mo_coeff_target)
    1112          618 :                CALL cp_fm_to_fm(mo_coeff, mo_coeff_target)
    1113              :             END DO
    1114          206 :             IF (local_ot_env(local_channel)%settings%do_ener) THEN
    1115           96 :                DO energy_spin = 1, nspin_energy
    1116           64 :                   energy_start = (energy_spin - 1)*homo + 1
    1117              :                   kp%mos(1, energy_spin)%eigenvalues(1:homo) = &
    1118         1280 :                      local_ot_env(local_channel)%ener_x(energy_start:energy_start + homo - 1)
    1119              :                   kp%mos(2, energy_spin)%eigenvalues(1:homo) = &
    1120         1312 :                      local_ot_env(local_channel)%ener_x(energy_start:energy_start + homo - 1)
    1121              :                END DO
    1122              :             END IF
    1123              :          END IF
    1124         3996 :          CALL dbcsr_release_p(matrix_s_re)
    1125         6586 :          CALL dbcsr_release_p(matrix_s_im)
    1126              :       END DO
    1127              : 
    1128         2590 :       IF (local_ot_env(1)%settings%do_ener) THEN
    1129              :          CALL kpoint_set_mo_occupation(kpoints, scf_control%smear, &
    1130              :                                        added_mos_auto=scf_control%added_mos_auto, &
    1131              :                                        added_mos_auto_grow=added_mos_auto_grow, &
    1132         1526 :                                        separate_spin_occupations=restricted_roks)
    1133              :       END IF
    1134              : 
    1135         2590 :       IF (ALLOCATED(trial_eigenvalues)) DEALLOCATE (trial_eigenvalues)
    1136         2590 :       IF (ALLOCATED(trial_occupation)) DEALLOCATE (trial_occupation)
    1137         2590 :       IF (ALLOCATED(trial_mu)) DEALLOCATE (trial_mu)
    1138              : 
    1139         2590 :       IF (.NOT. added_mos_auto_grow) THEN
    1140         2584 :          fmwork => scf_env%scf_work1
    1141         2584 :          IF (ASSOCIATED(scf_env%p_mix_new)) THEN
    1142            0 :             density_target => scf_env%p_mix_new
    1143              :          ELSE
    1144         2584 :             CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
    1145         2584 :             density_target => rho_ao_kp
    1146              :          END IF
    1147         2584 :          CALL kpoint_density_matrices(kpoints)
    1148              :          CALL kpoint_density_transform(kpoints, density_target, .FALSE., &
    1149              :                                        matrix_s(1, 1)%matrix, sab_nl, fmwork, &
    1150         2584 :                                        overlap_rs=matrix_s)
    1151              :       END IF
    1152         2590 :       scf_env%iter_method = scf_env%qs_ot_env(first_channel)%OT_METHOD_FULL
    1153         2590 :       scf_env%iter_param = scf_env%qs_ot_env(first_channel)%ds_min
    1154         2590 :       qs_env%broyden_adaptive_sigma = scf_env%qs_ot_env(first_channel)%broyden_adaptive_sigma
    1155              : 
    1156         6886 :       DO local_channel = 1, nlocal_channels
    1157         4296 :          CALL dbcsr_release(matrix_hc(local_channel)%matrix)
    1158         4296 :          CALL dbcsr_release(matrix_hc_im(local_channel)%matrix)
    1159         4296 :          DEALLOCATE (matrix_hc(local_channel)%matrix)
    1160         4296 :          DEALLOCATE (matrix_hc_im(local_channel)%matrix)
    1161         6886 :          IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
    1162         1880 :             CALL dbcsr_release(matrix_hc_physical(local_channel)%matrix)
    1163         1880 :             CALL dbcsr_release(matrix_hc_physical_im(local_channel)%matrix)
    1164         1880 :             DEALLOCATE (matrix_hc_physical(local_channel)%matrix)
    1165         1880 :             DEALLOCATE (matrix_hc_physical_im(local_channel)%matrix)
    1166              :          END IF
    1167              :       END DO
    1168         2590 :       DEALLOCATE (matrix_hc, matrix_hc_im)
    1169         2590 :       IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
    1170         1328 :          DEALLOCATE (matrix_hc_physical, matrix_hc_physical_im)
    1171              :       END IF
    1172              : 
    1173         2590 :       CALL timestop(handle)
    1174              : 
    1175         5180 :    END SUBROUTINE qs_scf_loop_do_ot_kp
    1176              : 
    1177              : ! **************************************************************************************************
    1178              : !> \brief roll one accepted physical K-point Mermin endpoint into a bounded response history
    1179              : !> \param qs_ot_env local spin/K-point OT channel
    1180              : !> \param c_re current real orbital coefficients
    1181              : !> \param c_im current imaginary orbital coefficients
    1182              : !> \param h_re current real self-consistent Hamiltonian
    1183              : !> \param h_im current imaginary self-consistent Hamiltonian
    1184              : !> \param occupation current fixed-N occupations
    1185              : ! **************************************************************************************************
    1186          932 :    SUBROUTINE qs_scf_kp_roll_physical_secant(qs_ot_env, c_re, c_im, h_re, h_im, occupation)
    1187              :       TYPE(qs_ot_type)                                   :: qs_ot_env
    1188              :       TYPE(cp_fm_type), INTENT(IN), TARGET               :: c_re, c_im, h_re, h_im
    1189              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: occupation
    1190              : 
    1191              :       INTEGER                                            :: nmo
    1192              :       LOGICAL                                            :: previous_valid
    1193              : 
    1194          932 :       nmo = SIZE(occupation)
    1195          932 :       CPASSERT(nmo > 0)
    1196              :       previous_valid = qs_ot_env%mermin_physical_ref_valid .AND. &
    1197              :                        ASSOCIATED(qs_ot_env%fm_mermin_c0) .AND. &
    1198              :                        ASSOCIATED(qs_ot_env%fm_mermin_c0_im) .AND. &
    1199              :                        ASSOCIATED(qs_ot_env%fm_mermin_h0) .AND. &
    1200              :                        ASSOCIATED(qs_ot_env%fm_mermin_h0_im) .AND. &
    1201          932 :                        ALLOCATED(qs_ot_env%mermin_occupation0)
    1202          828 :       IF (previous_valid) previous_valid = SIZE(qs_ot_env%mermin_occupation0) == nmo
    1203          104 :       qs_ot_env%mermin_physical_secant_valid = .FALSE.
    1204          828 :       IF (previous_valid) THEN
    1205              :          CALL store_physical_fm_matrix( &
    1206          828 :             qs_ot_env%fm_mermin_c0, qs_ot_env%fm_mermin_c_previous, "mermin_previous_c")
    1207              :          CALL store_physical_fm_matrix( &
    1208          828 :             qs_ot_env%fm_mermin_c0_im, qs_ot_env%fm_mermin_c_previous_im, "mermin_previous_c_im")
    1209          828 :          CALL store_physical_fm_matrix(h_re, qs_ot_env%fm_mermin_y_previous, "mermin_previous_y")
    1210          828 :          CALL store_physical_fm_matrix(h_im, qs_ot_env%fm_mermin_y_previous_im, "mermin_previous_y_im")
    1211              :          CALL cp_fm_scale_and_add( &
    1212          828 :             1.0_dp, qs_ot_env%fm_mermin_y_previous, -1.0_dp, qs_ot_env%fm_mermin_h0)
    1213              :          CALL cp_fm_scale_and_add( &
    1214          828 :             1.0_dp, qs_ot_env%fm_mermin_y_previous_im, -1.0_dp, qs_ot_env%fm_mermin_h0_im)
    1215          828 :          IF (ALLOCATED(qs_ot_env%mermin_occupation_previous)) THEN
    1216          732 :             IF (SIZE(qs_ot_env%mermin_occupation_previous) /= nmo) THEN
    1217            0 :                DEALLOCATE (qs_ot_env%mermin_occupation_previous)
    1218              :             END IF
    1219              :          END IF
    1220          828 :          IF (.NOT. ALLOCATED(qs_ot_env%mermin_occupation_previous)) THEN
    1221          288 :             ALLOCATE (qs_ot_env%mermin_occupation_previous(nmo))
    1222              :          END IF
    1223         5700 :          qs_ot_env%mermin_occupation_previous(:) = qs_ot_env%mermin_occupation0(:)
    1224          828 :          qs_ot_env%mermin_physical_secant_valid = .TRUE.
    1225              :       END IF
    1226              : 
    1227          932 :       CALL store_physical_fm_matrix(c_re, qs_ot_env%fm_mermin_c0, "mermin_c0")
    1228          932 :       CALL store_physical_fm_matrix(c_im, qs_ot_env%fm_mermin_c0_im, "mermin_c0_im")
    1229          932 :       CALL store_physical_fm_matrix(h_re, qs_ot_env%fm_mermin_h0, "mermin_h0")
    1230          932 :       CALL store_physical_fm_matrix(h_im, qs_ot_env%fm_mermin_h0_im, "mermin_h0_im")
    1231          932 :       IF (ALLOCATED(qs_ot_env%mermin_occupation0)) THEN
    1232          828 :          IF (SIZE(qs_ot_env%mermin_occupation0) /= nmo) DEALLOCATE (qs_ot_env%mermin_occupation0)
    1233              :       END IF
    1234         1140 :       IF (.NOT. ALLOCATED(qs_ot_env%mermin_occupation0)) ALLOCATE (qs_ot_env%mermin_occupation0(nmo))
    1235         6404 :       qs_ot_env%mermin_occupation0(:) = occupation(:)
    1236          932 :       qs_ot_env%mermin_physical_ref_valid = .TRUE.
    1237              : 
    1238          932 :    END SUBROUTINE qs_scf_kp_roll_physical_secant
    1239              : 
    1240              : ! **************************************************************************************************
    1241              : !> \brief store the raw physical Mermin gradient at one accepted K-point endpoint
    1242              : !> \param qs_ot_env local spin/K-point OT channel
    1243              : ! **************************************************************************************************
    1244          472 :    SUBROUTINE qs_scf_kp_store_mermin_gradient(qs_ot_env)
    1245              :       TYPE(qs_ot_type)                                   :: qs_ot_env
    1246              : 
    1247          472 :       CPASSERT(ASSOCIATED(qs_ot_env%matrix_mermin_g0))
    1248          472 :       CPASSERT(ASSOCIATED(qs_ot_env%matrix_mermin_g0_im))
    1249          472 :       CPASSERT(ASSOCIATED(qs_ot_env%rot_mat_mermin_g0))
    1250          472 :       CPASSERT(ASSOCIATED(qs_ot_env%rot_mat_mermin_g0_im))
    1251          472 :       CPASSERT(ALLOCATED(qs_ot_env%ener_mermin_g0))
    1252          472 :       CPASSERT(SIZE(qs_ot_env%ener_mermin_g0) == SIZE(qs_ot_env%ener_gx))
    1253              : 
    1254          472 :       CALL dbcsr_copy(qs_ot_env%matrix_mermin_g0, qs_ot_env%matrix_gx)
    1255          472 :       CALL dbcsr_copy(qs_ot_env%matrix_mermin_g0_im, qs_ot_env%matrix_gx_im)
    1256          472 :       CALL dbcsr_copy(qs_ot_env%rot_mat_mermin_g0, qs_ot_env%rot_mat_gx)
    1257          472 :       CALL dbcsr_copy(qs_ot_env%rot_mat_mermin_g0_im, qs_ot_env%rot_mat_gx_im)
    1258         2888 :       qs_ot_env%ener_mermin_g0(:) = qs_ot_env%ener_gx(:)
    1259          472 :       qs_ot_env%mermin_gradient_ref_valid = .TRUE.
    1260              : 
    1261          472 :    END SUBROUTINE qs_scf_kp_store_mermin_gradient
    1262              : 
    1263              : ! **************************************************************************************************
    1264              : !> \brief copy an owned physical full-matrix snapshot, reallocating on shape changes
    1265              : !> \param source transient or persistent source matrix
    1266              : !> \param snapshot owned response-history matrix
    1267              : !> \param name matrix name
    1268              : ! **************************************************************************************************
    1269         7040 :    SUBROUTINE store_physical_fm_matrix(source, snapshot, name)
    1270              :       TYPE(cp_fm_type), INTENT(IN), TARGET               :: source
    1271              :       TYPE(cp_fm_type), INTENT(INOUT), POINTER           :: snapshot
    1272              :       CHARACTER(LEN=*), INTENT(IN)                       :: name
    1273              : 
    1274              :       INTEGER                                            :: ncol_snapshot, ncol_source, &
    1275              :                                                             nrow_snapshot, nrow_source
    1276              :       LOGICAL                                            :: shape_changed
    1277              : 
    1278         7040 :       CALL cp_fm_get_info(source, nrow_global=nrow_source, ncol_global=ncol_source)
    1279         7040 :       shape_changed = .FALSE.
    1280         7040 :       IF (ASSOCIATED(snapshot)) THEN
    1281         6240 :          CALL cp_fm_get_info(snapshot, nrow_global=nrow_snapshot, ncol_global=ncol_snapshot)
    1282         6240 :          shape_changed = nrow_snapshot /= nrow_source .OR. ncol_snapshot /= ncol_source
    1283              :          IF (shape_changed) THEN
    1284            0 :             CALL cp_fm_release(snapshot)
    1285            0 :             DEALLOCATE (snapshot)
    1286              :          END IF
    1287              :       END IF
    1288         7040 :       IF (.NOT. ASSOCIATED(snapshot)) THEN
    1289          800 :          ALLOCATE (snapshot)
    1290          800 :          CALL cp_fm_create(snapshot, source%matrix_struct, name=name)
    1291              :       END IF
    1292         7040 :       CALL cp_fm_to_fm(source, snapshot)
    1293              : 
    1294         7040 :    END SUBROUTINE store_physical_fm_matrix
    1295              : 
    1296              : ! **************************************************************************************************
    1297              : !> \brief project one accepted physical Hxc secant onto current-orbital density tangents
    1298              : !> \param qs_ot_env channel owning the accepted endpoint snapshots
    1299              : !> \param overlap_re real part of the AO overlap matrix
    1300              : !> \param overlap_im imaginary part of the AO overlap matrix
    1301              : !> \param density_modes current-orbital density tangents including the K-point weight
    1302              : !> \param kpoint_weight irreducible K-point weight
    1303              : !> \param density_norm_sq physical density-step norm
    1304              : !> \param response_work density/Hamiltonian response work
    1305              : !> \param density_overlap projections of the density step onto density_modes
    1306              : !> \param response_overlap projections of the Hamiltonian step onto density_modes
    1307              : !> \param valid whether a finite accepted secant was available
    1308              : ! **************************************************************************************************
    1309          238 :    SUBROUTINE qs_scf_kp_physical_secant_overlaps( &
    1310          238 :       qs_ot_env, overlap_re, overlap_im, density_modes, kpoint_weight, density_norm_sq, &
    1311          238 :       response_work, density_overlap, response_overlap, valid)
    1312              : 
    1313              :       TYPE(qs_ot_type), INTENT(IN)                       :: qs_ot_env
    1314              :       TYPE(cp_fm_type), INTENT(IN)                       :: overlap_re, overlap_im
    1315              :       COMPLEX(KIND=dp), DIMENSION(:, :, :), INTENT(IN)   :: density_modes
    1316              :       REAL(KIND=dp), INTENT(IN)                          :: kpoint_weight
    1317              :       REAL(KIND=dp), INTENT(OUT)                         :: density_norm_sq, response_work
    1318              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: density_overlap, response_overlap
    1319              :       LOGICAL, INTENT(OUT)                               :: valid
    1320              : 
    1321          238 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :)     :: hamiltonian_step_current, &
    1322          238 :                                                             hamiltonian_step_previous, &
    1323          238 :                                                             overlap_previous_current
    1324              :       INTEGER                                            :: nmo
    1325          238 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: dense_im, dense_re
    1326              :       TYPE(cp_fm_type)                                   :: action_im, action_re, cross_im, cross_re, &
    1327              :                                                             projection_im, projection_re
    1328              : 
    1329          238 :       nmo = SIZE(density_modes, 1)
    1330            0 :       CPASSERT(nmo > 0)
    1331          238 :       CPASSERT(SIZE(density_modes, 2) == nmo)
    1332          238 :       CPASSERT(SIZE(density_overlap) == SIZE(density_modes, 3))
    1333          238 :       CPASSERT(SIZE(response_overlap) == SIZE(density_modes, 3))
    1334              :       valid = qs_ot_env%mermin_physical_secant_valid .AND. &
    1335              :               ASSOCIATED(qs_ot_env%fm_mermin_c0) .AND. &
    1336              :               ASSOCIATED(qs_ot_env%fm_mermin_c0_im) .AND. &
    1337              :               ASSOCIATED(qs_ot_env%fm_mermin_c_previous) .AND. &
    1338              :               ASSOCIATED(qs_ot_env%fm_mermin_c_previous_im) .AND. &
    1339              :               ASSOCIATED(qs_ot_env%fm_mermin_y_previous) .AND. &
    1340              :               ASSOCIATED(qs_ot_env%fm_mermin_y_previous_im) .AND. &
    1341              :               ALLOCATED(qs_ot_env%mermin_occupation0) .AND. &
    1342          238 :               ALLOCATED(qs_ot_env%mermin_occupation_previous)
    1343          238 :       density_norm_sq = 0.0_dp
    1344          238 :       response_work = 0.0_dp
    1345          714 :       density_overlap(:) = 0.0_dp
    1346          714 :       response_overlap(:) = 0.0_dp
    1347          238 :       IF (.NOT. valid) RETURN
    1348          238 :       CPASSERT(SIZE(qs_ot_env%mermin_occupation0) == nmo)
    1349          238 :       CPASSERT(SIZE(qs_ot_env%mermin_occupation_previous) == nmo)
    1350              : 
    1351              :       CALL cp_fm_create(action_re, qs_ot_env%fm_mermin_c0%matrix_struct, &
    1352          238 :                         name="mermin_hxc_action_re", set_zero=.TRUE.)
    1353              :       CALL cp_fm_create(action_im, qs_ot_env%fm_mermin_c0%matrix_struct, &
    1354          238 :                         name="mermin_hxc_action_im", set_zero=.TRUE.)
    1355              :       CALL cp_fm_create(cross_re, qs_ot_env%fm_mermin_c0%matrix_struct, &
    1356          238 :                         name="mermin_hxc_cross_re", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
    1357              :       CALL cp_fm_create(cross_im, qs_ot_env%fm_mermin_c0%matrix_struct, &
    1358          238 :                         name="mermin_hxc_cross_im", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
    1359              :       CALL cp_fm_create(projection_re, qs_ot_env%fm_mermin_c0%matrix_struct, &
    1360          238 :                         name="mermin_hxc_projection_re", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
    1361              :       CALL cp_fm_create(projection_im, qs_ot_env%fm_mermin_c0%matrix_struct, &
    1362          238 :                         name="mermin_hxc_projection_im", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
    1363              :       ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo), &
    1364              :                 hamiltonian_step_current(nmo, nmo), hamiltonian_step_previous(nmo, nmo), &
    1365         3094 :                 overlap_previous_current(nmo, nmo))
    1366              : 
    1367              :       CALL multiply_complex_fm_nn( &
    1368              :          overlap_re, overlap_im, qs_ot_env%fm_mermin_c0, qs_ot_env%fm_mermin_c0_im, &
    1369          238 :          action_re, action_im, 1.0_dp, 0.0_dp)
    1370              :       CALL multiply_complex_fm_adjoint( &
    1371              :          qs_ot_env%fm_mermin_c_previous, qs_ot_env%fm_mermin_c_previous_im, &
    1372          238 :          action_re, action_im, cross_re, cross_im, 1.0_dp, 0.0_dp)
    1373          238 :       CALL cp_fm_get_submatrix(cross_re, dense_re)
    1374          238 :       CALL cp_fm_get_submatrix(cross_im, dense_im)
    1375         7706 :       overlap_previous_current(:, :) = CMPLX(dense_re, dense_im, KIND=dp)
    1376              : 
    1377              :       CALL project_physical_response( &
    1378              :          qs_ot_env, qs_ot_env%fm_mermin_c0, qs_ot_env%fm_mermin_c0_im, &
    1379          238 :          action_re, action_im, projection_re, projection_im, hamiltonian_step_current)
    1380              :       CALL project_physical_response( &
    1381              :          qs_ot_env, qs_ot_env%fm_mermin_c_previous, qs_ot_env%fm_mermin_c_previous_im, &
    1382          238 :          action_re, action_im, projection_re, projection_im, hamiltonian_step_previous)
    1383              :       CALL qs_ot_density_secant_orbital_overlaps( &
    1384              :          overlap_previous_current, qs_ot_env%mermin_occupation_previous, &
    1385              :          qs_ot_env%mermin_occupation0, hamiltonian_step_previous, hamiltonian_step_current, &
    1386              :          density_modes, kpoint_weight, density_norm_sq, response_work, density_overlap, &
    1387          238 :          response_overlap, valid)
    1388              : 
    1389            0 :       DEALLOCATE (dense_re, dense_im, hamiltonian_step_current, &
    1390          238 :                   hamiltonian_step_previous, overlap_previous_current)
    1391          238 :       CALL cp_fm_release(action_re)
    1392          238 :       CALL cp_fm_release(action_im)
    1393          238 :       CALL cp_fm_release(cross_re)
    1394          238 :       CALL cp_fm_release(cross_im)
    1395          238 :       CALL cp_fm_release(projection_re)
    1396          476 :       CALL cp_fm_release(projection_im)
    1397              : 
    1398              :    CONTAINS
    1399              : 
    1400              : ! **************************************************************************************************
    1401              : !> \brief ...
    1402              : !> \param env ...
    1403              : !> \param c_re ...
    1404              : !> \param c_im ...
    1405              : !> \param action_re ...
    1406              : !> \param action_im ...
    1407              : !> \param projected_re ...
    1408              : !> \param projected_im ...
    1409              : !> \param projected ...
    1410              : ! **************************************************************************************************
    1411          476 :       SUBROUTINE project_physical_response( &
    1412          476 :          env, c_re, c_im, action_re, action_im, projected_re, projected_im, projected)
    1413              :       TYPE(qs_ot_type), INTENT(IN)                       :: env
    1414              :       TYPE(cp_fm_type), INTENT(IN)                       :: c_re, c_im, action_re, action_im, &
    1415              :                                                             projected_re, projected_im
    1416              :       COMPLEX(KIND=dp), DIMENSION(:, :), INTENT(OUT)     :: projected
    1417              : 
    1418              :          CALL multiply_complex_fm_nn( &
    1419              :             env%fm_mermin_y_previous, env%fm_mermin_y_previous_im, c_re, c_im, &
    1420          476 :             action_re, action_im, 1.0_dp, 0.0_dp)
    1421              :          CALL multiply_complex_fm_adjoint( &
    1422          476 :             c_re, c_im, action_re, action_im, projected_re, projected_im, 1.0_dp, 0.0_dp)
    1423          476 :          CALL cp_fm_get_submatrix(projected_re, dense_re)
    1424          476 :          CALL cp_fm_get_submatrix(projected_im, dense_im)
    1425        15412 :          projected(:, :) = CMPLX(dense_re, dense_im, KIND=dp)
    1426        30824 :          projected(:, :) = 0.5_dp*(projected + CONJG(TRANSPOSE(projected)))
    1427          476 :       END SUBROUTINE project_physical_response
    1428              : 
    1429              :    END SUBROUTINE qs_scf_kp_physical_secant_overlaps
    1430              : 
    1431              : ! **************************************************************************************************
    1432              : !> \brief accumulate C=beta*C+alpha*A*B for split-complex distributed full matrices
    1433              : !> \param a_re ...
    1434              : !> \param a_im ...
    1435              : !> \param b_re ...
    1436              : !> \param b_im ...
    1437              : !> \param c_re ...
    1438              : !> \param c_im ...
    1439              : !> \param alpha ...
    1440              : !> \param beta ...
    1441              : ! **************************************************************************************************
    1442         3096 :    SUBROUTINE multiply_complex_fm_nn(a_re, a_im, b_re, b_im, c_re, c_im, alpha, beta)
    1443              :       TYPE(cp_fm_type), INTENT(IN)                       :: a_re, a_im, b_re, b_im, c_re, c_im
    1444              :       REAL(KIND=dp), INTENT(IN)                          :: alpha, beta
    1445              : 
    1446              :       INTEGER                                            :: k, k_b, m, m_c, n, n_c
    1447              : 
    1448         1032 :       CALL cp_fm_get_info(a_re, nrow_global=m, ncol_global=k)
    1449         1032 :       CALL cp_fm_get_info(b_re, nrow_global=k_b, ncol_global=n)
    1450         1032 :       CALL cp_fm_get_info(c_re, nrow_global=m_c, ncol_global=n_c)
    1451         1032 :       CPASSERT(k_b == k .AND. m_c == m .AND. n_c == n)
    1452         1032 :       CALL cp_fm_gemm('N', 'N', m, n, k, alpha, a_re, b_re, beta, c_re)
    1453         1032 :       CALL cp_fm_gemm('N', 'N', m, n, k, -alpha, a_im, b_im, 1.0_dp, c_re)
    1454         1032 :       CALL cp_fm_gemm('N', 'N', m, n, k, alpha, a_re, b_im, beta, c_im)
    1455         1032 :       CALL cp_fm_gemm('N', 'N', m, n, k, alpha, a_im, b_re, 1.0_dp, c_im)
    1456              : 
    1457         1032 :    END SUBROUTINE multiply_complex_fm_nn
    1458              : 
    1459              : ! **************************************************************************************************
    1460              : !> \brief accumulate C=beta*C+alpha*A^H*B for split-complex distributed full matrices
    1461              : !> \param a_re ...
    1462              : !> \param a_im ...
    1463              : !> \param b_re ...
    1464              : !> \param b_im ...
    1465              : !> \param c_re ...
    1466              : !> \param c_im ...
    1467              : !> \param alpha ...
    1468              : !> \param beta ...
    1469              : ! **************************************************************************************************
    1470         9522 :    SUBROUTINE multiply_complex_fm_adjoint(a_re, a_im, b_re, b_im, c_re, c_im, alpha, beta)
    1471              :       TYPE(cp_fm_type), INTENT(IN)                       :: a_re, a_im, b_re, b_im, c_re, c_im
    1472              :       REAL(KIND=dp), INTENT(IN)                          :: alpha, beta
    1473              : 
    1474              :       INTEGER                                            :: k, k_b, m, m_c, n, n_c
    1475              : 
    1476         3174 :       CALL cp_fm_get_info(a_re, nrow_global=k, ncol_global=m)
    1477         3174 :       CALL cp_fm_get_info(b_re, nrow_global=k_b, ncol_global=n)
    1478         3174 :       CALL cp_fm_get_info(c_re, nrow_global=m_c, ncol_global=n_c)
    1479         3174 :       CPASSERT(k_b == k .AND. m_c == m .AND. n_c == n)
    1480         3174 :       CALL cp_fm_gemm('T', 'N', m, n, k, alpha, a_re, b_re, beta, c_re)
    1481         3174 :       CALL cp_fm_gemm('T', 'N', m, n, k, alpha, a_im, b_im, 1.0_dp, c_re)
    1482         3174 :       CALL cp_fm_gemm('T', 'N', m, n, k, alpha, a_re, b_im, beta, c_im)
    1483         3174 :       CALL cp_fm_gemm('T', 'N', m, n, k, -alpha, a_im, b_re, 1.0_dp, c_im)
    1484              : 
    1485         3174 :    END SUBROUTINE multiply_complex_fm_adjoint
    1486              : 
    1487              : ! **************************************************************************************************
    1488              : !> \brief accumulate C=beta*C+alpha*A*B^H for split-complex distributed full matrices
    1489              : !> \param a_re real part of A
    1490              : !> \param a_im imaginary part of A
    1491              : !> \param b_re real part of B
    1492              : !> \param b_im imaginary part of B
    1493              : !> \param c_re real part of C
    1494              : !> \param c_im imaginary part of C
    1495              : !> \param alpha product scaling factor
    1496              : !> \param beta initial C scaling factor
    1497              : ! **************************************************************************************************
    1498          954 :    SUBROUTINE multiply_complex_fm_right_adjoint(a_re, a_im, b_re, b_im, c_re, c_im, alpha, beta)
    1499              :       TYPE(cp_fm_type), INTENT(IN)                       :: a_re, a_im, b_re, b_im, c_re, c_im
    1500              :       REAL(KIND=dp), INTENT(IN)                          :: alpha, beta
    1501              : 
    1502              :       INTEGER                                            :: k, k_b, m, m_c, n, n_c
    1503              : 
    1504          318 :       CALL cp_fm_get_info(a_re, nrow_global=m, ncol_global=k)
    1505          318 :       CALL cp_fm_get_info(b_re, nrow_global=n, ncol_global=k_b)
    1506          318 :       CALL cp_fm_get_info(c_re, nrow_global=m_c, ncol_global=n_c)
    1507          318 :       CPASSERT(k_b == k .AND. m_c == m .AND. n_c == n)
    1508          318 :       CALL cp_fm_gemm('N', 'T', m, n, k, alpha, a_re, b_re, beta, c_re)
    1509          318 :       CALL cp_fm_gemm('N', 'T', m, n, k, alpha, a_im, b_im, 1.0_dp, c_re)
    1510          318 :       CALL cp_fm_gemm('N', 'T', m, n, k, -alpha, a_re, b_im, beta, c_im)
    1511          318 :       CALL cp_fm_gemm('N', 'T', m, n, k, alpha, a_im, b_re, 1.0_dp, c_im)
    1512              : 
    1513          318 :    END SUBROUTINE multiply_complex_fm_right_adjoint
    1514              : 
    1515              : ! **************************************************************************************************
    1516              : !> \brief evaluate the exact GPW Hartree-XC curvature of a complex K-point density mode
    1517              : !> \param qs_env ground-state QS environment defining the current density and XC kernel
    1518              : !> \param kpoints K-point environment and group distribution
    1519              : !> \param local_ot_env local spin/K-point OT channels
    1520              : !> \param first_channel global index of the first local channel
    1521              : !> \param nspin_ot number of physical spin channels
    1522              : !> \param wkp irreducible K-point weights
    1523              : !> \param para_env_inter_kp communicator between distributed K-point groups
    1524              : !> \param sab_nl real-space neighbor lists used by the K-point density transform
    1525              : !> \param fmwork full-matrix workspaces on the global communicator
    1526              : !> \param rho_ao_kp template AO density matrices for the real-space images
    1527              : !> \param channel_density_modes weighted current-orbital density modes per local channel
    1528              : !> \param number_of_modes number of populated modes to apply
    1529              : !> \param projected_hxc projected Hartree-XC Hessian in the supplied density-mode basis
    1530              : !> \param valid whether the projected block is finite and Hermitian within tolerance
    1531              : ! **************************************************************************************************
    1532          116 :    SUBROUTINE qs_scf_kp_exact_hxc_projected( &
    1533              :       qs_env, kpoints, local_ot_env, first_channel, nspin_ot, wkp, para_env_inter_kp, &
    1534          232 :       sab_nl, fmwork, rho_ao_kp, channel_density_modes, number_of_modes, &
    1535          116 :       projected_hxc, valid)
    1536              : 
    1537              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1538              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1539              :       TYPE(qs_ot_type), DIMENSION(:), POINTER            :: local_ot_env
    1540              :       INTEGER, INTENT(IN)                                :: first_channel, nspin_ot
    1541              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    1542              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
    1543              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1544              :          POINTER                                         :: sab_nl
    1545              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    1546              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
    1547              :       COMPLEX(KIND=dp), DIMENSION(:, :, :, :), &
    1548              :          INTENT(IN)                                      :: channel_density_modes
    1549              :       INTEGER, INTENT(IN)                                :: number_of_modes
    1550              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT)        :: projected_hxc
    1551              :       LOGICAL, INTENT(OUT)                               :: valid
    1552              : 
    1553          116 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :)     :: projected
    1554              :       INTEGER :: ikpoint, ispin, local_channel, local_kpoint, nao, nimages, nkp_groups, &
    1555              :          nlocal_kpoints, nmo, nmode, response_mode, test_mode
    1556              :       LOGICAL                                            :: do_hfx
    1557              :       REAL(KIND=dp)                                      :: symmetry_error, symmetry_scale
    1558          116 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: dense_im, dense_re
    1559              :       TYPE(cp_fm_type)                                   :: action_im, action_re, density_im, &
    1560              :                                                             density_re, projected_im, projected_re
    1561          116 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: operator_im, operator_re
    1562          116 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: density_kp
    1563          116 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: density_rs, potential_rs
    1564              :       TYPE(dbcsr_type), POINTER                          :: matrix_k_im, matrix_k_re, template
    1565              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1566              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1567              :       TYPE(qs_kpp1_env_type)                             :: kernel_env
    1568              :       TYPE(section_vals_type), POINTER                   :: hfx_section, input
    1569              : 
    1570          812 :       projected_hxc(:, :) = 0.0_dp
    1571          116 :       symmetry_error = 0.0_dp
    1572          116 :       valid = .FALSE.
    1573          116 :       NULLIFY (density_rs, dft_control, hfx_section, input, matrix_k_im, matrix_k_re, &
    1574          116 :                potential_rs, template)
    1575          116 :       CALL get_qs_env(qs_env, dft_control=dft_control, input=input)
    1576              :       IF (dft_control%qs_control%semi_empirical .OR. dft_control%qs_control%dftb .OR. &
    1577              :           dft_control%qs_control%xtb .OR. dft_control%qs_control%gapw .OR. &
    1578              :           dft_control%qs_control%gapw_xc .OR. dft_control%qs_control%lrigpw .OR. &
    1579          116 :           dft_control%qs_control%rigpw .OR. dft_control%do_admm) RETURN
    1580          116 :       hfx_section => section_vals_get_subs_vals(input, "DFT%XC%HF")
    1581          116 :       CALL section_vals_get(hfx_section, explicit=do_hfx)
    1582          116 :       IF (do_hfx) RETURN
    1583          116 :       CALL get_kpoint_info(kpoints, nkp_groups=nkp_groups)
    1584              : 
    1585          116 :       nlocal_kpoints = SIZE(kpoints%kp_env)
    1586          116 :       nmo = SIZE(channel_density_modes, 1)
    1587          116 :       nmode = number_of_modes
    1588          116 :       nimages = SIZE(rho_ao_kp, 2)
    1589          116 :       CPASSERT(nmo > 0)
    1590          116 :       CPASSERT(nmode > 0 .AND. nmode <= SIZE(channel_density_modes, 3))
    1591          116 :       CPASSERT(SIZE(channel_density_modes, 2) == nmo)
    1592          116 :       CPASSERT(SIZE(channel_density_modes, 4) == SIZE(local_ot_env))
    1593          116 :       CPASSERT(SIZE(projected_hxc, 1) >= nmode .AND. SIZE(projected_hxc, 2) >= nmode)
    1594          116 :       CPASSERT(SIZE(rho_ao_kp, 1) == nspin_ot)
    1595          116 :       CPASSERT(ASSOCIATED(fmwork))
    1596              : 
    1597          116 :       template => rho_ao_kp(1, 1)%matrix
    1598          116 :       CALL cp_fm_get_info(local_ot_env(1)%fm_mermin_c0, nrow_global=nao)
    1599         1356 :       ALLOCATE (operator_re(nlocal_kpoints, nspin_ot), operator_im(nlocal_kpoints, nspin_ot))
    1600          274 :       DO local_kpoint = 1, nlocal_kpoints
    1601          460 :          DO ispin = 1, nspin_ot
    1602              :             local_channel = qs_ot_channel_index( &
    1603              :                             ispin, kpoints%kp_env(local_kpoint)%kpoint_env%nkpoint, nspin_ot) - &
    1604          186 :                             first_channel + 1
    1605              :             CALL cp_fm_create(operator_re(local_kpoint, ispin), &
    1606              :                               local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1607          186 :                               name="hxc_operator_k_re", nrow=nao, ncol=nao, set_zero=.TRUE.)
    1608              :             CALL cp_fm_create(operator_im(local_kpoint, ispin), &
    1609              :                               local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1610          344 :                               name="hxc_operator_k_im", nrow=nao, ncol=nao, set_zero=.TRUE.)
    1611              :          END DO
    1612              :       END DO
    1613         1044 :       ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo), projected(nmo, nmo))
    1614          314 :       DO response_mode = 1, nmode
    1615         2172 :          ALLOCATE (density_kp(nlocal_kpoints, 2, nspin_ot))
    1616          466 :          DO local_kpoint = 1, nlocal_kpoints
    1617          268 :             kp => kpoints%kp_env(local_kpoint)%kpoint_env
    1618          268 :             ikpoint = kp%nkpoint
    1619          784 :             DO ispin = 1, nspin_ot
    1620          318 :                local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    1621          318 :                CPASSERT(ASSOCIATED(local_ot_env(local_channel)%fm_mermin_c0))
    1622          318 :                CPASSERT(ASSOCIATED(local_ot_env(local_channel)%fm_mermin_c0_im))
    1623              :                CALL cp_fm_create(density_re, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1624          318 :                                  name="hxc_density_mode_re", nrow=nmo, ncol=nmo)
    1625              :                CALL cp_fm_create(density_im, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1626          318 :                                  name="hxc_density_mode_im", nrow=nmo, ncol=nmo)
    1627              :                CALL cp_fm_set_submatrix( &
    1628              :                   density_re, REAL(channel_density_modes(:, :, response_mode, local_channel), &
    1629        10194 :                                    KIND=dp)/wkp(ikpoint))
    1630              :                CALL cp_fm_set_submatrix( &
    1631              :                   density_im, AIMAG(channel_density_modes(:, :, response_mode, local_channel))/ &
    1632        10194 :                   wkp(ikpoint))
    1633              :                CALL cp_fm_create(action_re, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1634          318 :                                  name="hxc_density_action_re", set_zero=.TRUE.)
    1635              :                CALL cp_fm_create(action_im, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1636          318 :                                  name="hxc_density_action_im", set_zero=.TRUE.)
    1637              :                CALL multiply_complex_fm_nn( &
    1638              :                   local_ot_env(local_channel)%fm_mermin_c0, &
    1639              :                   local_ot_env(local_channel)%fm_mermin_c0_im, density_re, density_im, &
    1640          318 :                   action_re, action_im, 1.0_dp, 0.0_dp)
    1641          318 :                CALL cp_fm_get_info(local_ot_env(local_channel)%fm_mermin_c0, nrow_global=nao)
    1642              :                CALL cp_fm_create(density_kp(local_kpoint, 1, ispin), &
    1643              :                                  local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1644          318 :                                  name="hxc_density_k_re", nrow=nao, ncol=nao, set_zero=.TRUE.)
    1645              :                CALL cp_fm_create(density_kp(local_kpoint, 2, ispin), &
    1646              :                                  local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1647          318 :                                  name="hxc_density_k_im", nrow=nao, ncol=nao, set_zero=.TRUE.)
    1648              :                CALL multiply_complex_fm_right_adjoint( &
    1649              :                   action_re, action_im, local_ot_env(local_channel)%fm_mermin_c0, &
    1650              :                   local_ot_env(local_channel)%fm_mermin_c0_im, &
    1651              :                   density_kp(local_kpoint, 1, ispin), density_kp(local_kpoint, 2, ispin), &
    1652          318 :                   1.0_dp, 0.0_dp)
    1653          318 :                CALL cp_fm_release(action_re)
    1654          318 :                CALL cp_fm_release(action_im)
    1655          318 :                CALL cp_fm_release(density_re)
    1656         1222 :                CALL cp_fm_release(density_im)
    1657              :             END DO
    1658              :          END DO
    1659              : 
    1660          198 :          CALL dbcsr_allocate_matrix_set(density_rs, nspin_ot, nimages)
    1661          446 :          DO ispin = 1, nspin_ot
    1662        54270 :             DO local_kpoint = 1, nimages
    1663        53824 :                ALLOCATE (density_rs(ispin, local_kpoint)%matrix)
    1664              :                CALL dbcsr_copy(density_rs(ispin, local_kpoint)%matrix, &
    1665        53824 :                                rho_ao_kp(ispin, local_kpoint)%matrix, name="Hxc density response")
    1666        54072 :                CALL dbcsr_set(density_rs(ispin, local_kpoint)%matrix, 0.0_dp)
    1667              :             END DO
    1668              :          END DO
    1669              :          CALL kpoint_density_transform(kpoints, density_rs, .FALSE., template, sab_nl, fmwork, &
    1670          198 :                                        pmat_ext=density_kp)
    1671          466 :          DO local_kpoint = 1, nlocal_kpoints
    1672          784 :             DO ispin = 1, nspin_ot
    1673          318 :                CALL cp_fm_release(density_kp(local_kpoint, 1, ispin))
    1674          586 :                CALL cp_fm_release(density_kp(local_kpoint, 2, ispin))
    1675              :             END DO
    1676              :          END DO
    1677          198 :          DEALLOCATE (density_kp)
    1678              : 
    1679          198 :          CALL apply_hxc_kernel_kp(qs_env, kernel_env, density_rs, potential_rs)
    1680          198 :          IF (nkp_groups > 1) THEN
    1681              :             CALL qs_scf_distribute_kpoint_operator( &
    1682           56 :                potential_rs, kpoints, fmwork, operator_re, operator_im)
    1683              :          END IF
    1684          466 :          DO local_kpoint = 1, nlocal_kpoints
    1685          268 :             kp => kpoints%kp_env(local_kpoint)%kpoint_env
    1686          268 :             ikpoint = kp%nkpoint
    1687          784 :             DO ispin = 1, nspin_ot
    1688          318 :                local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    1689              :                CALL cp_fm_create(action_re, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1690          318 :                                  name="hxc_potential_action_re", set_zero=.TRUE.)
    1691              :                CALL cp_fm_create(action_im, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1692          318 :                                  name="hxc_potential_action_im", set_zero=.TRUE.)
    1693              :                CALL qs_scf_get_ot_kpoint_operator( &
    1694              :                   potential_rs, kpoints, kp, ispin, operator_re(local_kpoint, ispin), &
    1695          318 :                   operator_im(local_kpoint, ispin), matrix_k_re, matrix_k_im)
    1696              :                CALL cp_dbcsr_sm_fm_multiply( &
    1697          318 :                   matrix_k_re, local_ot_env(local_channel)%fm_mermin_c0, action_re, nmo)
    1698              :                CALL cp_dbcsr_sm_fm_multiply( &
    1699              :                   matrix_k_im, local_ot_env(local_channel)%fm_mermin_c0_im, action_re, nmo, &
    1700          318 :                   alpha=-1.0_dp, beta=1.0_dp)
    1701              :                CALL cp_dbcsr_sm_fm_multiply( &
    1702          318 :                   matrix_k_re, local_ot_env(local_channel)%fm_mermin_c0_im, action_im, nmo)
    1703              :                CALL cp_dbcsr_sm_fm_multiply( &
    1704              :                   matrix_k_im, local_ot_env(local_channel)%fm_mermin_c0, action_im, nmo, &
    1705          318 :                   alpha=1.0_dp, beta=1.0_dp)
    1706              :                CALL cp_fm_create(projected_re, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1707          318 :                                  name="hxc_projected_re", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
    1708              :                CALL cp_fm_create(projected_im, local_ot_env(local_channel)%fm_mermin_c0%matrix_struct, &
    1709          318 :                                  name="hxc_projected_im", nrow=nmo, ncol=nmo, set_zero=.TRUE.)
    1710              :                CALL multiply_complex_fm_adjoint( &
    1711              :                   local_ot_env(local_channel)%fm_mermin_c0, &
    1712              :                   local_ot_env(local_channel)%fm_mermin_c0_im, action_re, action_im, &
    1713          318 :                   projected_re, projected_im, 1.0_dp, 0.0_dp)
    1714          318 :                CALL cp_fm_get_submatrix(projected_re, dense_re)
    1715          318 :                CALL cp_fm_get_submatrix(projected_im, dense_im)
    1716        10194 :                projected(:, :) = CMPLX(dense_re, dense_im, KIND=dp)
    1717          900 :                DO test_mode = 1, nmode
    1718              :                   projected_hxc(test_mode, response_mode) = &
    1719              :                      projected_hxc(test_mode, response_mode) + REAL(SUM( &
    1720        18904 :                                                    CONJG(channel_density_modes(:, :, test_mode, local_channel))*projected), KIND=dp)
    1721              :                END DO
    1722          318 :                CALL cp_fm_release(projected_re)
    1723          318 :                CALL cp_fm_release(projected_im)
    1724          318 :                CALL cp_fm_release(action_re)
    1725          318 :                CALL cp_fm_release(action_im)
    1726          318 :                CALL dbcsr_release_p(matrix_k_re)
    1727          586 :                CALL dbcsr_release_p(matrix_k_im)
    1728              :             END DO
    1729              :          END DO
    1730          198 :          CALL dbcsr_deallocate_matrix_set(density_rs)
    1731          198 :          CALL dbcsr_deallocate_matrix_set(potential_rs)
    1732          314 :          NULLIFY (density_rs, potential_rs)
    1733              :       END DO
    1734              : 
    1735         1508 :       CALL para_env_inter_kp%sum(projected_hxc)
    1736              :       symmetry_error = MAXVAL(ABS( &
    1737              :                               projected_hxc(1:nmode, 1:nmode) - &
    1738          676 :                               TRANSPOSE(projected_hxc(1:nmode, 1:nmode))))
    1739              :       symmetry_scale = MAX(SQRT(EPSILON(1.0_dp)), &
    1740          676 :                            MAXVAL(ABS(projected_hxc(1:nmode, 1:nmode))))
    1741              :       projected_hxc(1:nmode, 1:nmode) = 0.5_dp*( &
    1742              :                                         projected_hxc(1:nmode, 1:nmode) + &
    1743         1236 :                                         TRANSPOSE(projected_hxc(1:nmode, 1:nmode)))
    1744              :       valid = ALL(ieee_is_finite(projected_hxc(1:nmode, 1:nmode))) .AND. &
    1745              :               ieee_is_finite(symmetry_error) .AND. &
    1746          676 :               symmetry_error <= 1.0E-10_dp*symmetry_scale
    1747              : 
    1748          116 :       DEALLOCATE (dense_re, dense_im, projected)
    1749          274 :       DO local_kpoint = 1, nlocal_kpoints
    1750          460 :          DO ispin = 1, nspin_ot
    1751          186 :             CALL cp_fm_release(operator_re(local_kpoint, ispin))
    1752          344 :             CALL cp_fm_release(operator_im(local_kpoint, ispin))
    1753              :          END DO
    1754              :       END DO
    1755          116 :       DEALLOCATE (operator_re, operator_im)
    1756          116 :       CALL kpp1_release(kernel_env)
    1757              : 
    1758          464 :    END SUBROUTINE qs_scf_kp_exact_hxc_projected
    1759              : 
    1760              : ! **************************************************************************************************
    1761              : !> \brief collect the global fixed-N trial smearing state used by k-point OT
    1762              : !> \param kpoints ...
    1763              : !> \param local_ot_env ...
    1764              : !> \param first_channel ...
    1765              : !> \param nspin_ot ...
    1766              : !> \param nspin_energy number of physical spin-resolved auxiliary-energy blocks
    1767              : !> \param restricted_roks whether both energy blocks share one orbital channel
    1768              : !> \param kp_range ...
    1769              : !> \param wkp ...
    1770              : !> \param para_env_inter_kp ...
    1771              : !> \param smear ...
    1772              : !> \param trial_eigenvalues ...
    1773              : !> \param trial_occupation ...
    1774              : !> \param trial_mu chemical potential for each spin channel
    1775              : !> \param trial_kTS ...
    1776              : ! **************************************************************************************************
    1777         1526 :    SUBROUTINE qs_scf_loop_collect_ot_kp_trial_smearing( &
    1778              :       kpoints, local_ot_env, first_channel, nspin_ot, nspin_energy, restricted_roks, &
    1779              :       kp_range, wkp, para_env_inter_kp, smear, trial_eigenvalues, trial_occupation, trial_mu, trial_kTS)
    1780              : 
    1781              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1782              :       TYPE(qs_ot_type), DIMENSION(:), POINTER            :: local_ot_env
    1783              :       INTEGER, INTENT(IN)                                :: first_channel, nspin_ot, nspin_energy
    1784              :       LOGICAL, INTENT(IN)                                :: restricted_roks
    1785              :       INTEGER, DIMENSION(2), INTENT(IN)                  :: kp_range
    1786              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    1787              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
    1788              :       TYPE(smear_type), INTENT(IN)                       :: smear
    1789              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    1790              :          INTENT(OUT)                                     :: trial_eigenvalues, trial_occupation
    1791              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    1792              :          INTENT(OUT)                                     :: trial_mu
    1793              :       REAL(KIND=dp), INTENT(OUT)                         :: trial_kTS
    1794              : 
    1795              :       INTEGER                                            :: energy_start, ikpoint, ispin, &
    1796              :                                                             local_channel, local_kpoint, ne_a, &
    1797              :                                                             ne_b, nelectron, nkpoint, nmo
    1798              :       REAL(KIND=dp)                                      :: kTS, mu, nel, sigma
    1799              :       REAL(KIND=dp), DIMENSION(2)                        :: mus
    1800              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1801              : 
    1802         1526 :       CPASSERT(smear%do_smear)
    1803         2902 :       SELECT CASE (smear%method)
    1804              :       CASE (smear_fermi_dirac)
    1805         1376 :          sigma = smear%electronic_temperature
    1806              :       CASE (smear_gaussian, smear_mp, smear_mv)
    1807          150 :          sigma = smear%smearing_width
    1808              :       CASE DEFAULT
    1809         1526 :          CPABORT("K-point Mermin OT does not support the selected smearing method")
    1810              :       END SELECT
    1811         1526 :       CPASSERT(sigma > EPSILON(sigma))
    1812         1526 :       CPASSERT(ASSOCIATED(para_env_inter_kp))
    1813         1526 :       CALL get_kpoint_info(kpoints, nkp=nkpoint)
    1814         1526 :       kp => kpoints%kp_env(1)%kpoint_env
    1815         1526 :       CALL get_mo_set(kp%mos(1, 1), nelectron=nelectron, nmo=nmo)
    1816         1526 :       ne_a = nelectron
    1817         1526 :       ne_b = 0
    1818         1526 :       IF (nspin_energy == 2) CALL get_mo_set(kp%mos(1, 2), nelectron=ne_b)
    1819              : 
    1820         7630 :       ALLOCATE (trial_eigenvalues(nmo, nkpoint, nspin_energy))
    1821         6104 :       ALLOCATE (trial_occupation(nmo, nkpoint, nspin_energy))
    1822         4578 :       ALLOCATE (trial_mu(nspin_energy))
    1823         1526 :       trial_eigenvalues(:, :, :) = 0.0_dp
    1824         1526 :       trial_occupation(:, :, :) = 0.0_dp
    1825         1526 :       mus(:) = 0.0_dp
    1826              : 
    1827         3368 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    1828         1842 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    1829         1842 :          ikpoint = kp%nkpoint
    1830         1842 :          CPASSERT(ikpoint >= kp_range(1) .AND. ikpoint <= kp_range(2))
    1831         5478 :          DO ispin = 1, nspin_energy
    1832              :             local_channel = qs_ot_channel_index(MERGE(1, ispin, restricted_roks), &
    1833         4156 :                                                 ikpoint, nspin_ot) - first_channel + 1
    1834         2110 :             energy_start = 1
    1835         2110 :             IF (restricted_roks) energy_start = (ispin - 1)*nmo + 1
    1836              :             trial_eigenvalues(1:nmo, ikpoint, ispin) = &
    1837        18412 :                local_ot_env(local_channel)%ener_x(energy_start:energy_start + nmo - 1)
    1838              :          END DO
    1839              :       END DO
    1840         1526 :       CALL para_env_inter_kp%sum(trial_eigenvalues)
    1841              : 
    1842         1526 :       IF (nspin_energy == 1) THEN
    1843         1258 :          nel = REAL(nelectron, KIND=dp)
    1844              :          CALL Smearkp(trial_occupation(:, :, 1), mus(1), trial_kTS, &
    1845         1258 :                       trial_eigenvalues(:, :, 1), nel, wkp, sigma, 2.0_dp, smear%method)
    1846          268 :       ELSE IF (restricted_roks .OR. smear%fixed_mag_mom > 0.0_dp) THEN
    1847           76 :          nel = REAL(ne_a, KIND=dp)
    1848              :          CALL Smearkp(trial_occupation(:, :, 1), mus(1), kTS, &
    1849           76 :                       trial_eigenvalues(:, :, 1), nel, wkp, sigma, 1.0_dp, smear%method)
    1850           76 :          trial_kTS = kTS
    1851           76 :          nel = REAL(ne_b, KIND=dp)
    1852              :          CALL Smearkp(trial_occupation(:, :, 2), mus(2), kTS, &
    1853           76 :                       trial_eigenvalues(:, :, 2), nel, wkp, sigma, 1.0_dp, smear%method)
    1854           76 :          trial_kTS = trial_kTS + kTS
    1855              :       ELSE
    1856          192 :          nel = REAL(ne_a + ne_b, KIND=dp)
    1857              :          CALL Smearkp2(trial_occupation, mu, trial_kTS, trial_eigenvalues, nel, wkp, &
    1858          192 :                        sigma, smear%method)
    1859          576 :          mus(1:2) = mu
    1860              :       END IF
    1861         3320 :       trial_mu(:) = mus(1:nspin_energy)
    1862         1526 :    END SUBROUTINE qs_scf_loop_collect_ot_kp_trial_smearing
    1863              : 
    1864              : ! **************************************************************************************************
    1865              : !> \brief construct auxiliary-energy gradients on the global fixed-N Mermin surface
    1866              : !> \param kpoints ...
    1867              : !> \param local_ot_env ...
    1868              : !> \param first_channel ...
    1869              : !> \param nspin_ot ...
    1870              : !> \param nspin_energy ...
    1871              : !> \param restricted_roks ...
    1872              : !> \param wkp ...
    1873              : !> \param para_env_inter_kp ...
    1874              : !> \param smear ...
    1875              : !> \param trial_eigenvalues ...
    1876              : !> \param trial_occupation ...
    1877              : !> \param trial_mu ...
    1878              : ! **************************************************************************************************
    1879         1526 :    SUBROUTINE qs_scf_loop_prepare_ot_kp_energy_gradient( &
    1880              :       kpoints, local_ot_env, first_channel, nspin_ot, nspin_energy, restricted_roks, &
    1881         1526 :       wkp, para_env_inter_kp, smear, trial_eigenvalues, trial_occupation, trial_mu)
    1882              : 
    1883              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1884              :       TYPE(qs_ot_type), DIMENSION(:), POINTER            :: local_ot_env
    1885              :       INTEGER, INTENT(IN)                                :: first_channel, nspin_ot, nspin_energy
    1886              :       LOGICAL, INTENT(IN)                                :: restricted_roks
    1887              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    1888              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
    1889              :       TYPE(smear_type), INTENT(IN)                       :: smear
    1890              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: trial_eigenvalues, trial_occupation
    1891              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: trial_mu
    1892              : 
    1893              :       INTEGER                                            :: energy_start, group, ikpoint, imo, &
    1894              :                                                             ispin, local_channel, local_kpoint, &
    1895              :                                                             ngroups, nmo
    1896              :       REAL(KIND=dp)                                      :: fixed_n_mean, maxocc, sigma
    1897         1526 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: fixed_n_residual, fixed_n_weight, &
    1898         1526 :                                                             preconditioner_count, &
    1899         1526 :                                                             preconditioner_shift, response_weight
    1900              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1901              : 
    1902         1526 :       IF (.NOT. local_ot_env(1)%settings%do_ener) RETURN
    1903              : 
    1904         1526 :       CPASSERT(smear%do_smear)
    1905         1526 :       CPASSERT(ASSOCIATED(para_env_inter_kp))
    1906         2902 :       SELECT CASE (smear%method)
    1907              :       CASE (smear_fermi_dirac)
    1908         1376 :          sigma = smear%electronic_temperature
    1909              :       CASE (smear_gaussian, smear_mp, smear_mv)
    1910          150 :          sigma = smear%smearing_width
    1911              :       CASE DEFAULT
    1912         1526 :          CPABORT("K-point Mermin OT does not support the selected smearing method")
    1913              :       END SELECT
    1914         1526 :       CPASSERT(sigma > EPSILON(sigma))
    1915              : 
    1916         1526 :       ngroups = 1
    1917         1526 :       IF (restricted_roks .OR. &
    1918           76 :           (nspin_energy == 2 .AND. smear%fixed_mag_mom > 0.0_dp)) ngroups = 2
    1919         1526 :       nmo = SIZE(trial_eigenvalues, 1)
    1920              :       ALLOCATE (fixed_n_residual(ngroups), fixed_n_weight(ngroups), &
    1921              :                 preconditioner_count(ngroups), preconditioner_shift(ngroups), &
    1922        10682 :                 response_weight(nmo))
    1923         1526 :       fixed_n_residual(:) = 0.0_dp
    1924         1526 :       fixed_n_weight(:) = 0.0_dp
    1925         1526 :       preconditioner_count(:) = 0.0_dp
    1926         1526 :       preconditioner_shift(:) = 0.0_dp
    1927              : 
    1928         3368 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    1929         1842 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    1930         1842 :          ikpoint = kp%nkpoint
    1931         5478 :          DO ispin = 1, nspin_energy
    1932         2110 :             group = MERGE(ispin, 1, ngroups == nspin_energy)
    1933              :             local_channel = qs_ot_channel_index(MERGE(1, ispin, restricted_roks), &
    1934         4156 :                                                 ikpoint, nspin_ot) - first_channel + 1
    1935         2110 :             energy_start = 1
    1936         2110 :             IF (restricted_roks) energy_start = (ispin - 1)*nmo + 1
    1937         2110 :             CALL get_mo_set(kp%mos(1, ispin), maxocc=maxocc, nmo=nmo)
    1938         2110 :             CPASSERT(maxocc > EPSILON(maxocc))
    1939         2110 :             CPASSERT(energy_start + nmo - 1 <= SIZE(local_ot_env(local_channel)%ener_x))
    1940              :             CALL smearing_response_weight( &
    1941              :                response_weight, trial_occupation(:, ikpoint, ispin), &
    1942              :                trial_eigenvalues(:, ikpoint, ispin), trial_mu(ispin), sigma, maxocc, nmo, &
    1943         2110 :                smear%method)
    1944        16570 :             response_weight(:) = wkp(ikpoint)*response_weight
    1945        20522 :             DO imo = 1, nmo
    1946              :                fixed_n_weight(group) = fixed_n_weight(group) + &
    1947        14460 :                                        response_weight(imo)
    1948              :                fixed_n_residual(group) = fixed_n_residual(group) + &
    1949              :                                          response_weight(imo)* &
    1950              :                                          (local_ot_env(local_channel)%ener_rayleigh(energy_start + imo - 1) - &
    1951        16570 :                                           trial_eigenvalues(imo, ikpoint, ispin))
    1952              :             END DO
    1953              :          END DO
    1954              :       END DO
    1955         1526 :       CALL para_env_inter_kp%sum(fixed_n_weight)
    1956         1526 :       CALL para_env_inter_kp%sum(fixed_n_residual)
    1957              : 
    1958         1526 :       IF (local_ot_env(1)%settings%occupation_preconditioner) THEN
    1959         2972 :          DO local_kpoint = 1, SIZE(kpoints%kp_env)
    1960         1644 :             kp => kpoints%kp_env(local_kpoint)%kpoint_env
    1961         1644 :             ikpoint = kp%nkpoint
    1962         4884 :             DO ispin = 1, nspin_energy
    1963         1912 :                group = MERGE(ispin, 1, ngroups == nspin_energy)
    1964              :                local_channel = qs_ot_channel_index(MERGE(1, ispin, restricted_roks), &
    1965         3760 :                                                    ikpoint, nspin_ot) - first_channel + 1
    1966         1912 :                CALL get_mo_set(kp%mos(1, ispin), nmo=nmo)
    1967         1912 :                energy_start = 1
    1968         1912 :                IF (restricted_roks) energy_start = (ispin - 1)*nmo + 1
    1969         1912 :                fixed_n_mean = 0.0_dp
    1970         1912 :                IF (ABS(fixed_n_weight(group)) > EPSILON(fixed_n_weight(group))) THEN
    1971         1868 :                   fixed_n_mean = fixed_n_residual(group)/fixed_n_weight(group)
    1972              :                END IF
    1973              :                local_ot_env(local_channel)%ener_preconditioned_gx( &
    1974              :                   energy_start:energy_start + nmo - 1) = fixed_n_mean - &
    1975              :                                                       (local_ot_env(local_channel)%ener_rayleigh( &
    1976              :                                                        energy_start:energy_start + nmo - 1) - &
    1977        12016 :                                                        trial_eigenvalues(:, ikpoint, ispin))
    1978              :                preconditioner_shift(group) = preconditioner_shift(group) + &
    1979              :                                              SUM(local_ot_env(local_channel)%ener_preconditioned_gx( &
    1980        12016 :                                                  energy_start:energy_start + nmo - 1))
    1981         5468 :                preconditioner_count(group) = preconditioner_count(group) + REAL(nmo, KIND=dp)
    1982              :             END DO
    1983              :          END DO
    1984         1328 :          CALL para_env_inter_kp%sum(preconditioner_shift)
    1985         1328 :          CALL para_env_inter_kp%sum(preconditioner_count)
    1986              :       END IF
    1987              : 
    1988         3368 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    1989         1842 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    1990         1842 :          ikpoint = kp%nkpoint
    1991         5478 :          DO ispin = 1, nspin_energy
    1992         2110 :             group = MERGE(ispin, 1, ngroups == nspin_energy)
    1993              :             local_channel = qs_ot_channel_index(MERGE(1, ispin, restricted_roks), &
    1994         4156 :                                                 ikpoint, nspin_ot) - first_channel + 1
    1995         2110 :             CALL get_mo_set(kp%mos(1, ispin), maxocc=maxocc, nmo=nmo)
    1996         2110 :             energy_start = 1
    1997         2110 :             IF (restricted_roks) energy_start = (ispin - 1)*nmo + 1
    1998         2110 :             IF (local_ot_env(local_channel)%settings%occupation_preconditioner .AND. &
    1999              :                 preconditioner_count(group) > 0.0_dp) THEN
    2000              :                local_ot_env(local_channel)%ener_preconditioned_gx( &
    2001              :                   energy_start:energy_start + nmo - 1) = &
    2002              :                   local_ot_env(local_channel)%ener_preconditioned_gx( &
    2003              :                   energy_start:energy_start + nmo - 1) - &
    2004        12016 :                   preconditioner_shift(group)/preconditioner_count(group)
    2005              :             END IF
    2006              :             CALL smearing_response_weight( &
    2007              :                response_weight, trial_occupation(:, ikpoint, ispin), &
    2008              :                trial_eigenvalues(:, ikpoint, ispin), trial_mu(ispin), sigma, maxocc, nmo, &
    2009         2110 :                smear%method)
    2010        16570 :             response_weight(:) = wkp(ikpoint)*response_weight
    2011              :             CALL qs_ot_fixed_n_energy_gradient( &
    2012              :                local_ot_env(local_channel)%ener_rayleigh(energy_start:energy_start + nmo - 1), &
    2013              :                trial_eigenvalues(:, ikpoint, ispin), &
    2014              :                response_weight, fixed_n_weight(group), fixed_n_residual(group), &
    2015         6062 :                local_ot_env(local_channel)%ener_gx(energy_start:energy_start + nmo - 1))
    2016              :          END DO
    2017              :       END DO
    2018              : 
    2019            0 :       DEALLOCATE (fixed_n_residual, fixed_n_weight, preconditioner_count, preconditioner_shift, &
    2020         1526 :                   response_weight)
    2021              : 
    2022         1526 :    END SUBROUTINE qs_scf_loop_prepare_ot_kp_energy_gradient
    2023              : 
    2024              : ! **************************************************************************************************
    2025              : !> \brief build a coupled finite-complex rotation/energy preconditioner for K-point Mermin OT
    2026              : !> \param qs_env ground-state QS environment defining the current density and XC kernel
    2027              : !> \param kpoints K-point environment
    2028              : !> \param local_ot_env local spin/K-point OT channels
    2029              : !> \param first_channel global index of the first local channel
    2030              : !> \param nspin_ot number of spin channels
    2031              : !> \param restricted_roks whether two physical spin densities share each orbital channel
    2032              : !> \param wkp irreducible K-point weights
    2033              : !> \param para_env_inter_kp communicator between distributed K-point groups
    2034              : !> \param sab_nl real-space neighbor lists used by the K-point density transform
    2035              : !> \param fmwork full-matrix workspaces on the global communicator
    2036              : !> \param rho_ao_kp template AO density matrices for the real-space images
    2037              : !> \param smear smearing settings
    2038              : !> \param trial_eigenvalues current auxiliary band energies
    2039              : !> \param trial_occupation current fixed-N occupations
    2040              : !> \param trial_mu chemical potential for each spin channel
    2041              : ! **************************************************************************************************
    2042          812 :    SUBROUTINE qs_scf_loop_prepare_ot_kp_rotation_response( &
    2043              :       qs_env, kpoints, local_ot_env, first_channel, nspin_ot, restricted_roks, &
    2044              :       wkp, para_env_inter_kp, sab_nl, fmwork, rho_ao_kp, smear, &
    2045          812 :       trial_eigenvalues, trial_occupation, trial_mu)
    2046              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2047              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2048              :       TYPE(qs_ot_type), DIMENSION(:), POINTER            :: local_ot_env
    2049              :       INTEGER, INTENT(IN)                                :: first_channel, nspin_ot
    2050              :       LOGICAL, INTENT(IN)                                :: restricted_roks
    2051              :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    2052              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
    2053              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2054              :          POINTER                                         :: sab_nl
    2055              :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    2056              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
    2057              :       TYPE(smear_type), INTENT(IN)                       :: smear
    2058              :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: trial_eigenvalues, trial_occupation
    2059              :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: trial_mu
    2060              : 
    2061              :       INTEGER, PARAMETER :: finite_response_max_rotation = 800
    2062              :       REAL(KIND=dp), PARAMETER :: rotation_trust_rms = 0.25_dp, rotation_trust_spectral = 0.25_dp
    2063              : 
    2064          812 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :)     :: chc, generator
    2065          812 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)  :: channel_generator, density_modes
    2066              :       COMPLEX(KIND=dp), ALLOCATABLE, &
    2067          812 :          DIMENSION(:, :, :, :)                           :: channel_density_modes
    2068              :       INTEGER :: failure, gradient_secant_failure, group, i, ikpoint, ispin, j, local_channel, &
    2069              :          local_kpoint, ngroups, nlocal_channels, nmo, nrotation, r
    2070              :       LOGICAL :: accepted_cross_valid, accepted_curvature_valid, exact_hxc_valid, &
    2071              :          hxc_channel_valid, hxc_valid, projected_update_valid, shadow_pending, solve_valid
    2072              :       REAL(KIND=dp) :: accepted_cross, accepted_curvature, denominator, hxc_density_norm_sq, &
    2073              :          hxc_density_norm_sq_channel, hxc_response_work, hxc_response_work_channel, maxocc, &
    2074              :          response_cross, response_scale, sigma, tmp, unscaled_rotation_norm
    2075          812 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: coupling, curvature_sum, energy_count, &
    2076          812 :          energy_mean, energy_metric_step, energy_shift, energy_weighted_sum, rayleigh_step, &
    2077          812 :          response_curvature, response_weight, rotation_count, rotation_norm, rotation_scale, &
    2078          812 :          schur_rhs, shadow_curvature, shadow_energy_mean, shadow_energy_metric_step, &
    2079          812 :          shadow_energy_weighted_sum, shadow_rayleigh_step, vy, vz
    2080          812 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: channel_response_weight, &
    2081          812 :          channel_rotation_gradient, chc_im, chc_re, dense_im, dense_re, generator_im, &
    2082          812 :          generator_re, previous_rotation_step, rayleigh_response, rhs, rotation_gradient, &
    2083          812 :          rotation_hessian, rotation_step, rotation_y, rotation_z, schur_block, solution
    2084          812 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: channel_rayleigh_response, &
    2085          812 :                                                             channel_rotation_hessian
    2086              :       REAL(KIND=dp), DIMENSION(2) :: hxc_density_overlap, hxc_density_overlap_channel, &
    2087              :          hxc_response_overlap, hxc_response_overlap_channel, projected_coefficients, &
    2088              :          projected_gradient
    2089              :       REAL(KIND=dp), DIMENSION(2, 2)                     :: exact_hxc_correction, hxc_correction, &
    2090              :                                                             projected_hessian
    2091              :       TYPE(kpoint_env_type), POINTER                     :: kp
    2092              : 
    2093          812 :       nlocal_channels = SIZE(local_ot_env)
    2094         1860 :       DO local_channel = 1, nlocal_channels
    2095         1048 :          local_ot_env(local_channel)%rotation_response_valid = .FALSE.
    2096         1048 :          IF (ASSOCIATED(local_ot_env(local_channel)%rot_mat_response_gx)) THEN
    2097          948 :             CALL dbcsr_set(local_ot_env(local_channel)%rot_mat_response_gx, 0.0_dp)
    2098              :          END IF
    2099         1048 :          IF (ASSOCIATED(local_ot_env(local_channel)%rot_mat_response_gx_im)) THEN
    2100          948 :             CALL dbcsr_set(local_ot_env(local_channel)%rot_mat_response_gx_im, 0.0_dp)
    2101              :          END IF
    2102         1048 :          IF (ASSOCIATED(local_ot_env(local_channel)%ener_response_gx)) THEN
    2103         6708 :             local_ot_env(local_channel)%ener_response_gx(:) = 0.0_dp
    2104              :          END IF
    2105         1048 :          IF (ASSOCIATED(local_ot_env(local_channel)%matrix_response_gx)) THEN
    2106          472 :             CALL dbcsr_set(local_ot_env(local_channel)%matrix_response_gx, 0.0_dp)
    2107              :          END IF
    2108         1860 :          IF (ASSOCIATED(local_ot_env(local_channel)%matrix_response_gx_im)) THEN
    2109          472 :             CALL dbcsr_set(local_ot_env(local_channel)%matrix_response_gx_im, 0.0_dp)
    2110              :          END IF
    2111              :       END DO
    2112          812 :       local_ot_env(1)%response_model_curvature = 0.0_dp
    2113          812 :       local_ot_env(1)%response_shadow_curvature = 0.0_dp
    2114          812 :       local_ot_env(1)%response_hxc_direction_valid = .FALSE.
    2115              :       IF (.NOT. local_ot_env(1)%settings%occupation_preconditioner .OR. &
    2116          812 :           .NOT. local_ot_env(1)%settings%do_rotation .OR. &
    2117              :           .NOT. local_ot_env(1)%settings%do_ener) RETURN
    2118              :       ! The dense candidate is accepted through a physical line search. DIIS and Broyden use the
    2119              :       ! cheaper fixed-N response in their history residuals, but have no comparable accepted-step
    2120              :       ! model and therefore must not pay for an unused finite-response construction.
    2121          712 :       IF (local_ot_env(1)%settings%ot_method /= "CG" .AND. &
    2122              :           local_ot_env(1)%settings%ot_method /= "LBFG") RETURN
    2123              :       ! The shared ROKS orbital uses the exact occupation-weighted alpha+beta gradient and the two
    2124              :       ! fixed-N energy blocks use their dense projected preconditioner.  The Hxc response history
    2125              :       ! below is spin-channel-local, so do not construct a falsely alpha-only coupled candidate.
    2126          318 :       IF (restricted_roks) RETURN
    2127          302 :       IF (.NOT. ot_mermin_response_preparation_needed( &
    2128              :           local_ot_env(1)%delta, local_ot_env(1)%response_candidate_directions, &
    2129              :           local_ot_env(1)%response_shadow_good_samples, &
    2130              :           local_ot_env(1)%response_candidate_good_samples, &
    2131              :           local_ot_env(1)%response_candidate_cooldown, &
    2132              :           local_ot_env(1)%response_shadow_pending)) RETURN
    2133          186 :       CPASSERT(smear%do_smear)
    2134          186 :       CPASSERT(ASSOCIATED(para_env_inter_kp))
    2135          336 :       SELECT CASE (smear%method)
    2136              :       CASE (smear_fermi_dirac)
    2137          150 :          sigma = smear%electronic_temperature
    2138              :       CASE (smear_gaussian, smear_mp, smear_mv)
    2139           36 :          sigma = smear%smearing_width
    2140              :       CASE DEFAULT
    2141          186 :          RETURN
    2142              :       END SELECT
    2143          186 :       CPASSERT(sigma > EPSILON(sigma))
    2144              : 
    2145          186 :       nmo = SIZE(local_ot_env(1)%ener_x)
    2146          186 :       nrotation = nmo*(nmo - 1)
    2147          186 :       IF (nrotation <= 0 .OR. nrotation > finite_response_max_rotation) RETURN
    2148          484 :       DO local_channel = 1, nlocal_channels
    2149          298 :          CPASSERT(local_ot_env(local_channel)%has_complex_kpoint_state)
    2150          298 :          CPASSERT(SIZE(local_ot_env(local_channel)%ener_x) == nmo)
    2151          298 :          CPASSERT(ASSOCIATED(local_ot_env(local_channel)%rot_mat_response_gx))
    2152          298 :          CPASSERT(ASSOCIATED(local_ot_env(local_channel)%rot_mat_response_gx_im))
    2153          484 :          CPASSERT(ASSOCIATED(local_ot_env(local_channel)%ener_response_gx))
    2154              :       END DO
    2155              : 
    2156          186 :       ngroups = 1
    2157          186 :       IF (nspin_ot == 2 .AND. smear%fixed_mag_mom > 0.0_dp) ngroups = 2
    2158          186 :       shadow_pending = local_ot_env(1)%response_shadow_pending
    2159              :       ALLOCATE (coupling(nrotation), curvature_sum(ngroups), energy_count(ngroups), &
    2160              :                 energy_mean(ngroups), energy_metric_step(nmo), energy_shift(ngroups), &
    2161              :                 energy_weighted_sum(ngroups), rayleigh_step(nmo), response_curvature(ngroups), &
    2162              :                 response_weight(nmo), rotation_count(ngroups), &
    2163              :                 rotation_norm(ngroups), rotation_scale(ngroups), schur_rhs(nrotation), &
    2164              :                 shadow_curvature(ngroups), shadow_energy_mean(ngroups), &
    2165              :                 shadow_energy_metric_step(nmo), shadow_energy_weighted_sum(ngroups), &
    2166              :                 shadow_rayleigh_step(nmo), &
    2167              :                 vy(ngroups), vz(ngroups), rayleigh_response(nmo, nrotation), &
    2168              :                 rhs(nrotation, 2), rotation_gradient(nrotation, 1), &
    2169              :                 rotation_hessian(nrotation, nrotation), &
    2170              :                 previous_rotation_step(nrotation, nlocal_channels), &
    2171              :                 rotation_step(nrotation, nlocal_channels), &
    2172              :                 rotation_y(nrotation, nlocal_channels), rotation_z(nrotation, nlocal_channels), &
    2173              :                 schur_block(nrotation, nrotation), solution(nrotation, 2), &
    2174              :                 channel_rayleigh_response(nmo, nrotation, nlocal_channels), &
    2175              :                 channel_rotation_hessian(nrotation, nrotation, nlocal_channels), &
    2176              :                 channel_rotation_gradient(nrotation, nlocal_channels), &
    2177              :                 channel_response_weight(nmo, nlocal_channels), &
    2178        12276 :                 channel_generator(nmo, nmo, nlocal_channels), density_modes(nmo, nmo, 2))
    2179          930 :       ALLOCATE (channel_density_modes(nmo, nmo, 2, nlocal_channels))
    2180          186 :       curvature_sum(:) = 0.0_dp
    2181          186 :       vy(:) = 0.0_dp
    2182          186 :       vz(:) = 0.0_dp
    2183          186 :       rotation_y(:, :) = 0.0_dp
    2184          186 :       rotation_z(:, :) = 0.0_dp
    2185          186 :       previous_rotation_step(:, :) = 0.0_dp
    2186          186 :       channel_rayleigh_response(:, :, :) = 0.0_dp
    2187          186 :       channel_rotation_hessian(:, :, :) = 0.0_dp
    2188          186 :       channel_rotation_gradient(:, :) = 0.0_dp
    2189          186 :       channel_response_weight(:, :) = 0.0_dp
    2190          186 :       channel_generator(:, :, :) = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
    2191          186 :       channel_density_modes(:, :, :, :) = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
    2192          186 :       failure = 0
    2193          186 :       response_cross = 0.0_dp
    2194              : 
    2195          438 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2196          252 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2197          252 :          ikpoint = kp%nkpoint
    2198          736 :          DO ispin = 1, nspin_ot
    2199          298 :             group = MERGE(ispin, 1, ngroups == nspin_ot)
    2200          298 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2201          298 :             CALL get_mo_set(kp%mos(1, ispin), maxocc=maxocc)
    2202          298 :             CPASSERT(maxocc > EPSILON(maxocc))
    2203              :             CALL smearing_response_weight( &
    2204              :                response_weight, trial_occupation(:, ikpoint, ispin), &
    2205              :                trial_eigenvalues(:, ikpoint, ispin), trial_mu(ispin), sigma, maxocc, nmo, &
    2206          298 :                smear%method)
    2207         1638 :             response_weight(:) = wkp(ikpoint)*response_weight
    2208         1638 :             curvature_sum(group) = curvature_sum(group) + SUM(response_weight)
    2209              : 
    2210              :             CALL qs_scf_loop_ot_matrix_to_dense( &
    2211          298 :                local_ot_env(local_channel)%rot_mat_chc, local_ot_env(local_channel), chc_re)
    2212              :             CALL qs_scf_loop_ot_matrix_to_dense( &
    2213          298 :                local_ot_env(local_channel)%rot_mat_chc_im, local_ot_env(local_channel), chc_im)
    2214              :             CALL qs_scf_loop_ot_matrix_to_dense( &
    2215          298 :                local_ot_env(local_channel)%rot_mat_x, local_ot_env(local_channel), generator_re)
    2216              :             CALL qs_scf_loop_ot_matrix_to_dense( &
    2217          298 :                local_ot_env(local_channel)%rot_mat_x_im, local_ot_env(local_channel), generator_im)
    2218         1788 :             ALLOCATE (chc(nmo, nmo), generator(nmo, nmo))
    2219         8414 :             chc(:, :) = CMPLX(chc_re, chc_im, KIND=dp)
    2220         8414 :             generator(:, :) = CMPLX(generator_re, generator_im, KIND=dp)
    2221         8414 :             channel_generator(:, :, local_channel) = generator
    2222              :             CALL qs_ot_finite_rotation_response( &
    2223              :                chc, generator, trial_occupation(:, ikpoint, ispin), wkp(ikpoint), &
    2224          298 :                rotation_gradient(:, 1), rotation_hessian, rayleigh_response)
    2225         5734 :             channel_rotation_gradient(:, local_channel) = rotation_gradient(:, 1)
    2226       193198 :             channel_rotation_hessian(:, :, local_channel) = rotation_hessian
    2227         1638 :             channel_response_weight(:, local_channel) = response_weight
    2228              :             CALL qs_ot_fixed_n_schur_block( &
    2229              :                rotation_hessian, rayleigh_response, response_weight, rotation_gradient(:, 1), &
    2230          298 :                local_ot_env(local_channel)%ener_gx, schur_block, coupling, schur_rhs)
    2231         5734 :             rhs(:, 1) = schur_rhs
    2232         5734 :             rhs(:, 2) = coupling
    2233              :             CALL qs_ot_symmetric_abs_solve( &
    2234          298 :                schur_block, rhs, solution, solve_valid, relative_floor=1.0E-4_dp)
    2235          298 :             IF (solve_valid) THEN
    2236         5548 :                rotation_y(:, local_channel) = solution(:, 1)
    2237         5548 :                rotation_z(:, local_channel) = solution(:, 2)
    2238        37420 :                channel_rayleigh_response(:, :, local_channel) = rayleigh_response
    2239         5548 :                vy(group) = vy(group) + DOT_PRODUCT(coupling, solution(:, 1))
    2240         5548 :                vz(group) = vz(group) + DOT_PRODUCT(coupling, solution(:, 2))
    2241              :             ELSE
    2242           30 :                failure = 1
    2243              :             END IF
    2244          298 :             IF (shadow_pending .AND. local_ot_env(local_channel)%use_dx) THEN
    2245              :                CALL qs_scf_loop_ot_matrix_to_dense( &
    2246          168 :                   local_ot_env(local_channel)%rot_mat_dx, local_ot_env(local_channel), dense_re)
    2247              :                CALL qs_scf_loop_ot_matrix_to_dense( &
    2248          168 :                   local_ot_env(local_channel)%rot_mat_dx_im, local_ot_env(local_channel), dense_im)
    2249          168 :                r = 0
    2250          824 :                DO i = 1, nmo - 1
    2251         2612 :                   DO j = i + 1, nmo
    2252         1788 :                      r = r + 1
    2253         1788 :                      previous_rotation_step(r, local_channel) = dense_re(i, j)
    2254         1788 :                      r = r + 1
    2255         2444 :                      previous_rotation_step(r, local_channel) = dense_im(i, j)
    2256              :                   END DO
    2257              :                END DO
    2258          168 :                CPASSERT(r == nrotation)
    2259          168 :                DEALLOCATE (dense_im, dense_re)
    2260              :             END IF
    2261          848 :             DEALLOCATE (chc, generator, chc_im, chc_re, generator_im, generator_re)
    2262              :          END DO
    2263              :       END DO
    2264              : 
    2265          186 :       CALL para_env_inter_kp%sum(curvature_sum)
    2266          186 :       CALL para_env_inter_kp%sum(vy)
    2267          186 :       CALL para_env_inter_kp%sum(vz)
    2268          186 :       CALL para_env_inter_kp%sum(failure)
    2269          186 :       IF (failure /= 0) THEN
    2270            0 :          DEALLOCATE (coupling, curvature_sum, energy_count, energy_mean, energy_metric_step, &
    2271            0 :                      energy_shift, energy_weighted_sum, rayleigh_step, response_curvature, &
    2272            0 :                      response_weight, shadow_curvature, shadow_energy_mean, &
    2273            0 :                      shadow_energy_metric_step, shadow_energy_weighted_sum, shadow_rayleigh_step, &
    2274            0 :                      rotation_count, rotation_norm, rotation_scale, schur_rhs, vy, vz, &
    2275            0 :                      rayleigh_response, rhs, rotation_gradient, rotation_hessian, &
    2276            0 :                      previous_rotation_step, rotation_step, &
    2277            0 :                      rotation_y, rotation_z, schur_block, solution, channel_rayleigh_response, &
    2278            0 :                      channel_rotation_hessian, channel_rotation_gradient, channel_response_weight, &
    2279            0 :                      channel_density_modes, channel_generator, &
    2280           30 :                      density_modes)
    2281           30 :          RETURN
    2282              :       END IF
    2283              : 
    2284          156 :       rotation_norm(:) = 0.0_dp
    2285          156 :       rotation_count(:) = 0.0_dp
    2286          354 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2287          198 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2288          198 :          ikpoint = kp%nkpoint
    2289          592 :          DO ispin = 1, nspin_ot
    2290          238 :             group = MERGE(ispin, 1, ngroups == nspin_ot)
    2291          238 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2292          238 :             denominator = curvature_sum(group) + vz(group)
    2293          238 :             IF (ABS(denominator) > EPSILON(denominator)) THEN
    2294              :                rotation_step(:, local_channel) = rotation_y(:, local_channel) - &
    2295         5206 :                                                  rotation_z(:, local_channel)*vy(group)/denominator
    2296              :             ELSE
    2297          156 :                rotation_step(:, local_channel) = rotation_y(:, local_channel)
    2298              :             END IF
    2299              :             rotation_norm(group) = rotation_norm(group) + &
    2300              :                                    DOT_PRODUCT(rotation_step(:, local_channel), &
    2301         5362 :                                                rotation_step(:, local_channel))
    2302          436 :             rotation_count(group) = rotation_count(group) + REAL(nrotation, KIND=dp)
    2303              :          END DO
    2304              :       END DO
    2305          156 :       CALL para_env_inter_kp%sum(rotation_norm)
    2306          156 :       CALL para_env_inter_kp%sum(rotation_count)
    2307          324 :       rotation_scale(:) = 1.0_dp
    2308          324 :       DO group = 1, ngroups
    2309          324 :          IF (rotation_norm(group) > EPSILON(rotation_norm(group))) THEN
    2310              :             rotation_scale(group) = MIN( &
    2311          168 :                                     1.0_dp, rotation_trust_rms*SQRT(rotation_count(group)/rotation_norm(group)))
    2312              :          END IF
    2313              :       END DO
    2314              : 
    2315          156 :       energy_shift(:) = 0.0_dp
    2316          156 :       energy_count(:) = 0.0_dp
    2317          354 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2318          198 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2319          198 :          ikpoint = kp%nkpoint
    2320          592 :          DO ispin = 1, nspin_ot
    2321          238 :             group = MERGE(ispin, 1, ngroups == nspin_ot)
    2322          238 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2323         5362 :             rotation_step(:, local_channel) = rotation_scale(group)*rotation_step(:, local_channel)
    2324              :             local_ot_env(local_channel)%ener_response_gx(:) = &
    2325              :                local_ot_env(local_channel)%ener_preconditioned_gx + &
    2326              :                MATMUL(channel_rayleigh_response(:, :, local_channel), &
    2327        39122 :                       rotation_step(:, local_channel))
    2328              :             energy_shift(group) = energy_shift(group) + &
    2329         1410 :                                   SUM(local_ot_env(local_channel)%ener_response_gx)
    2330          238 :             energy_count(group) = energy_count(group) + REAL(nmo, KIND=dp)
    2331              : 
    2332         1428 :             ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo))
    2333          238 :             dense_re(:, :) = 0.0_dp
    2334          238 :             dense_im(:, :) = 0.0_dp
    2335          238 :             r = 0
    2336         1172 :             DO i = 1, nmo - 1
    2337         3734 :                DO j = i + 1, nmo
    2338         2562 :                   r = r + 1
    2339         2562 :                   dense_re(i, j) = rotation_step(r, local_channel)
    2340         2562 :                   dense_re(j, i) = -rotation_step(r, local_channel)
    2341         2562 :                   r = r + 1
    2342         2562 :                   dense_im(i, j) = rotation_step(r, local_channel)
    2343         3496 :                   dense_im(j, i) = rotation_step(r, local_channel)
    2344              :                END DO
    2345              :             END DO
    2346          238 :             CPASSERT(r == nrotation)
    2347              :             CALL qs_scf_loop_ot_dense_to_matrix( &
    2348              :                dense_re, local_ot_env(local_channel), &
    2349          238 :                local_ot_env(local_channel)%rot_mat_response_gx)
    2350              :             CALL qs_scf_loop_ot_dense_to_matrix( &
    2351              :                dense_im, local_ot_env(local_channel), &
    2352          238 :                local_ot_env(local_channel)%rot_mat_response_gx_im)
    2353          238 :             local_ot_env(local_channel)%rotation_response_valid = .TRUE.
    2354          436 :             DEALLOCATE (dense_im, dense_re)
    2355              :          END DO
    2356              :       END DO
    2357          156 :       CALL para_env_inter_kp%sum(energy_shift)
    2358          156 :       CALL para_env_inter_kp%sum(energy_count)
    2359          354 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2360          198 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2361          198 :          ikpoint = kp%nkpoint
    2362          592 :          DO ispin = 1, nspin_ot
    2363          238 :             group = MERGE(ispin, 1, ngroups == nspin_ot)
    2364          238 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2365          436 :             IF (energy_count(group) > 0.0_dp) THEN
    2366              :                local_ot_env(local_channel)%ener_response_gx(:) = &
    2367              :                   local_ot_env(local_channel)%ener_response_gx - &
    2368         1410 :                   energy_shift(group)/energy_count(group)
    2369              :             END IF
    2370              :          END DO
    2371              :       END DO
    2372              : 
    2373              :       ! The accepted gradient difference supplies the missing total cross curvature between the
    2374              :       ! finite rotation/energy candidate and the preceding accepted product direction.  Keep the
    2375              :       ! dedicated endpoint history separate from CG's preconditioned-gradient history.
    2376          156 :       accepted_cross = 0.0_dp
    2377          156 :       accepted_cross_valid = .FALSE.
    2378          156 :       gradient_secant_failure = 0
    2379          156 :       IF (shadow_pending .AND. ABS(local_ot_env(1)%ds_min) > SQRT(EPSILON(1.0_dp))) THEN
    2380          248 :          DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2381          138 :             kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2382          138 :             ikpoint = kp%nkpoint
    2383          416 :             DO ispin = 1, nspin_ot
    2384          168 :                local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2385              :                IF (local_ot_env(local_channel)%mermin_gradient_ref_valid .AND. &
    2386              :                    ASSOCIATED(local_ot_env(local_channel)%rot_mat_mermin_g0) .AND. &
    2387          168 :                    ASSOCIATED(local_ot_env(local_channel)%rot_mat_mermin_g0_im) .AND. &
    2388          138 :                    ALLOCATED(local_ot_env(local_channel)%ener_mermin_g0)) THEN
    2389              :                   CALL dbcsr_dot(local_ot_env(local_channel)%rot_mat_gx, &
    2390          168 :                                  local_ot_env(local_channel)%rot_mat_response_gx, tmp)
    2391          168 :                   accepted_cross = accepted_cross + 0.5_dp*tmp
    2392              :                   CALL dbcsr_dot(local_ot_env(local_channel)%rot_mat_mermin_g0, &
    2393          168 :                                  local_ot_env(local_channel)%rot_mat_response_gx, tmp)
    2394          168 :                   accepted_cross = accepted_cross - 0.5_dp*tmp
    2395              :                   CALL dbcsr_dot(local_ot_env(local_channel)%rot_mat_gx_im, &
    2396          168 :                                  local_ot_env(local_channel)%rot_mat_response_gx_im, tmp)
    2397          168 :                   accepted_cross = accepted_cross + 0.5_dp*tmp
    2398              :                   CALL dbcsr_dot(local_ot_env(local_channel)%rot_mat_mermin_g0_im, &
    2399          168 :                                  local_ot_env(local_channel)%rot_mat_response_gx_im, tmp)
    2400          168 :                   accepted_cross = accepted_cross - 0.5_dp*tmp
    2401              :                   accepted_cross = accepted_cross + &
    2402              :                                    DOT_PRODUCT( &
    2403              :                                    local_ot_env(local_channel)%ener_gx - &
    2404              :                                    local_ot_env(local_channel)%ener_mermin_g0, &
    2405          992 :                                    local_ot_env(local_channel)%ener_response_gx)
    2406              :                ELSE
    2407            0 :                   gradient_secant_failure = 1
    2408              :                END IF
    2409              :             END DO
    2410              :          END DO
    2411          110 :          CALL para_env_inter_kp%sum(accepted_cross)
    2412          110 :          CALL para_env_inter_kp%sum(gradient_secant_failure)
    2413          110 :          IF (gradient_secant_failure == 0) THEN
    2414          110 :             accepted_cross = accepted_cross/local_ot_env(1)%ds_min
    2415          110 :             accepted_cross_valid = ieee_is_finite(accepted_cross)
    2416              :          END IF
    2417              :       END IF
    2418              :       ! Evaluate the signed finite response in the same fixed-N tangent used to build the Schur
    2419              :       ! step. This is a prediction only; the minimizer calibrates it against accepted Mermin drops
    2420              :       ! before the candidate can be reused.
    2421          156 :       energy_weighted_sum(:) = 0.0_dp
    2422          354 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2423          198 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2424          198 :          ikpoint = kp%nkpoint
    2425          592 :          DO ispin = 1, nspin_ot
    2426          238 :             group = MERGE(ispin, 1, ngroups == nspin_ot)
    2427          238 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2428              :             energy_weighted_sum(group) = energy_weighted_sum(group) + &
    2429              :                                          DOT_PRODUCT(channel_response_weight(:, local_channel), &
    2430         1608 :                                                      local_ot_env(local_channel)%ener_response_gx)
    2431              :          END DO
    2432              :       END DO
    2433          156 :       CALL para_env_inter_kp%sum(energy_weighted_sum)
    2434          156 :       energy_mean(:) = 0.0_dp
    2435          324 :       DO group = 1, ngroups
    2436          324 :          IF (ABS(curvature_sum(group)) > EPSILON(curvature_sum(group))) THEN
    2437          156 :             energy_mean(group) = energy_weighted_sum(group)/curvature_sum(group)
    2438              :          END IF
    2439              :       END DO
    2440              : 
    2441          156 :       response_curvature(:) = 0.0_dp
    2442          354 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2443          198 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2444          198 :          ikpoint = kp%nkpoint
    2445          592 :          DO ispin = 1, nspin_ot
    2446          238 :             group = MERGE(ispin, 1, ngroups == nspin_ot)
    2447          238 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2448              :             energy_metric_step(:) = channel_response_weight(:, local_channel)* &
    2449              :                                     (local_ot_env(local_channel)%ener_response_gx - &
    2450         1410 :                                      energy_mean(group))
    2451              :             rayleigh_step(:) = MATMUL(channel_rayleigh_response(:, :, local_channel), &
    2452        36778 :                                       rotation_step(:, local_channel))
    2453              :             response_curvature(group) = response_curvature(group) + &
    2454              :                                         DOT_PRODUCT(rotation_step(:, local_channel), &
    2455          714 :                                                     MATMUL(channel_rotation_hessian(:, :, local_channel), &
    2456              :                                                            rotation_step(:, local_channel))) - &
    2457              :                                         2.0_dp*DOT_PRODUCT(rayleigh_step, energy_metric_step) + &
    2458       198716 :                                         DOT_PRODUCT(local_ot_env(local_channel)%ener_response_gx, energy_metric_step)
    2459              :          END DO
    2460              :       END DO
    2461          156 :       CALL para_env_inter_kp%sum(response_curvature)
    2462          324 :       local_ot_env(1)%response_model_curvature = SUM(response_curvature)
    2463              : 
    2464          156 :       IF (shadow_pending) THEN
    2465          110 :          shadow_energy_weighted_sum(:) = 0.0_dp
    2466          248 :          DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2467          138 :             kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2468          138 :             ikpoint = kp%nkpoint
    2469          416 :             DO ispin = 1, nspin_ot
    2470          168 :                group = MERGE(ispin, 1, ngroups == nspin_ot)
    2471          168 :                local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2472              :                shadow_energy_weighted_sum(group) = shadow_energy_weighted_sum(group) + &
    2473              :                                                    DOT_PRODUCT(channel_response_weight(:, local_channel), &
    2474         1130 :                                                                local_ot_env(local_channel)%ener_dx)
    2475              :             END DO
    2476              :          END DO
    2477          110 :          CALL para_env_inter_kp%sum(shadow_energy_weighted_sum)
    2478          110 :          shadow_energy_mean(:) = 0.0_dp
    2479          228 :          DO group = 1, ngroups
    2480          228 :             IF (ABS(curvature_sum(group)) > EPSILON(curvature_sum(group))) THEN
    2481          110 :                shadow_energy_mean(group) = shadow_energy_weighted_sum(group)/curvature_sum(group)
    2482              :             END IF
    2483              :          END DO
    2484              : 
    2485          110 :          shadow_curvature(:) = 0.0_dp
    2486          110 :          projected_gradient(:) = 0.0_dp
    2487          248 :          DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2488          138 :             kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2489          138 :             ikpoint = kp%nkpoint
    2490          416 :             DO ispin = 1, nspin_ot
    2491          168 :                group = MERGE(ispin, 1, ngroups == nspin_ot)
    2492          168 :                local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2493              :                energy_metric_step(:) = channel_response_weight(:, local_channel)* &
    2494              :                                        (local_ot_env(local_channel)%ener_response_gx - &
    2495          992 :                                         energy_mean(group))
    2496              :                shadow_energy_metric_step(:) = channel_response_weight(:, local_channel)* &
    2497              :                                               (local_ot_env(local_channel)%ener_dx - &
    2498          992 :                                                shadow_energy_mean(group))
    2499              :                rayleigh_step(:) = MATMUL(channel_rayleigh_response(:, :, local_channel), &
    2500        25488 :                                          rotation_step(:, local_channel))
    2501              :                shadow_rayleigh_step(:) = MATMUL( &
    2502              :                                          channel_rayleigh_response(:, :, local_channel), &
    2503        25488 :                                          previous_rotation_step(:, local_channel))
    2504              :                shadow_curvature(group) = shadow_curvature(group) + &
    2505              :                                          DOT_PRODUCT(previous_rotation_step(:, local_channel), &
    2506          504 :                                                      MATMUL(channel_rotation_hessian(:, :, local_channel), &
    2507              :                                                             previous_rotation_step(:, local_channel))) - &
    2508              :                                          2.0_dp*DOT_PRODUCT(shadow_rayleigh_step, &
    2509              :                                                             shadow_energy_metric_step) + &
    2510              :                                          DOT_PRODUCT(local_ot_env(local_channel)%ener_dx, &
    2511       136120 :                                                      shadow_energy_metric_step)
    2512              :                response_cross = response_cross + &
    2513              :                                 DOT_PRODUCT(rotation_step(:, local_channel), &
    2514          504 :                                             MATMUL(channel_rotation_hessian(:, :, local_channel), &
    2515              :                                                    previous_rotation_step(:, local_channel))) - &
    2516              :                                 DOT_PRODUCT(rayleigh_step, shadow_energy_metric_step) - &
    2517              :                                 DOT_PRODUCT(shadow_rayleigh_step, energy_metric_step) + &
    2518              :                                 0.5_dp*( &
    2519              :                                 DOT_PRODUCT(local_ot_env(local_channel)%ener_response_gx, &
    2520              :                                             shadow_energy_metric_step) + &
    2521       137768 :                                 DOT_PRODUCT(local_ot_env(local_channel)%ener_dx, energy_metric_step))
    2522              :                projected_gradient(1) = projected_gradient(1) + &
    2523              :                                        DOT_PRODUCT(channel_rotation_gradient(:, local_channel), &
    2524              :                                                    rotation_step(:, local_channel)) + &
    2525              :                                        DOT_PRODUCT(local_ot_env(local_channel)%ener_gx, &
    2526         4568 :                                                    local_ot_env(local_channel)%ener_response_gx)
    2527              :                CALL dbcsr_dot(local_ot_env(local_channel)%matrix_gx, &
    2528          168 :                               local_ot_env(local_channel)%matrix_dx, tmp)
    2529          168 :                projected_gradient(2) = projected_gradient(2) + tmp
    2530              :                CALL dbcsr_dot(local_ot_env(local_channel)%matrix_gx_im, &
    2531          168 :                               local_ot_env(local_channel)%matrix_dx_im, tmp)
    2532          168 :                projected_gradient(2) = projected_gradient(2) + tmp
    2533              :                projected_gradient(2) = projected_gradient(2) + &
    2534              :                                        DOT_PRODUCT(channel_rotation_gradient(:, local_channel), &
    2535              :                                                    previous_rotation_step(:, local_channel)) + &
    2536              :                                        DOT_PRODUCT(local_ot_env(local_channel)%ener_gx, &
    2537         4874 :                                                    local_ot_env(local_channel)%ener_dx)
    2538              :             END DO
    2539              :          END DO
    2540          110 :          CALL para_env_inter_kp%sum(shadow_curvature)
    2541          110 :          CALL para_env_inter_kp%sum(response_cross)
    2542          110 :          CALL para_env_inter_kp%sum(projected_gradient)
    2543          228 :          local_ot_env(1)%response_shadow_curvature = SUM(shadow_curvature)
    2544              :       END IF
    2545              : 
    2546              :       ! The frozen-H finite response above omits the self-consistent Hxc density response. Project
    2547              :       ! the most recent accepted physical density/Hamiltonian secant onto both the candidate and
    2548              :       ! conventional accepted directions. All spin/K-point overlaps are accumulated before the
    2549              :       ! minimum-Frobenius secant is formed: this is the direct-sum spin response, including the Hxc
    2550              :       ! cross-spin coupling, and not a sum of independently fitted spin Hessians. The resulting
    2551              :       ! sign-aware rank-two response is calibrated against accepted Mermin drops before it can replace
    2552              :       ! the conventional search direction.
    2553          156 :       hxc_density_norm_sq = 0.0_dp
    2554          156 :       hxc_response_work = 0.0_dp
    2555          156 :       hxc_density_overlap(:) = 0.0_dp
    2556          156 :       hxc_response_overlap(:) = 0.0_dp
    2557          156 :       failure = 0
    2558          354 :       DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2559          198 :          kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2560          198 :          ikpoint = kp%nkpoint
    2561          198 :          CPASSERT(ASSOCIATED(kp%ot_smat))
    2562          198 :          CPASSERT(SIZE(kp%ot_smat) >= 2)
    2563          592 :          DO ispin = 1, nspin_ot
    2564          238 :             group = MERGE(ispin, 1, ngroups == nspin_ot)
    2565          238 :             local_channel = qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2566              :             energy_metric_step(:) = -channel_response_weight(:, local_channel)* &
    2567              :                                     (local_ot_env(local_channel)%ener_response_gx - &
    2568         1410 :                                      energy_mean(group))
    2569              :             CALL qs_ot_density_tangent( &
    2570              :                channel_generator(:, :, local_channel), &
    2571              :                trial_occupation(:, ikpoint, ispin), wkp(ikpoint), &
    2572          238 :                rotation_step(:, local_channel), energy_metric_step, density_modes(:, :, 1))
    2573         7706 :             channel_density_modes(:, :, 1, local_channel) = density_modes(:, :, 1)
    2574         7706 :             density_modes(:, :, 2) = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
    2575          238 :             IF (shadow_pending) THEN
    2576              :                energy_metric_step(:) = -channel_response_weight(:, local_channel)* &
    2577              :                                        (local_ot_env(local_channel)%ener_dx - &
    2578          992 :                                         shadow_energy_mean(group))
    2579              :                CALL qs_ot_density_tangent( &
    2580              :                   channel_generator(:, :, local_channel), &
    2581              :                   trial_occupation(:, ikpoint, ispin), wkp(ikpoint), &
    2582              :                   previous_rotation_step(:, local_channel), energy_metric_step, &
    2583          168 :                   density_modes(:, :, 2))
    2584         5392 :                channel_density_modes(:, :, 2, local_channel) = density_modes(:, :, 2)
    2585              :             END IF
    2586              :             CALL qs_scf_kp_physical_secant_overlaps( &
    2587              :                local_ot_env(local_channel), kp%ot_smat(1), kp%ot_smat(2), density_modes, &
    2588              :                wkp(ikpoint), hxc_density_norm_sq_channel, hxc_response_work_channel, &
    2589          238 :                hxc_density_overlap_channel, hxc_response_overlap_channel, hxc_channel_valid)
    2590          436 :             IF (hxc_channel_valid) THEN
    2591          238 :                hxc_density_norm_sq = hxc_density_norm_sq + hxc_density_norm_sq_channel
    2592          238 :                hxc_response_work = hxc_response_work + hxc_response_work_channel
    2593          714 :                hxc_density_overlap(:) = hxc_density_overlap + hxc_density_overlap_channel
    2594          714 :                hxc_response_overlap(:) = hxc_response_overlap + hxc_response_overlap_channel
    2595              :             ELSE
    2596            0 :                failure = 1
    2597              :             END IF
    2598              :          END DO
    2599              :       END DO
    2600          156 :       exact_hxc_correction(:, :) = 0.0_dp
    2601          156 :       exact_hxc_valid = .FALSE.
    2602          156 :       IF (local_ot_env(1)%settings%ot_method == "CG") THEN
    2603              :          CALL qs_scf_kp_exact_hxc_projected( &
    2604              :             qs_env, kpoints, local_ot_env, first_channel, nspin_ot, wkp, para_env_inter_kp, &
    2605              :             sab_nl, fmwork, rho_ao_kp, channel_density_modes, MERGE(2, 1, shadow_pending), &
    2606          150 :             exact_hxc_correction, exact_hxc_valid)
    2607              :       END IF
    2608          156 :       CALL para_env_inter_kp%sum(failure)
    2609          156 :       CALL para_env_inter_kp%sum(hxc_density_norm_sq)
    2610          156 :       CALL para_env_inter_kp%sum(hxc_response_work)
    2611          156 :       CALL para_env_inter_kp%sum(hxc_density_overlap)
    2612          156 :       CALL para_env_inter_kp%sum(hxc_response_overlap)
    2613          156 :       hxc_correction(:, :) = 0.0_dp
    2614          156 :       hxc_valid = .FALSE.
    2615          156 :       IF (failure == 0) THEN
    2616          156 :          IF (shadow_pending .AND. &
    2617              :              ABS(local_ot_env(1)%ds_min) > SQRT(EPSILON(1.0_dp))) THEN
    2618              :             CALL qs_ot_density_secant_projected_hessian( &
    2619              :                hxc_density_norm_sq, hxc_response_work, hxc_density_overlap, &
    2620              :                hxc_response_overlap, hxc_correction, hxc_valid, &
    2621          110 :                secant_mode=2, secant_position=local_ot_env(1)%ds_min)
    2622              :          ELSE
    2623              :             CALL qs_ot_density_secant_projected_hessian( &
    2624              :                hxc_density_norm_sq, hxc_response_work, hxc_density_overlap, &
    2625           46 :                hxc_response_overlap, hxc_correction, hxc_valid)
    2626              :          END IF
    2627              :       END IF
    2628          156 :       IF (exact_hxc_valid) THEN
    2629          116 :          hxc_correction(:, :) = exact_hxc_correction
    2630          116 :          hxc_valid = .TRUE.
    2631              :       END IF
    2632          156 :       IF (hxc_valid) THEN
    2633              :          local_ot_env(1)%response_model_curvature = &
    2634          156 :             local_ot_env(1)%response_model_curvature + hxc_correction(1, 1)
    2635          156 :          IF (shadow_pending) THEN
    2636              :             local_ot_env(1)%response_shadow_curvature = &
    2637          110 :                local_ot_env(1)%response_shadow_curvature + hxc_correction(2, 2)
    2638              :          END IF
    2639          110 :          IF (shadow_pending) THEN
    2640              :             CALL ot_mermin_secant_curvature( &
    2641              :                local_ot_env(1)%response_reference_energy, local_ot_env(1)%etotal, &
    2642              :                local_ot_env(1)%response_predicted_slope, local_ot_env(1)%ds_min, &
    2643          110 :                accepted_curvature, accepted_curvature_valid)
    2644          228 :             projected_hessian(1, 1) = SUM(response_curvature)
    2645          110 :             projected_hessian(1, 2) = response_cross
    2646          110 :             projected_hessian(2, 1) = response_cross
    2647          228 :             projected_hessian(2, 2) = SUM(shadow_curvature)
    2648          110 :             IF (accepted_cross_valid) THEN
    2649          110 :                projected_hessian(1, 2) = accepted_cross - hxc_correction(1, 2)
    2650          110 :                projected_hessian(2, 1) = projected_hessian(1, 2)
    2651              :             END IF
    2652          110 :             IF (accepted_curvature_valid) THEN
    2653          110 :                projected_hessian(2, 2) = accepted_curvature - hxc_correction(2, 2)
    2654          110 :                local_ot_env(1)%response_shadow_curvature = accepted_curvature
    2655              :             END IF
    2656              :             CALL qs_ot_projected_response_update( &
    2657              :                projected_hessian, hxc_correction, projected_coefficients, projected_update_valid, &
    2658          110 :                projected_gradient=projected_gradient)
    2659          110 :             IF (projected_update_valid) THEN
    2660          108 :                rotation_norm(:) = 0.0_dp
    2661          108 :                rotation_count(:) = 0.0_dp
    2662          244 :                DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2663          136 :                   kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2664          136 :                   ikpoint = kp%nkpoint
    2665          408 :                   DO ispin = 1, nspin_ot
    2666          164 :                      group = MERGE(ispin, 1, ngroups == nspin_ot)
    2667              :                      local_channel = &
    2668          164 :                         qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2669              :                      rotation_step(:, local_channel) = &
    2670              :                         projected_coefficients(1)*rotation_step(:, local_channel) + &
    2671         3692 :                         projected_coefficients(2)*previous_rotation_step(:, local_channel)
    2672              :                      local_ot_env(local_channel)%ener_response_gx(:) = &
    2673              :                         projected_coefficients(1)* &
    2674              :                         local_ot_env(local_channel)%ener_response_gx + &
    2675          972 :                         projected_coefficients(2)*local_ot_env(local_channel)%ener_dx
    2676              :                      rotation_norm(group) = rotation_norm(group) + &
    2677              :                                             DOT_PRODUCT(rotation_step(:, local_channel), &
    2678         3692 :                                                         rotation_step(:, local_channel))
    2679          300 :                      rotation_count(group) = rotation_count(group) + REAL(nrotation, KIND=dp)
    2680              :                   END DO
    2681              :                END DO
    2682          108 :                CALL para_env_inter_kp%sum(rotation_norm)
    2683          108 :                CALL para_env_inter_kp%sum(rotation_count)
    2684          108 :                response_scale = 1.0_dp
    2685          224 :                IF (SUM(rotation_norm) > EPSILON(SUM(rotation_norm))) THEN
    2686              :                   response_scale = MIN( &
    2687              :                                    1.0_dp, rotation_trust_rms* &
    2688          340 :                                    SQRT(SUM(rotation_count)/SUM(rotation_norm)))
    2689              :                END IF
    2690          108 :                unscaled_rotation_norm = 0.0_dp
    2691          272 :                DO local_channel = 1, nlocal_channels
    2692          984 :                   ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo))
    2693          164 :                   dense_re(:, :) = 0.0_dp
    2694          164 :                   dense_im(:, :) = 0.0_dp
    2695          164 :                   r = 0
    2696          808 :                   DO i = 1, nmo - 1
    2697         2572 :                      DO j = i + 1, nmo
    2698         1764 :                         r = r + 1
    2699         1764 :                         dense_re(i, j) = rotation_step(r, local_channel)
    2700         1764 :                         dense_re(j, i) = -rotation_step(r, local_channel)
    2701         1764 :                         r = r + 1
    2702         1764 :                         dense_im(i, j) = rotation_step(r, local_channel)
    2703         2408 :                         dense_im(j, i) = rotation_step(r, local_channel)
    2704              :                      END DO
    2705              :                   END DO
    2706          164 :                   CPASSERT(r == nrotation)
    2707              :                   unscaled_rotation_norm = MAX( &
    2708              :                                            unscaled_rotation_norm, qs_ot_antihermitian_spectral_norm( &
    2709         5308 :                                            CMPLX(dense_re, dense_im, KIND=dp)))
    2710          272 :                   DEALLOCATE (dense_im, dense_re)
    2711              :                END DO
    2712          108 :                CALL para_env_inter_kp%max(unscaled_rotation_norm)
    2713          108 :                IF (unscaled_rotation_norm > EPSILON(unscaled_rotation_norm)) THEN
    2714              :                   response_scale = MIN( &
    2715              :                                    response_scale, &
    2716          108 :                                    rotation_trust_spectral/unscaled_rotation_norm)
    2717              :                END IF
    2718          244 :                DO local_kpoint = 1, SIZE(kpoints%kp_env)
    2719          136 :                   kp => kpoints%kp_env(local_kpoint)%kpoint_env
    2720          136 :                   ikpoint = kp%nkpoint
    2721          408 :                   DO ispin = 1, nspin_ot
    2722              :                      local_channel = &
    2723          164 :                         qs_ot_channel_index(ispin, ikpoint, nspin_ot) - first_channel + 1
    2724              :                      rotation_step(:, local_channel) = &
    2725         3692 :                         response_scale*rotation_step(:, local_channel)
    2726              :                      local_ot_env(local_channel)%ener_response_gx(:) = &
    2727          972 :                         response_scale*local_ot_env(local_channel)%ener_response_gx
    2728          164 :                      CPASSERT(ASSOCIATED(local_ot_env(local_channel)%matrix_response_gx))
    2729          164 :                      CPASSERT(ASSOCIATED(local_ot_env(local_channel)%matrix_response_gx_im))
    2730              :                      CALL dbcsr_copy(local_ot_env(local_channel)%matrix_response_gx, &
    2731          164 :                                      local_ot_env(local_channel)%matrix_dx)
    2732              :                      CALL dbcsr_scale(local_ot_env(local_channel)%matrix_response_gx, &
    2733          164 :                                       response_scale*projected_coefficients(2))
    2734              :                      CALL dbcsr_copy(local_ot_env(local_channel)%matrix_response_gx_im, &
    2735          164 :                                      local_ot_env(local_channel)%matrix_dx_im)
    2736              :                      CALL dbcsr_scale(local_ot_env(local_channel)%matrix_response_gx_im, &
    2737          164 :                                       response_scale*projected_coefficients(2))
    2738          984 :                      ALLOCATE (dense_re(nmo, nmo), dense_im(nmo, nmo))
    2739          164 :                      dense_re(:, :) = 0.0_dp
    2740          164 :                      dense_im(:, :) = 0.0_dp
    2741          164 :                      r = 0
    2742          808 :                      DO i = 1, nmo - 1
    2743         2572 :                         DO j = i + 1, nmo
    2744         1764 :                            r = r + 1
    2745         1764 :                            dense_re(i, j) = rotation_step(r, local_channel)
    2746         1764 :                            dense_re(j, i) = -rotation_step(r, local_channel)
    2747         1764 :                            r = r + 1
    2748         1764 :                            dense_im(i, j) = rotation_step(r, local_channel)
    2749         2408 :                            dense_im(j, i) = rotation_step(r, local_channel)
    2750              :                         END DO
    2751              :                      END DO
    2752          164 :                      CPASSERT(r == nrotation)
    2753              :                      CALL qs_scf_loop_ot_dense_to_matrix( &
    2754              :                         dense_re, local_ot_env(local_channel), &
    2755          164 :                         local_ot_env(local_channel)%rot_mat_response_gx)
    2756              :                      CALL qs_scf_loop_ot_dense_to_matrix( &
    2757              :                         dense_im, local_ot_env(local_channel), &
    2758          164 :                         local_ot_env(local_channel)%rot_mat_response_gx_im)
    2759          300 :                      DEALLOCATE (dense_im, dense_re)
    2760              :                   END DO
    2761              :                END DO
    2762          108 :                local_ot_env(1)%response_hxc_direction_valid = .TRUE.
    2763              :                local_ot_env(1)%response_model_curvature = response_scale**2* &
    2764              :                                                           DOT_PRODUCT(projected_coefficients, &
    2765              :                                                                       MATMUL(projected_hessian + hxc_correction, &
    2766         1620 :                                                                              projected_coefficients))
    2767              :             END IF
    2768              :          END IF
    2769              :       END IF
    2770              : 
    2771            0 :       DEALLOCATE (coupling, curvature_sum, energy_count, energy_mean, energy_metric_step, &
    2772            0 :                   energy_shift, energy_weighted_sum, rayleigh_step, response_curvature, &
    2773            0 :                   response_weight, shadow_curvature, shadow_energy_mean, &
    2774            0 :                   shadow_energy_metric_step, shadow_energy_weighted_sum, shadow_rayleigh_step, &
    2775            0 :                   rotation_count, rotation_norm, rotation_scale, schur_rhs, vy, vz, &
    2776            0 :                   rayleigh_response, rhs, rotation_gradient, rotation_hessian, &
    2777            0 :                   previous_rotation_step, rotation_step, &
    2778            0 :                   rotation_y, rotation_z, schur_block, solution, channel_rayleigh_response, &
    2779            0 :                   channel_rotation_hessian, channel_rotation_gradient, channel_response_weight, &
    2780            0 :                   channel_density_modes, channel_generator, &
    2781          156 :                   density_modes)
    2782              : 
    2783          812 :    END SUBROUTINE qs_scf_loop_prepare_ot_kp_rotation_response
    2784              : 
    2785              : ! **************************************************************************************************
    2786              : !> \brief copy a distributed OT matrix to a replicated dense matrix
    2787              : !> \param matrix distributed matrix
    2788              : !> \param ot_env channel owning the matrix distribution
    2789              : !> \param dense replicated result
    2790              : ! **************************************************************************************************
    2791         1528 :    SUBROUTINE qs_scf_loop_ot_matrix_to_dense(matrix, ot_env, dense)
    2792              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix
    2793              :       TYPE(qs_ot_type), INTENT(IN)                       :: ot_env
    2794              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
    2795              :          INTENT(OUT)                                     :: dense
    2796              : 
    2797              :       INTEGER                                            :: ncol, nrow
    2798              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    2799              :       TYPE(cp_fm_type)                                   :: fm
    2800              : 
    2801         1528 :       NULLIFY (fm_struct)
    2802            0 :       CPASSERT(ASSOCIATED(ot_env%blacs_env))
    2803         1528 :       CPASSERT(ASSOCIATED(ot_env%para_env))
    2804         1528 :       CALL dbcsr_get_info(matrix, nfullrows_total=nrow, nfullcols_total=ncol)
    2805         6112 :       ALLOCATE (dense(nrow, ncol))
    2806              :       CALL cp_fm_struct_create(fm_struct, context=ot_env%blacs_env, para_env=ot_env%para_env, &
    2807         1528 :                                nrow_global=nrow, ncol_global=ncol)
    2808         1528 :       CALL cp_fm_create(fm, fm_struct)
    2809         1528 :       CALL copy_dbcsr_to_fm(matrix, fm)
    2810         1528 :       CALL cp_fm_get_submatrix(fm, dense, n_rows=nrow, n_cols=ncol)
    2811         1528 :       CALL cp_fm_release(fm)
    2812         1528 :       CALL cp_fm_struct_release(fm_struct)
    2813              : 
    2814         4584 :    END SUBROUTINE qs_scf_loop_ot_matrix_to_dense
    2815              : 
    2816              : ! **************************************************************************************************
    2817              : !> \brief copy a replicated dense matrix into a distributed OT matrix
    2818              : !> \param dense replicated source
    2819              : !> \param ot_env channel owning the matrix distribution
    2820              : !> \param matrix distributed result
    2821              : ! **************************************************************************************************
    2822          804 :    SUBROUTINE qs_scf_loop_ot_dense_to_matrix(dense, ot_env, matrix)
    2823              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: dense
    2824              :       TYPE(qs_ot_type), INTENT(IN)                       :: ot_env
    2825              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: matrix
    2826              : 
    2827              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    2828              :       TYPE(cp_fm_type)                                   :: fm
    2829              : 
    2830          804 :       NULLIFY (fm_struct)
    2831            0 :       CPASSERT(ASSOCIATED(ot_env%blacs_env))
    2832          804 :       CPASSERT(ASSOCIATED(ot_env%para_env))
    2833              :       CALL cp_fm_struct_create(fm_struct, context=ot_env%blacs_env, para_env=ot_env%para_env, &
    2834          804 :                                nrow_global=SIZE(dense, 1), ncol_global=SIZE(dense, 2))
    2835          804 :       CALL cp_fm_create(fm, fm_struct)
    2836          804 :       CALL cp_fm_set_submatrix(fm, dense)
    2837          804 :       CALL copy_fm_to_dbcsr(fm, matrix)
    2838          804 :       CALL cp_fm_release(fm)
    2839          804 :       CALL cp_fm_struct_release(fm_struct)
    2840              : 
    2841          804 :    END SUBROUTINE qs_scf_loop_ot_dense_to_matrix
    2842              : 
    2843              : ! **************************************************************************************************
    2844              : !> \brief the inner loop of scf, specific to using to the orbital transformation method
    2845              : !>       basically, in goes the ks matrix out goes a new p matrix
    2846              : !> \param qs_env ...
    2847              : !> \param scf_env ...
    2848              : !> \param smear ...
    2849              : !> \param mos ...
    2850              : !> \param rho ...
    2851              : !> \param mo_derivs ...
    2852              : !> \param total_energy ...
    2853              : !> \param matrix_s ...
    2854              : !> \param energy_only ...
    2855              : !> \param has_unit_metric ...
    2856              : !> \par History
    2857              : !>      03.2006 created [Joost VandeVondele]
    2858              : !>      2013    moved from qs_scf [Florian Schiffmann]
    2859              : ! **************************************************************************************************
    2860        78780 :    SUBROUTINE qs_scf_loop_do_ot(qs_env, scf_env, smear, mos, rho, mo_derivs, total_energy, &
    2861              :                                 matrix_s, energy_only, has_unit_metric)
    2862              : 
    2863              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2864              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2865              :       TYPE(smear_type), POINTER                          :: smear
    2866              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
    2867              :       TYPE(qs_rho_type), POINTER                         :: rho
    2868              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mo_derivs
    2869              :       REAL(KIND=dp), INTENT(IN)                          :: total_energy
    2870              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    2871              :       LOGICAL, INTENT(INOUT)                             :: energy_only
    2872              :       LOGICAL, INTENT(IN)                                :: has_unit_metric
    2873              : 
    2874              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_scf_loop_do_ot'
    2875              : 
    2876              :       INTEGER                                            :: handle, ispin
    2877        78780 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao
    2878              :       TYPE(dbcsr_type), POINTER                          :: orthogonality_metric
    2879              : 
    2880        78780 :       CALL timeset(routineN, handle)
    2881        78780 :       NULLIFY (rho_ao)
    2882              : 
    2883        78780 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
    2884              : 
    2885        78780 :       IF (has_unit_metric) THEN
    2886        18424 :          NULLIFY (orthogonality_metric)
    2887              :       ELSE
    2888        60356 :          orthogonality_metric => matrix_s(1)%matrix
    2889              :       END IF
    2890              : 
    2891              :       ! in case of LSD the first spin qs_ot_env will drive the minimization
    2892              :       ! in the case of a restricted calculation, it will make sure the spin orbitals are equal
    2893              : 
    2894              :       CALL ot_scf_mini(mos, mo_derivs, smear, orthogonality_metric, &
    2895              :                        total_energy, energy_only, scf_env%iter_delta, &
    2896        78780 :                        scf_env%qs_ot_env)
    2897              : 
    2898       172051 :       DO ispin = 1, SIZE(mos)
    2899       172051 :          CALL set_mo_occupation(mo_set=mos(ispin), smear=smear)
    2900              :       END DO
    2901              : 
    2902       172051 :       DO ispin = 1, SIZE(mos)
    2903              :          CALL calculate_density_matrix(mos(ispin), &
    2904              :                                        rho_ao(ispin)%matrix, &
    2905       172051 :                                        use_dbcsr=.TRUE.)
    2906              :       END DO
    2907              : 
    2908        78780 :       scf_env%iter_method = scf_env%qs_ot_env(1)%OT_METHOD_FULL
    2909        78780 :       scf_env%iter_param = scf_env%qs_ot_env(1)%ds_min
    2910        78780 :       qs_env%broyden_adaptive_sigma = scf_env%qs_ot_env(1)%broyden_adaptive_sigma
    2911              : 
    2912        78780 :       CALL timestop(handle)
    2913              : 
    2914        78780 :    END SUBROUTINE qs_scf_loop_do_ot
    2915              : 
    2916              : ! **************************************************************************************************
    2917              : !> \brief Measure the distance between the diagonalized candidate density and the current density.
    2918              : !> \param scf_env Holds SCF environment information.
    2919              : !> \param rho Current electron density.
    2920              : !> \param para_env Parallel environment.
    2921              : !> \param delta Maximum matrix-element difference.
    2922              : ! **************************************************************************************************
    2923          220 :    SUBROUTINE qs_scf_candidate_density_delta(scf_env, rho, para_env, delta)
    2924              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2925              :       TYPE(qs_rho_type), POINTER                         :: rho
    2926              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2927              :       REAL(KIND=dp), INTENT(OUT)                         :: delta
    2928              : 
    2929              :       INTEGER                                            :: ic, ispin
    2930              :       REAL(KIND=dp)                                      :: tmp
    2931          220 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
    2932              : 
    2933          220 :       NULLIFY (rho_ao_kp)
    2934          220 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
    2935              : 
    2936          220 :       CPASSERT(ASSOCIATED(scf_env%p_mix_new))
    2937          220 :       delta = 0.0_dp
    2938        10852 :       DO ic = 1, SIZE(scf_env%p_mix_new, 2)
    2939        30388 :          DO ispin = 1, SIZE(scf_env%p_mix_new, 1)
    2940              :             ! p_mix=1 leaves the candidate unchanged while cp_sm_mix evaluates
    2941              :             ! the same max-element density difference used by direct mixing.
    2942              :             CALL cp_sm_mix(m1=scf_env%p_mix_new(ispin, ic)%matrix, &
    2943              :                            m2=rho_ao_kp(ispin, ic)%matrix, p_mix=1.0_dp, &
    2944        19536 :                            delta=tmp, para_env=para_env)
    2945        30168 :             delta = MAX(delta, tmp)
    2946              :          END DO
    2947              :       END DO
    2948              : 
    2949          220 :    END SUBROUTINE qs_scf_candidate_density_delta
    2950              : 
    2951              : ! **************************************************************************************************
    2952              : !> \brief Commit the diagonalized candidate density without numerical mixing.
    2953              : !> \param scf_env Holds SCF environment information.
    2954              : !> \param rho Electron density to update.
    2955              : ! **************************************************************************************************
    2956          186 :    SUBROUTINE qs_scf_commit_density_candidate(scf_env, rho)
    2957              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2958              :       TYPE(qs_rho_type), POINTER                         :: rho
    2959              : 
    2960              :       CHARACTER(len=default_string_length)               :: name
    2961              :       INTEGER                                            :: ic, ispin
    2962          186 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
    2963              : 
    2964          186 :       NULLIFY (rho_ao_kp)
    2965          186 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
    2966              : 
    2967          186 :       CPASSERT(ASSOCIATED(scf_env%p_mix_new))
    2968        10242 :       DO ic = 1, SIZE(scf_env%p_mix_new, 2)
    2969        28698 :          DO ispin = 1, SIZE(scf_env%p_mix_new, 1)
    2970        18456 :             CALL dbcsr_get_info(rho_ao_kp(ispin, ic)%matrix, name=name)
    2971        28512 :             CALL dbcsr_copy(rho_ao_kp(ispin, ic)%matrix, scf_env%p_mix_new(ispin, ic)%matrix, name=name)
    2972              :          END DO
    2973              :       END DO
    2974              : 
    2975          186 :    END SUBROUTINE qs_scf_commit_density_candidate
    2976              : 
    2977              : ! **************************************************************************************************
    2978              : !> \brief Performs the requested density mixing if any needed
    2979              : !> \param scf_env   Holds SCF environment information
    2980              : !> \param rho       All data for the electron density
    2981              : !> \param para_env  Parallel environment
    2982              : !> \param diis_step Did we do a DIIS step?
    2983              : ! **************************************************************************************************
    2984       230641 :    SUBROUTINE qs_scf_density_mixing(scf_env, rho, para_env, diis_step)
    2985              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    2986              :       TYPE(qs_rho_type), POINTER                         :: rho
    2987              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2988              :       LOGICAL                                            :: diis_step
    2989              : 
    2990       230641 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
    2991              : 
    2992       230641 :       NULLIFY (rho_ao_kp)
    2993              : 
    2994       230641 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
    2995              : 
    2996       372100 :       SELECT CASE (scf_env%mixing_method)
    2997              :       CASE (direct_mixing_nr)
    2998              :          CALL scf_env_density_mixing(scf_env%p_mix_new, &
    2999              :                                      scf_env%mixing_store, rho_ao_kp, para_env, scf_env%iter_delta, scf_env%iter_count, &
    3000       141459 :                                      diis=diis_step)
    3001              :       CASE (gspace_mixing_nr, pulay_mixing_nr, broyden_mixing_nr, modified_broyden_mixing_nr, &
    3002              :             multisecant_mixing_nr, new_pulay_mixing_nr)
    3003              :          ! Compute the difference p_out-p_in
    3004              :          CALL self_consistency_check(rho_ao_kp, scf_env%p_delta, para_env, scf_env%p_mix_new, &
    3005         7818 :                                      delta=scf_env%iter_delta)
    3006              :       CASE (no_mixing_nr)
    3007              :       CASE DEFAULT
    3008              :          CALL cp_abort(__LOCATION__, &
    3009              :                        "unknown scf mixing method: "// &
    3010       230641 :                        cp_to_string(scf_env%mixing_method))
    3011              :       END SELECT
    3012              : 
    3013       230641 :    END SUBROUTINE qs_scf_density_mixing
    3014              : 
    3015              : ! **************************************************************************************************
    3016              : !> \brief checks whether exit conditions for outer loop are satisfied
    3017              : !> \param qs_env ...
    3018              : !> \param scf_env ...
    3019              : !> \param scf_control ...
    3020              : !> \param should_stop ...
    3021              : !> \param outer_loop_converged ...
    3022              : !> \param exit_outer_loop ...
    3023              : ! **************************************************************************************************
    3024        25635 :    SUBROUTINE qs_scf_check_outer_exit(qs_env, scf_env, scf_control, should_stop, &
    3025              :                                       outer_loop_converged, exit_outer_loop)
    3026              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3027              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    3028              :       TYPE(scf_control_type), POINTER                    :: scf_control
    3029              :       LOGICAL                                            :: should_stop, outer_loop_converged, &
    3030              :                                                             exit_outer_loop
    3031              : 
    3032              :       REAL(KIND=dp)                                      :: outer_loop_eps
    3033              : 
    3034        25635 :       outer_loop_converged = .TRUE.
    3035        25635 :       IF (scf_control%outer_scf%have_scf) THEN
    3036              :          ! We have an outer SCF loop...
    3037         6135 :          scf_env%outer_scf%iter_count = scf_env%outer_scf%iter_count + 1
    3038         6135 :          outer_loop_converged = .FALSE.
    3039              : 
    3040         6135 :          CALL outer_loop_gradient(qs_env, scf_env)
    3041              :          ! Multiple constraints: get largest deviation
    3042        12358 :          outer_loop_eps = SQRT(MAXVAL(scf_env%outer_scf%gradient(:, scf_env%outer_scf%iter_count)**2))
    3043              : 
    3044         6135 :          IF (outer_loop_eps < scf_control%outer_scf%eps_scf) outer_loop_converged = .TRUE.
    3045              :       END IF
    3046              : 
    3047              :       exit_outer_loop = should_stop .OR. outer_loop_converged .OR. &
    3048        25635 :                         scf_env%outer_scf%iter_count > scf_control%outer_scf%max_scf
    3049              : 
    3050        25635 :    END SUBROUTINE qs_scf_check_outer_exit
    3051              : 
    3052              : ! **************************************************************************************************
    3053              : !> \brief checks whether exit conditions for inner loop are satisfied
    3054              : !> \param qs_env ...
    3055              : !> \param scf_env ...
    3056              : !> \param scf_control ...
    3057              : !> \param should_stop ...
    3058              : !> \param just_energy ...
    3059              : !> \param exit_inner_loop ...
    3060              : !> \param inner_loop_converged ...
    3061              : !> \param output_unit ...
    3062              : ! **************************************************************************************************
    3063       461722 :    SUBROUTINE qs_scf_check_inner_exit(qs_env, scf_env, scf_control, should_stop, just_energy, &
    3064              :                                       exit_inner_loop, inner_loop_converged, output_unit)
    3065              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3066              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    3067              :       TYPE(scf_control_type), POINTER                    :: scf_control
    3068              :       LOGICAL                                            :: should_stop, just_energy, &
    3069              :                                                             exit_inner_loop, inner_loop_converged
    3070              :       INTEGER                                            :: output_unit
    3071              : 
    3072              :       LOGICAL                                            :: davidson_tightening, update_validated
    3073              : 
    3074       230861 :       inner_loop_converged = .FALSE.
    3075       230861 :       exit_inner_loop = .FALSE.
    3076       230861 :       update_validated = scf_control%diagonalization%update_method /= diag_update_method_adiis
    3077       230861 :       IF (.NOT. update_validated) THEN
    3078          220 :          CPASSERT(ASSOCIATED(scf_env%scf_subspace_buffer))
    3079              :          update_validated = scf_env%adiis_validated .OR. &
    3080          220 :                             scf_env%scf_subspace_buffer%diis_weight >= 1.0_dp
    3081              :       END IF
    3082              : 
    3083              :       CALL external_control(should_stop, "SCF", target_time=qs_env%target_time, &
    3084       230861 :                             start_time=qs_env%start_time)
    3085       230861 :       IF (scf_env%iter_delta < scf_control%eps_scf .AND. update_validated) THEN
    3086              :          ! nested IFs on purpose: a .AND. chain leaves the evaluation order
    3087              :          ! unspecified. On non-Davidson runs the env array has size zero
    3088              :          ! while the tightening test below indexes its first channel
    3089        21855 :          davidson_tightening = .FALSE.
    3090        21855 :          IF (scf_env%method == block_davidson_diag_method_nr) THEN
    3091           34 :             IF (SIZE(scf_env%block_davidson_env) > 0) THEN
    3092              :                davidson_tightening = scf_env%block_davidson_env(1)%eps_iter_used > &
    3093              :                                      scf_env%block_davidson_env(1)%eps_iter .AND. &
    3094           34 :                                      scf_env%iter_delta < scf_env%block_davidson_env(1)%eps_iter_used
    3095              :             END IF
    3096              :          END IF
    3097              :          IF (davidson_tightening) THEN
    3098              :             ! the adaptive inner tolerance of the Davidson solve that produced
    3099              :             ! this mixing delta was looser than the delta itself. The apparent
    3100              :             ! convergence may be nothing but the noise floor of the loose
    3101              :             ! solve. Tighten the ratchet one decade below what that solve used
    3102              :             ! and keep iterating until the delta survives a tighter solve.
    3103            0 :             IF (output_unit > 0) THEN
    3104              :                WRITE (UNIT=output_unit, FMT="(T3,A,ES9.2,A)") &
    3105            0 :                   "*** SCF delta below the loose Davidson tolerance ", &
    3106            0 :                   scf_env%block_davidson_env(1)%eps_iter_used, " - tightening and continuing ***"
    3107              :             END IF
    3108              :             scf_env%block_davidson_env(1)%eps_iter_prev = &
    3109              :                MIN(scf_env%block_davidson_env(1)%eps_iter_prev, &
    3110              :                    MAX(scf_env%block_davidson_env(1)%eps_iter, &
    3111            0 :                        0.1_dp*scf_env%block_davidson_env(1)%eps_iter_used))
    3112              :          ELSE
    3113        21855 :             IF (output_unit > 0) THEN
    3114              :                WRITE (UNIT=output_unit, FMT="(/,T3,A,I5,A/)") &
    3115        11099 :                   "*** SCF run converged in ", scf_env%iter_count, " steps ***"
    3116              :             END IF
    3117        21855 :             inner_loop_converged = .TRUE.
    3118        21855 :             exit_inner_loop = .TRUE.
    3119              :          END IF
    3120       209006 :       ELSE IF (should_stop .OR. scf_env%iter_count >= scf_control%max_scf) THEN
    3121         4090 :          inner_loop_converged = .FALSE.
    3122         4090 :          IF (just_energy) THEN
    3123          904 :             exit_inner_loop = .FALSE.
    3124              :          ELSE
    3125         3186 :             exit_inner_loop = .TRUE.
    3126         3186 :             IF (output_unit > 0) THEN
    3127              :                WRITE (UNIT=output_unit, FMT="(/,T3,A,I5,A/)") &
    3128         1599 :                   "Leaving inner SCF loop after reaching ", scf_env%iter_count, " steps."
    3129              :             END IF
    3130              :          END IF
    3131              :       END IF
    3132              : 
    3133       230861 :    END SUBROUTINE qs_scf_check_inner_exit
    3134              : 
    3135              : ! **************************************************************************************************
    3136              : !> \brief undoing density mixing. Important upon convergence
    3137              : !> \param scf_env ...
    3138              : !> \param rho ...
    3139              : !> \param dft_control ...
    3140              : !> \param para_env ...
    3141              : !> \param diis_step ...
    3142              : ! **************************************************************************************************
    3143        25041 :    SUBROUTINE qs_scf_undo_mixing(scf_env, rho, dft_control, para_env, diis_step)
    3144              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    3145              :       TYPE(qs_rho_type), POINTER                         :: rho
    3146              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3147              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3148              :       LOGICAL                                            :: diis_step
    3149              : 
    3150              :       CHARACTER(len=default_string_length)               :: name
    3151              :       INTEGER                                            :: ic, ispin, nc
    3152        25041 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
    3153              : 
    3154        25041 :       NULLIFY (rho_ao_kp)
    3155              : 
    3156        25041 :       IF (scf_env%mixing_method > 0) THEN
    3157        17506 :          CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
    3158        17506 :          nc = SIZE(scf_env%p_mix_new, 2)
    3159        34202 :          SELECT CASE (scf_env%mixing_method)
    3160              :          CASE (direct_mixing_nr)
    3161              :             CALL scf_env_density_mixing(scf_env%p_mix_new, scf_env%mixing_store, &
    3162              :                                         rho_ao_kp, para_env, scf_env%iter_delta, &
    3163              :                                         scf_env%iter_count, diis=diis_step, &
    3164        16696 :                                         invert=.TRUE.)
    3165       159358 :             DO ic = 1, nc
    3166       319314 :                DO ispin = 1, dft_control%nspins
    3167       159956 :                   CALL dbcsr_get_info(rho_ao_kp(ispin, ic)%matrix, name=name) ! keep the name
    3168       302618 :                   CALL dbcsr_copy(rho_ao_kp(ispin, ic)%matrix, scf_env%p_mix_new(ispin, ic)%matrix, name=name)
    3169              :                END DO
    3170              :             END DO
    3171              :          CASE (gspace_mixing_nr, pulay_mixing_nr, broyden_mixing_nr, modified_broyden_mixing_nr, &
    3172              :                multisecant_mixing_nr, new_pulay_mixing_nr)
    3173        63930 :             DO ic = 1, nc
    3174        92740 :                DO ispin = 1, dft_control%nspins
    3175        46316 :                   CALL dbcsr_get_info(rho_ao_kp(ispin, ic)%matrix, name=name) ! keep the name
    3176        91930 :                   CALL dbcsr_copy(rho_ao_kp(ispin, ic)%matrix, scf_env%p_mix_new(ispin, ic)%matrix, name=name)
    3177              :                END DO
    3178              :             END DO
    3179              :          END SELECT
    3180              :       END IF
    3181        25041 :    END SUBROUTINE qs_scf_undo_mixing
    3182              : 
    3183              : ! **************************************************************************************************
    3184              : !> \brief Performs the updates rho (takes care of mixing as well)
    3185              : !> \param rho ...
    3186              : !> \param qs_env ...
    3187              : !> \param scf_env ...
    3188              : !> \param ks_env ...
    3189              : !> \param mix_rho ...
    3190              : ! **************************************************************************************************
    3191       230873 :    SUBROUTINE qs_scf_rho_update(rho, qs_env, scf_env, ks_env, mix_rho)
    3192              :       TYPE(qs_rho_type), POINTER                         :: rho
    3193              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3194              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    3195              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    3196              :       LOGICAL, INTENT(IN)                                :: mix_rho
    3197              : 
    3198              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3199              : 
    3200       230873 :       NULLIFY (para_env)
    3201       230873 :       CALL get_qs_env(qs_env, para_env=para_env)
    3202              :       ! ** update qs_env%rho
    3203       230873 :       CALL qs_rho_update_rho(rho, qs_env=qs_env)
    3204              :       ! ** Density mixing through density matrix or on the reciprocal space grid (exclusive)
    3205       230873 :       IF (mix_rho) THEN
    3206              :          CALL gspace_mixing(qs_env, scf_env%mixing_method, scf_env%mixing_store, rho, &
    3207         7008 :                             para_env, scf_env%iter_count)
    3208              : 
    3209              :       END IF
    3210       230873 :       CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
    3211              : 
    3212       230873 :    END SUBROUTINE qs_scf_rho_update
    3213              : 
    3214              : ! **************************************************************************************************
    3215              : !> \brief Performs the necessary steps before leaving innner scf loop
    3216              : !> \param scf_env ...
    3217              : !> \param qs_env ...
    3218              : !> \param diis_step ...
    3219              : !> \param output_unit ...
    3220              : ! **************************************************************************************************
    3221        25041 :    SUBROUTINE qs_scf_inner_finalize(scf_env, qs_env, diis_step, output_unit)
    3222              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    3223              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3224              :       LOGICAL                                            :: diis_step
    3225              :       INTEGER, INTENT(IN)                                :: output_unit
    3226              : 
    3227              :       LOGICAL                                            :: do_kpoints
    3228              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3229              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3230              :       TYPE(qs_energy_type), POINTER                      :: energy
    3231              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    3232              :       TYPE(qs_rho_type), POINTER                         :: rho
    3233              : 
    3234        25041 :       NULLIFY (energy, rho, dft_control, ks_env)
    3235              : 
    3236              :       CALL get_qs_env(qs_env=qs_env, energy=energy, ks_env=ks_env, &
    3237              :                       rho=rho, dft_control=dft_control, para_env=para_env, &
    3238        25041 :                       do_kpoints=do_kpoints)
    3239              : 
    3240        25041 :       CALL cleanup_scf_loop(scf_env)
    3241              : 
    3242              :       ! now, print out energies and charges corresponding to the obtained wfn
    3243              :       ! (this actually is not 100% consistent at this point)!
    3244        25041 :       CALL qs_scf_print_summary(output_unit, qs_env)
    3245              : 
    3246        25041 :       CALL qs_scf_undo_mixing(scf_env, rho, dft_control, para_env, diis_step)
    3247              : 
    3248              :       !   *** update rspace rho since the mo changed
    3249              :       !   *** this might not always be needed (i.e. no post calculation / no forces )
    3250              :       !   *** but guarantees that rho and wfn are consistent at this point
    3251        25041 :       CALL qs_scf_rho_update(rho, qs_env, scf_env, ks_env, mix_rho=.FALSE.)
    3252              : 
    3253        25041 :    END SUBROUTINE qs_scf_inner_finalize
    3254              : 
    3255              : ! **************************************************************************************************
    3256              : !> \brief perform cleanup operations at the end of an scf loop
    3257              : !> \param scf_env ...
    3258              : !> \par History
    3259              : !>      03.2006 created [Joost VandeVondele]
    3260              : ! **************************************************************************************************
    3261        25041 :    SUBROUTINE cleanup_scf_loop(scf_env)
    3262              :       TYPE(qs_scf_env_type), INTENT(INOUT)               :: scf_env
    3263              : 
    3264              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'cleanup_scf_loop'
    3265              : 
    3266              :       INTEGER                                            :: handle, ispin
    3267              : 
    3268        25041 :       CALL timeset(routineN, handle)
    3269              : 
    3270        32560 :       SELECT CASE (scf_env%method)
    3271              :       CASE (ot_method_nr)
    3272        16583 :          DO ispin = 1, SIZE(scf_env%qs_ot_env)
    3273        16583 :             CALL ot_scf_destroy(scf_env%qs_ot_env(ispin))
    3274              :          END DO
    3275         7519 :          DEALLOCATE (scf_env%qs_ot_env)
    3276              :       CASE (ot_diag_method_nr)
    3277              :          !
    3278              :       CASE (general_diag_method_nr)
    3279              :          !
    3280              :       CASE (special_diag_method_nr)
    3281              :          !
    3282              :       CASE (block_krylov_diag_method_nr, block_davidson_diag_method_nr)
    3283              :          !
    3284              :       CASE (filter_matrix_diag_method_nr)
    3285              :          !
    3286              :       CASE (smeagol_method_nr)
    3287              :          !
    3288              :       CASE DEFAULT
    3289              :          CALL cp_abort(__LOCATION__, &
    3290              :                        "unknown scf method method:"// &
    3291        25041 :                        cp_to_string(scf_env%method))
    3292              :       END SELECT
    3293              : 
    3294        25041 :       CALL timestop(handle)
    3295              : 
    3296        25041 :    END SUBROUTINE cleanup_scf_loop
    3297              : 
    3298          574 : END MODULE qs_scf_loop_utils
        

Generated by: LCOV version 2.0-1