LCOV - code coverage report
Current view: top level - src - qs_scf_loop_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 92.6 % 1741 1613
Test Date: 2026-11-04 00:58:17 Functions: 100.0 % 32 32

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

Generated by: LCOV version 2.0-1