LCOV - code coverage report
Current view: top level - src - qs_scf_loop_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:92574dc) Lines: 93.7 % 1579 1480
Test Date: 2026-09-24 01:27:39 Functions: 100.0 % 31 31

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

Generated by: LCOV version 2.0-1