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

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Contains ADMM methods which require molecular orbitals
      10              : !> \par History
      11              : !>      04.2008 created [Manuel Guidon]
      12              : !>      12.2019 Made GAPW compatible [A. Bussy]
      13              : !> \author Manuel Guidon
      14              : ! **************************************************************************************************
      15              : MODULE admm_methods
      16              :    USE admm_types,                      ONLY: admm_gapw_r3d_rs_type,&
      17              :                                               admm_type,&
      18              :                                               get_admm_env
      19              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      20              :    USE bibliography,                    ONLY: Merlot2014,&
      21              :                                               cite_reference
      22              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_scale,&
      23              :                                               cp_cfm_scale_and_add,&
      24              :                                               cp_cfm_scale_and_add_fm,&
      25              :                                               cp_cfm_uplo_to_full
      26              :    USE cp_cfm_cholesky,                 ONLY: cp_cfm_cholesky_decompose,&
      27              :                                               cp_cfm_cholesky_invert
      28              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      29              :                                               cp_cfm_release,&
      30              :                                               cp_cfm_to_fm,&
      31              :                                               cp_cfm_type,&
      32              :                                               cp_fm_to_cfm
      33              :    USE cp_control_types,                ONLY: dft_control_type
      34              :    USE cp_dbcsr_api,                    ONLY: &
      35              :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_desymmetrize, &
      36              :         dbcsr_get_block_p, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      37              :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, &
      38              :         dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, &
      39              :         dbcsr_type_no_symmetry, dbcsr_type_symmetric
      40              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_dot
      41              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      42              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      43              :                                               copy_fm_to_dbcsr,&
      44              :                                               cp_dbcsr_plus_fm_fm_t,&
      45              :                                               dbcsr_allocate_matrix_set,&
      46              :                                               dbcsr_deallocate_matrix_set
      47              :    USE cp_dbcsr_output,                 ONLY: cp_dbcsr_write_sparse_matrix
      48              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      49              :                                               cp_fm_scale,&
      50              :                                               cp_fm_scale_and_add,&
      51              :                                               cp_fm_schur_product,&
      52              :                                               cp_fm_uplo_to_full
      53              :    USE cp_fm_cholesky,                  ONLY: cp_fm_cholesky_decompose,&
      54              :                                               cp_fm_cholesky_invert,&
      55              :                                               cp_fm_cholesky_reduce,&
      56              :                                               cp_fm_cholesky_restore
      57              :    USE cp_fm_diag,                      ONLY: cp_fm_syevd
      58              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      59              :                                               cp_fm_struct_release,&
      60              :                                               cp_fm_struct_type
      61              :    USE cp_fm_types,                     ONLY: &
      62              :         copy_info_type, cp_fm_cleanup_copy_general, cp_fm_create, cp_fm_finish_copy_general, &
      63              :         cp_fm_get_info, cp_fm_release, cp_fm_set_all, cp_fm_set_element, cp_fm_start_copy_general, &
      64              :         cp_fm_to_fm, cp_fm_type
      65              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      66              :                                               cp_logger_type,&
      67              :                                               cp_to_string
      68              :    USE cp_output_handling,              ONLY: cp_p_file,&
      69              :                                               cp_print_key_finished_output,&
      70              :                                               cp_print_key_should_output,&
      71              :                                               cp_print_key_unit_nr
      72              :    USE input_constants,                 ONLY: do_admm_purify_cauchy,&
      73              :                                               do_admm_purify_cauchy_subspace,&
      74              :                                               do_admm_purify_mo_diag,&
      75              :                                               do_admm_purify_mo_no_diag,&
      76              :                                               do_admm_purify_none
      77              :    USE input_section_types,             ONLY: section_vals_type,&
      78              :                                               section_vals_val_get
      79              :    USE kinds,                           ONLY: default_string_length,&
      80              :                                               dp
      81              :    USE kpoint_methods,                  ONLY: kpoint_density_matrices,&
      82              :                                               kpoint_density_transform,&
      83              :                                               rskp_transform
      84              :    USE kpoint_types,                    ONLY: get_kpoint_env,&
      85              :                                               get_kpoint_info,&
      86              :                                               kpoint_env_type,&
      87              :                                               kpoint_type
      88              :    USE mathconstants,                   ONLY: gaussi,&
      89              :                                               z_one,&
      90              :                                               z_zero
      91              :    USE message_passing,                 ONLY: mp_para_env_type
      92              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      93              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      94              :                                               pw_r3d_rs_type
      95              :    USE qs_collocate_density,            ONLY: calculate_rho_elec
      96              :    USE qs_energy_types,                 ONLY: qs_energy_type
      97              :    USE qs_environment_types,            ONLY: get_qs_env,&
      98              :                                               qs_environment_type
      99              :    USE qs_force_types,                  ONLY: add_qs_force,&
     100              :                                               qs_force_type
     101              :    USE qs_gapw_densities,               ONLY: prepare_gapw_den
     102              :    USE qs_ks_atom,                      ONLY: update_ks_atom
     103              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
     104              :    USE qs_local_rho_types,              ONLY: local_rho_set_create,&
     105              :                                               local_rho_set_release,&
     106              :                                               local_rho_type
     107              :    USE qs_mo_types,                     ONLY: get_mo_set,&
     108              :                                               mo_set_type
     109              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
     110              :    USE qs_overlap,                      ONLY: build_overlap_force
     111              :    USE qs_rho_atom_methods,             ONLY: allocate_rho_atom_internals,&
     112              :                                               calculate_rho_atom_coeff
     113              :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     114              :                                               qs_rho_set,&
     115              :                                               qs_rho_type
     116              :    USE qs_scf_types,                    ONLY: qs_scf_env_type
     117              :    USE qs_vxc,                          ONLY: qs_vxc_create
     118              :    USE qs_vxc_atom,                     ONLY: calculate_vxc_atom
     119              :    USE task_list_types,                 ONLY: task_list_type
     120              : #include "./base/base_uses.f90"
     121              : 
     122              :    IMPLICIT NONE
     123              :    PRIVATE
     124              : 
     125              :    PUBLIC :: admm_mo_calc_rho_aux, &
     126              :              admm_mo_calc_rho_aux_kp, &
     127              :              admm_mo_merge_ks_matrix, &
     128              :              admm_mo_merge_derivs, &
     129              :              admm_aux_response_density, &
     130              :              calc_mixed_overlap_force, &
     131              :              scale_dm, &
     132              :              admm_fit_mo_coeffs, &
     133              :              admm_update_ks_atom, &
     134              :              calc_admm_mo_derivatives, &
     135              :              calc_admm_ovlp_forces, &
     136              :              calc_admm_ovlp_forces_kp, &
     137              :              admm_projection_derivative, &
     138              :              kpoint_calc_admm_matrices
     139              : 
     140              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'admm_methods'
     141              : 
     142              : CONTAINS
     143              : 
     144              : ! **************************************************************************************************
     145              : !> \brief ...
     146              : !> \param qs_env ...
     147              : ! **************************************************************************************************
     148        12902 :    SUBROUTINE admm_mo_calc_rho_aux(qs_env)
     149              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     150              : 
     151              :       CHARACTER(len=*), PARAMETER :: routineN = 'admm_mo_calc_rho_aux'
     152              : 
     153              :       CHARACTER(LEN=default_string_length)               :: basis_type
     154              :       INTEGER                                            :: handle, ispin
     155              :       LOGICAL                                            :: gapw, s_mstruct_changed
     156        12902 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: tot_rho_r_aux
     157              :       TYPE(admm_type), POINTER                           :: admm_env
     158        12902 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, matrix_s_aux_fit, &
     159        12902 :                                                             matrix_s_aux_fit_vs_orb, rho_ao, &
     160        12902 :                                                             rho_ao_aux
     161              :       TYPE(dft_control_type), POINTER                    :: dft_control
     162        12902 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos, mos_aux_fit
     163              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     164        12902 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g_aux
     165        12902 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r_aux
     166              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     167              :       TYPE(qs_rho_type), POINTER                         :: rho, rho_aux_fit
     168              :       TYPE(task_list_type), POINTER                      :: task_list
     169              : 
     170        12902 :       CALL timeset(routineN, handle)
     171              : 
     172        12902 :       NULLIFY (ks_env, admm_env, mos, mos_aux_fit, matrix_s_aux_fit, &
     173        12902 :                matrix_s_aux_fit_vs_orb, matrix_s, rho, rho_aux_fit, para_env)
     174        12902 :       NULLIFY (rho_g_aux, rho_r_aux, rho_ao, rho_ao_aux, tot_rho_r_aux, task_list)
     175              : 
     176              :       CALL get_qs_env(qs_env, &
     177              :                       ks_env=ks_env, &
     178              :                       admm_env=admm_env, &
     179              :                       dft_control=dft_control, &
     180              :                       mos=mos, &
     181              :                       matrix_s=matrix_s, &
     182              :                       para_env=para_env, &
     183              :                       s_mstruct_changed=s_mstruct_changed, &
     184        12902 :                       rho=rho)
     185              :       CALL get_admm_env(admm_env, mos_aux_fit=mos_aux_fit, matrix_s_aux_fit=matrix_s_aux_fit, &
     186        12902 :                         matrix_s_aux_fit_vs_orb=matrix_s_aux_fit_vs_orb, rho_aux_fit=rho_aux_fit)
     187              : 
     188        12902 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     189              :       CALL qs_rho_get(rho_aux_fit, &
     190              :                       rho_ao=rho_ao_aux, &
     191              :                       rho_g=rho_g_aux, &
     192              :                       rho_r=rho_r_aux, &
     193        12902 :                       tot_rho_r=tot_rho_r_aux)
     194              : 
     195        12902 :       gapw = admm_env%do_gapw
     196              : 
     197              :       ! convert mos from full to dbcsr matrices
     198        28238 :       DO ispin = 1, dft_control%nspins
     199        28238 :          IF (mos(ispin)%use_mo_coeff_b) THEN
     200         9582 :             CALL copy_dbcsr_to_fm(mos(ispin)%mo_coeff_b, mos(ispin)%mo_coeff)
     201              :          END IF
     202              :       END DO
     203              : 
     204              :       ! fit mo coeffcients
     205              :       CALL admm_fit_mo_coeffs(admm_env, matrix_s_aux_fit, matrix_s_aux_fit_vs_orb, &
     206        12902 :                               mos, mos_aux_fit, s_mstruct_changed)
     207              : 
     208        28238 :       DO ispin = 1, dft_control%nspins
     209        15336 :          IF (admm_env%block_dm) THEN
     210              :             CALL blockify_density_matrix(admm_env, &
     211              :                                          density_matrix=rho_ao(ispin)%matrix, &
     212              :                                          density_matrix_aux=rho_ao_aux(ispin)%matrix, &
     213              :                                          ispin=ispin, &
     214          354 :                                          nspins=dft_control%nspins)
     215              : 
     216              :          ELSE
     217              : 
     218              :             ! Here, the auxiliary DM gets calculated and is written into rho_aux_fit%...
     219              :             CALL calculate_dm_mo_no_diag(admm_env, &
     220              :                                          mo_set=mos(ispin), &
     221              :                                          overlap_matrix=matrix_s_aux_fit(1)%matrix, &
     222              :                                          density_matrix=rho_ao_aux(ispin)%matrix, &
     223              :                                          overlap_matrix_large=matrix_s(1)%matrix, &
     224              :                                          density_matrix_large=rho_ao(ispin)%matrix, &
     225        14982 :                                          ispin=ispin)
     226              : 
     227              :          END IF
     228              : 
     229        15336 :          IF (admm_env%purification_method == do_admm_purify_cauchy) THEN
     230              :             CALL purify_dm_cauchy(admm_env, &
     231              :                                   mo_set=mos_aux_fit(ispin), &
     232              :                                   density_matrix=rho_ao_aux(ispin)%matrix, &
     233              :                                   ispin=ispin, &
     234          484 :                                   blocked=admm_env%block_dm)
     235              :          END IF
     236              : 
     237              :          !GPW is the default, PW density is computed using the AUX_FIT basis and task_list
     238              :          !If GAPW, the we use the AUX_FIT_SOFT basis and task list
     239        15336 :          basis_type = "AUX_FIT"
     240        15336 :          task_list => admm_env%task_list_aux_fit
     241        15336 :          IF (gapw) THEN
     242         5346 :             basis_type = "AUX_FIT_SOFT"
     243         5346 :             task_list => admm_env%admm_gapw_env%task_list
     244              :          END IF
     245              : 
     246              :          CALL calculate_rho_elec(ks_env=ks_env, &
     247              :                                  matrix_p=rho_ao_aux(ispin)%matrix, &
     248              :                                  rho=rho_r_aux(ispin), &
     249              :                                  rho_gspace=rho_g_aux(ispin), &
     250              :                                  total_rho=tot_rho_r_aux(ispin), &
     251              :                                  soft_valid=.FALSE., &
     252              :                                  basis_type=basis_type, &
     253        28238 :                                  task_list_external=task_list)
     254              : 
     255              :       END DO
     256              : 
     257              :       !If GAPW, also need to prepare the atomic densities
     258        12902 :       IF (gapw) THEN
     259              : 
     260              :          CALL calculate_rho_atom_coeff(qs_env, rho_ao_aux, &
     261              :                                        rho_atom_set=admm_env%admm_gapw_env%local_rho_set%rho_atom_set, &
     262              :                                        qs_kind_set=admm_env%admm_gapw_env%admm_kind_set, &
     263         4596 :                                        oce=admm_env%admm_gapw_env%oce, sab=admm_env%sab_aux_fit, para_env=para_env)
     264              : 
     265              :          CALL prepare_gapw_den(qs_env, local_rho_set=admm_env%admm_gapw_env%local_rho_set, &
     266         4596 :                                do_rho0=.FALSE., kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
     267              :       END IF
     268              : 
     269        12902 :       IF (dft_control%nspins == 1) THEN
     270        10468 :          admm_env%gsi(3) = admm_env%gsi(1)
     271              :       ELSE
     272         2434 :          admm_env%gsi(3) = (admm_env%gsi(1) + admm_env%gsi(2))/2.0_dp
     273              :       END IF
     274              : 
     275        12902 :       CALL qs_rho_set(rho_aux_fit, rho_r_valid=.TRUE., rho_g_valid=.TRUE.)
     276              : 
     277        12902 :       CALL timestop(handle)
     278              : 
     279        12902 :    END SUBROUTINE admm_mo_calc_rho_aux
     280              : 
     281              : ! **************************************************************************************************
     282              : !> \brief ...
     283              : !> \param qs_env ...
     284              : ! **************************************************************************************************
     285          154 :    SUBROUTINE admm_mo_calc_rho_aux_kp(qs_env)
     286              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     287              : 
     288              :       CHARACTER(len=*), PARAMETER :: routineN = 'admm_mo_calc_rho_aux_kp'
     289              : 
     290              :       CHARACTER(LEN=default_string_length)               :: basis_type
     291              :       INTEGER                                            :: handle, i, igroup, ik, ikp, img, indx, &
     292              :                                                             ispin, kplocal, kpmax, nao_aux_fit, &
     293              :                                                             nao_orb, natom, nkp, nkp_groups, nmo, &
     294              :                                                             nspins
     295              :       INTEGER, DIMENSION(2)                              :: kp_range
     296          154 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
     297          154 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     298              :       LOGICAL                                            :: gapw, my_kpgrp, pmat_from_rs, &
     299              :                                                             use_real_wfn
     300              :       REAL(dp)                                           :: maxval_mos, nelec_aux(2), nelec_orb(2), &
     301              :                                                             tmp
     302          154 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occ_num, occ_num_aux, tot_rho_r_aux
     303          154 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
     304              :       TYPE(admm_type), POINTER                           :: admm_env
     305          154 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:, :) :: info
     306              :       TYPE(cp_cfm_type)                                  :: cA, cmo_coeff, cmo_coeff_aux_fit, &
     307              :                                                             cpmatrix, cwork_aux_aux, cwork_aux_orb
     308              :       TYPE(cp_fm_struct_type), POINTER                   :: mo_struct, mo_struct_aux_fit, &
     309              :                                                             struct_aux_aux, struct_aux_orb, &
     310              :                                                             struct_orb_orb
     311              :       TYPE(cp_fm_type)                                   :: fmdummy, work_aux_orb, work_orb_orb, &
     312              :                                                             work_orb_orb2
     313              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_coeff_aux_fit
     314          154 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao
     315          154 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s, matrix_s_aux_fit, rho_ao_aux, &
     316          154 :                                                             rho_ao_orb
     317              :       TYPE(dbcsr_type)                                   :: pmatrix_tmp
     318          154 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: pmatrix
     319              :       TYPE(dft_control_type), POINTER                    :: dft_control
     320              :       TYPE(kpoint_env_type), POINTER                     :: kp
     321              :       TYPE(kpoint_type), POINTER                         :: kpoints
     322          154 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos, mos_aux_fit
     323          154 :       TYPE(mo_set_type), DIMENSION(:, :), POINTER        :: mos_aux_fit_kp, mos_kp
     324              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     325              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     326          154 :          POINTER                                         :: sab_aux_fit, sab_kp
     327          154 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g_aux
     328          154 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r_aux
     329              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     330              :       TYPE(qs_rho_type), POINTER                         :: rho_aux_fit, rho_orb
     331              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     332              :       TYPE(task_list_type), POINTER                      :: task_list
     333              : 
     334          154 :       CALL timeset(routineN, handle)
     335              : 
     336          154 :       NULLIFY (ks_env, admm_env, mos, mos_aux_fit, matrix_s, rho_orb, &
     337          154 :                matrix_s_aux_fit, rho_aux_fit, rho_ao_orb, &
     338          154 :                para_env, rho_g_aux, rho_r_aux, rho_ao_aux, tot_rho_r_aux, &
     339          154 :                kpoints, sab_aux_fit, sab_kp, kp, &
     340          154 :                struct_orb_orb, struct_aux_orb, struct_aux_aux, mo_struct, mo_struct_aux_fit)
     341              : 
     342              :       CALL get_qs_env(qs_env, &
     343              :                       ks_env=ks_env, &
     344              :                       admm_env=admm_env, &
     345              :                       dft_control=dft_control, &
     346              :                       kpoints=kpoints, &
     347              :                       natom=natom, &
     348              :                       scf_env=scf_env, &
     349              :                       matrix_s_kp=matrix_s, &
     350          154 :                       rho=rho_orb)
     351              :       CALL get_admm_env(admm_env, &
     352              :                         rho_aux_fit=rho_aux_fit, &
     353              :                         matrix_s_aux_fit_kp=matrix_s_aux_fit, &
     354          154 :                         sab_aux_fit=sab_aux_fit)
     355          154 :       gapw = admm_env%do_gapw
     356              : 
     357              :       CALL qs_rho_get(rho_aux_fit, &
     358              :                       rho_ao_kp=rho_ao_aux, &
     359              :                       rho_g=rho_g_aux, &
     360              :                       rho_r=rho_r_aux, &
     361          154 :                       tot_rho_r=tot_rho_r_aux)
     362              : 
     363          154 :       CALL qs_rho_get(rho_orb, rho_ao_kp=rho_ao_orb)
     364              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
     365              :                            nkp_groups=nkp_groups, kp_dist=kp_dist, &
     366          154 :                            cell_to_index=cell_to_index, sab_nl=sab_kp)
     367              : 
     368              :       ! the temporary DBCSR matrices for the rskp_transform we have to manually allocate
     369              :       ! index 1 => real, index 2 => imaginary
     370          462 :       ALLOCATE (pmatrix(2))
     371              :       CALL dbcsr_create(pmatrix(1), template=matrix_s(1, 1)%matrix, &
     372          154 :                         matrix_type=dbcsr_type_symmetric)
     373              :       CALL dbcsr_create(pmatrix(2), template=matrix_s(1, 1)%matrix, &
     374          154 :                         matrix_type=dbcsr_type_antisymmetric)
     375              :       CALL dbcsr_create(pmatrix_tmp, template=matrix_s(1, 1)%matrix, &
     376          154 :                         matrix_type=dbcsr_type_no_symmetry)
     377          154 :       CALL cp_dbcsr_alloc_block_from_nbl(pmatrix(1), sab_kp)
     378          154 :       CALL cp_dbcsr_alloc_block_from_nbl(pmatrix(2), sab_kp)
     379              : 
     380          154 :       nao_aux_fit = admm_env%nao_aux_fit
     381          154 :       nao_orb = admm_env%nao_orb
     382          154 :       nspins = dft_control%nspins
     383              : 
     384              :       !Create fm and cfm work matrices, for each KP subgroup
     385              :       CALL cp_fm_struct_create(struct_orb_orb, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
     386          154 :                                nrow_global=nao_orb, ncol_global=nao_orb)
     387          154 :       CALL cp_fm_create(work_orb_orb, struct_orb_orb)
     388          154 :       CALL cp_fm_create(work_orb_orb2, struct_orb_orb)
     389              : 
     390              :       CALL cp_fm_struct_create(struct_aux_aux, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
     391          154 :                                nrow_global=nao_aux_fit, ncol_global=nao_aux_fit)
     392              : 
     393              :       CALL cp_fm_struct_create(struct_aux_orb, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
     394          154 :                                nrow_global=nao_aux_fit, ncol_global=nao_orb)
     395          154 :       CALL cp_fm_create(work_aux_orb, struct_orb_orb)
     396              : 
     397          154 :       IF (.NOT. use_real_wfn) THEN
     398          154 :          CALL cp_cfm_create(cpmatrix, struct_orb_orb)
     399              : 
     400          154 :          CALL cp_cfm_create(cwork_aux_aux, struct_aux_aux)
     401              : 
     402          154 :          CALL cp_cfm_create(cA, struct_aux_orb)
     403          154 :          CALL cp_cfm_create(cwork_aux_orb, struct_aux_orb)
     404              : 
     405          154 :          CALL get_kpoint_env(kpoints%kp_env(1)%kpoint_env, mos=mos_kp)
     406          154 :          mos => mos_kp(1, :)
     407          154 :          CALL get_mo_set(mos(1), mo_coeff=mo_coeff)
     408          154 :          CALL cp_fm_get_info(mo_coeff, matrix_struct=mo_struct)
     409          154 :          CALL cp_cfm_create(cmo_coeff, mo_struct)
     410              : 
     411          154 :          CALL get_kpoint_env(kpoints%kp_aux_env(1)%kpoint_env, mos=mos_aux_fit_kp)
     412          154 :          mos => mos_aux_fit_kp(1, :)
     413          154 :          CALL get_mo_set(mos(1), mo_coeff=mo_coeff_aux_fit)
     414          154 :          CALL cp_fm_get_info(mo_coeff_aux_fit, matrix_struct=mo_struct_aux_fit)
     415          154 :          CALL cp_cfm_create(cmo_coeff_aux_fit, mo_struct_aux_fit)
     416              :       END IF
     417              : 
     418          154 :       CALL cp_fm_struct_release(struct_orb_orb)
     419          154 :       CALL cp_fm_struct_release(struct_aux_aux)
     420          154 :       CALL cp_fm_struct_release(struct_aux_orb)
     421              : 
     422          154 :       para_env => kpoints%blacs_env_all%para_env
     423          154 :       kplocal = kp_range(2) - kp_range(1) + 1
     424          462 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
     425              : 
     426              :       !We querry the maximum absolute value of the KP MOs to see if they are populated at all. If not, we
     427              :       !need to get the KP Pmat from the RS ones (happens at first SCF step, for example)
     428          154 :       maxval_mos = 0.0_dp
     429         1378 :       DO ikp = 1, kplocal
     430         1224 :          CALL get_kpoint_env(kpoints%kp_env(ikp)%kpoint_env, mos=mos_kp)
     431         2725 :          DO ispin = 1, nspins
     432         1347 :             mos => mos_kp(1, :)
     433         1347 :             CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
     434        82467 :             maxval_mos = MAX(maxval_mos, MAXVAL(ABS(mo_coeff%local_data)))
     435              : 
     436         2571 :             IF (.NOT. use_real_wfn) THEN
     437         1347 :                mos => mos_kp(2, :)
     438         1347 :                CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
     439        82467 :                maxval_mos = MAX(maxval_mos, MAXVAL(ABS(mo_coeff%local_data)))
     440              :             END IF
     441              :          END DO
     442              :       END DO
     443          154 :       CALL para_env%sum(maxval_mos) !I think para_env is the global one
     444              : 
     445          154 :       pmat_from_rs = .FALSE.
     446          154 :       IF (maxval_mos < EPSILON(0.0_dp)) pmat_from_rs = .TRUE.
     447              : 
     448              :       !TODO: issue a warning when doing ADMM with ATOMIC guess. If small number of K-points => leads to bad things
     449              : 
     450         7390 :       ALLOCATE (info(nkp*nspins, 2))
     451              :       !Start communication: only P matrix, and only if required
     452          154 :       indx = 0
     453          154 :       IF (pmat_from_rs) THEN
     454          208 :          DO ikp = 1, kpmax
     455          424 :             DO ispin = 1, nspins
     456          824 :                DO igroup = 1, nkp_groups
     457              :                   ! number of current kpoint
     458          432 :                   ik = kp_dist(1, igroup) + ikp - 1
     459          432 :                   IF (ik > kp_dist(2, igroup)) CYCLE
     460          418 :                   my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
     461          418 :                   indx = indx + 1
     462              : 
     463              :                   ! FT of matrices P if required, then transfer to FM type
     464          418 :                   IF (use_real_wfn) THEN
     465            0 :                      CALL dbcsr_set(pmatrix(1), 0.0_dp)
     466              :                      CALL rskp_transform(rmatrix=pmatrix(1), rsmat=rho_ao_orb, ispin=ispin, &
     467            0 :                                          xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_kp)
     468            0 :                      CALL dbcsr_desymmetrize(pmatrix(1), pmatrix_tmp)
     469            0 :                      CALL copy_dbcsr_to_fm(pmatrix_tmp, admm_env%work_orb_orb)
     470              :                   ELSE
     471          418 :                      CALL dbcsr_set(pmatrix(1), 0.0_dp)
     472          418 :                      CALL dbcsr_set(pmatrix(2), 0.0_dp)
     473              :                      CALL rskp_transform(rmatrix=pmatrix(1), cmatrix=pmatrix(2), rsmat=rho_ao_orb, ispin=ispin, &
     474          418 :                                          xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_kp)
     475          418 :                      CALL dbcsr_desymmetrize(pmatrix(1), pmatrix_tmp)
     476          418 :                      CALL copy_dbcsr_to_fm(pmatrix_tmp, admm_env%work_orb_orb)
     477          418 :                      CALL dbcsr_desymmetrize(pmatrix(2), pmatrix_tmp)
     478          418 :                      CALL copy_dbcsr_to_fm(pmatrix_tmp, admm_env%work_orb_orb2)
     479              :                   END IF
     480              : 
     481          634 :                   IF (my_kpgrp) THEN
     482          209 :                      CALL cp_fm_start_copy_general(admm_env%work_orb_orb, work_orb_orb, para_env, info(indx, 1))
     483          209 :                      IF (.NOT. use_real_wfn) THEN
     484          209 :                         CALL cp_fm_start_copy_general(admm_env%work_orb_orb2, work_orb_orb2, para_env, info(indx, 2))
     485              :                      END IF
     486              :                   ELSE
     487          209 :                      CALL cp_fm_start_copy_general(admm_env%work_orb_orb, fmdummy, para_env, info(indx, 1))
     488          209 :                      IF (.NOT. use_real_wfn) THEN
     489          209 :                         CALL cp_fm_start_copy_general(admm_env%work_orb_orb2, fmdummy, para_env, info(indx, 2))
     490              :                      END IF
     491              :                   END IF !my_kpgrp
     492              :                END DO
     493              :             END DO
     494              :          END DO
     495              :       END IF !pmat_from_rs
     496              : 
     497              :       indx = 0
     498         1418 :       DO ikp = 1, kpmax
     499         2810 :          DO ispin = 1, nspins
     500         4176 :             DO igroup = 1, nkp_groups
     501              :                ! number of current kpoint
     502         2784 :                ik = kp_dist(1, igroup) + ikp - 1
     503         2784 :                IF (ik > kp_dist(2, igroup)) CYCLE
     504         2694 :                my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
     505         2694 :                indx = indx + 1
     506         4086 :                IF (my_kpgrp .AND. pmat_from_rs) THEN
     507          209 :                   CALL cp_fm_finish_copy_general(work_orb_orb, info(indx, 1))
     508          209 :                   IF (.NOT. use_real_wfn) THEN
     509          209 :                      CALL cp_fm_finish_copy_general(work_orb_orb2, info(indx, 2))
     510          209 :                      CALL cp_fm_to_cfm(work_orb_orb, work_orb_orb2, cpmatrix)
     511              :                   END IF
     512              :                END IF
     513              :             END DO
     514              : 
     515         1392 :             IF (ikp > kplocal) CYCLE
     516         2611 :             IF (use_real_wfn) THEN
     517              : 
     518            0 :                nmo = admm_env%nmo(ispin)
     519              :                !! Each kpoint group has now information on a kpoint for which to calculate the MOS_aux
     520            0 :                CALL get_kpoint_env(kpoints%kp_env(ikp)%kpoint_env, mos=mos_kp)
     521            0 :                CALL get_kpoint_env(kpoints%kp_aux_env(ikp)%kpoint_env, mos=mos_aux_fit_kp)
     522            0 :                mos => mos_kp(1, :)
     523            0 :                mos_aux_fit => mos_aux_fit_kp(1, :)
     524              : 
     525            0 :                CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, occupation_numbers=occ_num)
     526              :                CALL get_mo_set(mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit, &
     527            0 :                                occupation_numbers=occ_num_aux)
     528              : 
     529            0 :                kp => kpoints%kp_aux_env(ikp)%kpoint_env
     530              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_orb, 1.0_dp, kp%amat(1, 1), &
     531            0 :                                   mo_coeff, 0.0_dp, mo_coeff_aux_fit)
     532              : 
     533            0 :                occ_num_aux(1:nmo) = occ_num(1:nmo)
     534              : 
     535            0 :                IF (pmat_from_rs) THEN
     536              :                   !We project on the AUX basis: P_aux = A * P *A^T
     537              :                   CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, 1.0_dp, kp%amat(1, 1), &
     538            0 :                                      work_orb_orb, 0.0_dp, work_aux_orb)
     539              :                   CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nao_orb, 1.0_dp, work_aux_orb, &
     540            0 :                                      kp%amat(1, 1), 0.0_dp, kpoints%kp_aux_env(ikp)%kpoint_env%pmat(1, ispin))
     541              :                END IF
     542              : 
     543              :             ELSE !complex wfn
     544              : 
     545              :                !construct the ORB MOs in complex format
     546         1347 :                nmo = admm_env%nmo(ispin)
     547         1347 :                CALL get_kpoint_env(kpoints%kp_env(ikp)%kpoint_env, mos=mos_kp)
     548         1347 :                mos => mos_kp(1, :) !real
     549         1347 :                CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
     550         1347 :                CALL cp_cfm_scale_and_add_fm(z_zero, cmo_coeff, z_one, mo_coeff)
     551         1347 :                mos => mos_kp(2, :) !complex
     552         1347 :                CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
     553         1347 :                CALL cp_cfm_scale_and_add_fm(z_one, cmo_coeff, gaussi, mo_coeff)
     554              : 
     555              :                !project
     556         1347 :                kp => kpoints%kp_aux_env(ikp)%kpoint_env
     557         1347 :                CALL cp_fm_to_cfm(kp%amat(1, 1), kp%amat(2, 1), cA)
     558              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_orb, &
     559         1347 :                                   z_one, cA, cmo_coeff, z_zero, cmo_coeff_aux_fit)
     560              : 
     561              :                !write result back to KP MOs
     562         1347 :                CALL get_kpoint_env(kpoints%kp_aux_env(ikp)%kpoint_env, mos=mos_aux_fit_kp)
     563         1347 :                mos_aux_fit => mos_aux_fit_kp(1, :)
     564         1347 :                CALL get_mo_set(mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit)
     565         1347 :                CALL cp_cfm_to_fm(cmo_coeff_aux_fit, mtargetr=mo_coeff_aux_fit)
     566         1347 :                mos_aux_fit => mos_aux_fit_kp(2, :)
     567         1347 :                CALL get_mo_set(mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit)
     568         1347 :                CALL cp_cfm_to_fm(cmo_coeff_aux_fit, mtargeti=mo_coeff_aux_fit)
     569              : 
     570         4041 :                DO i = 1, 2
     571         2694 :                   mos => mos_kp(i, :)
     572         2694 :                   CALL get_mo_set(mos(ispin), occupation_numbers=occ_num)
     573         2694 :                   mos_aux_fit => mos_aux_fit_kp(i, :)
     574         2694 :                   CALL get_mo_set(mos_aux_fit(ispin), occupation_numbers=occ_num_aux)
     575        19647 :                   occ_num_aux(:) = occ_num(:)
     576              :                END DO
     577              : 
     578         1347 :                IF (pmat_from_rs) THEN
     579              :                   CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, z_one, cA, &
     580          209 :                                      cpmatrix, z_zero, cwork_aux_orb)
     581              :                   CALL parallel_gemm('N', 'C', nao_aux_fit, nao_aux_fit, nao_orb, z_one, cwork_aux_orb, &
     582          209 :                                      cA, z_zero, cwork_aux_aux)
     583              : 
     584              :                   CALL cp_cfm_to_fm(cwork_aux_aux, mtargetr=kpoints%kp_aux_env(ikp)%kpoint_env%pmat(1, ispin), &
     585          209 :                                     mtargeti=kpoints%kp_aux_env(ikp)%kpoint_env%pmat(2, ispin))
     586              :                END IF
     587              :             END IF
     588              : 
     589              :          END DO
     590              :       END DO
     591              : 
     592              :       !Clean-up communication
     593          154 :       IF (pmat_from_rs) THEN
     594          450 :          DO indx = 1, SIZE(info, 1)
     595          418 :             CALL cp_fm_cleanup_copy_general(info(indx, 1))
     596          450 :             IF (.NOT. use_real_wfn) CALL cp_fm_cleanup_copy_general(info(indx, 2))
     597              :          END DO
     598              :       END IF
     599              : 
     600         5696 :       DEALLOCATE (info)
     601          154 :       CALL dbcsr_release(pmatrix(1))
     602          154 :       CALL dbcsr_release(pmatrix(2))
     603          154 :       CALL dbcsr_release(pmatrix_tmp)
     604              : 
     605          154 :       CALL cp_fm_release(work_orb_orb)
     606          154 :       CALL cp_fm_release(work_orb_orb2)
     607          154 :       CALL cp_fm_release(work_aux_orb)
     608          154 :       IF (.NOT. use_real_wfn) THEN
     609          154 :          CALL cp_cfm_release(cpmatrix)
     610          154 :          CALL cp_cfm_release(cwork_aux_aux)
     611          154 :          CALL cp_cfm_release(cwork_aux_orb)
     612          154 :          CALL cp_cfm_release(cA)
     613          154 :          CALL cp_cfm_release(cmo_coeff)
     614          154 :          CALL cp_cfm_release(cmo_coeff_aux_fit)
     615              :       END IF
     616              : 
     617          154 :       IF (.NOT. pmat_from_rs) CALL kpoint_density_matrices(kpoints, for_aux_fit=.TRUE.)
     618              :       CALL kpoint_density_transform(kpoints, rho_ao_aux, .FALSE., &
     619              :                                     matrix_s_aux_fit(1, 1)%matrix, sab_aux_fit, &
     620          154 :                                     admm_env%scf_work_aux_fit, for_aux_fit=.TRUE.)
     621              : 
     622              :       !ADMMQ, ADMMP, ADMMS
     623          154 :       IF (admm_env%do_admmq .OR. admm_env%do_admmp .OR. admm_env%do_admms) THEN
     624              : 
     625           94 :          CALL cite_reference(Merlot2014)
     626              : 
     627           94 :          nelec_orb = 0.0_dp
     628           94 :          nelec_aux = 0.0_dp
     629          376 :          admm_env%n_large_basis = 0.0_dp
     630              :          !Note: we can take the trace of the symmetric-typed matrices as P_mu^0,nu^b = P_nu^0,mu^-b
     631              :          !      and because of the sum over all images, all atomic blocks are accounted for
     632         3680 :          DO img = 1, dft_control%nimages
     633         7496 :             DO ispin = 1, dft_control%nspins
     634         3816 :                CALL dbcsr_dot(rho_ao_orb(ispin, img)%matrix, matrix_s(1, img)%matrix, tmp)
     635         3816 :                nelec_orb(ispin) = nelec_orb(ispin) + tmp
     636         3816 :                CALL dbcsr_dot(rho_ao_aux(ispin, img)%matrix, matrix_s_aux_fit(1, img)%matrix, tmp)
     637         7402 :                nelec_aux(ispin) = nelec_aux(ispin) + tmp
     638              :             END DO
     639              :          END DO
     640              : 
     641          202 :          DO ispin = 1, dft_control%nspins
     642          108 :             admm_env%n_large_basis(ispin) = nelec_orb(ispin)
     643          202 :             admm_env%gsi(ispin) = nelec_orb(ispin)/nelec_aux(ispin)
     644              :          END DO
     645              : 
     646           94 :          IF (admm_env%charge_constrain) THEN
     647         3102 :             DO img = 1, dft_control%nimages
     648         6354 :                DO ispin = 1, dft_control%nspins
     649         6274 :                   CALL dbcsr_scale(rho_ao_aux(ispin, img)%matrix, admm_env%gsi(ispin))
     650              :                END DO
     651              :             END DO
     652              :          END IF
     653              : 
     654           94 :          IF (dft_control%nspins == 1) THEN
     655           80 :             admm_env%gsi(3) = admm_env%gsi(1)
     656              :          ELSE
     657           14 :             admm_env%gsi(3) = (admm_env%gsi(1) + admm_env%gsi(2))/2.0_dp
     658              :          END IF
     659              :       END IF
     660              : 
     661          154 :       basis_type = "AUX_FIT"
     662          154 :       task_list => admm_env%task_list_aux_fit
     663          154 :       IF (gapw) THEN
     664           84 :          basis_type = "AUX_FIT_SOFT"
     665           84 :          task_list => admm_env%admm_gapw_env%task_list
     666              :       END IF
     667              : 
     668          332 :       DO ispin = 1, nspins
     669          178 :          rho_ao => rho_ao_aux(ispin, :)
     670              :          CALL calculate_rho_elec(ks_env=ks_env, &
     671              :                                  matrix_p_kp=rho_ao, &
     672              :                                  rho=rho_r_aux(ispin), &
     673              :                                  rho_gspace=rho_g_aux(ispin), &
     674              :                                  total_rho=tot_rho_r_aux(ispin), &
     675              :                                  soft_valid=.FALSE., &
     676              :                                  basis_type=basis_type, &
     677          332 :                                  task_list_external=task_list)
     678              :       END DO
     679              : 
     680          154 :       IF (gapw) THEN
     681              :          CALL calculate_rho_atom_coeff(qs_env, rho_ao_aux, &
     682              :                                        rho_atom_set=admm_env%admm_gapw_env%local_rho_set%rho_atom_set, &
     683              :                                        qs_kind_set=admm_env%admm_gapw_env%admm_kind_set, &
     684              :                                        oce=admm_env%admm_gapw_env%oce, &
     685           84 :                                        sab=admm_env%sab_aux_fit, para_env=para_env)
     686              : 
     687              :          CALL prepare_gapw_den(qs_env, local_rho_set=admm_env%admm_gapw_env%local_rho_set, &
     688           84 :                                do_rho0=.FALSE., kind_set_external=admm_env%admm_gapw_env%admm_kind_set)
     689              :       END IF
     690              : 
     691          154 :       CALL qs_rho_set(rho_aux_fit, rho_r_valid=.TRUE., rho_g_valid=.TRUE.)
     692              : 
     693          154 :       CALL timestop(handle)
     694              : 
     695          616 :    END SUBROUTINE admm_mo_calc_rho_aux_kp
     696              : 
     697              : ! **************************************************************************************************
     698              : !> \brief Adds the GAPW exchange contribution to the aux_fit ks matrices
     699              : !> \param qs_env ...
     700              : !> \param calculate_forces ...
     701              : ! **************************************************************************************************
     702         4718 :    SUBROUTINE admm_update_ks_atom(qs_env, calculate_forces)
     703              : 
     704              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     705              :       LOGICAL, INTENT(IN)                                :: calculate_forces
     706              : 
     707              :       CHARACTER(len=*), PARAMETER :: routineN = 'admm_update_ks_atom'
     708              : 
     709              :       INTEGER                                            :: handle, img, ispin
     710              :       REAL(dp)                                           :: force_fac(2)
     711              :       TYPE(admm_type), POINTER                           :: admm_env
     712         4718 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_aux_fit, &
     713         4718 :                                                             matrix_ks_aux_fit_dft, &
     714         4718 :                                                             matrix_ks_aux_fit_hfx, rho_ao_aux
     715              :       TYPE(dft_control_type), POINTER                    :: dft_control
     716              :       TYPE(qs_rho_type), POINTER                         :: rho_aux_fit
     717              : 
     718         4718 :       NULLIFY (matrix_ks_aux_fit, matrix_ks_aux_fit_dft, matrix_ks_aux_fit_hfx, rho_ao_aux, rho_aux_fit)
     719         4718 :       NULLIFY (admm_env, dft_control)
     720              : 
     721         4718 :       CALL timeset(routineN, handle)
     722              : 
     723         4718 :       CALL get_qs_env(qs_env, admm_env=admm_env, dft_control=dft_control)
     724              :       CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit, matrix_ks_aux_fit_kp=matrix_ks_aux_fit, &
     725              :                         matrix_ks_aux_fit_dft_kp=matrix_ks_aux_fit_dft, &
     726         4718 :                         matrix_ks_aux_fit_hfx_kp=matrix_ks_aux_fit_hfx)
     727         4718 :       CALL qs_rho_get(rho_aux_fit, rho_ao_kp=rho_ao_aux)
     728              : 
     729              :       !In case of ADMMS or ADMMP, need to scale the forces stemming from DFT exchagne correction
     730        14154 :       force_fac = 1.0_dp
     731         4718 :       IF (admm_env%do_admms) THEN
     732          298 :          DO ispin = 1, dft_control%nspins
     733          298 :             force_fac(ispin) = admm_env%gsi(ispin)**(2.0_dp/3.0_dp)
     734              :          END DO
     735         4600 :       ELSE IF (admm_env%do_admmp) THEN
     736          752 :          DO ispin = 1, dft_control%nspins
     737          752 :             force_fac(ispin) = admm_env%gsi(ispin)**2
     738              :          END DO
     739              :       END IF
     740              : 
     741              :       CALL update_ks_atom(qs_env, matrix_ks_aux_fit, rho_ao_aux, calculate_forces, tddft=.FALSE., &
     742              :                           rho_atom_external=admm_env%admm_gapw_env%local_rho_set%rho_atom_set, &
     743              :                           kind_set_external=admm_env%admm_gapw_env%admm_kind_set, &
     744              :                           oce_external=admm_env%admm_gapw_env%oce, &
     745         4718 :                           sab_external=admm_env%sab_aux_fit, fscale=force_fac)
     746              : 
     747              :       !Following the logic of sum_up_and_integrate to recover the pure DFT exchange contribution
     748        12640 :       DO img = 1, dft_control%nimages
     749        21564 :          DO ispin = 1, dft_control%nspins
     750              :             CALL dbcsr_add(matrix_ks_aux_fit_dft(ispin, img)%matrix, matrix_ks_aux_fit(ispin, img)%matrix, &
     751         8924 :                            0.0_dp, -1.0_dp)
     752              :             CALL dbcsr_add(matrix_ks_aux_fit_dft(ispin, img)%matrix, matrix_ks_aux_fit_hfx(ispin, img)%matrix, &
     753        16846 :                            1.0_dp, 1.0_dp)
     754              :          END DO
     755              :       END DO
     756              : 
     757         4718 :       CALL timestop(handle)
     758              : 
     759         4718 :    END SUBROUTINE admm_update_ks_atom
     760              : 
     761              : ! **************************************************************************************************
     762              : !> \brief ...
     763              : !> \param qs_env ...
     764              : ! **************************************************************************************************
     765        13044 :    SUBROUTINE admm_mo_merge_ks_matrix(qs_env)
     766              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     767              : 
     768              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'admm_mo_merge_ks_matrix'
     769              : 
     770              :       INTEGER                                            :: handle
     771              :       TYPE(admm_type), POINTER                           :: admm_env
     772              :       TYPE(dft_control_type), POINTER                    :: dft_control
     773              : 
     774        13044 :       CALL timeset(routineN, handle)
     775        13044 :       NULLIFY (admm_env)
     776              : 
     777        13044 :       CALL get_qs_env(qs_env, admm_env=admm_env, dft_control=dft_control)
     778              : 
     779        13334 :       SELECT CASE (admm_env%purification_method)
     780              :       CASE (do_admm_purify_cauchy)
     781          290 :          CALL merge_ks_matrix_cauchy(qs_env)
     782              : 
     783              :       CASE (do_admm_purify_cauchy_subspace)
     784          154 :          CALL merge_ks_matrix_cauchy_subspace(qs_env)
     785              : 
     786              :       CASE (do_admm_purify_none)
     787        10924 :          IF (dft_control%nimages > 1) THEN
     788          154 :             CALL merge_ks_matrix_none_kp(qs_env)
     789              :          ELSE
     790        10770 :             CALL merge_ks_matrix_none(qs_env)
     791              :          END IF
     792              : 
     793              :       CASE (do_admm_purify_mo_diag, do_admm_purify_mo_no_diag)
     794              :          !do nothing
     795              :       CASE DEFAULT
     796        13044 :          CPABORT("admm_mo_merge_ks_matrix: unknown purification method")
     797              :       END SELECT
     798              : 
     799        13044 :       CALL timestop(handle)
     800              : 
     801        13044 :    END SUBROUTINE admm_mo_merge_ks_matrix
     802              : 
     803              : ! **************************************************************************************************
     804              : !> \brief ...
     805              : !> \param ispin ...
     806              : !> \param admm_env ...
     807              : !> \param mo_set ...
     808              : !> \param mo_coeff ...
     809              : !> \param mo_coeff_aux_fit ...
     810              : !> \param mo_derivs ...
     811              : !> \param mo_derivs_aux_fit ...
     812              : !> \param matrix_ks_aux_fit ...
     813              : ! **************************************************************************************************
     814         8000 :    SUBROUTINE admm_mo_merge_derivs(ispin, admm_env, mo_set, mo_coeff, mo_coeff_aux_fit, mo_derivs, &
     815         8000 :                                    mo_derivs_aux_fit, matrix_ks_aux_fit)
     816              :       INTEGER, INTENT(IN)                                :: ispin
     817              :       TYPE(admm_type), POINTER                           :: admm_env
     818              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
     819              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff, mo_coeff_aux_fit
     820              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mo_derivs, mo_derivs_aux_fit
     821              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks_aux_fit
     822              : 
     823              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'admm_mo_merge_derivs'
     824              : 
     825              :       INTEGER                                            :: handle
     826              : 
     827         8000 :       CALL timeset(routineN, handle)
     828              : 
     829         9100 :       SELECT CASE (admm_env%purification_method)
     830              :       CASE (do_admm_purify_mo_diag)
     831              :          CALL merge_mo_derivs_diag(ispin, admm_env, mo_set, mo_coeff, mo_coeff_aux_fit, &
     832         1100 :                                    mo_derivs, mo_derivs_aux_fit, matrix_ks_aux_fit)
     833              : 
     834              :       CASE (do_admm_purify_mo_no_diag)
     835          100 :          CALL merge_mo_derivs_no_diag(ispin, admm_env, mo_set, mo_derivs, matrix_ks_aux_fit)
     836              : 
     837              :       CASE (do_admm_purify_none, do_admm_purify_cauchy, do_admm_purify_cauchy_subspace)
     838              :          !do nothing
     839              :       CASE DEFAULT
     840         8000 :          CPABORT("admm_mo_merge_derivs: unknown purification method")
     841              :       END SELECT
     842              : 
     843         8000 :       CALL timestop(handle)
     844              : 
     845         8000 :    END SUBROUTINE admm_mo_merge_derivs
     846              : 
     847              : ! **************************************************************************************************
     848              : !> \brief ...
     849              : !> \param admm_env ...
     850              : !> \param matrix_s_aux_fit ...
     851              : !> \param matrix_s_mixed ...
     852              : !> \param mos ...
     853              : !> \param mos_aux_fit ...
     854              : !> \param geometry_did_change ...
     855              : ! **************************************************************************************************
     856        25812 :    SUBROUTINE admm_fit_mo_coeffs(admm_env, matrix_s_aux_fit, matrix_s_mixed, &
     857        12906 :                                  mos, mos_aux_fit, geometry_did_change)
     858              : 
     859              :       TYPE(admm_type), POINTER                           :: admm_env
     860              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s_aux_fit, matrix_s_mixed
     861              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos, mos_aux_fit
     862              :       LOGICAL, INTENT(IN)                                :: geometry_did_change
     863              : 
     864              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'admm_fit_mo_coeffs'
     865              : 
     866              :       INTEGER                                            :: handle
     867              : 
     868        12906 :       CALL timeset(routineN, handle)
     869              : 
     870        12906 :       IF (geometry_did_change) THEN
     871          908 :          CALL fit_mo_coeffs(admm_env, matrix_s_aux_fit, matrix_s_mixed)
     872              :       END IF
     873              : 
     874        13174 :       SELECT CASE (admm_env%purification_method)
     875              :       CASE (do_admm_purify_mo_no_diag, do_admm_purify_cauchy_subspace)
     876          268 :          CALL purify_mo_cholesky(admm_env, mos, mos_aux_fit)
     877              : 
     878              :       CASE (do_admm_purify_mo_diag)
     879         1562 :          CALL purify_mo_diag(admm_env, mos, mos_aux_fit)
     880              : 
     881              :       CASE DEFAULT
     882        12906 :          CALL purify_mo_none(admm_env, mos, mos_aux_fit)
     883              :       END SELECT
     884              : 
     885        12906 :       CALL timestop(handle)
     886              : 
     887        12906 :    END SUBROUTINE admm_fit_mo_coeffs
     888              : 
     889              : ! **************************************************************************************************
     890              : !> \brief Calculate S^-1, Q, B full-matrices given sparse S_tilde and Q
     891              : !> \param admm_env ...
     892              : !> \param matrix_s_aux_fit ...
     893              : !> \param matrix_s_mixed ...
     894              : ! **************************************************************************************************
     895          908 :    SUBROUTINE fit_mo_coeffs(admm_env, matrix_s_aux_fit, matrix_s_mixed)
     896              :       TYPE(admm_type), POINTER                           :: admm_env
     897              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s_aux_fit, matrix_s_mixed
     898              : 
     899              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'fit_mo_coeffs'
     900              : 
     901              :       INTEGER                                            :: handle, iatom, jatom, nao_aux_fit, &
     902              :                                                             nao_orb
     903          908 :       REAL(dp), DIMENSION(:, :), POINTER                 :: sparse_block
     904              :       TYPE(dbcsr_iterator_type)                          :: iter
     905              :       TYPE(dbcsr_type), POINTER                          :: matrix_s_tilde
     906              : 
     907          908 :       CALL timeset(routineN, handle)
     908              : 
     909          908 :       nao_aux_fit = admm_env%nao_aux_fit
     910          908 :       nao_orb = admm_env%nao_orb
     911              : 
     912              :       ! *** This part only depends on overlap matrices ==> needs only to be calculated if the geometry changed
     913              : 
     914          908 :       IF (.NOT. admm_env%block_fit) THEN
     915          900 :          CALL copy_dbcsr_to_fm(matrix_s_aux_fit(1)%matrix, admm_env%S_inv)
     916              :       ELSE
     917              :          NULLIFY (matrix_s_tilde)
     918            8 :          ALLOCATE (matrix_s_tilde)
     919              :          CALL dbcsr_create(matrix_s_tilde, template=matrix_s_aux_fit(1)%matrix, &
     920              :                            name='MATRIX s_tilde', &
     921            8 :                            matrix_type=dbcsr_type_symmetric)
     922              : 
     923            8 :          CALL dbcsr_copy(matrix_s_tilde, matrix_s_aux_fit(1)%matrix)
     924              : 
     925            8 :          CALL dbcsr_iterator_start(iter, matrix_s_tilde)
     926           48 :          DO WHILE (dbcsr_iterator_blocks_left(iter))
     927           40 :             CALL dbcsr_iterator_next_block(iter, iatom, jatom, sparse_block)
     928           48 :             IF (admm_env%block_map(iatom, jatom) == 0) THEN
     929          102 :                sparse_block = 0.0_dp
     930              :             END IF
     931              :          END DO
     932            8 :          CALL dbcsr_iterator_stop(iter)
     933            8 :          CALL copy_dbcsr_to_fm(matrix_s_tilde, admm_env%S_inv)
     934            8 :          CALL dbcsr_deallocate_matrix(matrix_s_tilde)
     935              :       END IF
     936              : 
     937          908 :       CALL cp_fm_uplo_to_full(admm_env%S_inv, admm_env%work_aux_aux)
     938          908 :       CALL cp_fm_to_fm(admm_env%S_inv, admm_env%S)
     939              : 
     940          908 :       CALL copy_dbcsr_to_fm(matrix_s_mixed(1)%matrix, admm_env%Q)
     941              : 
     942              :       !! Calculate S'_inverse
     943          908 :       CALL cp_fm_cholesky_decompose(admm_env%S_inv)
     944          908 :       CALL cp_fm_cholesky_invert(admm_env%S_inv)
     945              :       !! Symmetrize the guy
     946          908 :       CALL cp_fm_uplo_to_full(admm_env%S_inv, admm_env%work_aux_aux)
     947              : 
     948              :       !! Calculate A=S'^(-1)*Q
     949          908 :       IF (admm_env%block_fit) THEN
     950            8 :          CALL cp_fm_set_all(admm_env%A, 0.0_dp, 1.0_dp)
     951              :       ELSE
     952              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
     953              :                             1.0_dp, admm_env%S_inv, admm_env%Q, 0.0_dp, &
     954          900 :                             admm_env%A)
     955              : 
     956              :          ! this multiplication is apparent not need for purify_none
     957              :          !! B=Q^(T)*A
     958              :          CALL parallel_gemm('T', 'N', nao_orb, nao_orb, nao_aux_fit, &
     959              :                             1.0_dp, admm_env%Q, admm_env%A, 0.0_dp, &
     960          900 :                             admm_env%B)
     961              :       END IF
     962              : 
     963          908 :       CALL timestop(handle)
     964              : 
     965          908 :    END SUBROUTINE fit_mo_coeffs
     966              : 
     967              : ! **************************************************************************************************
     968              : !> \brief Calculates the MO coefficients for the auxiliary fitting basis set
     969              : !>        by minimizing int (psi_i - psi_aux_i)^2 using Lagrangian Multipliers
     970              : !>
     971              : !> \param admm_env The ADMM env
     972              : !> \param mos the MO's of the orbital basis set
     973              : !> \param mos_aux_fit the MO's of the auxiliary fitting basis set
     974              : !> \par History
     975              : !>      05.2008 created [Manuel Guidon]
     976              : !> \author Manuel Guidon
     977              : ! **************************************************************************************************
     978          268 :    SUBROUTINE purify_mo_cholesky(admm_env, mos, mos_aux_fit)
     979              : 
     980              :       TYPE(admm_type), POINTER                           :: admm_env
     981              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos, mos_aux_fit
     982              : 
     983              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'purify_mo_cholesky'
     984              : 
     985              :       INTEGER                                            :: handle, ispin, nao_aux_fit, nao_orb, &
     986              :                                                             nmo, nspins
     987              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_coeff_aux_fit
     988              : 
     989          268 :       CALL timeset(routineN, handle)
     990              : 
     991          268 :       nao_aux_fit = admm_env%nao_aux_fit
     992          268 :       nao_orb = admm_env%nao_orb
     993          268 :       nspins = SIZE(mos)
     994              : 
     995              :       ! *** Calculate the mo_coeffs for the fitting basis
     996          670 :       DO ispin = 1, nspins
     997          402 :          nmo = admm_env%nmo(ispin)
     998          402 :          IF (nmo == 0) CYCLE
     999              :          !! Lambda = C^(T)*B*C
    1000          402 :          CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
    1001          402 :          CALL get_mo_set(mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit)
    1002              :          CALL parallel_gemm('N', 'N', nao_orb, nmo, nao_orb, &
    1003              :                             1.0_dp, admm_env%B, mo_coeff, 0.0_dp, &
    1004          402 :                             admm_env%work_orb_nmo(ispin))
    1005              :          CALL parallel_gemm('T', 'N', nmo, nmo, nao_orb, &
    1006              :                             1.0_dp, mo_coeff, admm_env%work_orb_nmo(ispin), 0.0_dp, &
    1007          402 :                             admm_env%lambda(ispin))
    1008          402 :          CALL cp_fm_to_fm(admm_env%lambda(ispin), admm_env%work_nmo_nmo1(ispin))
    1009              : 
    1010          402 :          CALL cp_fm_cholesky_decompose(admm_env%work_nmo_nmo1(ispin))
    1011          402 :          CALL cp_fm_cholesky_invert(admm_env%work_nmo_nmo1(ispin))
    1012              :          !! Symmetrize the guy
    1013          402 :          CALL cp_fm_uplo_to_full(admm_env%work_nmo_nmo1(ispin), admm_env%lambda_inv(ispin))
    1014          402 :          CALL cp_fm_to_fm(admm_env%work_nmo_nmo1(ispin), admm_env%lambda_inv(ispin))
    1015              : 
    1016              :          !! ** C_hat = AC
    1017              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_orb, &
    1018              :                             1.0_dp, admm_env%A, mo_coeff, 0.0_dp, &
    1019          402 :                             admm_env%C_hat(ispin))
    1020          670 :          CALL cp_fm_to_fm(admm_env%C_hat(ispin), mo_coeff_aux_fit)
    1021              : 
    1022              :       END DO
    1023              : 
    1024          268 :       CALL timestop(handle)
    1025              : 
    1026          268 :    END SUBROUTINE purify_mo_cholesky
    1027              : 
    1028              : ! **************************************************************************************************
    1029              : !> \brief Calculates the MO coefficients for the auxiliary fitting basis set
    1030              : !>        by minimizing int (psi_i - psi_aux_i)^2 using Lagrangian Multipliers
    1031              : !>
    1032              : !> \param admm_env The ADMM env
    1033              : !> \param mos the MO's of the orbital basis set
    1034              : !> \param mos_aux_fit the MO's of the auxiliary fitting basis set
    1035              : !> \par History
    1036              : !>      05.2008 created [Manuel Guidon]
    1037              : !> \author Manuel Guidon
    1038              : ! **************************************************************************************************
    1039         1562 :    SUBROUTINE purify_mo_diag(admm_env, mos, mos_aux_fit)
    1040              : 
    1041              :       TYPE(admm_type), POINTER                           :: admm_env
    1042              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos, mos_aux_fit
    1043              : 
    1044              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'purify_mo_diag'
    1045              : 
    1046              :       INTEGER                                            :: handle, i, ispin, nao_aux_fit, nao_orb, &
    1047              :                                                             nmo, nspins
    1048         1562 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: eig_work
    1049              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_coeff_aux_fit
    1050              : 
    1051         1562 :       CALL timeset(routineN, handle)
    1052              : 
    1053         1562 :       nao_aux_fit = admm_env%nao_aux_fit
    1054         1562 :       nao_orb = admm_env%nao_orb
    1055         1562 :       nspins = SIZE(mos)
    1056              : 
    1057              :       ! *** Calculate the mo_coeffs for the fitting basis
    1058         3496 :       DO ispin = 1, nspins
    1059         1934 :          nmo = admm_env%nmo(ispin)
    1060         1934 :          IF (nmo == 0) CYCLE
    1061              :          !! Lambda = C^(T)*B*C
    1062         1934 :          CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
    1063         1934 :          CALL get_mo_set(mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit)
    1064              :          CALL parallel_gemm('N', 'N', nao_orb, nmo, nao_orb, &
    1065              :                             1.0_dp, admm_env%B, mo_coeff, 0.0_dp, &
    1066         1934 :                             admm_env%work_orb_nmo(ispin))
    1067              :          CALL parallel_gemm('T', 'N', nmo, nmo, nao_orb, &
    1068              :                             1.0_dp, mo_coeff, admm_env%work_orb_nmo(ispin), 0.0_dp, &
    1069         1934 :                             admm_env%lambda(ispin))
    1070         1934 :          CALL cp_fm_to_fm(admm_env%lambda(ispin), admm_env%work_nmo_nmo1(ispin))
    1071              : 
    1072              :          CALL cp_fm_syevd(admm_env%work_nmo_nmo1(ispin), admm_env%R(ispin), &
    1073         1934 :                           admm_env%eigvals_lambda(ispin)%eigvals%data)
    1074         5802 :          ALLOCATE (eig_work(nmo))
    1075         9638 :          DO i = 1, nmo
    1076         9638 :             eig_work(i) = 1.0_dp/SQRT(admm_env%eigvals_lambda(ispin)%eigvals%data(i))
    1077              :          END DO
    1078         1934 :          CALL cp_fm_to_fm(admm_env%R(ispin), admm_env%work_nmo_nmo1(ispin))
    1079         1934 :          CALL cp_fm_column_scale(admm_env%work_nmo_nmo1(ispin), eig_work)
    1080              :          CALL parallel_gemm('N', 'T', nmo, nmo, nmo, &
    1081              :                             1.0_dp, admm_env%work_nmo_nmo1(ispin), admm_env%R(ispin), 0.0_dp, &
    1082         1934 :                             admm_env%lambda_inv_sqrt(ispin))
    1083              :          CALL parallel_gemm('N', 'N', nao_orb, nmo, nmo, &
    1084              :                             1.0_dp, mo_coeff, admm_env%lambda_inv_sqrt(ispin), 0.0_dp, &
    1085         1934 :                             admm_env%work_orb_nmo(ispin))
    1086              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_orb, &
    1087              :                             1.0_dp, admm_env%A, admm_env%work_orb_nmo(ispin), 0.0_dp, &
    1088         1934 :                             mo_coeff_aux_fit)
    1089              : 
    1090         1934 :          CALL cp_fm_to_fm(mo_coeff_aux_fit, admm_env%C_hat(ispin))
    1091         1934 :          CALL cp_fm_set_all(admm_env%lambda_inv(ispin), 0.0_dp, 1.0_dp)
    1092         3496 :          DEALLOCATE (eig_work)
    1093              :       END DO
    1094              : 
    1095         1562 :       CALL timestop(handle)
    1096              : 
    1097         1562 :    END SUBROUTINE purify_mo_diag
    1098              : 
    1099              : ! **************************************************************************************************
    1100              : !> \brief ...
    1101              : !> \param admm_env ...
    1102              : !> \param mos ...
    1103              : !> \param mos_aux_fit ...
    1104              : ! **************************************************************************************************
    1105        11076 :    SUBROUTINE purify_mo_none(admm_env, mos, mos_aux_fit)
    1106              :       TYPE(admm_type), POINTER                           :: admm_env
    1107              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos, mos_aux_fit
    1108              : 
    1109              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'purify_mo_none'
    1110              : 
    1111              :       INTEGER                                            :: handle, ispin, nao_aux_fit, nao_orb, &
    1112              :                                                             nmo, nmo_mos, nspins
    1113        11076 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occ_num, occ_num_aux
    1114              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_coeff_aux_fit
    1115              : 
    1116        11076 :       CALL timeset(routineN, handle)
    1117              : 
    1118        11076 :       nao_aux_fit = admm_env%nao_aux_fit
    1119        11076 :       nao_orb = admm_env%nao_orb
    1120        11076 :       nspins = SIZE(mos)
    1121              : 
    1122        24080 :       DO ispin = 1, nspins
    1123        13004 :          nmo = admm_env%nmo(ispin)
    1124        13004 :          CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, occupation_numbers=occ_num, nmo=nmo_mos)
    1125              :          CALL get_mo_set(mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit, &
    1126        13004 :                          occupation_numbers=occ_num_aux)
    1127              : 
    1128              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_orb, &
    1129              :                             1.0_dp, admm_env%A, mo_coeff, 0.0_dp, &
    1130        13004 :                             mo_coeff_aux_fit)
    1131        13004 :          CALL cp_fm_to_fm(mo_coeff_aux_fit, admm_env%C_hat(ispin))
    1132              : 
    1133       142432 :          occ_num_aux(1:nmo) = occ_num(1:nmo)
    1134              :          ! XXXX should only be done first time XXXX
    1135        13004 :          CALL cp_fm_set_all(admm_env%lambda(ispin), 0.0_dp, 1.0_dp)
    1136        13004 :          CALL cp_fm_set_all(admm_env%lambda_inv(ispin), 0.0_dp, 1.0_dp)
    1137        37084 :          CALL cp_fm_set_all(admm_env%lambda_inv_sqrt(ispin), 0.0_dp, 1.0_dp)
    1138              :       END DO
    1139              : 
    1140        11076 :       CALL timestop(handle)
    1141              : 
    1142        11076 :    END SUBROUTINE purify_mo_none
    1143              : 
    1144              : ! **************************************************************************************************
    1145              : !> \brief ...
    1146              : !> \param admm_env ...
    1147              : !> \param mo_set ...
    1148              : !> \param density_matrix ...
    1149              : !> \param ispin ...
    1150              : !> \param blocked ...
    1151              : ! **************************************************************************************************
    1152          484 :    SUBROUTINE purify_dm_cauchy(admm_env, mo_set, density_matrix, ispin, blocked)
    1153              : 
    1154              :       TYPE(admm_type), POINTER                           :: admm_env
    1155              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
    1156              :       TYPE(dbcsr_type), POINTER                          :: density_matrix
    1157              :       INTEGER                                            :: ispin
    1158              :       LOGICAL, INTENT(IN)                                :: blocked
    1159              : 
    1160              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'purify_dm_cauchy'
    1161              : 
    1162              :       INTEGER                                            :: handle, i, nao_aux_fit, nao_orb, nmo, &
    1163              :                                                             nspins
    1164              :       REAL(KIND=dp)                                      :: pole
    1165              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff_aux_fit
    1166              : 
    1167          484 :       CALL timeset(routineN, handle)
    1168              : 
    1169          484 :       nao_aux_fit = admm_env%nao_aux_fit
    1170          484 :       nao_orb = admm_env%nao_orb
    1171          484 :       nmo = admm_env%nmo(ispin)
    1172              : 
    1173          484 :       nspins = SIZE(admm_env%P_to_be_purified)
    1174              : 
    1175          484 :       CALL get_mo_set(mo_set=mo_set, mo_coeff=mo_coeff_aux_fit)
    1176              : 
    1177              :       !! * For the time beeing, get the P to be purified from the mo_coeffs
    1178              :       !! * This needs to be replaced with the a block modified P
    1179              : 
    1180          484 :       IF (.NOT. blocked) THEN
    1181              :          CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nmo, &
    1182              :                             1.0_dp, mo_coeff_aux_fit, mo_coeff_aux_fit, 0.0_dp, &
    1183          250 :                             admm_env%P_to_be_purified(ispin))
    1184              :       END IF
    1185              : 
    1186          484 :       CALL cp_fm_to_fm(admm_env%S, admm_env%work_aux_aux)
    1187          484 :       CALL cp_fm_to_fm(admm_env%P_to_be_purified(ispin), admm_env%work_aux_aux2)
    1188              : 
    1189          484 :       CALL cp_fm_cholesky_decompose(admm_env%work_aux_aux)
    1190              : 
    1191          484 :       CALL cp_fm_cholesky_reduce(admm_env%work_aux_aux2, admm_env%work_aux_aux, itype=3)
    1192              : 
    1193              :       CALL cp_fm_syevd(admm_env%work_aux_aux2, admm_env%R_purify(ispin), &
    1194          484 :                        admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data)
    1195              : 
    1196              :       CALL cp_fm_cholesky_restore(admm_env%R_purify(ispin), nao_aux_fit, admm_env%work_aux_aux, &
    1197          484 :                                   admm_env%work_aux_aux3, op="MULTIPLY", pos="LEFT", transa="T")
    1198              : 
    1199          484 :       CALL cp_fm_to_fm(admm_env%work_aux_aux3, admm_env%R_purify(ispin))
    1200              : 
    1201              :       ! *** Construct Matrix M for Hadamard Product
    1202          484 :       CALL cp_fm_set_all(admm_env%M_purify(ispin), 0.0_dp)
    1203              :       pole = 0.0_dp
    1204         3140 :       DO i = 1, nao_aux_fit
    1205         2656 :          pole = Heaviside(admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(i) - 0.5_dp)
    1206         3140 :          CALL cp_fm_set_element(admm_env%M_purify(ispin), i, i, pole)
    1207              :       END DO
    1208          484 :       CALL cp_fm_uplo_to_full(admm_env%M_purify(ispin), admm_env%work_aux_aux)
    1209              : 
    1210          484 :       CALL copy_dbcsr_to_fm(density_matrix, admm_env%work_aux_aux3)
    1211          484 :       CALL cp_fm_uplo_to_full(admm_env%work_aux_aux3, admm_env%work_aux_aux)
    1212              : 
    1213              :       ! ** S^(-1)*R
    1214              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1215              :                          1.0_dp, admm_env%S_inv, admm_env%R_purify(ispin), 0.0_dp, &
    1216          484 :                          admm_env%work_aux_aux)
    1217              :       ! ** S^(-1)*R*M
    1218              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1219              :                          1.0_dp, admm_env%work_aux_aux, admm_env%M_purify(ispin), 0.0_dp, &
    1220          484 :                          admm_env%work_aux_aux2)
    1221              :       ! ** S^(-1)*R*M*R^T*S^(-1)
    1222              :       CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1223              :                          1.0_dp, admm_env%work_aux_aux2, admm_env%work_aux_aux, 0.0_dp, &
    1224          484 :                          admm_env%work_aux_aux3)
    1225              : 
    1226          484 :       CALL copy_fm_to_dbcsr(admm_env%work_aux_aux3, density_matrix, keep_sparsity=.TRUE.)
    1227              : 
    1228          484 :       IF (nspins == 1) THEN
    1229           96 :          CALL dbcsr_scale(density_matrix, 2.0_dp)
    1230              :       END IF
    1231              : 
    1232          484 :       CALL timestop(handle)
    1233              : 
    1234          484 :    END SUBROUTINE purify_dm_cauchy
    1235              : 
    1236              : ! **************************************************************************************************
    1237              : !> \brief ...
    1238              : !> \param qs_env ...
    1239              : ! **************************************************************************************************
    1240          290 :    SUBROUTINE merge_ks_matrix_cauchy(qs_env)
    1241              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1242              : 
    1243              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'merge_ks_matrix_cauchy'
    1244              : 
    1245              :       INTEGER                                            :: handle, i, iatom, ispin, j, jatom, &
    1246              :                                                             nao_aux_fit, nao_orb, nmo
    1247              :       REAL(dp)                                           :: eig_diff, pole, tmp
    1248          290 :       REAL(dp), DIMENSION(:, :), POINTER                 :: sparse_block
    1249              :       TYPE(admm_type), POINTER                           :: admm_env
    1250              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1251              :       TYPE(dbcsr_iterator_type)                          :: iter
    1252          290 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_ks_aux_fit
    1253              :       TYPE(dbcsr_type), POINTER                          :: matrix_k_tilde
    1254              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1255          290 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1256              : 
    1257          290 :       CALL timeset(routineN, handle)
    1258          290 :       NULLIFY (admm_env, dft_control, matrix_ks, matrix_ks_aux_fit, mos, mo_coeff)
    1259              : 
    1260              :       CALL get_qs_env(qs_env, &
    1261              :                       admm_env=admm_env, &
    1262              :                       dft_control=dft_control, &
    1263              :                       matrix_ks=matrix_ks, &
    1264          290 :                       mos=mos)
    1265          290 :       CALL get_admm_env(admm_env, matrix_ks_aux_fit=matrix_ks_aux_fit)
    1266              : 
    1267          774 :       DO ispin = 1, dft_control%nspins
    1268          484 :          nao_aux_fit = admm_env%nao_aux_fit
    1269          484 :          nao_orb = admm_env%nao_orb
    1270          484 :          nmo = admm_env%nmo(ispin)
    1271          484 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
    1272              : 
    1273          484 :          IF (.NOT. admm_env%block_dm) THEN
    1274              :             !** Get P from mo_coeffs, otherwise we have troubles with occupation numbers ...
    1275              :             CALL parallel_gemm('N', 'T', nao_orb, nao_orb, nmo, &
    1276              :                                1.0_dp, mo_coeff, mo_coeff, 0.0_dp, &
    1277          250 :                                admm_env%work_orb_orb)
    1278              : 
    1279              :             !! A*P
    1280              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, &
    1281              :                                1.0_dp, admm_env%A, admm_env%work_orb_orb, 0.0_dp, &
    1282          250 :                                admm_env%work_aux_orb2)
    1283              :             !! A*P*A^T
    1284              :             CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nao_orb, &
    1285              :                                1.0_dp, admm_env%work_aux_orb2, admm_env%A, 0.0_dp, &
    1286          250 :                                admm_env%P_to_be_purified(ispin))
    1287              : 
    1288              :          END IF
    1289              : 
    1290          484 :          CALL cp_fm_to_fm(admm_env%S, admm_env%work_aux_aux)
    1291          484 :          CALL cp_fm_to_fm(admm_env%P_to_be_purified(ispin), admm_env%work_aux_aux2)
    1292              : 
    1293          484 :          CALL cp_fm_cholesky_decompose(admm_env%work_aux_aux)
    1294              : 
    1295          484 :          CALL cp_fm_cholesky_reduce(admm_env%work_aux_aux2, admm_env%work_aux_aux, itype=3)
    1296              : 
    1297              :          CALL cp_fm_syevd(admm_env%work_aux_aux2, admm_env%R_purify(ispin), &
    1298          484 :                           admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data)
    1299              : 
    1300              :          CALL cp_fm_cholesky_restore(admm_env%R_purify(ispin), nao_aux_fit, admm_env%work_aux_aux, &
    1301          484 :                                      admm_env%work_aux_aux3, op="MULTIPLY", pos="LEFT", transa="T")
    1302              : 
    1303          484 :          CALL cp_fm_to_fm(admm_env%work_aux_aux3, admm_env%R_purify(ispin))
    1304              : 
    1305              :          ! *** Construct Matrix M for Hadamard Product
    1306          484 :          pole = 0.0_dp
    1307         3140 :          DO i = 1, nao_aux_fit
    1308        14156 :             DO j = i, nao_aux_fit
    1309              :                eig_diff = (admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(i) - &
    1310        11016 :                            admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(j))
    1311              :                ! *** two eigenvalues could be the degenerated. In that case use 2nd order formula for the poles
    1312        13672 :                IF (ABS(eig_diff) == 0.0_dp) THEN
    1313         2754 :                   pole = delta(admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(i) - 0.5_dp)
    1314         2754 :                   CALL cp_fm_set_element(admm_env%M_purify(ispin), i, j, pole)
    1315              :                ELSE
    1316              :                   pole = 1.0_dp/(admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(i) - &
    1317         8262 :                                  admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(j))
    1318         8262 :                   tmp = Heaviside(admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(i) - 0.5_dp)
    1319         8262 :                   tmp = tmp - Heaviside(admm_env%eigvals_P_to_be_purified(ispin)%eigvals%data(j) - 0.5_dp)
    1320         8262 :                   pole = tmp*pole
    1321         8262 :                   CALL cp_fm_set_element(admm_env%M_purify(ispin), i, j, pole)
    1322              :                END IF
    1323              :             END DO
    1324              :          END DO
    1325          484 :          CALL cp_fm_uplo_to_full(admm_env%M_purify(ispin), admm_env%work_aux_aux)
    1326              : 
    1327          484 :          CALL copy_dbcsr_to_fm(matrix_ks_aux_fit(ispin)%matrix, admm_env%K(ispin))
    1328          484 :          CALL cp_fm_uplo_to_full(admm_env%K(ispin), admm_env%work_aux_aux)
    1329              : 
    1330              :          !! S^(-1)*R
    1331              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1332              :                             1.0_dp, admm_env%S_inv, admm_env%R_purify(ispin), 0.0_dp, &
    1333          484 :                             admm_env%work_aux_aux)
    1334              :          !! K*S^(-1)*R
    1335              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1336              :                             1.0_dp, admm_env%K(ispin), admm_env%work_aux_aux, 0.0_dp, &
    1337          484 :                             admm_env%work_aux_aux2)
    1338              :          !! R^T*S^(-1)*K*S^(-1)*R
    1339              :          CALL parallel_gemm('T', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1340              :                             1.0_dp, admm_env%work_aux_aux, admm_env%work_aux_aux2, 0.0_dp, &
    1341          484 :                             admm_env%work_aux_aux3)
    1342              :          !! R^T*S^(-1)*K*S^(-1)*R x M
    1343              :          CALL cp_fm_schur_product(admm_env%work_aux_aux3, admm_env%M_purify(ispin), &
    1344          484 :                                   admm_env%work_aux_aux)
    1345              : 
    1346              :          !! R^T*A
    1347              :          CALL parallel_gemm('T', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
    1348              :                             1.0_dp, admm_env%R_purify(ispin), admm_env%A, 0.0_dp, &
    1349          484 :                             admm_env%work_aux_orb)
    1350              : 
    1351              :          !! (R^T*S^(-1)*K*S^(-1)*R x M) * R^T*A
    1352              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
    1353              :                             1.0_dp, admm_env%work_aux_aux, admm_env%work_aux_orb, 0.0_dp, &
    1354          484 :                             admm_env%work_aux_orb2)
    1355              :          !! A^T*R*(R^T*S^(-1)*K*S^(-1)*R x M) * R^T*A
    1356              :          CALL parallel_gemm('T', 'N', nao_orb, nao_orb, nao_aux_fit, &
    1357              :                             1.0_dp, admm_env%work_aux_orb, admm_env%work_aux_orb2, 0.0_dp, &
    1358          484 :                             admm_env%work_orb_orb)
    1359              : 
    1360              :          NULLIFY (matrix_k_tilde)
    1361          484 :          ALLOCATE (matrix_k_tilde)
    1362              :          CALL dbcsr_create(matrix_k_tilde, template=matrix_ks(ispin)%matrix, &
    1363              :                            name='MATRIX K_tilde', &
    1364          484 :                            matrix_type=dbcsr_type_symmetric)
    1365              : 
    1366          484 :          CALL cp_fm_to_fm(admm_env%work_orb_orb, admm_env%ks_to_be_merged(ispin))
    1367              : 
    1368          484 :          CALL dbcsr_copy(matrix_k_tilde, matrix_ks(ispin)%matrix)
    1369          484 :          CALL dbcsr_set(matrix_k_tilde, 0.0_dp)
    1370          484 :          CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, matrix_k_tilde, keep_sparsity=.TRUE.)
    1371              : 
    1372          484 :          IF (admm_env%block_dm) THEN
    1373              :             ! ** now loop through the list and nullify blocks
    1374          234 :             CALL dbcsr_iterator_start(iter, matrix_k_tilde)
    1375          851 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
    1376          617 :                CALL dbcsr_iterator_next_block(iter, iatom, jatom, sparse_block)
    1377          851 :                IF (admm_env%block_map(iatom, jatom) == 0) THEN
    1378         1206 :                   sparse_block = 0.0_dp
    1379              :                END IF
    1380              :             END DO
    1381          234 :             CALL dbcsr_iterator_stop(iter)
    1382              :          END IF
    1383              : 
    1384          484 :          CALL dbcsr_add(matrix_ks(ispin)%matrix, matrix_k_tilde, 1.0_dp, 1.0_dp)
    1385              : 
    1386          774 :          CALL dbcsr_deallocate_matrix(matrix_k_tilde)
    1387              : 
    1388              :       END DO !spin-loop
    1389              : 
    1390          290 :       CALL timestop(handle)
    1391              : 
    1392          290 :    END SUBROUTINE merge_ks_matrix_cauchy
    1393              : 
    1394              : ! **************************************************************************************************
    1395              : !> \brief ...
    1396              : !> \param qs_env ...
    1397              : ! **************************************************************************************************
    1398          154 :    SUBROUTINE merge_ks_matrix_cauchy_subspace(qs_env)
    1399              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1400              : 
    1401              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'merge_ks_matrix_cauchy_subspace'
    1402              : 
    1403              :       INTEGER                                            :: handle, ispin, nao_aux_fit, nao_orb, nmo
    1404              :       TYPE(admm_type), POINTER                           :: admm_env
    1405              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_coeff_aux_fit
    1406          154 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_ks_aux_fit
    1407              :       TYPE(dbcsr_type), POINTER                          :: matrix_k_tilde
    1408              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1409          154 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos, mos_aux_fit
    1410              : 
    1411          154 :       CALL timeset(routineN, handle)
    1412          154 :       NULLIFY (admm_env, dft_control, matrix_ks, matrix_ks_aux_fit, mos, mos_aux_fit, &
    1413          154 :                mo_coeff, mo_coeff_aux_fit)
    1414              : 
    1415              :       CALL get_qs_env(qs_env, &
    1416              :                       admm_env=admm_env, &
    1417              :                       dft_control=dft_control, &
    1418              :                       matrix_ks=matrix_ks, &
    1419          154 :                       mos=mos)
    1420          154 :       CALL get_admm_env(admm_env, matrix_ks_aux_fit=matrix_ks_aux_fit, mos_aux_fit=mos_aux_fit)
    1421              : 
    1422          366 :       DO ispin = 1, dft_control%nspins
    1423          212 :          nao_aux_fit = admm_env%nao_aux_fit
    1424          212 :          nao_orb = admm_env%nao_orb
    1425          212 :          nmo = admm_env%nmo(ispin)
    1426          212 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
    1427          212 :          CALL get_mo_set(mo_set=mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit)
    1428              : 
    1429              :          !! Calculate Lambda^{-2}
    1430          212 :          CALL cp_fm_to_fm(admm_env%lambda(ispin), admm_env%work_nmo_nmo1(ispin))
    1431          212 :          CALL cp_fm_cholesky_decompose(admm_env%work_nmo_nmo1(ispin))
    1432          212 :          CALL cp_fm_cholesky_invert(admm_env%work_nmo_nmo1(ispin))
    1433              :          !! Symmetrize the guy
    1434          212 :          CALL cp_fm_uplo_to_full(admm_env%work_nmo_nmo1(ispin), admm_env%lambda_inv2(ispin))
    1435              :          !! Take square
    1436              :          CALL parallel_gemm('N', 'T', nmo, nmo, nmo, &
    1437              :                             1.0_dp, admm_env%work_nmo_nmo1(ispin), admm_env%work_nmo_nmo1(ispin), 0.0_dp, &
    1438          212 :                             admm_env%lambda_inv2(ispin))
    1439              : 
    1440              :          !! ** C_hat = AC
    1441              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_orb, &
    1442              :                             1.0_dp, admm_env%A, mo_coeff, 0.0_dp, &
    1443          212 :                             admm_env%C_hat(ispin))
    1444              : 
    1445              :          !! calc P_tilde from C_hat
    1446              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nmo, &
    1447              :                             1.0_dp, admm_env%C_hat(ispin), admm_env%lambda_inv(ispin), 0.0_dp, &
    1448          212 :                             admm_env%work_aux_nmo(ispin))
    1449              : 
    1450              :          CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nmo, &
    1451              :                             1.0_dp, admm_env%C_hat(ispin), admm_env%work_aux_nmo(ispin), 0.0_dp, &
    1452          212 :                             admm_env%P_tilde(ispin))
    1453              : 
    1454              :          !! ** C_hat*Lambda^{-2}
    1455              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nmo, &
    1456              :                             1.0_dp, admm_env%C_hat(ispin), admm_env%lambda_inv2(ispin), 0.0_dp, &
    1457          212 :                             admm_env%work_aux_nmo(ispin))
    1458              : 
    1459              :          !! ** C_hat*Lambda^{-2}*C_hat^T
    1460              :          CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nmo, &
    1461              :                             1.0_dp, admm_env%work_aux_nmo(ispin), admm_env%C_hat(ispin), 0.0_dp, &
    1462          212 :                             admm_env%work_aux_aux)
    1463              : 
    1464              :          !! ** S*C_hat*Lambda^{-2}*C_hat^T
    1465              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1466              :                             1.0_dp, admm_env%S, admm_env%work_aux_aux, 0.0_dp, &
    1467          212 :                             admm_env%work_aux_aux2)
    1468              : 
    1469          212 :          CALL copy_dbcsr_to_fm(matrix_ks_aux_fit(ispin)%matrix, admm_env%K(ispin))
    1470          212 :          CALL cp_fm_uplo_to_full(admm_env%K(ispin), admm_env%work_aux_aux)
    1471              : 
    1472              :          !! ** S*C_hat*Lambda^{-2}*C_hat^T*H_tilde
    1473              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1474              :                             1.0_dp, admm_env%work_aux_aux2, admm_env%K(ispin), 0.0_dp, &
    1475          212 :                             admm_env%work_aux_aux)
    1476              : 
    1477              :          !! ** P_tilde*S
    1478              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1479              :                             1.0_dp, admm_env%P_tilde(ispin), admm_env%S, 0.0_dp, &
    1480          212 :                             admm_env%work_aux_aux2)
    1481              : 
    1482              :          !! ** -S*C_hat*Lambda^{-2}*C_hat^T*H_tilde*P_tilde*S
    1483              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, &
    1484              :                             -1.0_dp, admm_env%work_aux_aux, admm_env%work_aux_aux2, 0.0_dp, &
    1485          212 :                             admm_env%work_aux_aux3)
    1486              : 
    1487              :          !! ** -S*C_hat*Lambda^{-2}*C_hat^T*H_tilde*P_tilde*S+S*C_hat*Lambda^{-2}*C_hat^T*H_tilde
    1488          212 :          CALL cp_fm_scale_and_add(1.0_dp, admm_env%work_aux_aux3, 1.0_dp, admm_env%work_aux_aux)
    1489              : 
    1490              :          !! first_part*A
    1491              :          CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
    1492              :                             1.0_dp, admm_env%work_aux_aux3, admm_env%A, 0.0_dp, &
    1493          212 :                             admm_env%work_aux_orb)
    1494              : 
    1495              :          !! + first_part^T*A
    1496              :          CALL parallel_gemm('T', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
    1497              :                             1.0_dp, admm_env%work_aux_aux3, admm_env%A, 1.0_dp, &
    1498          212 :                             admm_env%work_aux_orb)
    1499              : 
    1500              :          !! A^T*(first+seccond)=H
    1501              :          CALL parallel_gemm('T', 'N', nao_orb, nao_orb, nao_aux_fit, &
    1502              :                             1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
    1503          212 :                             admm_env%work_orb_orb)
    1504              : 
    1505              :          NULLIFY (matrix_k_tilde)
    1506          212 :          ALLOCATE (matrix_k_tilde)
    1507              :          CALL dbcsr_create(matrix_k_tilde, template=matrix_ks(ispin)%matrix, &
    1508              :                            name='MATRIX K_tilde', &
    1509          212 :                            matrix_type=dbcsr_type_symmetric)
    1510              : 
    1511          212 :          CALL cp_fm_to_fm(admm_env%work_orb_orb, admm_env%ks_to_be_merged(ispin))
    1512              : 
    1513          212 :          CALL dbcsr_copy(matrix_k_tilde, matrix_ks(ispin)%matrix)
    1514          212 :          CALL dbcsr_set(matrix_k_tilde, 0.0_dp)
    1515          212 :          CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, matrix_k_tilde, keep_sparsity=.TRUE.)
    1516              : 
    1517              :          CALL parallel_gemm('N', 'N', nao_orb, nmo, nao_orb, &
    1518              :                             1.0_dp, admm_env%work_orb_orb, mo_coeff, 0.0_dp, &
    1519          212 :                             admm_env%mo_derivs_tmp(ispin))
    1520              : 
    1521          212 :          CALL dbcsr_add(matrix_ks(ispin)%matrix, matrix_k_tilde, 1.0_dp, 1.0_dp)
    1522              : 
    1523          366 :          CALL dbcsr_deallocate_matrix(matrix_k_tilde)
    1524              : 
    1525              :       END DO !spin loop
    1526          154 :       CALL timestop(handle)
    1527              : 
    1528          154 :    END SUBROUTINE merge_ks_matrix_cauchy_subspace
    1529              : 
    1530              : ! **************************************************************************************************
    1531              : !> \brief Calculates the product Kohn-Sham-Matrix x mo_coeff for the auxiliary
    1532              : !>        basis set and transforms it into the orbital basis. This is needed
    1533              : !>        in order to use OT
    1534              : !>
    1535              : !> \param ispin which spin to transform
    1536              : !> \param admm_env The ADMM env
    1537              : !> \param mo_set ...
    1538              : !> \param mo_coeff the MO coefficients from the orbital basis set
    1539              : !> \param mo_coeff_aux_fit the MO coefficients from the auxiliary fitting basis set
    1540              : !> \param mo_derivs KS x mo_coeff from the orbital basis set to which we add the
    1541              : !>        auxiliary basis set part
    1542              : !> \param mo_derivs_aux_fit ...
    1543              : !> \param matrix_ks_aux_fit the Kohn-Sham matrix from the auxiliary fitting basis set
    1544              : !> \par History
    1545              : !>      05.2008 created [Manuel Guidon]
    1546              : !> \author Manuel Guidon
    1547              : ! **************************************************************************************************
    1548         3300 :    SUBROUTINE merge_mo_derivs_diag(ispin, admm_env, mo_set, mo_coeff, mo_coeff_aux_fit, mo_derivs, &
    1549         1100 :                                    mo_derivs_aux_fit, matrix_ks_aux_fit)
    1550              :       INTEGER, INTENT(IN)                                :: ispin
    1551              :       TYPE(admm_type), POINTER                           :: admm_env
    1552              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
    1553              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff, mo_coeff_aux_fit
    1554              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mo_derivs, mo_derivs_aux_fit
    1555              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks_aux_fit
    1556              : 
    1557              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'merge_mo_derivs_diag'
    1558              : 
    1559              :       INTEGER                                            :: handle, i, j, nao_aux_fit, nao_orb, nmo
    1560              :       REAL(dp)                                           :: eig_diff, pole, tmp32, tmp52, tmp72, &
    1561              :                                                             tmp92
    1562         1100 :       REAL(dp), DIMENSION(:), POINTER                    :: occupation_numbers, scaling_factor
    1563              : 
    1564         1100 :       CALL timeset(routineN, handle)
    1565              : 
    1566         1100 :       nao_aux_fit = admm_env%nao_aux_fit
    1567         1100 :       nao_orb = admm_env%nao_orb
    1568         1100 :       nmo = admm_env%nmo(ispin)
    1569              : 
    1570         1100 :       CALL copy_dbcsr_to_fm(matrix_ks_aux_fit(ispin)%matrix, admm_env%K(ispin))
    1571         1100 :       CALL cp_fm_uplo_to_full(admm_env%K(ispin), admm_env%work_aux_aux)
    1572              : 
    1573              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_aux_fit, &
    1574              :                          1.0_dp, admm_env%K(ispin), mo_coeff_aux_fit, 0.0_dp, &
    1575         1100 :                          admm_env%H(ispin))
    1576              : 
    1577         1100 :       CALL get_mo_set(mo_set=mo_set, occupation_numbers=occupation_numbers)
    1578         3300 :       ALLOCATE (scaling_factor(SIZE(occupation_numbers)))
    1579        10008 :       scaling_factor = 2.0_dp*occupation_numbers
    1580              : 
    1581         1100 :       CALL cp_fm_column_scale(admm_env%H(ispin), scaling_factor)
    1582              : 
    1583         1100 :       CALL cp_fm_to_fm(admm_env%H(ispin), mo_derivs_aux_fit(ispin))
    1584              : 
    1585              :       ! *** Add first term
    1586              :       CALL parallel_gemm('N', 'T', nao_aux_fit, nmo, nmo, &
    1587              :                          1.0_dp, admm_env%H(ispin), admm_env%lambda_inv_sqrt(ispin), 0.0_dp, &
    1588         1100 :                          admm_env%work_aux_nmo(ispin))
    1589              :       CALL parallel_gemm('T', 'N', nao_orb, nmo, nao_aux_fit, &
    1590              :                          1.0_dp, admm_env%A, admm_env%work_aux_nmo(ispin), 0.0_dp, &
    1591         1100 :                          admm_env%mo_derivs_tmp(ispin))
    1592              : 
    1593              :       ! *** Construct Matrix M for Hadamard Product
    1594              :       pole = 0.0_dp
    1595         5554 :       DO i = 1, nmo
    1596        20152 :          DO j = i, nmo
    1597              :             eig_diff = (admm_env%eigvals_lambda(ispin)%eigvals%data(i) - &
    1598        14598 :                         admm_env%eigvals_lambda(ispin)%eigvals%data(j))
    1599              :             ! *** two eigenvalues could be the degenerated. In that case use 2nd order formula for the poles
    1600        19052 :             IF (ABS(eig_diff) < 0.0001_dp) THEN
    1601         6068 :                tmp32 = 1.0_dp/SQRT(admm_env%eigvals_lambda(ispin)%eigvals%data(j))**3
    1602         6068 :                tmp52 = tmp32/admm_env%eigvals_lambda(ispin)%eigvals%data(j)*eig_diff
    1603         6068 :                tmp72 = tmp52/admm_env%eigvals_lambda(ispin)%eigvals%data(j)*eig_diff
    1604         6068 :                tmp92 = tmp72/admm_env%eigvals_lambda(ispin)%eigvals%data(j)*eig_diff
    1605              : 
    1606         6068 :                pole = -0.5_dp*tmp32 + 3.0_dp/8.0_dp*tmp52 - 5.0_dp/16.0_dp*tmp72 + 35.0_dp/128.0_dp*tmp92
    1607         6068 :                CALL cp_fm_set_element(admm_env%M(ispin), i, j, pole)
    1608              :             ELSE
    1609         8530 :                pole = 1.0_dp/SQRT(admm_env%eigvals_lambda(ispin)%eigvals%data(i))
    1610         8530 :                pole = pole - 1.0_dp/SQRT(admm_env%eigvals_lambda(ispin)%eigvals%data(j))
    1611              :                pole = pole/(admm_env%eigvals_lambda(ispin)%eigvals%data(i) - &
    1612         8530 :                             admm_env%eigvals_lambda(ispin)%eigvals%data(j))
    1613         8530 :                CALL cp_fm_set_element(admm_env%M(ispin), i, j, pole)
    1614              :             END IF
    1615              :          END DO
    1616              :       END DO
    1617         1100 :       CALL cp_fm_uplo_to_full(admm_env%M(ispin), admm_env%work_nmo_nmo1(ispin))
    1618              : 
    1619              :       ! *** 2nd term to be added to fm_H
    1620              : 
    1621              :       !! Part 1: B^(T)*C* R*[R^(T)*c^(T)*A^(T)*H_aux_fit*R x M]*R^(T)
    1622              :       !! Part 2: B*C*(R*[R^(T)*c^(T)*A^(T)*H_aux_fit*R x M]*R^(T))^(T)
    1623              : 
    1624              :       ! *** H'*R
    1625              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nmo, &
    1626              :                          1.0_dp, admm_env%H(ispin), admm_env%R(ispin), 0.0_dp, &
    1627         1100 :                          admm_env%work_aux_nmo(ispin))
    1628              :       ! *** A^(T)*H'*R
    1629              :       CALL parallel_gemm('T', 'N', nao_orb, nmo, nao_aux_fit, &
    1630              :                          1.0_dp, admm_env%A, admm_env%work_aux_nmo(ispin), 0.0_dp, &
    1631         1100 :                          admm_env%work_orb_nmo(ispin))
    1632              :       ! *** c^(T)*A^(T)*H'*R
    1633              :       CALL parallel_gemm('T', 'N', nmo, nmo, nao_orb, &
    1634              :                          1.0_dp, mo_coeff, admm_env%work_orb_nmo(ispin), 0.0_dp, &
    1635         1100 :                          admm_env%work_nmo_nmo1(ispin))
    1636              :       ! *** R^(T)*c^(T)*A^(T)*H'*R
    1637              :       CALL parallel_gemm('T', 'N', nmo, nmo, nmo, &
    1638              :                          1.0_dp, admm_env%R(ispin), admm_env%work_nmo_nmo1(ispin), 0.0_dp, &
    1639         1100 :                          admm_env%work_nmo_nmo2(ispin))
    1640              :       ! *** R^(T)*c^(T)*A^(T)*H'*R x M
    1641              :       CALL cp_fm_schur_product(admm_env%work_nmo_nmo2(ispin), &
    1642         1100 :                                admm_env%M(ispin), admm_env%work_nmo_nmo1(ispin))
    1643              :       ! *** R* (R^(T)*c^(T)*A^(T)*H'*R x M)
    1644              :       CALL parallel_gemm('N', 'N', nmo, nmo, nmo, &
    1645              :                          1.0_dp, admm_env%R(ispin), admm_env%work_nmo_nmo1(ispin), 0.0_dp, &
    1646         1100 :                          admm_env%work_nmo_nmo2(ispin))
    1647              : 
    1648              :       ! *** R* (R^(T)*c^(T)*A^(T)*H'*R x M) *R^(T)
    1649              :       CALL parallel_gemm('N', 'T', nmo, nmo, nmo, &
    1650              :                          1.0_dp, admm_env%work_nmo_nmo2(ispin), admm_env%R(ispin), 0.0_dp, &
    1651         1100 :                          admm_env%R_schur_R_t(ispin))
    1652              : 
    1653              :       ! *** B^(T)*c
    1654              :       CALL parallel_gemm('T', 'N', nao_orb, nmo, nao_orb, &
    1655              :                          1.0_dp, admm_env%B, mo_coeff, 0.0_dp, &
    1656         1100 :                          admm_env%work_orb_nmo(ispin))
    1657              : 
    1658              :       ! *** Add first term to fm_H
    1659              :       ! *** B^(T)*c* R* (R^(T)*c^(T)*A^(T)*H'*R x M) *R^(T)
    1660              :       CALL parallel_gemm('N', 'N', nao_orb, nmo, nmo, &
    1661              :                          1.0_dp, admm_env%work_orb_nmo(ispin), admm_env%R_schur_R_t(ispin), 1.0_dp, &
    1662         1100 :                          admm_env%mo_derivs_tmp(ispin))
    1663              : 
    1664              :       ! *** Add second term to fm_H
    1665              :       ! *** B*C *[ R* (R^(T)*c^(T)*A^(T)*H'*R x M) *R^(T)]^(T)
    1666              :       CALL parallel_gemm('N', 'T', nao_orb, nmo, nmo, &
    1667              :                          1.0_dp, admm_env%work_orb_nmo(ispin), admm_env%R_schur_R_t(ispin), 1.0_dp, &
    1668         1100 :                          admm_env%mo_derivs_tmp(ispin))
    1669              : 
    1670         5554 :       DO i = 1, SIZE(scaling_factor)
    1671         5554 :          scaling_factor(i) = 1.0_dp/scaling_factor(i)
    1672              :       END DO
    1673              : 
    1674         1100 :       CALL cp_fm_column_scale(admm_env%mo_derivs_tmp(ispin), scaling_factor)
    1675              : 
    1676         1100 :       CALL cp_fm_scale_and_add(1.0_dp, mo_derivs(ispin), 1.0_dp, admm_env%mo_derivs_tmp(ispin))
    1677              : 
    1678         1100 :       DEALLOCATE (scaling_factor)
    1679              : 
    1680         1100 :       CALL timestop(handle)
    1681              : 
    1682         1100 :    END SUBROUTINE merge_mo_derivs_diag
    1683              : 
    1684              : ! **************************************************************************************************
    1685              : !> \brief ...
    1686              : !> \param qs_env ...
    1687              : ! **************************************************************************************************
    1688        10770 :    SUBROUTINE merge_ks_matrix_none(qs_env)
    1689              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1690              : 
    1691              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'merge_ks_matrix_none'
    1692              : 
    1693              :       INTEGER                                            :: handle, iatom, ispin, jatom, &
    1694              :                                                             nao_aux_fit, nao_orb, nmo
    1695        10770 :       REAL(dp), DIMENSION(:, :), POINTER                 :: sparse_block
    1696              :       REAL(KIND=dp)                                      :: ener_k(2), ener_x(2), ener_x1(2), &
    1697              :                                                             gsi_square, trace_tmp, trace_tmp_two
    1698              :       TYPE(admm_type), POINTER                           :: admm_env
    1699              :       TYPE(dbcsr_iterator_type)                          :: iter
    1700        10770 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_ks_aux_fit, &
    1701        10770 :          matrix_ks_aux_fit_dft, matrix_ks_aux_fit_hfx, matrix_s, matrix_s_aux_fit, rho_ao, &
    1702        10770 :          rho_ao_aux
    1703              :       TYPE(dbcsr_type), POINTER                          :: matrix_k_tilde, &
    1704              :                                                             matrix_ks_aux_fit_admms_tmp, &
    1705              :                                                             matrix_TtsT
    1706              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1707              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1708              :       TYPE(qs_energy_type), POINTER                      :: energy
    1709              :       TYPE(qs_rho_type), POINTER                         :: rho, rho_aux_fit
    1710              : 
    1711        10770 :       CALL timeset(routineN, handle)
    1712        10770 :       NULLIFY (admm_env, dft_control, matrix_ks, matrix_ks_aux_fit, matrix_ks_aux_fit_dft, &
    1713        10770 :                matrix_ks_aux_fit_hfx, matrix_s, matrix_s_aux_fit, rho_ao, rho_ao_aux, matrix_k_tilde, &
    1714        10770 :                matrix_TtsT, matrix_ks_aux_fit_admms_tmp, rho, rho_aux_fit, sparse_block, para_env, energy)
    1715              : 
    1716              :       CALL get_qs_env(qs_env, &
    1717              :                       admm_env=admm_env, &
    1718              :                       dft_control=dft_control, &
    1719              :                       matrix_ks=matrix_ks, &
    1720              :                       rho=rho, &
    1721              :                       matrix_s=matrix_s, &
    1722              :                       energy=energy, &
    1723        10770 :                       para_env=para_env)
    1724              :       CALL get_admm_env(admm_env, matrix_ks_aux_fit=matrix_ks_aux_fit, matrix_ks_aux_fit_dft=matrix_ks_aux_fit_dft, &
    1725              :                         matrix_ks_aux_fit_hfx=matrix_ks_aux_fit_hfx, rho_aux_fit=rho_aux_fit, &
    1726        10770 :                         matrix_s_aux_fit=matrix_s_aux_fit)
    1727              : 
    1728        10770 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
    1729              :       CALL qs_rho_get(rho_aux_fit, &
    1730        10770 :                       rho_ao=rho_ao_aux)
    1731              : 
    1732        23276 :       DO ispin = 1, dft_control%nspins
    1733        23276 :          IF (admm_env%block_dm) THEN
    1734          120 :             CALL dbcsr_iterator_start(iter, matrix_ks_aux_fit(ispin)%matrix)
    1735          832 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
    1736          712 :                CALL dbcsr_iterator_next_block(iter, iatom, jatom, sparse_block)
    1737          832 :                IF (admm_env%block_map(iatom, jatom) == 0) THEN
    1738         1890 :                   sparse_block = 0.0_dp
    1739              :                END IF
    1740              :             END DO
    1741          120 :             CALL dbcsr_iterator_stop(iter)
    1742          120 :             CALL dbcsr_add(matrix_ks(ispin)%matrix, matrix_ks_aux_fit(ispin)%matrix, 1.0_dp, 1.0_dp)
    1743              : 
    1744              :          ELSE
    1745              : 
    1746        12386 :             nao_aux_fit = admm_env%nao_aux_fit
    1747        12386 :             nao_orb = admm_env%nao_orb
    1748        12386 :             nmo = admm_env%nmo(ispin)
    1749              : 
    1750              :             ! ADMMS: different matrix for calculating A^(T)*K*A, see Eq. (37) Merlot
    1751        12386 :             IF (admm_env%do_admms) THEN
    1752              :                NULLIFY (matrix_ks_aux_fit_admms_tmp)
    1753          392 :                ALLOCATE (matrix_ks_aux_fit_admms_tmp)
    1754              :                CALL dbcsr_create(matrix_ks_aux_fit_admms_tmp, template=matrix_ks_aux_fit(ispin)%matrix, &
    1755          392 :                                  name='matrix_ks_aux_fit_admms_tmp', matrix_type='s')
    1756              :                ! matrix_ks_aux_fit_admms_tmp = k(d_Q)
    1757          392 :                CALL dbcsr_copy(matrix_ks_aux_fit_admms_tmp, matrix_ks_aux_fit_hfx(ispin)%matrix)
    1758              : 
    1759              :                ! matrix_ks_aux_fit_admms_tmp = k(d_Q) - gsi^2/3 x(d_Q)
    1760              :                CALL dbcsr_add(matrix_ks_aux_fit_admms_tmp, matrix_ks_aux_fit_dft(ispin)%matrix, &
    1761          392 :                               1.0_dp, -(admm_env%gsi(ispin))**(2.0_dp/3.0_dp))
    1762          392 :                CALL copy_dbcsr_to_fm(matrix_ks_aux_fit_admms_tmp, admm_env%K(ispin))
    1763          392 :                CALL dbcsr_deallocate_matrix(matrix_ks_aux_fit_admms_tmp)
    1764              :             ELSE
    1765        11994 :                CALL copy_dbcsr_to_fm(matrix_ks_aux_fit(ispin)%matrix, admm_env%K(ispin))
    1766              :             END IF
    1767              : 
    1768        12386 :             CALL cp_fm_uplo_to_full(admm_env%K(ispin), admm_env%work_aux_aux)
    1769              : 
    1770              :             !! K*A
    1771              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
    1772              :                                1.0_dp, admm_env%K(ispin), admm_env%A, 0.0_dp, &
    1773        12386 :                                admm_env%work_aux_orb)
    1774              :             !! A^T*K*A
    1775              :             CALL parallel_gemm('T', 'N', nao_orb, nao_orb, nao_aux_fit, &
    1776              :                                1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
    1777        12386 :                                admm_env%work_orb_orb)
    1778              : 
    1779              :             NULLIFY (matrix_k_tilde)
    1780        12386 :             ALLOCATE (matrix_k_tilde)
    1781              :             CALL dbcsr_create(matrix_k_tilde, template=matrix_ks(ispin)%matrix, &
    1782        12386 :                               name='MATRIX K_tilde', matrix_type='S')
    1783        12386 :             CALL dbcsr_copy(matrix_k_tilde, matrix_ks(ispin)%matrix)
    1784        12386 :             CALL dbcsr_set(matrix_k_tilde, 0.0_dp)
    1785        12386 :             CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, matrix_k_tilde, keep_sparsity=.TRUE.)
    1786              : 
    1787              :             ! Scale matrix_K_tilde here. Then, the scaling has to be done for forces separately
    1788              :             ! Scale matrix_K_tilde by gsi for ADMMQ and ADMMS (Eqs. (27), (37) in Merlot, 2014)
    1789        12386 :             IF (admm_env%do_admmq .OR. admm_env%do_admms) THEN
    1790          600 :                CALL dbcsr_scale(matrix_k_tilde, admm_env%gsi(ispin))
    1791              :             END IF
    1792              : 
    1793              :             ! Scale matrix_K_tilde by gsi^2 for ADMMP (Eq. (35) in Merlot, 2014)
    1794        12386 :             IF (admm_env%do_admmp) THEN
    1795          428 :                gsi_square = (admm_env%gsi(ispin))*(admm_env%gsi(ispin))
    1796          428 :                CALL dbcsr_scale(matrix_k_tilde, gsi_square)
    1797              :             END IF
    1798              : 
    1799        12386 :             admm_env%lambda_merlot(ispin) = 0
    1800              : 
    1801              :             ! Calculate LAMBDA according to Merlot, 1. IF: ADMMQ, 2. IF: ADMMP, 3. IF: ADMMS,
    1802        12386 :             IF (admm_env%do_admmq) THEN
    1803          208 :                CALL dbcsr_dot(matrix_ks_aux_fit(ispin)%matrix, rho_ao_aux(ispin)%matrix, trace_tmp)
    1804              : 
    1805              :                ! Factor of 2 is missing compared to Eq. 28 in Merlot due to
    1806              :                ! Tr(ds) = N in the code \neq 2N in Merlot
    1807          208 :                admm_env%lambda_merlot(ispin) = trace_tmp/(admm_env%n_large_basis(ispin))
    1808              : 
    1809        12178 :             ELSE IF (admm_env%do_admmp) THEN
    1810          428 :                IF (dft_control%nspins == 2) THEN
    1811              :                   CALL calc_spin_dep_aux_exch_ener(qs_env=qs_env, admm_env=admm_env, ener_k_ispin=ener_k(ispin), &
    1812              :                                                    ener_x_ispin=ener_x(ispin), ener_x1_ispin=ener_x1(ispin), &
    1813           52 :                                                    ispin=ispin)
    1814              :                   admm_env%lambda_merlot(ispin) = 2.0_dp*(admm_env%gsi(ispin))**2* &
    1815              :                                                   (ener_k(ispin) + ener_x(ispin) + ener_x1(ispin))/ &
    1816           52 :                                                   (admm_env%n_large_basis(ispin))
    1817              : 
    1818              :                ELSE
    1819              :                   admm_env%lambda_merlot(ispin) = 2.0_dp*(admm_env%gsi(ispin))**2* &
    1820              :                                                   (energy%ex + energy%exc_aux_fit + energy%exc1_aux_fit) &
    1821          376 :                                                   /(admm_env%n_large_basis(ispin))
    1822              :                END IF
    1823              : 
    1824        11750 :             ELSE IF (admm_env%do_admms) THEN
    1825          392 :                CALL dbcsr_dot(matrix_ks_aux_fit_hfx(ispin)%matrix, rho_ao_aux(ispin)%matrix, trace_tmp)
    1826          392 :                CALL dbcsr_dot(matrix_ks_aux_fit_dft(ispin)%matrix, rho_ao_aux(ispin)%matrix, trace_tmp_two)
    1827              :                ! For ADMMS open-shell case we need k and x (Merlot) separately since gsi(a)\=gsi(b)
    1828          392 :                IF (dft_control%nspins == 2) THEN
    1829              :                   CALL calc_spin_dep_aux_exch_ener(qs_env=qs_env, admm_env=admm_env, ener_k_ispin=ener_k(ispin), &
    1830              :                                                    ener_x_ispin=ener_x(ispin), ener_x1_ispin=ener_x1(ispin), &
    1831          324 :                                                    ispin=ispin)
    1832              :                   admm_env%lambda_merlot(ispin) = &
    1833              :                      (trace_tmp + 2.0_dp/3.0_dp*((admm_env%gsi(ispin))**(2.0_dp/3.0_dp))* &
    1834              :                       (ener_x(ispin) + ener_x1(ispin)) - ((admm_env%gsi(ispin))**(2.0_dp/3.0_dp))* &
    1835          324 :                       trace_tmp_two)/(admm_env%n_large_basis(ispin))
    1836              : 
    1837              :                ELSE
    1838              :                   admm_env%lambda_merlot(ispin) = (trace_tmp + (admm_env%gsi(ispin))**(2.0_dp/3.0_dp)* &
    1839              :                                                    (2.0_dp/3.0_dp*(energy%exc_aux_fit + energy%exc1_aux_fit) - &
    1840           68 :                                                     trace_tmp_two))/(admm_env%n_large_basis(ispin))
    1841              :                END IF
    1842              :             END IF
    1843              : 
    1844              :             ! Calculate variational distribution to KS matrix according
    1845              :             ! to Eqs. (27), (35) and (37) in Merlot, 2014
    1846              : 
    1847        12386 :             IF (admm_env%do_admmp .OR. admm_env%do_admmq .OR. admm_env%do_admms) THEN
    1848              : 
    1849              :                !! T^T*s_aux*T in (27) Merlot (T=A), as calculating A^T*K*A few lines above
    1850         1028 :                CALL copy_dbcsr_to_fm(matrix_s_aux_fit(1)%matrix, admm_env%work_aux_aux4)
    1851         1028 :                CALL cp_fm_uplo_to_full(admm_env%work_aux_aux4, admm_env%work_aux_aux5)
    1852              : 
    1853              :                ! s_aux*T
    1854              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
    1855              :                                   1.0_dp, admm_env%work_aux_aux4, admm_env%A, 0.0_dp, &
    1856         1028 :                                   admm_env%work_aux_orb3)
    1857              :                ! T^T*s_aux*T
    1858              :                CALL parallel_gemm('T', 'N', nao_orb, nao_orb, nao_aux_fit, &
    1859              :                                   1.0_dp, admm_env%A, admm_env%work_aux_orb3, 0.0_dp, &
    1860         1028 :                                   admm_env%work_orb_orb3)
    1861              : 
    1862              :                NULLIFY (matrix_TtsT)
    1863         1028 :                ALLOCATE (matrix_TtsT)
    1864              :                CALL dbcsr_create(matrix_TtsT, template=matrix_ks(ispin)%matrix, &
    1865         1028 :                                  name='MATRIX TtsT', matrix_type='S')
    1866         1028 :                CALL dbcsr_copy(matrix_TtsT, matrix_ks(ispin)%matrix)
    1867         1028 :                CALL dbcsr_set(matrix_TtsT, 0.0_dp)
    1868         1028 :                CALL copy_fm_to_dbcsr(admm_env%work_orb_orb3, matrix_TtsT, keep_sparsity=.TRUE.)
    1869              : 
    1870              :                !Add -(gsi)*Lambda*TtsT and Lambda*S to the KS matrix according to Merlot2014
    1871              : 
    1872              :                CALL dbcsr_add(matrix_ks(ispin)%matrix, matrix_TtsT, 1.0_dp, &
    1873         1028 :                               (-admm_env%lambda_merlot(ispin))*admm_env%gsi(ispin))
    1874              : 
    1875         1028 :                CALL dbcsr_add(matrix_ks(ispin)%matrix, matrix_s(1)%matrix, 1.0_dp, admm_env%lambda_merlot(ispin))
    1876              : 
    1877         1028 :                CALL dbcsr_deallocate_matrix(matrix_TtsT)
    1878              : 
    1879              :             END IF
    1880              : 
    1881        12386 :             CALL dbcsr_add(matrix_ks(ispin)%matrix, matrix_k_tilde, 1.0_dp, 1.0_dp)
    1882              : 
    1883        12386 :             CALL dbcsr_deallocate_matrix(matrix_k_tilde)
    1884              : 
    1885              :          END IF
    1886              :       END DO !spin loop
    1887              : 
    1888              :       ! Scale energy for ADMMP and ADMMS
    1889        10770 :       IF (admm_env%do_admmp) THEN
    1890              :          !       ener_k = ener_k*(admm_env%gsi(1))*(admm_env%gsi(1))
    1891              :          !       ener_x = ener_x*(admm_env%gsi(1))*(admm_env%gsi(1))
    1892              :          !        PRINT *, 'energy%ex = ', energy%ex
    1893          402 :          IF (dft_control%nspins == 2) THEN
    1894           26 :             energy%exc_aux_fit = 0.0_dp
    1895           26 :             energy%exc1_aux_fit = 0.0_dp
    1896           26 :             energy%ex = 0.0_dp
    1897           78 :             DO ispin = 1, dft_control%nspins
    1898           52 :                energy%exc_aux_fit = energy%exc_aux_fit + (admm_env%gsi(ispin))**2.0_dp*ener_x(ispin)
    1899           52 :                energy%exc1_aux_fit = energy%exc1_aux_fit + (admm_env%gsi(ispin))**2.0_dp*ener_x1(ispin)
    1900           78 :                energy%ex = energy%ex + (admm_env%gsi(ispin))**2.0_dp*ener_k(ispin)
    1901              :             END DO
    1902              :          ELSE
    1903          376 :             energy%exc_aux_fit = (admm_env%gsi(1))**2.0_dp*energy%exc_aux_fit
    1904          376 :             energy%exc1_aux_fit = (admm_env%gsi(1))**2.0_dp*energy%exc1_aux_fit
    1905          376 :             energy%ex = (admm_env%gsi(1))**2.0_dp*energy%ex
    1906              :          END IF
    1907              : 
    1908        10368 :       ELSE IF (admm_env%do_admms) THEN
    1909          230 :          IF (dft_control%nspins == 2) THEN
    1910          162 :             energy%exc_aux_fit = 0.0_dp
    1911          162 :             energy%exc1_aux_fit = 0.0_dp
    1912          486 :             DO ispin = 1, dft_control%nspins
    1913          324 :                energy%exc_aux_fit = energy%exc_aux_fit + (admm_env%gsi(ispin))**(2.0_dp/3.0_dp)*ener_x(ispin)
    1914          486 :                energy%exc1_aux_fit = energy%exc1_aux_fit + (admm_env%gsi(ispin))**(2.0_dp/3.0_dp)*ener_x1(ispin)
    1915              :             END DO
    1916              :          ELSE
    1917           68 :             energy%exc_aux_fit = (admm_env%gsi(1))**(2.0_dp/3.0_dp)*energy%exc_aux_fit
    1918           68 :             energy%exc1_aux_fit = (admm_env%gsi(1))**(2.0_dp/3.0_dp)*energy%exc1_aux_fit
    1919              :          END IF
    1920              :       END IF
    1921              : 
    1922        10770 :       CALL timestop(handle)
    1923              : 
    1924        10770 :    END SUBROUTINE merge_ks_matrix_none
    1925              : 
    1926              : ! **************************************************************************************************
    1927              : !> \brief ...
    1928              : !> \param qs_env ...
    1929              : ! **************************************************************************************************
    1930          154 :    SUBROUTINE merge_ks_matrix_none_kp(qs_env)
    1931              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1932              : 
    1933              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'merge_ks_matrix_none_kp'
    1934              : 
    1935              :       COMPLEX(dp)                                        :: fac, fac2
    1936              :       INTEGER                                            :: handle, i, igroup, ik, ikp, img, indx, &
    1937              :                                                             ispin, kplocal, kpmax, nao_aux_fit, &
    1938              :                                                             nao_orb, natom, nkp, nkp_groups, nspins
    1939              :       INTEGER, DIMENSION(2)                              :: kp_range
    1940          154 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    1941          154 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1942              :       LOGICAL                                            :: my_kpgrp, use_real_wfn
    1943              :       REAL(dp)                                           :: ener_k(2), ener_x(2), ener_x1(2), tmp, &
    1944              :                                                             trace_tmp, trace_tmp_two
    1945          154 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1946              :       TYPE(admm_type), POINTER                           :: admm_env
    1947          154 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:, :) :: info
    1948              :       TYPE(cp_cfm_type)                                  :: cA, cK, cS, cwork_aux_aux, &
    1949              :                                                             cwork_aux_orb, cwork_orb_orb
    1950              :       TYPE(cp_fm_struct_type), POINTER                   :: struct_aux_aux, struct_aux_orb, &
    1951              :                                                             struct_orb_orb
    1952              :       TYPE(cp_fm_type)                                   :: fmdummy, work_aux_aux, work_aux_aux2, &
    1953              :                                                             work_aux_orb
    1954          154 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fmwork
    1955          154 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: fm_ks
    1956          154 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_k_tilde, matrix_ks_aux_fit, &
    1957          154 :          matrix_ks_aux_fit_dft, matrix_ks_aux_fit_hfx, matrix_ks_kp, matrix_s, matrix_s_aux_fit, &
    1958          154 :          rho_ao_aux
    1959              :       TYPE(dbcsr_type)                                   :: tmpmatrix_ks
    1960          154 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: ksmatrix
    1961              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1962              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1963              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1964              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1965              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1966          154 :          POINTER                                         :: sab_aux_fit, sab_kp
    1967              :       TYPE(qs_energy_type), POINTER                      :: energy
    1968              :       TYPE(qs_rho_type), POINTER                         :: rho_aux_fit
    1969              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
    1970              : 
    1971          154 :       CALL timeset(routineN, handle)
    1972          154 :       NULLIFY (admm_env, rho_ao_aux, rho_aux_fit, &
    1973          154 :                matrix_s_aux_fit, energy, &
    1974          154 :                para_env, kpoints, sab_aux_fit, &
    1975          154 :                matrix_k_tilde, matrix_ks_kp, matrix_ks_aux_fit, scf_env, &
    1976          154 :                struct_orb_orb, struct_aux_orb, struct_aux_aux, kp, &
    1977          154 :                matrix_ks_aux_fit_hfx, matrix_ks_aux_fit_dft)
    1978              : 
    1979              :       CALL get_qs_env(qs_env, &
    1980              :                       admm_env=admm_env, &
    1981              :                       dft_control=dft_control, &
    1982              :                       matrix_ks_kp=matrix_ks_kp, &
    1983              :                       matrix_s_kp=matrix_s, &
    1984              :                       para_env=para_env, &
    1985              :                       scf_env=scf_env, &
    1986              :                       natom=natom, &
    1987              :                       kpoints=kpoints, &
    1988          154 :                       energy=energy)
    1989              : 
    1990              :       CALL get_admm_env(admm_env, &
    1991              :                         matrix_ks_aux_fit_kp=matrix_ks_aux_fit, &
    1992              :                         matrix_ks_aux_fit_hfx_kp=matrix_ks_aux_fit_hfx, &
    1993              :                         matrix_ks_aux_fit_dft_kp=matrix_ks_aux_fit_dft, &
    1994              :                         matrix_s_aux_fit_kp=matrix_s_aux_fit, &
    1995              :                         sab_aux_fit=sab_aux_fit, &
    1996          154 :                         rho_aux_fit=rho_aux_fit)
    1997          154 :       CALL qs_rho_get(rho_aux_fit, rho_ao_kp=rho_ao_aux)
    1998              : 
    1999              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
    2000              :                            nkp_groups=nkp_groups, kp_dist=kp_dist, sab_nl=sab_kp, &
    2001          154 :                            cell_to_index=cell_to_index)
    2002              : 
    2003          154 :       nao_aux_fit = admm_env%nao_aux_fit
    2004          154 :       nao_orb = admm_env%nao_orb
    2005          154 :       nspins = dft_control%nspins
    2006              : 
    2007              :       !Case study on ADMMQ, ADMMS and ADMMP
    2008              : 
    2009              :       !ADMMQ: calculate lamda as in Merlot eq (28)
    2010          154 :       IF (admm_env%do_admmq) THEN
    2011           30 :          admm_env%lambda_merlot = 0.0_dp
    2012          506 :          DO img = 1, dft_control%nimages
    2013         1002 :             DO ispin = 1, nspins
    2014          496 :                CALL dbcsr_dot(matrix_ks_aux_fit(ispin, img)%matrix, rho_ao_aux(ispin, img)%matrix, trace_tmp)
    2015          992 :                admm_env%lambda_merlot(ispin) = admm_env%lambda_merlot(ispin) + trace_tmp/admm_env%n_large_basis(ispin)
    2016              :             END DO
    2017              :          END DO
    2018              :       END IF
    2019              : 
    2020              :       !ADMMP: calculate lamda as in Merlot eq (34)
    2021          154 :       IF (admm_env%do_admmp) THEN
    2022           14 :          IF (nspins == 1) THEN
    2023              :             admm_env%lambda_merlot(1) = 2.0_dp*(admm_env%gsi(1))**2* &
    2024              :                                         (energy%ex + energy%exc_aux_fit + energy%exc1_aux_fit) &
    2025           14 :                                         /(admm_env%n_large_basis(1))
    2026              :          ELSE
    2027            0 :             DO ispin = 1, nspins
    2028              :                CALL calc_spin_dep_aux_exch_ener(qs_env=qs_env, admm_env=admm_env, &
    2029              :                                                 ener_k_ispin=ener_k(ispin), ener_x_ispin=ener_x(ispin), &
    2030            0 :                                                 ener_x1_ispin=ener_x1(ispin), ispin=ispin)
    2031              :                admm_env%lambda_merlot(ispin) = 2.0_dp*(admm_env%gsi(ispin))**2* &
    2032              :                                                (ener_k(ispin) + ener_x(ispin) + ener_x1(ispin))/ &
    2033            0 :                                                (admm_env%n_large_basis(ispin))
    2034              :             END DO
    2035              :          END IF
    2036              :       END IF
    2037              : 
    2038              :       !ADMMS: calculate lambda as in Merlot eq (36)
    2039          154 :       IF (admm_env%do_admms) THEN
    2040           70 :          IF (nspins == 1) THEN
    2041           56 :             trace_tmp = 0.0_dp
    2042           56 :             trace_tmp_two = 0.0_dp
    2043         2352 :             DO img = 1, dft_control%nimages
    2044         2296 :                CALL dbcsr_dot(matrix_ks_aux_fit_hfx(1, img)%matrix, rho_ao_aux(1, img)%matrix, tmp)
    2045         2296 :                trace_tmp = trace_tmp + tmp
    2046         2296 :                CALL dbcsr_dot(matrix_ks_aux_fit_dft(1, img)%matrix, rho_ao_aux(1, img)%matrix, tmp)
    2047         2352 :                trace_tmp_two = trace_tmp_two + tmp
    2048              :             END DO
    2049              :             admm_env%lambda_merlot(1) = (trace_tmp + (admm_env%gsi(1))**(2.0_dp/3.0_dp)* &
    2050              :                                          (2.0_dp/3.0_dp*(energy%exc_aux_fit + energy%exc1_aux_fit) - &
    2051           56 :                                           trace_tmp_two))/(admm_env%n_large_basis(1))
    2052              :          ELSE
    2053              : 
    2054           42 :             DO ispin = 1, nspins
    2055           28 :                trace_tmp = 0.0_dp
    2056           28 :                trace_tmp_two = 0.0_dp
    2057          488 :                DO img = 1, dft_control%nimages
    2058          460 :                   CALL dbcsr_dot(matrix_ks_aux_fit_hfx(ispin, img)%matrix, rho_ao_aux(ispin, img)%matrix, tmp)
    2059          460 :                   trace_tmp = trace_tmp + tmp
    2060          460 :                   CALL dbcsr_dot(matrix_ks_aux_fit_dft(ispin, img)%matrix, rho_ao_aux(ispin, img)%matrix, tmp)
    2061          488 :                   trace_tmp_two = trace_tmp_two + tmp
    2062              :                END DO
    2063              : 
    2064              :                CALL calc_spin_dep_aux_exch_ener(qs_env=qs_env, admm_env=admm_env, &
    2065              :                                                 ener_k_ispin=ener_k(ispin), ener_x_ispin=ener_x(ispin), &
    2066           28 :                                                 ener_x1_ispin=ener_x1(ispin), ispin=ispin)
    2067              : 
    2068              :                admm_env%lambda_merlot(ispin) = &
    2069              :                   (trace_tmp + 2.0_dp/3.0_dp*((admm_env%gsi(ispin))**(2.0_dp/3.0_dp))* &
    2070              :                    (ener_x(ispin) + ener_x1(ispin)) - ((admm_env%gsi(ispin))**(2.0_dp/3.0_dp))* &
    2071           42 :                    trace_tmp_two)/(admm_env%n_large_basis(ispin))
    2072              :             END DO
    2073              :          END IF
    2074              : 
    2075              :          !Here we buld the KS matrix: KS_hfx = gsi^2/3*KS_dft, the we then pass as the ususal KS_aux_fit
    2076           70 :          NULLIFY (matrix_ks_aux_fit)
    2077         5562 :          ALLOCATE (matrix_ks_aux_fit(nspins, dft_control%nimages))
    2078         2596 :          DO img = 1, dft_control%nimages
    2079         5352 :             DO ispin = 1, nspins
    2080         2756 :                NULLIFY (matrix_ks_aux_fit(ispin, img)%matrix)
    2081         2756 :                ALLOCATE (matrix_ks_aux_fit(ispin, img)%matrix)
    2082         2756 :                CALL dbcsr_create(matrix_ks_aux_fit(ispin, img)%matrix, template=matrix_s_aux_fit(1, 1)%matrix)
    2083         2756 :                CALL dbcsr_copy(matrix_ks_aux_fit(ispin, img)%matrix, matrix_ks_aux_fit_hfx(ispin, img)%matrix)
    2084              :                CALL dbcsr_add(matrix_ks_aux_fit(ispin, img)%matrix, matrix_ks_aux_fit_dft(ispin, img)%matrix, &
    2085         5282 :                               1.0_dp, -admm_env%gsi(ispin)**(2.0_dp/3.0_dp))
    2086              :             END DO
    2087              :          END DO
    2088              :       END IF
    2089              : 
    2090              :       ! the temporary DBCSR matrices for the rskp_transform we have to manually allocate
    2091          462 :       ALLOCATE (ksmatrix(2))
    2092              :       CALL dbcsr_create(ksmatrix(1), template=matrix_ks_aux_fit(1, 1)%matrix, &
    2093          154 :                         matrix_type=dbcsr_type_symmetric)
    2094              :       CALL dbcsr_create(ksmatrix(2), template=matrix_ks_aux_fit(1, 1)%matrix, &
    2095          154 :                         matrix_type=dbcsr_type_antisymmetric)
    2096              :       CALL dbcsr_create(tmpmatrix_ks, template=matrix_ks_aux_fit(1, 1)%matrix, &
    2097          154 :                         matrix_type=dbcsr_type_symmetric)
    2098          154 :       CALL cp_dbcsr_alloc_block_from_nbl(ksmatrix(1), sab_aux_fit)
    2099          154 :       CALL cp_dbcsr_alloc_block_from_nbl(ksmatrix(2), sab_aux_fit)
    2100              : 
    2101          154 :       kplocal = kp_range(2) - kp_range(1) + 1
    2102          462 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
    2103          154 :       para_env => kpoints%blacs_env_all%para_env
    2104              : 
    2105              :       CALL cp_fm_struct_create(struct_aux_aux, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
    2106          154 :                                nrow_global=nao_aux_fit, ncol_global=nao_aux_fit)
    2107          154 :       CALL cp_fm_create(work_aux_aux, struct_aux_aux)
    2108          154 :       CALL cp_fm_create(work_aux_aux2, struct_aux_aux)
    2109              : 
    2110              :       CALL cp_fm_struct_create(struct_aux_orb, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
    2111          154 :                                nrow_global=nao_aux_fit, ncol_global=nao_orb)
    2112          154 :       CALL cp_fm_create(work_aux_orb, struct_aux_orb)
    2113              : 
    2114              :       CALL cp_fm_struct_create(struct_orb_orb, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
    2115          154 :                                nrow_global=nao_orb, ncol_global=nao_orb)
    2116              : 
    2117              :       !Create cfm work matrices
    2118          154 :       IF (.NOT. use_real_wfn) THEN
    2119          154 :          CALL cp_cfm_create(cS, struct_aux_aux)
    2120          154 :          CALL cp_cfm_create(cK, struct_aux_aux)
    2121          154 :          CALL cp_cfm_create(cwork_aux_aux, struct_aux_aux)
    2122              : 
    2123          154 :          CALL cp_cfm_create(cA, struct_aux_orb)
    2124          154 :          CALL cp_cfm_create(cwork_aux_orb, struct_aux_orb)
    2125              : 
    2126          154 :          CALL cp_cfm_create(cwork_orb_orb, struct_orb_orb)
    2127              :       END IF
    2128              : 
    2129              :       !We create the fms in which we store the KS ORB matrix at each kp
    2130         3844 :       ALLOCATE (fm_ks(kplocal, 2, nspins))
    2131          332 :       DO ispin = 1, nspins
    2132          688 :          DO i = 1, 2
    2133         3228 :             DO ikp = 1, kplocal
    2134         3050 :                CALL cp_fm_create(fm_ks(ikp, i, ispin), struct_orb_orb)
    2135              :             END DO
    2136              :          END DO
    2137              :       END DO
    2138              : 
    2139          154 :       CALL cp_fm_struct_release(struct_aux_aux)
    2140          154 :       CALL cp_fm_struct_release(struct_aux_orb)
    2141          154 :       CALL cp_fm_struct_release(struct_orb_orb)
    2142              : 
    2143         7082 :       ALLOCATE (info(nkp*nspins, 2))
    2144          154 :       indx = 0
    2145         1418 :       DO ikp = 1, kpmax
    2146         2810 :          DO ispin = 1, nspins
    2147         5440 :             DO igroup = 1, nkp_groups
    2148              :                ! number of current kpoint
    2149         2784 :                ik = kp_dist(1, igroup) + ikp - 1
    2150         2784 :                IF (ik > kp_dist(2, igroup)) CYCLE
    2151         2694 :                my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    2152         2694 :                indx = indx + 1
    2153              : 
    2154         2694 :                IF (use_real_wfn) THEN
    2155            0 :                   CALL dbcsr_set(ksmatrix(1), 0.0_dp)
    2156              :                   CALL rskp_transform(rmatrix=ksmatrix(1), rsmat=matrix_ks_aux_fit, ispin=ispin, &
    2157            0 :                                       xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_aux_fit)
    2158            0 :                   CALL dbcsr_desymmetrize(ksmatrix(1), tmpmatrix_ks)
    2159            0 :                   CALL copy_dbcsr_to_fm(tmpmatrix_ks, admm_env%work_aux_aux)
    2160              :                ELSE
    2161         2694 :                   CALL dbcsr_set(ksmatrix(1), 0.0_dp)
    2162         2694 :                   CALL dbcsr_set(ksmatrix(2), 0.0_dp)
    2163              :                   CALL rskp_transform(rmatrix=ksmatrix(1), cmatrix=ksmatrix(2), rsmat=matrix_ks_aux_fit, ispin=ispin, &
    2164         2694 :                                       xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_aux_fit)
    2165         2694 :                   CALL dbcsr_desymmetrize(ksmatrix(1), tmpmatrix_ks)
    2166         2694 :                   CALL copy_dbcsr_to_fm(tmpmatrix_ks, admm_env%work_aux_aux)
    2167         2694 :                   CALL dbcsr_desymmetrize(ksmatrix(2), tmpmatrix_ks)
    2168         2694 :                   CALL copy_dbcsr_to_fm(tmpmatrix_ks, admm_env%work_aux_aux2)
    2169              :                END IF
    2170              : 
    2171         4086 :                IF (my_kpgrp) THEN
    2172         1347 :                   CALL cp_fm_start_copy_general(admm_env%work_aux_aux, work_aux_aux, para_env, info(indx, 1))
    2173         1347 :                   IF (.NOT. use_real_wfn) THEN
    2174              :                      CALL cp_fm_start_copy_general(admm_env%work_aux_aux2, work_aux_aux2, &
    2175         1347 :                                                    para_env, info(indx, 2))
    2176              :                   END IF
    2177              :                ELSE
    2178         1347 :                   CALL cp_fm_start_copy_general(admm_env%work_aux_aux, fmdummy, para_env, info(indx, 1))
    2179         1347 :                   IF (.NOT. use_real_wfn) THEN
    2180         1347 :                      CALL cp_fm_start_copy_general(admm_env%work_aux_aux2, fmdummy, para_env, info(indx, 2))
    2181              :                   END IF
    2182              :                END IF
    2183              :             END DO
    2184              :          END DO
    2185              :       END DO
    2186              : 
    2187              :       indx = 0
    2188         1418 :       DO ikp = 1, kpmax
    2189         2810 :          DO ispin = 1, nspins
    2190         4176 :             DO igroup = 1, nkp_groups
    2191              :                ! number of current kpoint
    2192         2784 :                ik = kp_dist(1, igroup) + ikp - 1
    2193         2784 :                IF (ik > kp_dist(2, igroup)) CYCLE
    2194         2694 :                my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    2195         1347 :                indx = indx + 1
    2196         1392 :                IF (my_kpgrp) THEN
    2197         1347 :                   CALL cp_fm_finish_copy_general(work_aux_aux, info(indx, 1))
    2198         1347 :                   IF (.NOT. use_real_wfn) THEN
    2199         1347 :                      CALL cp_fm_finish_copy_general(work_aux_aux2, info(indx, 2))
    2200         1347 :                      CALL cp_fm_to_cfm(work_aux_aux, work_aux_aux2, cK)
    2201              :                   END IF
    2202              :                END IF
    2203              :             END DO
    2204              : 
    2205         1392 :             IF (ikp > kplocal) CYCLE
    2206         1347 :             kp => kpoints%kp_aux_env(ikp)%kpoint_env
    2207         2611 :             IF (use_real_wfn) THEN
    2208              : 
    2209              :                !! K*A
    2210              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
    2211              :                                   1.0_dp, work_aux_aux, kp%amat(1, 1), 0.0_dp, &
    2212            0 :                                   work_aux_orb)
    2213              :                !! A^T*K*A
    2214              :                CALL parallel_gemm('T', 'N', nao_orb, nao_orb, nao_aux_fit, &
    2215              :                                   1.0_dp, kp%amat(1, 1), work_aux_orb, 0.0_dp, &
    2216            0 :                                   fm_ks(ikp, 1, ispin))
    2217              :             ELSE
    2218              : 
    2219         1347 :                IF (admm_env%do_admmq .OR. admm_env%do_admms) THEN
    2220         1022 :                   CALL cp_fm_to_cfm(kp%smat(1, 1), kp%smat(2, 1), cS)
    2221              : 
    2222              :                   !Need to subdtract lambda* S_aux to K_aux, and scale the whole thing by gsi
    2223         1022 :                   fac = CMPLX(-admm_env%lambda_merlot(ispin), 0.0_dp, dp)
    2224         1022 :                   CALL cp_cfm_scale_and_add(z_one, cK, fac, cS)
    2225         1022 :                   CALL cp_cfm_scale(admm_env%gsi(ispin), cK)
    2226              :                END IF
    2227              : 
    2228         1347 :                IF (admm_env%do_admmp) THEN
    2229           98 :                   CALL cp_fm_to_cfm(kp%smat(1, 1), kp%smat(2, 1), cS)
    2230              : 
    2231              :                   !Need to substract labda*gsi*S_aux to gsi**2*K_aux
    2232           98 :                   fac = CMPLX(-admm_env%gsi(ispin)*admm_env%lambda_merlot(ispin), 0.0_dp, dp)
    2233           98 :                   fac2 = CMPLX(admm_env%gsi(ispin)**2, 0.0_dp, dp)
    2234           98 :                   CALL cp_cfm_scale_and_add(fac2, cK, fac, cS)
    2235              :                END IF
    2236              : 
    2237         1347 :                CALL cp_fm_to_cfm(kp%amat(1, 1), kp%amat(2, 1), cA)
    2238              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, &
    2239         1347 :                                   z_one, cK, cA, z_zero, cwork_aux_orb)
    2240              : 
    2241              :                CALL parallel_gemm('C', 'N', nao_orb, nao_orb, nao_aux_fit, &
    2242         1347 :                                   z_one, cA, cwork_aux_orb, z_zero, cwork_orb_orb)
    2243              : 
    2244         1347 :                CALL cp_cfm_to_fm(cwork_orb_orb, mtargetr=fm_ks(ikp, 1, ispin), mtargeti=fm_ks(ikp, 2, ispin))
    2245              :             END IF
    2246              :          END DO
    2247              :       END DO
    2248              : 
    2249         2848 :       DO indx = 1, SIZE(info, 1)
    2250         2694 :          CALL cp_fm_cleanup_copy_general(info(indx, 1))
    2251         2848 :          IF (.NOT. use_real_wfn) CALL cp_fm_cleanup_copy_general(info(indx, 2))
    2252              :       END DO
    2253              : 
    2254         5542 :       DEALLOCATE (info)
    2255          154 :       CALL dbcsr_release(ksmatrix(1))
    2256          154 :       CALL dbcsr_release(ksmatrix(2))
    2257          154 :       CALL dbcsr_release(tmpmatrix_ks)
    2258              : 
    2259          154 :       CALL cp_fm_release(work_aux_aux)
    2260          154 :       CALL cp_fm_release(work_aux_aux2)
    2261          154 :       CALL cp_fm_release(work_aux_orb)
    2262          154 :       IF (.NOT. use_real_wfn) THEN
    2263          154 :          CALL cp_cfm_release(cS)
    2264          154 :          CALL cp_cfm_release(cK)
    2265          154 :          CALL cp_cfm_release(cwork_aux_aux)
    2266          154 :          CALL cp_cfm_release(cA)
    2267          154 :          CALL cp_cfm_release(cwork_aux_orb)
    2268          154 :          CALL cp_cfm_release(cwork_orb_orb)
    2269              :       END IF
    2270              : 
    2271          154 :       NULLIFY (matrix_k_tilde)
    2272              : 
    2273          154 :       CALL dbcsr_allocate_matrix_set(matrix_k_tilde, dft_control%nspins, dft_control%nimages)
    2274              : 
    2275          332 :       DO ispin = 1, nspins
    2276        10396 :          DO img = 1, dft_control%nimages
    2277        10064 :             ALLOCATE (matrix_k_tilde(ispin, img)%matrix)
    2278              :             CALL dbcsr_create(matrix=matrix_k_tilde(ispin, img)%matrix, template=matrix_ks_kp(1, 1)%matrix, &
    2279              :                               name='MATRIX K_tilde '//TRIM(ADJUSTL(cp_to_string(ispin)))//'_'//TRIM(ADJUSTL(cp_to_string(img))), &
    2280        10064 :                               matrix_type=dbcsr_type_symmetric)
    2281        10064 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_k_tilde(ispin, img)%matrix, sab_kp)
    2282        10242 :             CALL dbcsr_set(matrix_k_tilde(ispin, img)%matrix, 0.0_dp)
    2283              :          END DO
    2284              :       END DO
    2285              : 
    2286          154 :       CALL cp_fm_get_info(admm_env%work_orb_orb, matrix_struct=struct_orb_orb)
    2287          462 :       ALLOCATE (fmwork(2))
    2288          154 :       CALL cp_fm_create(fmwork(1), struct_orb_orb)
    2289          154 :       CALL cp_fm_create(fmwork(2), struct_orb_orb)
    2290              : 
    2291              :       ! reuse the density transform to FT the KS matrix
    2292              :       CALL kpoint_density_transform(kpoints, matrix_k_tilde, .FALSE., &
    2293              :                                     matrix_k_tilde(1, 1)%matrix, sab_kp, &
    2294          154 :                                     fmwork, for_aux_fit=.FALSE., pmat_ext=fm_ks)
    2295          154 :       CALL cp_fm_release(fmwork(1))
    2296          154 :       CALL cp_fm_release(fmwork(2))
    2297              : 
    2298          332 :       DO ispin = 1, nspins
    2299          688 :          DO i = 1, 2
    2300         3228 :             DO ikp = 1, kplocal
    2301         3050 :                CALL cp_fm_release(fm_ks(ikp, i, ispin))
    2302              :             END DO
    2303              :          END DO
    2304              :       END DO
    2305              : 
    2306          332 :       DO ispin = 1, nspins
    2307        10396 :          DO img = 1, dft_control%nimages
    2308        10064 :             CALL dbcsr_add(matrix_ks_kp(ispin, img)%matrix, matrix_k_tilde(ispin, img)%matrix, 1.0_dp, 1.0_dp)
    2309        10242 :             IF (admm_env%do_admmq .OR. admm_env%do_admmp .OR. admm_env%do_admms) THEN
    2310              :                !In ADMMQ and ADMMP, need to add lambda*S_orb (Merlot eq 27)
    2311              :                CALL dbcsr_add(matrix_ks_kp(ispin, img)%matrix, matrix_s(1, img)%matrix, &
    2312         3816 :                               1.0_dp, admm_env%lambda_merlot(ispin))
    2313              :             END IF
    2314              :          END DO
    2315              :       END DO
    2316              : 
    2317              :       !Scale the energies
    2318          154 :       IF (admm_env%do_admmp) THEN
    2319           14 :          IF (nspins == 1) THEN
    2320           14 :             energy%exc_aux_fit = (admm_env%gsi(1))**2.0_dp*energy%exc_aux_fit
    2321           14 :             energy%exc1_aux_fit = (admm_env%gsi(1))**2.0_dp*energy%exc1_aux_fit
    2322           14 :             energy%ex = (admm_env%gsi(1))**2.0_dp*energy%ex
    2323              :          ELSE
    2324            0 :             energy%exc_aux_fit = 0.0_dp
    2325            0 :             energy%exc1_aux_fit = 0.0_dp
    2326            0 :             energy%ex = 0.0_dp
    2327            0 :             DO ispin = 1, dft_control%nspins
    2328            0 :                energy%exc_aux_fit = energy%exc_aux_fit + (admm_env%gsi(ispin))**2.0_dp*ener_x(ispin)
    2329            0 :                energy%exc1_aux_fit = energy%exc1_aux_fit + (admm_env%gsi(ispin))**2.0_dp*ener_x1(ispin)
    2330            0 :                energy%ex = energy%ex + (admm_env%gsi(ispin))**2.0_dp*ener_k(ispin)
    2331              :             END DO
    2332              :          END IF
    2333              :       END IF
    2334              : 
    2335              :       !Scale the energies and clean-up
    2336          154 :       IF (admm_env%do_admms) THEN
    2337           70 :          IF (nspins == 1) THEN
    2338           56 :             energy%exc_aux_fit = (admm_env%gsi(1))**(2.0_dp/3.0_dp)*energy%exc_aux_fit
    2339           56 :             energy%exc1_aux_fit = (admm_env%gsi(1))**(2.0_dp/3.0_dp)*energy%exc1_aux_fit
    2340              :          ELSE
    2341           14 :             energy%exc_aux_fit = 0.0_dp
    2342           14 :             energy%exc1_aux_fit = 0.0_dp
    2343           42 :             DO ispin = 1, nspins
    2344           28 :                energy%exc_aux_fit = energy%exc_aux_fit + (admm_env%gsi(ispin))**(2.0_dp/3.0_dp)*ener_x(ispin)
    2345           42 :                energy%exc1_aux_fit = energy%exc1_aux_fit + (admm_env%gsi(ispin))**(2.0_dp/3.0_dp)*ener_x1(ispin)
    2346              :             END DO
    2347              :          END IF
    2348              : 
    2349           70 :          CALL dbcsr_deallocate_matrix_set(matrix_ks_aux_fit)
    2350              :       END IF
    2351              : 
    2352          154 :       CALL dbcsr_deallocate_matrix_set(matrix_k_tilde)
    2353              : 
    2354          154 :       CALL timestop(handle)
    2355              : 
    2356          616 :    END SUBROUTINE merge_ks_matrix_none_kp
    2357              : 
    2358              : ! **************************************************************************************************
    2359              : !> \brief Calculate exchange correction energy (Merlot2014 Eqs. 32, 33) for every spin, for KP
    2360              : !> \param qs_env ...
    2361              : !> \param admm_env ...
    2362              : !> \param ener_k_ispin exact ispin (Fock) exchange in auxiliary basis
    2363              : !> \param ener_x_ispin ispin DFT exchange in auxiliary basis
    2364              : !> \param ener_x1_ispin ispin DFT exchange in auxiliary basis, due to the GAPW atomic contributions
    2365              : !> \param ispin ...
    2366              : ! **************************************************************************************************
    2367          404 :    SUBROUTINE calc_spin_dep_aux_exch_ener(qs_env, admm_env, ener_k_ispin, ener_x_ispin, &
    2368              :                                           ener_x1_ispin, ispin)
    2369              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2370              :       TYPE(admm_type), POINTER                           :: admm_env
    2371              :       REAL(dp), INTENT(INOUT)                            :: ener_k_ispin, ener_x_ispin, ener_x1_ispin
    2372              :       INTEGER, INTENT(IN)                                :: ispin
    2373              : 
    2374              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calc_spin_dep_aux_exch_ener'
    2375              : 
    2376              :       CHARACTER(LEN=default_string_length)               :: basis_type
    2377              :       INTEGER                                            :: handle, img, myspin, nimg
    2378              :       LOGICAL                                            :: gapw
    2379              :       REAL(dp)                                           :: tmp
    2380          404 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: tot_rho_r
    2381              :       TYPE(admm_gapw_r3d_rs_type), POINTER               :: admm_gapw_env
    2382          404 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2383          404 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao
    2384          404 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_aux_fit_hfx, rho_ao_aux, &
    2385          404 :                                                             rho_ao_aux_buffer
    2386              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2387              :       TYPE(local_rho_type), POINTER                      :: local_rho_buffer
    2388              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2389          404 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g
    2390          404 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r, v_rspace_dummy, v_tau_rspace_dummy
    2391              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    2392              :       TYPE(qs_rho_type), POINTER                         :: rho_aux_fit, rho_aux_fit_buffer
    2393              :       TYPE(section_vals_type), POINTER                   :: xc_section_aux
    2394              :       TYPE(task_list_type), POINTER                      :: task_list
    2395              : 
    2396          404 :       CALL timeset(routineN, handle)
    2397              : 
    2398          404 :       NULLIFY (ks_env, rho_aux_fit, rho_aux_fit_buffer, rho_ao, &
    2399          404 :                xc_section_aux, v_rspace_dummy, v_tau_rspace_dummy, &
    2400          404 :                rho_ao_aux, rho_ao_aux_buffer, dft_control, &
    2401          404 :                matrix_ks_aux_fit_hfx, task_list, local_rho_buffer, admm_gapw_env)
    2402              : 
    2403          404 :       NULLIFY (rho_g, rho_r, tot_rho_r)
    2404              : 
    2405          404 :       CALL get_qs_env(qs_env, ks_env=ks_env, dft_control=dft_control)
    2406              :       CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit, rho_aux_fit_buffer=rho_aux_fit_buffer, &
    2407          404 :                         matrix_ks_aux_fit_hfx_kp=matrix_ks_aux_fit_hfx)
    2408              : 
    2409              :       CALL qs_rho_get(rho_aux_fit, &
    2410          404 :                       rho_ao_kp=rho_ao_aux)
    2411              : 
    2412              :       CALL qs_rho_get(rho_aux_fit_buffer, &
    2413              :                       rho_ao_kp=rho_ao_aux_buffer, &
    2414              :                       rho_g=rho_g, &
    2415              :                       rho_r=rho_r, &
    2416          404 :                       tot_rho_r=tot_rho_r)
    2417              : 
    2418          404 :       gapw = admm_env%do_gapw
    2419          404 :       nimg = dft_control%nimages
    2420              : 
    2421              : !   Calculate rho_buffer = rho_aux(ispin) to get exchange of ispin electrons
    2422         1240 :       DO img = 1, nimg
    2423          836 :          CALL dbcsr_set(rho_ao_aux_buffer(1, img)%matrix, 0.0_dp)
    2424          836 :          CALL dbcsr_set(rho_ao_aux_buffer(2, img)%matrix, 0.0_dp)
    2425              :          CALL dbcsr_add(rho_ao_aux_buffer(ispin, img)%matrix, &
    2426         1240 :                         rho_ao_aux(ispin, img)%matrix, 0.0_dp, 1.0_dp)
    2427              :       END DO
    2428              : 
    2429              :       ! By default use standard AUX_FIT basis and task_list. IF GAPW use the soft ones
    2430              :       basis_type = "AUX_FIT"
    2431          404 :       task_list => admm_env%task_list_aux_fit
    2432          404 :       IF (gapw) THEN
    2433              :          basis_type = "AUX_FIT_SOFT"
    2434          124 :          task_list => admm_env%admm_gapw_env%task_list
    2435              :       END IF
    2436              : 
    2437              :       ! integration for getting the spin dependent density has to done for both spins!
    2438         1212 :       DO myspin = 1, dft_control%nspins
    2439              : 
    2440          808 :          rho_ao => rho_ao_aux_buffer(myspin, :)
    2441              :          CALL calculate_rho_elec(ks_env=ks_env, &
    2442              :                                  matrix_p_kp=rho_ao, &
    2443              :                                  rho=rho_r(myspin), &
    2444              :                                  rho_gspace=rho_g(myspin), &
    2445              :                                  total_rho=tot_rho_r(myspin), &
    2446              :                                  soft_valid=.FALSE., &
    2447              :                                  basis_type="AUX_FIT", &
    2448         1212 :                                  task_list_external=task_list)
    2449              : 
    2450              :       END DO
    2451              : 
    2452              :       ! Write changes in buffer density matrix
    2453          404 :       CALL qs_rho_set(rho_aux_fit_buffer, rho_r_valid=.TRUE., rho_g_valid=.TRUE.)
    2454              : 
    2455          404 :       xc_section_aux => admm_env%xc_section_aux
    2456              : 
    2457              :       ener_x_ispin = 0.0_dp
    2458              : 
    2459              :       CALL qs_vxc_create(ks_env=ks_env, rho_struct=rho_aux_fit_buffer, xc_section=xc_section_aux, &
    2460              :                          vxc_rho=v_rspace_dummy, vxc_tau=v_tau_rspace_dummy, exc=ener_x_ispin, &
    2461          404 :                          just_energy=.TRUE.)
    2462              : 
    2463              :       !atomic contributions: use the atomic density as stored in admm_env%gapw_env
    2464          404 :       ener_x1_ispin = 0.0_dp
    2465          404 :       IF (gapw) THEN
    2466              : 
    2467          124 :          admm_gapw_env => admm_env%admm_gapw_env
    2468              :          CALL get_qs_env(qs_env, &
    2469              :                          atomic_kind_set=atomic_kind_set, &
    2470          124 :                          para_env=para_env)
    2471              : 
    2472          124 :          CALL local_rho_set_create(local_rho_buffer)
    2473              :          CALL allocate_rho_atom_internals(local_rho_buffer%rho_atom_set, atomic_kind_set, &
    2474          124 :                                           admm_gapw_env%admm_kind_set, dft_control, para_env)
    2475              : 
    2476              :          CALL calculate_rho_atom_coeff(qs_env, rho_ao_aux_buffer, &
    2477              :                                        rho_atom_set=local_rho_buffer%rho_atom_set, &
    2478              :                                        qs_kind_set=admm_gapw_env%admm_kind_set, &
    2479              :                                        oce=admm_gapw_env%oce, sab=admm_env%sab_aux_fit, &
    2480          124 :                                        para_env=para_env)
    2481              : 
    2482              :          CALL prepare_gapw_den(qs_env, local_rho_set=local_rho_buffer, do_rho0=.FALSE., &
    2483          124 :                                kind_set_external=admm_gapw_env%admm_kind_set)
    2484              : 
    2485              :          CALL calculate_vxc_atom(qs_env, energy_only=.TRUE., exc1=ener_x1_ispin, &
    2486              :                                  kind_set_external=admm_env%admm_gapw_env%admm_kind_set, &
    2487              :                                  xc_section_external=xc_section_aux, &
    2488          124 :                                  rho_atom_set_external=local_rho_buffer%rho_atom_set)
    2489              : 
    2490          124 :          CALL local_rho_set_release(local_rho_buffer)
    2491              :       END IF
    2492              : 
    2493          404 :       ener_k_ispin = 0.0_dp
    2494              : 
    2495              :       !! ** Calculate the exchange energy
    2496         1240 :       DO img = 1, nimg
    2497          836 :          CALL dbcsr_dot(matrix_ks_aux_fit_hfx(ispin, img)%matrix, rho_ao_aux_buffer(ispin, img)%matrix, tmp)
    2498         1240 :          ener_k_ispin = ener_k_ispin + tmp
    2499              :       END DO
    2500              : 
    2501              :       ! Divide exchange for indivivual spin by two, since the ener_k_ispin originally is total
    2502              :       ! exchange of alpha and beta
    2503          404 :       ener_k_ispin = ener_k_ispin/2.0_dp
    2504              : 
    2505          404 :       CALL timestop(handle)
    2506              : 
    2507          404 :    END SUBROUTINE calc_spin_dep_aux_exch_ener
    2508              : 
    2509              : ! **************************************************************************************************
    2510              : !> \brief Scale density matrix by gsi(ispin), is needed for force scaling in ADMMP
    2511              : !> \param qs_env ...
    2512              : !> \param rho_ao_orb ...
    2513              : !> \param scale_back ...
    2514              : !> \author Jan Wilhelm, 12/2014
    2515              : ! **************************************************************************************************
    2516          632 :    SUBROUTINE scale_dm(qs_env, rho_ao_orb, scale_back)
    2517              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2518              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_orb
    2519              :       LOGICAL, INTENT(IN)                                :: scale_back
    2520              : 
    2521              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'scale_dm'
    2522              : 
    2523              :       INTEGER                                            :: handle, img, ispin
    2524              :       TYPE(admm_type), POINTER                           :: admm_env
    2525              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2526              : 
    2527          632 :       CALL timeset(routineN, handle)
    2528              : 
    2529          632 :       NULLIFY (admm_env, dft_control)
    2530              : 
    2531              :       CALL get_qs_env(qs_env, &
    2532              :                       admm_env=admm_env, &
    2533          632 :                       dft_control=dft_control)
    2534              : 
    2535              :       ! only for ADMMP
    2536          632 :       IF (admm_env%do_admmp) THEN
    2537           72 :          DO ispin = 1, dft_control%nspins
    2538          296 :             DO img = 1, dft_control%nimages
    2539          264 :                IF (scale_back) THEN
    2540          112 :                   CALL dbcsr_scale(rho_ao_orb(ispin, img)%matrix, 1.0_dp/admm_env%gsi(ispin))
    2541              :                ELSE
    2542          112 :                   CALL dbcsr_scale(rho_ao_orb(ispin, img)%matrix, admm_env%gsi(ispin))
    2543              :                END IF
    2544              :             END DO
    2545              :          END DO
    2546              :       END IF
    2547              : 
    2548          632 :       CALL timestop(handle)
    2549              : 
    2550          632 :    END SUBROUTINE scale_dm
    2551              : 
    2552              : ! **************************************************************************************************
    2553              : !> \brief ...
    2554              : !> \param ispin ...
    2555              : !> \param admm_env ...
    2556              : !> \param mo_set ...
    2557              : !> \param mo_coeff_aux_fit ...
    2558              : ! **************************************************************************************************
    2559          230 :    SUBROUTINE calc_aux_mo_derivs_none(ispin, admm_env, mo_set, mo_coeff_aux_fit)
    2560              :       INTEGER, INTENT(IN)                                :: ispin
    2561              :       TYPE(admm_type), POINTER                           :: admm_env
    2562              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
    2563              :       TYPE(cp_fm_type), INTENT(IN)                       :: mo_coeff_aux_fit
    2564              : 
    2565              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calc_aux_mo_derivs_none'
    2566              : 
    2567              :       INTEGER                                            :: handle, nao_aux_fit, nao_orb, nmo
    2568          230 :       REAL(dp), DIMENSION(:), POINTER                    :: occupation_numbers, scaling_factor
    2569          230 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks_aux_fit, &
    2570          230 :                                                             matrix_ks_aux_fit_dft, &
    2571          230 :                                                             matrix_ks_aux_fit_hfx
    2572              :       TYPE(dbcsr_type)                                   :: dbcsr_work
    2573              : 
    2574          230 :       NULLIFY (matrix_ks_aux_fit, matrix_ks_aux_fit_dft, matrix_ks_aux_fit_hfx)
    2575              : 
    2576          230 :       CALL timeset(routineN, handle)
    2577              : 
    2578          230 :       nao_aux_fit = admm_env%nao_aux_fit
    2579          230 :       nao_orb = admm_env%nao_orb
    2580          230 :       nmo = admm_env%nmo(ispin)
    2581              : 
    2582              :       CALL get_admm_env(admm_env, matrix_ks_aux_fit=matrix_ks_aux_fit, &
    2583              :                         matrix_ks_aux_fit_hfx=matrix_ks_aux_fit_hfx, &
    2584          230 :                         matrix_ks_aux_fit_dft=matrix_ks_aux_fit_dft)
    2585              : 
    2586              :       ! just calculate the mo derivs in the aux basis
    2587              :       ! only needs to be done on the converged ks matrix for the force calc
    2588              :       ! Note with OT and purification NONE, the merging of the derivs
    2589              :       ! happens implicitly because the KS matrices have been already been merged
    2590              :       ! and adding them here would be double counting.
    2591              : 
    2592          230 :       IF (admm_env%do_admms) THEN
    2593              :          !In ADMMS, we use the K matrix defined as K_hf - gsi^2/3*K_dft
    2594           12 :          CALL dbcsr_create(dbcsr_work, template=matrix_ks_aux_fit(ispin)%matrix)
    2595           12 :          CALL dbcsr_copy(dbcsr_work, matrix_ks_aux_fit_hfx(ispin)%matrix)
    2596           12 :          CALL dbcsr_add(dbcsr_work, matrix_ks_aux_fit_dft(ispin)%matrix, 1.0_dp, -admm_env%gsi(ispin)**(2.0_dp/3.0_dp))
    2597           12 :          CALL copy_dbcsr_to_fm(dbcsr_work, admm_env%K(ispin))
    2598           12 :          CALL dbcsr_release(dbcsr_work)
    2599              :       ELSE
    2600          218 :          CALL copy_dbcsr_to_fm(matrix_ks_aux_fit(ispin)%matrix, admm_env%K(ispin))
    2601              :       END IF
    2602          230 :       CALL cp_fm_uplo_to_full(admm_env%K(ispin), admm_env%work_aux_aux)
    2603              : 
    2604              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_aux_fit, &
    2605              :                          1.0_dp, admm_env%K(ispin), mo_coeff_aux_fit, 0.0_dp, &
    2606          230 :                          admm_env%H(ispin))
    2607              : 
    2608          230 :       CALL get_mo_set(mo_set=mo_set, occupation_numbers=occupation_numbers)
    2609          690 :       ALLOCATE (scaling_factor(SIZE(occupation_numbers)))
    2610              : 
    2611         2194 :       scaling_factor = 2.0_dp*occupation_numbers
    2612              : 
    2613          230 :       CALL cp_fm_column_scale(admm_env%H(ispin), scaling_factor)
    2614              : 
    2615          230 :       DEALLOCATE (scaling_factor)
    2616              : 
    2617          230 :       CALL timestop(handle)
    2618              : 
    2619          230 :    END SUBROUTINE calc_aux_mo_derivs_none
    2620              : 
    2621              : ! **************************************************************************************************
    2622              : !> \brief ...
    2623              : !> \param ispin ...
    2624              : !> \param admm_env ...
    2625              : !> \param mo_set ...
    2626              : !> \param mo_derivs ...
    2627              : !> \param matrix_ks_aux_fit ...
    2628              : ! **************************************************************************************************
    2629          100 :    SUBROUTINE merge_mo_derivs_no_diag(ispin, admm_env, mo_set, mo_derivs, matrix_ks_aux_fit)
    2630              :       INTEGER, INTENT(IN)                                :: ispin
    2631              :       TYPE(admm_type), POINTER                           :: admm_env
    2632              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
    2633              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: mo_derivs
    2634              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks_aux_fit
    2635              : 
    2636              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'merge_mo_derivs_no_diag'
    2637              : 
    2638              :       INTEGER                                            :: handle, nao_aux_fit, nao_orb, nmo
    2639          100 :       REAL(dp), DIMENSION(:), POINTER                    :: occupation_numbers, scaling_factor
    2640              : 
    2641          100 :       CALL timeset(routineN, handle)
    2642              : 
    2643          100 :       nao_aux_fit = admm_env%nao_aux_fit
    2644          100 :       nao_orb = admm_env%nao_orb
    2645          100 :       nmo = admm_env%nmo(ispin)
    2646              : 
    2647          100 :       CALL copy_dbcsr_to_fm(matrix_ks_aux_fit(ispin)%matrix, admm_env%K(ispin))
    2648          100 :       CALL cp_fm_uplo_to_full(admm_env%K(ispin), admm_env%work_aux_aux)
    2649              : 
    2650          100 :       CALL get_mo_set(mo_set=mo_set, occupation_numbers=occupation_numbers)
    2651          300 :       ALLOCATE (scaling_factor(SIZE(occupation_numbers)))
    2652          460 :       scaling_factor = 0.5_dp
    2653              : 
    2654              :       !! ** calculate first part
    2655              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nmo, &
    2656              :                          1.0_dp, admm_env%C_hat(ispin), admm_env%lambda_inv(ispin), 0.0_dp, &
    2657          100 :                          admm_env%work_aux_nmo(ispin))
    2658              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_aux_fit, &
    2659              :                          1.0_dp, admm_env%K(ispin), admm_env%work_aux_nmo(ispin), 0.0_dp, &
    2660          100 :                          admm_env%work_aux_nmo2(ispin))
    2661              :       CALL parallel_gemm('T', 'N', nao_orb, nmo, nao_aux_fit, &
    2662              :                          2.0_dp, admm_env%A, admm_env%work_aux_nmo2(ispin), 0.0_dp, &
    2663          100 :                          admm_env%mo_derivs_tmp(ispin))
    2664              :       !! ** calculate second part
    2665              :       CALL parallel_gemm('T', 'N', nmo, nmo, nao_aux_fit, &
    2666              :                          1.0_dp, admm_env%work_aux_nmo(ispin), admm_env%work_aux_nmo2(ispin), 0.0_dp, &
    2667          100 :                          admm_env%work_orb_orb)
    2668              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nmo, &
    2669              :                          1.0_dp, admm_env%C_hat(ispin), admm_env%work_orb_orb, 0.0_dp, &
    2670          100 :                          admm_env%work_aux_orb)
    2671              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nao_aux_fit, &
    2672              :                          1.0_dp, admm_env%S, admm_env%work_aux_orb, 0.0_dp, &
    2673          100 :                          admm_env%work_aux_nmo(ispin))
    2674              :       CALL parallel_gemm('T', 'N', nao_orb, nmo, nao_aux_fit, &
    2675              :                          -2.0_dp, admm_env%A, admm_env%work_aux_nmo(ispin), 1.0_dp, &
    2676          100 :                          admm_env%mo_derivs_tmp(ispin))
    2677              : 
    2678          100 :       CALL cp_fm_column_scale(admm_env%mo_derivs_tmp(ispin), scaling_factor)
    2679              : 
    2680          100 :       CALL cp_fm_scale_and_add(1.0_dp, mo_derivs(ispin), 1.0_dp, admm_env%mo_derivs_tmp(ispin))
    2681              : 
    2682          100 :       DEALLOCATE (scaling_factor)
    2683              : 
    2684          100 :       CALL timestop(handle)
    2685              : 
    2686          100 :    END SUBROUTINE merge_mo_derivs_no_diag
    2687              : 
    2688              : ! **************************************************************************************************
    2689              : !> \brief Calculate the derivative of the AUX_FIT mo, based on the ORB mo_derivs
    2690              : !> \param qs_env ...
    2691              : !> \param mo_derivs the MO derivatives in the orbital basis
    2692              : ! **************************************************************************************************
    2693         6802 :    SUBROUTINE calc_admm_mo_derivatives(qs_env, mo_derivs)
    2694              : 
    2695              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2696              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mo_derivs
    2697              : 
    2698              :       INTEGER                                            :: ispin, nspins
    2699              :       TYPE(admm_type), POINTER                           :: admm_env
    2700         6802 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: mo_derivs_fm
    2701         6802 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mo_derivs_aux_fit
    2702              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_coeff_aux_fit
    2703         6802 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks_aux_fit
    2704         6802 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mo_array, mos_aux_fit
    2705              : 
    2706         6802 :       NULLIFY (mo_array, mos_aux_fit, matrix_ks_aux_fit, mo_coeff_aux_fit, &
    2707         6802 :                mo_derivs_aux_fit, mo_coeff)
    2708              : 
    2709         6802 :       CALL get_qs_env(qs_env, admm_env=admm_env, mos=mo_array)
    2710              :       CALL get_admm_env(admm_env, mos_aux_fit=mos_aux_fit, mo_derivs_aux_fit=mo_derivs_aux_fit, &
    2711         6802 :                         matrix_ks_aux_fit=matrix_ks_aux_fit)
    2712              : 
    2713         6802 :       nspins = SIZE(mo_derivs)
    2714        28406 :       ALLOCATE (mo_derivs_fm(nspins))
    2715        14802 :       DO ispin = 1, nspins
    2716         8000 :          CALL get_mo_set(mo_set=mo_array(ispin), mo_coeff=mo_coeff)
    2717        14802 :          CALL cp_fm_create(mo_derivs_fm(ispin), mo_coeff%matrix_struct)
    2718              :       END DO
    2719              : 
    2720        14802 :       DO ispin = 1, nspins
    2721         8000 :          CALL get_mo_set(mo_set=mo_array(ispin), mo_coeff=mo_coeff)
    2722         8000 :          CALL get_mo_set(mo_set=mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit)
    2723              : 
    2724         8000 :          CALL copy_dbcsr_to_fm(mo_derivs(ispin)%matrix, mo_derivs_fm(ispin))
    2725              :          CALL admm_mo_merge_derivs(ispin, admm_env, mo_array(ispin), mo_coeff, mo_coeff_aux_fit, &
    2726         8000 :                                    mo_derivs_fm, mo_derivs_aux_fit, matrix_ks_aux_fit)
    2727        14802 :          CALL copy_fm_to_dbcsr(mo_derivs_fm(ispin), mo_derivs(ispin)%matrix)
    2728              :       END DO
    2729              : 
    2730         6802 :       CALL cp_fm_release(mo_derivs_fm)
    2731              : 
    2732        13604 :    END SUBROUTINE calc_admm_mo_derivatives
    2733              : 
    2734              : ! **************************************************************************************************
    2735              : !> \brief Calculate the forces due to the AUX/ORB basis overlap in ADMM
    2736              : !> \param qs_env ...
    2737              : ! **************************************************************************************************
    2738          286 :    SUBROUTINE calc_admm_ovlp_forces(qs_env)
    2739              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2740              : 
    2741              :       INTEGER                                            :: ispin
    2742              :       TYPE(admm_type), POINTER                           :: admm_env
    2743              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff, mo_coeff_aux_fit
    2744          286 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s_aux_fit, matrix_s_aux_fit_vs_orb
    2745              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2746          286 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos, mos_aux_fit
    2747              :       TYPE(mo_set_type), POINTER                         :: mo_set
    2748              : 
    2749          286 :       CALL get_qs_env(qs_env, dft_control=dft_control)
    2750              : 
    2751          286 :       IF (dft_control%do_admm_dm) THEN
    2752            0 :          CPABORT("Forces with ADMM DM methods not implemented")
    2753              :       END IF
    2754          286 :       IF (dft_control%do_admm_mo .AND. .NOT. qs_env%run_rtp) THEN
    2755          256 :          NULLIFY (matrix_s_aux_fit, matrix_s_aux_fit_vs_orb, mos_aux_fit, mos, admm_env)
    2756              :          CALL get_qs_env(qs_env=qs_env, &
    2757              :                          mos=mos, &
    2758          256 :                          admm_env=admm_env)
    2759              :          CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit, mos_aux_fit=mos_aux_fit, &
    2760          256 :                            matrix_s_aux_fit_vs_orb=matrix_s_aux_fit_vs_orb)
    2761          554 :          DO ispin = 1, dft_control%nspins
    2762          298 :             mo_set => mos(ispin)
    2763          298 :             CALL get_mo_set(mo_set=mo_set, mo_coeff=mo_coeff)
    2764              :             ! if no purification we need to calculate the H matrix for forces
    2765          554 :             IF (admm_env%purification_method == do_admm_purify_none) THEN
    2766          230 :                CALL get_mo_set(mo_set=mos_aux_fit(ispin), mo_coeff=mo_coeff_aux_fit)
    2767          230 :                CALL calc_aux_mo_derivs_none(ispin, qs_env%admm_env, mo_set, mo_coeff_aux_fit)
    2768              :             END IF
    2769              :          END DO
    2770          256 :          CALL calc_mixed_overlap_force(qs_env)
    2771              :       END IF
    2772              : 
    2773          286 :    END SUBROUTINE calc_admm_ovlp_forces
    2774              : 
    2775              : ! **************************************************************************************************
    2776              : !> \brief Calculate the forces due to the AUX/ORB basis overlap in ADMM, in the KP case
    2777              : !> \param qs_env ...
    2778              : ! **************************************************************************************************
    2779           30 :    SUBROUTINE calc_admm_ovlp_forces_kp(qs_env)
    2780              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2781              : 
    2782              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calc_admm_ovlp_forces_kp'
    2783              : 
    2784              :       COMPLEX(dp)                                        :: fac, fac2
    2785              :       INTEGER                                            :: handle, i, igroup, ik, ikp, img, indx, &
    2786              :                                                             ispin, kplocal, kpmax, nao_aux_fit, &
    2787              :                                                             nao_orb, natom, nimg, nkp, nkp_groups, &
    2788              :                                                             nspins
    2789              :       INTEGER, DIMENSION(2)                              :: kp_range
    2790           30 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    2791           30 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    2792              :       LOGICAL                                            :: gapw, my_kpgrp, use_real_wfn
    2793           30 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: admm_force
    2794           30 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    2795              :       TYPE(admm_type), POINTER                           :: admm_env
    2796           30 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2797           30 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:, :) :: info
    2798              :       TYPE(cp_cfm_type)                                  :: cA, ckmatrix, cpmatrix, cQ, cS, cS_inv, &
    2799              :                                                             cwork_aux_aux, cwork_aux_orb, &
    2800              :                                                             cwork_aux_orb2
    2801              :       TYPE(cp_fm_struct_type), POINTER                   :: struct_aux_aux, struct_aux_orb, &
    2802              :                                                             struct_orb_orb
    2803              :       TYPE(cp_fm_type)                                   :: fmdummy, S_inv, work_aux_aux, &
    2804              :                                                             work_aux_aux2, work_aux_aux3, &
    2805              :                                                             work_aux_orb
    2806           30 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :)  :: fm_skap, fm_skapa
    2807           30 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: fmwork
    2808           30 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_aux_fit, matrix_ks_aux_fit_dft, &
    2809           30 :          matrix_ks_aux_fit_hfx, matrix_s_aux_fit, matrix_s_aux_fit_vs_orb, matrix_skap, &
    2810           30 :          matrix_skapa, rho_ao_orb
    2811              :       TYPE(dbcsr_type)                                   :: kmatrix_tmp
    2812           30 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: kmatrix
    2813              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2814              :       TYPE(kpoint_env_type), POINTER                     :: kp
    2815              :       TYPE(kpoint_type), POINTER                         :: kpoints
    2816              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2817              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2818           30 :          POINTER                                         :: sab_aux_fit, sab_aux_fit_asymm, &
    2819           30 :                                                             sab_aux_fit_vs_orb, sab_kp
    2820           30 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    2821              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    2822              :       TYPE(qs_rho_type), POINTER                         :: rho
    2823              : 
    2824           30 :       CALL timeset(routineN, handle)
    2825              : 
    2826              :       !Note: we only treat the case with purification none, there the overlap forces read as:
    2827              :       !F = 2*Tr[P * A^T * K_aux * S^-1_aux * Q^(x)] - 2*Tr[A * P * A^T * K_aux * S^-1_aux *S_aux^(x)]
    2828              :       !where P is the density matrix in the ORB basis. As a strategy, we FT all relevant matrices
    2829              :       !from real space to KP, calculate the matrix products, back FT to real space, and calculate the
    2830              :       !overlap forces
    2831              : 
    2832           30 :       NULLIFY (ks_env, admm_env, matrix_ks_aux_fit, &
    2833           30 :                matrix_s_aux_fit, matrix_s_aux_fit_vs_orb, rho, force, &
    2834           30 :                para_env, atomic_kind_set, kpoints, sab_aux_fit, &
    2835           30 :                sab_aux_fit_vs_orb, sab_aux_fit_asymm, struct_orb_orb, &
    2836           30 :                struct_aux_orb, struct_aux_aux)
    2837              : 
    2838              :       CALL get_qs_env(qs_env, &
    2839              :                       ks_env=ks_env, &
    2840              :                       admm_env=admm_env, &
    2841              :                       dft_control=dft_control, &
    2842              :                       kpoints=kpoints, &
    2843              :                       natom=natom, &
    2844              :                       atomic_kind_set=atomic_kind_set, &
    2845              :                       force=force, &
    2846           30 :                       rho=rho)
    2847           30 :       nimg = dft_control%nimages
    2848              :       CALL get_admm_env(admm_env, &
    2849              :                         matrix_s_aux_fit_kp=matrix_s_aux_fit, &
    2850              :                         matrix_s_aux_fit_vs_orb_kp=matrix_s_aux_fit_vs_orb, &
    2851              :                         sab_aux_fit=sab_aux_fit, &
    2852              :                         sab_aux_fit_vs_orb=sab_aux_fit_vs_orb, &
    2853              :                         sab_aux_fit_asymm=sab_aux_fit_asymm, &
    2854              :                         matrix_ks_aux_fit_kp=matrix_ks_aux_fit, &
    2855              :                         matrix_ks_aux_fit_dft_kp=matrix_ks_aux_fit_dft, &
    2856           30 :                         matrix_ks_aux_fit_hfx_kp=matrix_ks_aux_fit_hfx)
    2857              : 
    2858           30 :       gapw = admm_env%do_gapw
    2859           30 :       nao_aux_fit = admm_env%nao_aux_fit
    2860           30 :       nao_orb = admm_env%nao_orb
    2861           30 :       nspins = dft_control%nspins
    2862              : 
    2863              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
    2864              :                            nkp_groups=nkp_groups, kp_dist=kp_dist, &
    2865           30 :                            cell_to_index=cell_to_index, sab_nl=sab_kp)
    2866              : 
    2867              :       !Case study on ADMMQ, ADMMS and ADMMP
    2868           30 :       IF (admm_env%do_admms) THEN
    2869              :          !Here we buld the KS matrix: KS_hfx = gsi^2/3*KS_dft, the we then pass as the ususal KS_aux_fit
    2870            6 :          NULLIFY (matrix_ks_aux_fit)
    2871          362 :          ALLOCATE (matrix_ks_aux_fit(nspins, dft_control%nimages))
    2872          146 :          DO img = 1, dft_control%nimages
    2873          344 :             DO ispin = 1, nspins
    2874          198 :                NULLIFY (matrix_ks_aux_fit(ispin, img)%matrix)
    2875          198 :                ALLOCATE (matrix_ks_aux_fit(ispin, img)%matrix)
    2876          198 :                CALL dbcsr_create(matrix_ks_aux_fit(ispin, img)%matrix, template=matrix_s_aux_fit(1, 1)%matrix)
    2877          198 :                CALL dbcsr_copy(matrix_ks_aux_fit(ispin, img)%matrix, matrix_ks_aux_fit_hfx(ispin, img)%matrix)
    2878              :                CALL dbcsr_add(matrix_ks_aux_fit(ispin, img)%matrix, matrix_ks_aux_fit_dft(ispin, img)%matrix, &
    2879          338 :                               1.0_dp, -admm_env%gsi(ispin)**(2.0_dp/3.0_dp))
    2880              :             END DO
    2881              :          END DO
    2882              :       END IF
    2883              : 
    2884              :       ! the temporary DBCSR matrices for the rskp_transform we have to manually allocate
    2885              :       ! index 1 => real, index 2 => imaginary
    2886           90 :       ALLOCATE (kmatrix(2))
    2887              :       CALL dbcsr_create(kmatrix(1), template=matrix_ks_aux_fit(1, 1)%matrix, &
    2888           30 :                         matrix_type=dbcsr_type_symmetric)
    2889              :       CALL dbcsr_create(kmatrix(2), template=matrix_ks_aux_fit(1, 1)%matrix, &
    2890           30 :                         matrix_type=dbcsr_type_antisymmetric)
    2891              :       CALL dbcsr_create(kmatrix_tmp, template=matrix_ks_aux_fit(1, 1)%matrix, &
    2892           30 :                         matrix_type=dbcsr_type_no_symmetry)
    2893           30 :       CALL cp_dbcsr_alloc_block_from_nbl(kmatrix(1), sab_aux_fit)
    2894           30 :       CALL cp_dbcsr_alloc_block_from_nbl(kmatrix(2), sab_aux_fit)
    2895              : 
    2896           30 :       kplocal = kp_range(2) - kp_range(1) + 1
    2897           90 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
    2898           30 :       para_env => kpoints%blacs_env_all%para_env
    2899         1086 :       ALLOCATE (info(nkp*nspins, 2))
    2900              : 
    2901              :       CALL cp_fm_struct_create(struct_aux_aux, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
    2902           30 :                                nrow_global=nao_aux_fit, ncol_global=nao_aux_fit)
    2903           30 :       CALL cp_fm_create(work_aux_aux, struct_aux_aux)
    2904           30 :       CALL cp_fm_create(work_aux_aux2, struct_aux_aux)
    2905           30 :       CALL cp_fm_create(work_aux_aux3, struct_aux_aux)
    2906           30 :       CALL cp_fm_create(s_inv, struct_aux_aux)
    2907              : 
    2908              :       CALL cp_fm_struct_create(struct_aux_orb, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
    2909           30 :                                nrow_global=nao_aux_fit, ncol_global=nao_orb)
    2910           30 :       CALL cp_fm_create(work_aux_orb, struct_aux_orb)
    2911              : 
    2912              :       CALL cp_fm_struct_create(struct_orb_orb, context=kpoints%blacs_env, para_env=kpoints%para_env_kp, &
    2913           30 :                                nrow_global=nao_orb, ncol_global=nao_orb)
    2914              : 
    2915              :       !Create cfm work matrices
    2916           30 :       IF (.NOT. use_real_wfn) THEN
    2917           30 :          CALL cp_cfm_create(cpmatrix, struct_orb_orb)
    2918              : 
    2919           30 :          CALL cp_cfm_create(cS_inv, struct_aux_aux)
    2920           30 :          CALL cp_cfm_create(cS, struct_aux_aux)
    2921           30 :          CALL cp_cfm_create(cwork_aux_aux, struct_aux_aux)
    2922           30 :          CALL cp_cfm_create(ckmatrix, struct_aux_aux)
    2923              : 
    2924           30 :          CALL cp_cfm_create(cA, struct_aux_orb)
    2925           30 :          CALL cp_cfm_create(cQ, struct_aux_orb)
    2926           30 :          CALL cp_cfm_create(cwork_aux_orb, struct_aux_orb)
    2927           30 :          CALL cp_cfm_create(cwork_aux_orb2, struct_aux_orb)
    2928              :       END IF
    2929              : 
    2930              :       !We create the fms in which we store the KP matrix products
    2931         1152 :       ALLOCATE (fm_skap(kplocal, 2, nspins), fm_skapa(kplocal, 2, nspins))
    2932           66 :       DO ispin = 1, nspins
    2933          138 :          DO i = 1, 2
    2934          486 :             DO ikp = 1, kplocal
    2935          378 :                CALL cp_fm_create(fm_skap(ikp, i, ispin), struct_aux_orb)
    2936          450 :                CALL cp_fm_create(fm_skapa(ikp, i, ispin), struct_aux_aux)
    2937              :             END DO
    2938              :          END DO
    2939              :       END DO
    2940              : 
    2941           30 :       CALL cp_fm_struct_release(struct_aux_aux)
    2942           30 :       CALL cp_fm_struct_release(struct_aux_orb)
    2943           30 :       CALL cp_fm_struct_release(struct_orb_orb)
    2944              : 
    2945           30 :       indx = 0
    2946          190 :       DO ikp = 1, kpmax
    2947          384 :          DO ispin = 1, nspins
    2948          742 :             DO igroup = 1, nkp_groups
    2949              :                ! number of current kpoint
    2950          388 :                ik = kp_dist(1, igroup) + ikp - 1
    2951          388 :                IF (ik > kp_dist(2, igroup)) CYCLE
    2952          378 :                my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    2953          378 :                indx = indx + 1
    2954              : 
    2955              :                ! FT of matrices KS, then transfer to FM type
    2956          378 :                IF (use_real_wfn) THEN
    2957            0 :                   CALL dbcsr_set(kmatrix(1), 0.0_dp)
    2958              :                   CALL rskp_transform(rmatrix=kmatrix(1), rsmat=matrix_ks_aux_fit, ispin=ispin, &
    2959            0 :                                       xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_aux_fit)
    2960            0 :                   CALL dbcsr_desymmetrize(kmatrix(1), kmatrix_tmp)
    2961            0 :                   CALL copy_dbcsr_to_fm(kmatrix_tmp, admm_env%work_aux_aux)
    2962              :                ELSE
    2963          378 :                   CALL dbcsr_set(kmatrix(1), 0.0_dp)
    2964          378 :                   CALL dbcsr_set(kmatrix(2), 0.0_dp)
    2965              :                   CALL rskp_transform(rmatrix=kmatrix(1), cmatrix=kmatrix(2), rsmat=matrix_ks_aux_fit, ispin=ispin, &
    2966          378 :                                       xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_aux_fit)
    2967          378 :                   CALL dbcsr_desymmetrize(kmatrix(1), kmatrix_tmp)
    2968          378 :                   CALL copy_dbcsr_to_fm(kmatrix_tmp, admm_env%work_aux_aux)
    2969          378 :                   CALL dbcsr_desymmetrize(kmatrix(2), kmatrix_tmp)
    2970          378 :                   CALL copy_dbcsr_to_fm(kmatrix_tmp, admm_env%work_aux_aux2)
    2971              :                END IF
    2972              : 
    2973          572 :                IF (my_kpgrp) THEN
    2974          189 :                   CALL cp_fm_start_copy_general(admm_env%work_aux_aux, work_aux_aux, para_env, info(indx, 1))
    2975          189 :                   IF (.NOT. use_real_wfn) THEN
    2976          189 :                      CALL cp_fm_start_copy_general(admm_env%work_aux_aux2, work_aux_aux2, para_env, info(indx, 2))
    2977              :                   END IF
    2978              :                ELSE
    2979          189 :                   CALL cp_fm_start_copy_general(admm_env%work_aux_aux, fmdummy, para_env, info(indx, 1))
    2980          189 :                   IF (.NOT. use_real_wfn) THEN
    2981          189 :                      CALL cp_fm_start_copy_general(admm_env%work_aux_aux2, fmdummy, para_env, info(indx, 2))
    2982              :                   END IF
    2983              :                END IF
    2984              :             END DO
    2985              :          END DO
    2986              :       END DO
    2987              : 
    2988              :       indx = 0
    2989          190 :       DO ikp = 1, kpmax
    2990          384 :          DO ispin = 1, nspins
    2991          582 :             DO igroup = 1, nkp_groups
    2992              :                ! number of current kpoint
    2993          388 :                ik = kp_dist(1, igroup) + ikp - 1
    2994          388 :                IF (ik > kp_dist(2, igroup)) CYCLE
    2995          378 :                my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    2996          189 :                indx = indx + 1
    2997          194 :                IF (my_kpgrp) THEN
    2998          189 :                   CALL cp_fm_finish_copy_general(work_aux_aux, info(indx, 1))
    2999          189 :                   IF (.NOT. use_real_wfn) THEN
    3000          189 :                      CALL cp_fm_finish_copy_general(work_aux_aux2, info(indx, 2))
    3001          189 :                      CALL cp_fm_to_cfm(work_aux_aux, work_aux_aux2, ckmatrix)
    3002              :                   END IF
    3003              :                END IF
    3004              :             END DO
    3005          194 :             IF (ikp > kplocal) CYCLE
    3006          189 :             kp => kpoints%kp_aux_env(ikp)%kpoint_env
    3007              : 
    3008          349 :             IF (use_real_wfn) THEN
    3009              : 
    3010              :                !! Calculate S'_inverse
    3011            0 :                CALL cp_fm_to_fm(kp%smat(1, 1), S_inv)
    3012            0 :                CALL cp_fm_cholesky_decompose(S_inv)
    3013            0 :                CALL cp_fm_cholesky_invert(S_inv)
    3014              :                !! Symmetrize the guy
    3015            0 :                CALL cp_fm_uplo_to_full(S_inv, work_aux_aux3)
    3016              : 
    3017              :                !We need to calculate S^-1*K*A*P and S^-1*K*A*P*A^T
    3018              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, 1.0_dp, S_inv, &
    3019            0 :                                   work_aux_aux, 0.0_dp, work_aux_aux3) ! S^-1 * K
    3020              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, 1.0_dp, work_aux_aux3, &
    3021            0 :                                   kp%amat(1, 1), 0.0_dp, work_aux_orb) ! S^-1 * K * A
    3022              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, 1.0_dp, work_aux_orb, &
    3023              :                                   kpoints%kp_env(ikp)%kpoint_env%pmat(1, ispin), 0.0_dp, &
    3024            0 :                                   fm_skap(ikp, 1, ispin)) ! S^-1 * K * A * P
    3025              :                CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nao_orb, 1.0_dp, fm_skap(ikp, 1, ispin), &
    3026            0 :                                   kp%amat(1, 1), 0.0_dp, fm_skapa(ikp, 1, ispin))
    3027              : 
    3028              :             ELSE !complex wfn
    3029              : 
    3030          189 :                IF (admm_env%do_admmq .OR. admm_env%do_admms) THEN
    3031           97 :                   CALL cp_fm_to_cfm(kp%smat(1, 1), kp%smat(2, 1), cS)
    3032              : 
    3033              :                   !Need to subdtract lambda* S_aux to K_aux, and scale the whole thing by gsi
    3034           97 :                   fac = CMPLX(-admm_env%lambda_merlot(ispin), 0.0_dp, dp)
    3035           97 :                   CALL cp_cfm_scale_and_add(z_one, ckmatrix, fac, cS)
    3036           97 :                   CALL cp_cfm_scale(admm_env%gsi(ispin), ckmatrix)
    3037              :                END IF
    3038              : 
    3039          189 :                IF (admm_env%do_admmp) THEN
    3040           28 :                   CALL cp_fm_to_cfm(kp%smat(1, 1), kp%smat(2, 1), cS)
    3041              : 
    3042              :                   !Need to substract labda*gsi*S_aux to gsi**2*K_aux
    3043           28 :                   fac = CMPLX(-admm_env%gsi(ispin)*admm_env%lambda_merlot(ispin), 0.0_dp, dp)
    3044           28 :                   fac2 = CMPLX(admm_env%gsi(ispin)**2, 0.0_dp, dp)
    3045           28 :                   CALL cp_cfm_scale_and_add(fac2, ckmatrix, fac, cS)
    3046              :                END IF
    3047              : 
    3048          189 :                CALL cp_fm_to_cfm(kp%smat(1, 1), kp%smat(2, 1), cS_inv)
    3049          189 :                CALL cp_cfm_cholesky_decompose(cS_inv)
    3050          189 :                CALL cp_cfm_cholesky_invert(cS_inv)
    3051          189 :                CALL cp_cfm_uplo_to_full(cS_inv, cwork_aux_aux)
    3052              : 
    3053              :                !Take the ORB density matrix from the kp_env
    3054              :                CALL cp_fm_to_cfm(kpoints%kp_env(ikp)%kpoint_env%pmat(1, ispin), &
    3055              :                                  kpoints%kp_env(ikp)%kpoint_env%pmat(2, ispin), &
    3056          189 :                                  cpmatrix)
    3057              : 
    3058              :                !Do the same thing as in the real case
    3059              :                !We need to calculate S^-1*K*A*P and S^-1*K*A*P*A^T
    3060          189 :                CALL cp_fm_to_cfm(kp%amat(1, 1), kp%amat(2, 1), cA)
    3061              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_aux_fit, nao_aux_fit, z_one, cS_inv, &
    3062          189 :                                   ckmatrix, z_zero, cwork_aux_aux) ! S^-1 * K
    3063              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, z_one, cwork_aux_aux, &
    3064          189 :                                   cA, z_zero, cwork_aux_orb) ! S^-1 * K * A
    3065              :                CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, z_one, cwork_aux_orb, &
    3066          189 :                                   cpmatrix, z_zero, cwork_aux_orb2) ! S^-1 * K * A * P
    3067              :                CALL parallel_gemm('N', 'C', nao_aux_fit, nao_aux_fit, nao_orb, z_one, cwork_aux_orb2, &
    3068          189 :                                   cA, z_zero, cwork_aux_aux)
    3069              : 
    3070          189 :                IF (admm_env%do_admmq .OR. admm_env%do_admmp .OR. admm_env%do_admms) THEN
    3071              :                   !In ADMMQ, ADMMS, and ADMMP, there is an extra lambda*Tq *P* Tq^T matrix to contract with S_aux^(x)
    3072              :                   !we calculate it and add it to fm_skapa (aka cwork_aux_aux)
    3073              : 
    3074              :                   !factor 0.5 because later multiplied by 2
    3075          125 :                   fac = CMPLX(0.5_dp*admm_env%lambda_merlot(ispin)*admm_env%gsi(ispin), 0.0_dp, dp)
    3076              :                   CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, z_one, cA, cpmatrix, &
    3077          125 :                                      z_zero, cwork_aux_orb)
    3078              :                   CALL parallel_gemm('N', 'C', nao_aux_fit, nao_aux_fit, nao_orb, fac, cwork_aux_orb, &
    3079          125 :                                      cA, z_one, cwork_aux_aux)
    3080              :                END IF
    3081              : 
    3082          189 :                CALL cp_cfm_to_fm(cwork_aux_orb2, mtargetr=fm_skap(ikp, 1, ispin), mtargeti=fm_skap(ikp, 2, ispin))
    3083          189 :                CALL cp_cfm_to_fm(cwork_aux_aux, mtargetr=fm_skapa(ikp, 1, ispin), mtargeti=fm_skapa(ikp, 2, ispin))
    3084              : 
    3085              :             END IF
    3086              : 
    3087              :          END DO
    3088              :       END DO
    3089              : 
    3090          408 :       DO indx = 1, SIZE(info, 1)
    3091          378 :          CALL cp_fm_cleanup_copy_general(info(indx, 1))
    3092          408 :          IF (.NOT. use_real_wfn) CALL cp_fm_cleanup_copy_general(info(indx, 2))
    3093              :       END DO
    3094              : 
    3095          786 :       DEALLOCATE (info)
    3096           30 :       CALL dbcsr_release(kmatrix(1))
    3097           30 :       CALL dbcsr_release(kmatrix(2))
    3098           30 :       CALL dbcsr_release(kmatrix_tmp)
    3099              : 
    3100           30 :       CALL cp_fm_release(work_aux_aux)
    3101           30 :       CALL cp_fm_release(work_aux_aux2)
    3102           30 :       CALL cp_fm_release(work_aux_aux3)
    3103           30 :       CALL cp_fm_release(S_inv)
    3104           30 :       CALL cp_fm_release(work_aux_orb)
    3105           30 :       IF (.NOT. use_real_wfn) THEN
    3106           30 :          CALL cp_cfm_release(ckmatrix)
    3107           30 :          CALL cp_cfm_release(cpmatrix)
    3108           30 :          CALL cp_cfm_release(cS_inv)
    3109           30 :          CALL cp_cfm_release(cS)
    3110           30 :          CALL cp_cfm_release(cwork_aux_aux)
    3111           30 :          CALL cp_cfm_release(cwork_aux_orb)
    3112           30 :          CALL cp_cfm_release(cwork_aux_orb2)
    3113           30 :          CALL cp_cfm_release(cA)
    3114           30 :          CALL cp_cfm_release(cQ)
    3115              :       END IF
    3116              : 
    3117              :       !Back FT to real space
    3118         9944 :       ALLOCATE (matrix_skap(nspins, nimg), matrix_skapa(nspins, nimg))
    3119         2428 :       DO img = 1, nimg
    3120         4912 :          DO ispin = 1, nspins
    3121         2484 :             ALLOCATE (matrix_skap(ispin, img)%matrix)
    3122              :             CALL dbcsr_create(matrix_skap(ispin, img)%matrix, template=matrix_s_aux_fit_vs_orb(1, 1)%matrix, &
    3123         2484 :                               matrix_type=dbcsr_type_no_symmetry)
    3124         2484 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_skap(ispin, img)%matrix, sab_aux_fit_vs_orb)
    3125              : 
    3126         2484 :             ALLOCATE (matrix_skapa(ispin, img)%matrix)
    3127              :             CALL dbcsr_create(matrix_skapa(ispin, img)%matrix, template=matrix_s_aux_fit(1, 1)%matrix, &
    3128         2484 :                               matrix_type=dbcsr_type_no_symmetry)
    3129         4882 :             CALL cp_dbcsr_alloc_block_from_nbl(matrix_skapa(ispin, img)%matrix, sab_aux_fit_asymm)
    3130              :          END DO
    3131              :       END DO
    3132              : 
    3133           90 :       ALLOCATE (fmwork(2))
    3134           30 :       CALL cp_fm_get_info(admm_env%work_aux_orb, matrix_struct=struct_aux_orb)
    3135           30 :       CALL cp_fm_create(fmwork(1), struct_aux_orb)
    3136           30 :       CALL cp_fm_create(fmwork(2), struct_aux_orb)
    3137              :       CALL kpoint_density_transform(kpoints, matrix_skap, .FALSE., &
    3138              :                                     matrix_s_aux_fit_vs_orb(1, 1)%matrix, sab_aux_fit_vs_orb, &
    3139           30 :                                     fmwork, for_aux_fit=.TRUE., pmat_ext=fm_skap)
    3140           30 :       CALL cp_fm_release(fmwork(1))
    3141           30 :       CALL cp_fm_release(fmwork(2))
    3142              : 
    3143           30 :       CALL cp_fm_get_info(admm_env%work_aux_aux, matrix_struct=struct_aux_aux)
    3144           30 :       CALL cp_fm_create(fmwork(1), struct_aux_aux)
    3145           30 :       CALL cp_fm_create(fmwork(2), struct_aux_aux)
    3146              :       CALL kpoint_density_transform(kpoints, matrix_skapa, .FALSE., &
    3147              :                                     matrix_s_aux_fit(1, 1)%matrix, sab_aux_fit_asymm, &
    3148           30 :                                     fmwork, for_aux_fit=.TRUE., pmat_ext=fm_skapa)
    3149           30 :       CALL cp_fm_release(fmwork(1))
    3150           30 :       CALL cp_fm_release(fmwork(2))
    3151           30 :       DEALLOCATE (fmwork)
    3152              : 
    3153         2428 :       DO img = 1, nimg
    3154         4882 :          DO ispin = 1, nspins
    3155         2484 :             CALL dbcsr_scale(matrix_skap(ispin, img)%matrix, -2.0_dp)
    3156         4882 :             CALL dbcsr_scale(matrix_skapa(ispin, img)%matrix, 2.0_dp)
    3157              :          END DO
    3158         2428 :          IF (nspins == 2) THEN
    3159           86 :             CALL dbcsr_add(matrix_skap(1, img)%matrix, matrix_skap(2, img)%matrix, 1.0_dp, 1.0_dp)
    3160           86 :             CALL dbcsr_add(matrix_skapa(1, img)%matrix, matrix_skapa(2, img)%matrix, 1.0_dp, 1.0_dp)
    3161              :          END IF
    3162              :       END DO
    3163              : 
    3164           90 :       ALLOCATE (admm_force(3, natom))
    3165           30 :       admm_force = 0.0_dp
    3166              : 
    3167           30 :       IF (admm_env%do_admmq .OR. admm_env%do_admmp .OR. admm_env%do_admms) THEN
    3168           12 :          CALL qs_rho_get(rho, rho_ao_kp=rho_ao_orb)
    3169          310 :          DO img = 1, nimg
    3170          654 :             DO ispin = 1, nspins
    3171          654 :                CALL dbcsr_scale(rho_ao_orb(ispin, img)%matrix, -admm_env%lambda_merlot(ispin))
    3172              :             END DO
    3173          310 :             IF (nspins == 2) CALL dbcsr_add(rho_ao_orb(1, img)%matrix, rho_ao_orb(2, img)%matrix, 1.0_dp, 1.0_dp)
    3174              :          END DO
    3175              : 
    3176              :          !In ADMMQ, ADMMS and ADMMP, there is an extra contribution from lambda*P_orb*S^(x)
    3177              :          CALL build_overlap_force(qs_env%ks_env, admm_force, basis_type_a="ORB", basis_type_b="ORB", &
    3178           12 :                                   sab_nl=sab_kp, matrixkp_p=rho_ao_orb(1, :))
    3179          310 :          DO img = 1, nimg
    3180          298 :             IF (nspins == 2) CALL dbcsr_add(rho_ao_orb(1, img)%matrix, rho_ao_orb(2, img)%matrix, 1.0_dp, -1.0_dp)
    3181          684 :             DO ispin = 1, nspins
    3182          654 :                CALL dbcsr_scale(rho_ao_orb(ispin, img)%matrix, -1.0_dp/admm_env%lambda_merlot(ispin))
    3183              :             END DO
    3184              :          END DO
    3185              :       END IF
    3186              : 
    3187              :       CALL build_overlap_force(qs_env%ks_env, admm_force, basis_type_a="AUX_FIT", basis_type_b="ORB", &
    3188           30 :                                sab_nl=sab_aux_fit_vs_orb, matrixkp_p=matrix_skap(1, :))
    3189              :       CALL build_overlap_force(qs_env%ks_env, admm_force, basis_type_a="AUX_FIT", basis_type_b="AUX_FIT", &
    3190           30 :                                sab_nl=sab_aux_fit_asymm, matrixkp_p=matrix_skapa(1, :))
    3191              : 
    3192           30 :       CALL add_qs_force(admm_force, force, "overlap_admm", atomic_kind_set)
    3193           30 :       DEALLOCATE (admm_force)
    3194              : 
    3195           66 :       DO ispin = 1, nspins
    3196          138 :          DO i = 1, 2
    3197          486 :             DO ikp = 1, kplocal
    3198          378 :                CALL cp_fm_release(fm_skap(ikp, i, ispin))
    3199          450 :                CALL cp_fm_release(fm_skapa(ikp, i, ispin))
    3200              :             END DO
    3201              :          END DO
    3202              :       END DO
    3203           30 :       CALL dbcsr_deallocate_matrix_set(matrix_skap)
    3204           30 :       CALL dbcsr_deallocate_matrix_set(matrix_skapa)
    3205              : 
    3206           30 :       IF (admm_env%do_admms) THEN
    3207            6 :          CALL dbcsr_deallocate_matrix_set(matrix_ks_aux_fit)
    3208              :       END IF
    3209              : 
    3210           30 :       CALL timestop(handle)
    3211              : 
    3212          120 :    END SUBROUTINE calc_admm_ovlp_forces_kp
    3213              : 
    3214              : ! **************************************************************************************************
    3215              : !> \brief Calculate derivatives terms from overlap matrices
    3216              : !> \param qs_env ...
    3217              : !> \param matrix_hz Fock matrix part using the response density in admm basis
    3218              : !> \param matrix_pz response density in orbital basis
    3219              : !> \param fval ...
    3220              : ! **************************************************************************************************
    3221          880 :    SUBROUTINE admm_projection_derivative(qs_env, matrix_hz, matrix_pz, fval)
    3222              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3223              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: matrix_hz, matrix_pz
    3224              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: fval
    3225              : 
    3226              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'admm_projection_derivative'
    3227              : 
    3228              :       INTEGER                                            :: handle, ispin, nao, natom, naux, nspins
    3229              :       REAL(KIND=dp)                                      :: my_fval
    3230              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: admm_force
    3231              :       TYPE(admm_type), POINTER                           :: admm_env
    3232          880 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    3233          880 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s_aux_fit, matrix_s_aux_fit_vs_orb
    3234              :       TYPE(dbcsr_type), POINTER                          :: matrix_w_q, matrix_w_s
    3235              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3236          880 :          POINTER                                         :: sab_aux_fit_asymm, sab_aux_fit_vs_orb
    3237          880 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    3238              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    3239              : 
    3240          880 :       CALL timeset(routineN, handle)
    3241              : 
    3242          880 :       CPASSERT(ASSOCIATED(qs_env))
    3243              : 
    3244          880 :       CALL get_qs_env(qs_env, ks_env=ks_env, admm_env=admm_env)
    3245              :       CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit, sab_aux_fit_asymm=sab_aux_fit_asymm, &
    3246          880 :                         matrix_s_aux_fit_vs_orb=matrix_s_aux_fit_vs_orb, sab_aux_fit_vs_orb=sab_aux_fit_vs_orb)
    3247              : 
    3248          880 :       my_fval = 2.0_dp
    3249          880 :       IF (PRESENT(fval)) my_fval = fval
    3250              : 
    3251          880 :       ALLOCATE (matrix_w_q)
    3252              :       CALL dbcsr_copy(matrix_w_q, matrix_s_aux_fit_vs_orb(1)%matrix, &
    3253          880 :                       "W MATRIX AUX Q")
    3254          880 :       CALL cp_dbcsr_alloc_block_from_nbl(matrix_w_q, sab_aux_fit_vs_orb)
    3255          880 :       ALLOCATE (matrix_w_s)
    3256              :       CALL dbcsr_create(matrix_w_s, template=matrix_s_aux_fit(1)%matrix, &
    3257              :                         name='W MATRIX AUX S', &
    3258          880 :                         matrix_type=dbcsr_type_no_symmetry)
    3259          880 :       CALL cp_dbcsr_alloc_block_from_nbl(matrix_w_s, sab_aux_fit_asymm)
    3260              : 
    3261              :       CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, &
    3262          880 :                       natom=natom, force=force)
    3263         2640 :       ALLOCATE (admm_force(3, natom))
    3264          880 :       admm_force = 0.0_dp
    3265              : 
    3266          880 :       nspins = SIZE(matrix_pz)
    3267          880 :       nao = admm_env%nao_orb
    3268          880 :       naux = admm_env%nao_aux_fit
    3269              : 
    3270          880 :       CALL cp_fm_set_all(admm_env%work_aux_orb2, 0.0_dp)
    3271              : 
    3272         1860 :       DO ispin = 1, nspins
    3273          980 :          CALL copy_dbcsr_to_fm(matrix_hz(ispin)%matrix, admm_env%work_aux_aux)
    3274              :          CALL parallel_gemm("N", "T", naux, naux, naux, 1.0_dp, admm_env%s_inv, &
    3275          980 :                             admm_env%work_aux_aux, 0.0_dp, admm_env%work_aux_aux2)
    3276              :          CALL parallel_gemm("N", "N", naux, nao, naux, 1.0_dp, admm_env%work_aux_aux2, &
    3277          980 :                             admm_env%A, 0.0_dp, admm_env%work_aux_orb)
    3278          980 :          CALL copy_dbcsr_to_fm(matrix_pz(ispin)%matrix, admm_env%work_orb_orb)
    3279              :          ! admm_env%work_aux_orb2 = S-1*H*A*P
    3280              :          CALL parallel_gemm("N", "N", naux, nao, nao, 1.0_dp, admm_env%work_aux_orb, &
    3281         1860 :                             admm_env%work_orb_orb, 1.0_dp, admm_env%work_aux_orb2)
    3282              :       END DO
    3283              : 
    3284          880 :       CALL copy_fm_to_dbcsr(admm_env%work_aux_orb2, matrix_w_q, keep_sparsity=.TRUE.)
    3285              : 
    3286              :       ! admm_env%work_aux_aux = S-1*H*A*P*A(T)
    3287              :       CALL parallel_gemm("N", "T", naux, naux, nao, 1.0_dp, admm_env%work_aux_orb2, &
    3288          880 :                          admm_env%A, 0.0_dp, admm_env%work_aux_aux)
    3289          880 :       CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, matrix_w_s, keep_sparsity=.TRUE.)
    3290              : 
    3291          880 :       CALL dbcsr_scale(matrix_w_q, -my_fval)
    3292          880 :       CALL dbcsr_scale(matrix_w_s, my_fval)
    3293              : 
    3294              :       CALL build_overlap_force(ks_env, admm_force, &
    3295              :                                basis_type_a="AUX_FIT", basis_type_b="AUX_FIT", &
    3296          880 :                                sab_nl=sab_aux_fit_asymm, matrix_p=matrix_w_s)
    3297              :       CALL build_overlap_force(ks_env, admm_force, &
    3298              :                                basis_type_a="AUX_FIT", basis_type_b="ORB", &
    3299          880 :                                sab_nl=sab_aux_fit_vs_orb, matrix_p=matrix_w_q)
    3300              : 
    3301              :       ! add forces
    3302          880 :       CALL add_qs_force(admm_force, force, "overlap_admm", atomic_kind_set)
    3303              : 
    3304          880 :       DEALLOCATE (admm_force)
    3305          880 :       CALL dbcsr_deallocate_matrix(matrix_w_s)
    3306          880 :       CALL dbcsr_deallocate_matrix(matrix_w_q)
    3307              : 
    3308          880 :       CALL timestop(handle)
    3309              : 
    3310          880 :    END SUBROUTINE admm_projection_derivative
    3311              : 
    3312              : ! **************************************************************************************************
    3313              : !> \brief Calculates contribution of forces due to basis transformation
    3314              : !>
    3315              : !>        dE/dR = dE/dC'*dC'/dR
    3316              : !>        dE/dC = Ks'*c'*occ = H'
    3317              : !>
    3318              : !>        dC'/dR = - tr(A*lambda^(-1/2)*H'^(T)*S^(-1) * dS'/dR)
    3319              : !>                 - tr(A*C*Y^(T)*C^(T)*Q^(T)*A^(T) * dS'/dR)
    3320              : !>                 + tr(C*lambda^(-1/2)*H'^(T)*S^(-1) * dQ/dR)
    3321              : !>                 + tr(A*C*Y^(T)*c^(T) * dQ/dR)
    3322              : !>                 + tr(C*Y^(T)*C^(T)*A^(T) * dQ/dR)
    3323              : !>
    3324              : !>        where
    3325              : !>
    3326              : !>        A = S'^(-1)*Q
    3327              : !>        lambda = C^(T)*B*C
    3328              : !>        B = Q^(T)*A
    3329              : !>        Y = R*[ (R^(T)*C^(T)*A^(T)*H'*R) xx M ]*R^(T)
    3330              : !>        lambda = R*D*R^(T)
    3331              : !>        Mij = Poles-Matrix (see above)
    3332              : !>        xx = schur product
    3333              : !>
    3334              : !> \param qs_env the QS environment
    3335              : !> \par History
    3336              : !>      05.2008 created [Manuel Guidon]
    3337              : !> \author Manuel Guidon
    3338              : ! **************************************************************************************************
    3339          256 :    SUBROUTINE calc_mixed_overlap_force(qs_env)
    3340              : 
    3341              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3342              : 
    3343              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calc_mixed_overlap_force'
    3344              : 
    3345              :       INTEGER                                            :: handle, ispin, iw, nao_aux_fit, nao_orb, &
    3346              :                                                             natom, neighbor_list_id, nmo
    3347              :       LOGICAL                                            :: omit_headers
    3348          256 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: admm_force
    3349              :       TYPE(admm_type), POINTER                           :: admm_env
    3350          256 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    3351              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    3352              :       TYPE(cp_logger_type), POINTER                      :: logger
    3353          256 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, matrix_s_aux_fit, &
    3354          256 :                                                             matrix_s_aux_fit_vs_orb, rho_ao, &
    3355          256 :                                                             rho_ao_aux
    3356              :       TYPE(dbcsr_type), POINTER                          :: matrix_rho_aux_desymm_tmp, matrix_w_q, &
    3357              :                                                             matrix_w_s
    3358              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3359          256 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    3360              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3361              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3362          256 :          POINTER                                         :: sab_orb
    3363              :       TYPE(qs_energy_type), POINTER                      :: energy
    3364          256 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    3365              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
    3366              :       TYPE(qs_rho_type), POINTER                         :: rho, rho_aux_fit
    3367              : 
    3368          256 :       CALL timeset(routineN, handle)
    3369              : 
    3370          256 :       NULLIFY (admm_env, logger, dft_control, para_env, mos, mo_coeff, matrix_w_q, matrix_w_s, &
    3371          256 :                rho, rho_aux_fit, energy, sab_orb, ks_env, matrix_s_aux_fit, matrix_s_aux_fit_vs_orb, matrix_s)
    3372              : 
    3373              :       CALL get_qs_env(qs_env, &
    3374              :                       admm_env=admm_env, &
    3375              :                       ks_env=ks_env, &
    3376              :                       dft_control=dft_control, &
    3377              :                       matrix_s=matrix_s, &
    3378              :                       neighbor_list_id=neighbor_list_id, &
    3379              :                       rho=rho, &
    3380              :                       energy=energy, &
    3381              :                       sab_orb=sab_orb, &
    3382              :                       mos=mos, &
    3383          256 :                       para_env=para_env)
    3384              :       CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux_fit, rho_aux_fit=rho_aux_fit, &
    3385          256 :                         matrix_s_aux_fit_vs_orb=matrix_s_aux_fit_vs_orb)
    3386              : 
    3387          256 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
    3388              :       CALL qs_rho_get(rho_aux_fit, &
    3389          256 :                       rho_ao=rho_ao_aux)
    3390              : 
    3391          256 :       nao_aux_fit = admm_env%nao_aux_fit
    3392          256 :       nao_orb = admm_env%nao_orb
    3393              : 
    3394          256 :       logger => cp_get_default_logger()
    3395              : 
    3396              :       ! *** forces are only implemented for mo_diag or none and basis_projection ***
    3397          256 :       IF (admm_env%block_dm) THEN
    3398            0 :          CPABORT("ADMM Forces not implemented for blocked projection methods!")
    3399              :       END IF
    3400              : 
    3401          256 :       IF (.NOT. (admm_env%purification_method == do_admm_purify_mo_diag .OR. &
    3402              :                  admm_env%purification_method == do_admm_purify_none)) THEN
    3403            0 :          CPABORT("ADMM Forces only implemented without purification or for MO_DIAG.")
    3404              :       END IF
    3405              : 
    3406              :       ! *** Create sparse work matrices
    3407              : 
    3408          256 :       ALLOCATE (matrix_w_s)
    3409              :       CALL dbcsr_create(matrix_w_s, template=matrix_s_aux_fit(1)%matrix, &
    3410              :                         name='W MATRIX AUX S', &
    3411          256 :                         matrix_type=dbcsr_type_no_symmetry)
    3412          256 :       CALL cp_dbcsr_alloc_block_from_nbl(matrix_w_s, admm_env%sab_aux_fit_asymm)
    3413              : 
    3414          256 :       ALLOCATE (matrix_w_q)
    3415              :       CALL dbcsr_copy(matrix_w_q, matrix_s_aux_fit_vs_orb(1)%matrix, &
    3416          256 :                       "W MATRIX AUX Q")
    3417              : 
    3418          554 :       DO ispin = 1, dft_control%nspins
    3419          298 :          nmo = admm_env%nmo(ispin)
    3420          298 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
    3421              : 
    3422              :          ! *** S'^(-T)*H'
    3423          298 :          IF (.NOT. admm_env%purification_method == do_admm_purify_none) THEN
    3424              :             CALL parallel_gemm('T', 'N', nao_aux_fit, nmo, nao_aux_fit, &
    3425              :                                1.0_dp, admm_env%S_inv, admm_env%mo_derivs_aux_fit(ispin), 0.0_dp, &
    3426           68 :                                admm_env%work_aux_nmo(ispin))
    3427              :          ELSE
    3428              : 
    3429              :             CALL parallel_gemm('T', 'N', nao_aux_fit, nmo, nao_aux_fit, &
    3430              :                                1.0_dp, admm_env%S_inv, admm_env%H(ispin), 0.0_dp, &
    3431          230 :                                admm_env%work_aux_nmo(ispin))
    3432              :          END IF
    3433              : 
    3434              :          ! *** S'^(-T)*H'*Lambda^(-T/2)
    3435              :          CALL parallel_gemm('N', 'T', nao_aux_fit, nmo, nmo, &
    3436              :                             1.0_dp, admm_env%work_aux_nmo(ispin), admm_env%lambda_inv_sqrt(ispin), 0.0_dp, &
    3437          298 :                             admm_env%work_aux_nmo2(ispin))
    3438              : 
    3439              :          ! *** C*Lambda^(-1/2)*H'^(T)*S'^(-1) minus sign due to force = -dE/dR
    3440              :          CALL parallel_gemm('N', 'T', nao_aux_fit, nao_orb, nmo, &
    3441              :                             -1.0_dp, admm_env%work_aux_nmo2(ispin), mo_coeff, 0.0_dp, &
    3442          298 :                             admm_env%work_aux_orb)
    3443              : 
    3444              :          ! *** A*C*Lambda^(-1/2)*H'^(T)*S'^(-1), minus sign to recover from above
    3445              :          CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nao_orb, &
    3446              :                             -1.0_dp, admm_env%work_aux_orb, admm_env%A, 0.0_dp, &
    3447          298 :                             admm_env%work_aux_aux)
    3448              : 
    3449          298 :          IF (.NOT. (admm_env%purification_method == do_admm_purify_none)) THEN
    3450              :             ! *** C*Y
    3451              :             CALL parallel_gemm('N', 'N', nao_orb, nmo, nmo, &
    3452              :                                1.0_dp, mo_coeff, admm_env%R_schur_R_t(ispin), 0.0_dp, &
    3453           68 :                                admm_env%work_orb_nmo(ispin))
    3454              :             ! *** C*Y^(T)*C^(T)
    3455              :             CALL parallel_gemm('N', 'T', nao_orb, nao_orb, nmo, &
    3456              :                                1.0_dp, mo_coeff, admm_env%work_orb_nmo(ispin), 0.0_dp, &
    3457           68 :                                admm_env%work_orb_orb)
    3458              :             ! *** A*C*Y^(T)*C^(T) Add to work aux_orb, minus sign due to force = -dE/dR
    3459              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, &
    3460              :                                -1.0_dp, admm_env%A, admm_env%work_orb_orb, 1.0_dp, &
    3461           68 :                                admm_env%work_aux_orb)
    3462              : 
    3463              :             ! *** C*Y^(T)
    3464              :             CALL parallel_gemm('N', 'T', nao_orb, nmo, nmo, &
    3465              :                                1.0_dp, mo_coeff, admm_env%R_schur_R_t(ispin), 0.0_dp, &
    3466           68 :                                admm_env%work_orb_nmo(ispin))
    3467              :             ! *** C*Y*C^(T)
    3468              :             CALL parallel_gemm('N', 'T', nao_orb, nao_orb, nmo, &
    3469              :                                1.0_dp, mo_coeff, admm_env%work_orb_nmo(ispin), 0.0_dp, &
    3470           68 :                                admm_env%work_orb_orb)
    3471              :             ! *** A*C*Y*C^(T) Add to work aux_orb, minus sign due to -dE/dR
    3472              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, &
    3473              :                                -1.0_dp, admm_env%A, admm_env%work_orb_orb, 1.0_dp, &
    3474           68 :                                admm_env%work_aux_orb)
    3475              :          END IF
    3476              : 
    3477              :          ! Add derivative contribution matrix*dQ/dR in additional last term in
    3478              :          ! Eq. (26,32, 33) in Merlot2014 to the force
    3479              :          ! ADMMS
    3480          298 :          IF (admm_env%do_admms) THEN
    3481              :             ! *** scale admm_env%work_aux_orb by gsi due to inner derivative
    3482           12 :             CALL cp_fm_scale(admm_env%gsi(ispin), admm_env%work_aux_orb)
    3483              :             CALL parallel_gemm('N', 'T', nao_orb, nao_orb, nmo, &
    3484              :                                4.0_dp*(admm_env%gsi(ispin))*admm_env%lambda_merlot(ispin)/dft_control%nspins, &
    3485           12 :                                mo_coeff, mo_coeff, 0.0_dp, admm_env%work_orb_orb2)
    3486              : 
    3487              :             ! *** prefactor*A*C*C^(T) Add to work aux_orb
    3488              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, &
    3489              :                                1.0_dp, admm_env%A, admm_env%work_orb_orb2, 1.0_dp, &
    3490           12 :                                admm_env%work_aux_orb)
    3491              : 
    3492              :             ! ADMMP
    3493          286 :          ELSE IF (admm_env%do_admmp) THEN
    3494           16 :             CALL cp_fm_scale(admm_env%gsi(ispin)**2, admm_env%work_aux_orb)
    3495              :             ! *** prefactor*C*C^(T), nspins since 2/n_spin*C*C^(T)=P
    3496              :             CALL parallel_gemm('N', 'T', nao_orb, nao_orb, nmo, &
    3497              :                                4.0_dp*(admm_env%gsi(ispin))*admm_env%lambda_merlot(ispin)/dft_control%nspins, &
    3498           16 :                                mo_coeff, mo_coeff, 0.0_dp, admm_env%work_orb_orb2)
    3499              : 
    3500              :             ! *** prefactor*A*C*C^(T) Add to work aux_orb
    3501              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, &
    3502              :                                1.0_dp, admm_env%A, admm_env%work_orb_orb2, 1.0_dp, &
    3503           16 :                                admm_env%work_aux_orb)
    3504              : 
    3505              :             ! ADMMQ
    3506          270 :          ELSE IF (admm_env%do_admmq) THEN
    3507              :             ! *** scale admm_env%work_aux_orb by gsi due to inner derivative
    3508           12 :             CALL cp_fm_scale(admm_env%gsi(ispin), admm_env%work_aux_orb)
    3509              :             CALL parallel_gemm('N', 'T', nao_orb, nao_orb, nmo, &
    3510              :                                4.0_dp*(admm_env%gsi(ispin))*admm_env%lambda_merlot(ispin)/dft_control%nspins, &
    3511           12 :                                mo_coeff, mo_coeff, 0.0_dp, admm_env%work_orb_orb2)
    3512              : 
    3513              :             ! *** prefactor*A*C*C^(T) Add to work aux_orb
    3514              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, &
    3515              :                                1.0_dp, admm_env%A, admm_env%work_orb_orb2, 1.0_dp, &
    3516           12 :                                admm_env%work_aux_orb)
    3517              :          END IF
    3518              : 
    3519              :          ! *** copy to sparse matrix
    3520          298 :          CALL copy_fm_to_dbcsr(admm_env%work_aux_orb, matrix_w_q, keep_sparsity=.TRUE.)
    3521              : 
    3522          298 :          IF (.NOT. (admm_env%purification_method == do_admm_purify_none)) THEN
    3523              :             ! *** A*C*Y^(T)*C^(T)
    3524              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_orb, &
    3525              :                                1.0_dp, admm_env%A, admm_env%work_orb_orb, 0.0_dp, &
    3526           68 :                                admm_env%work_aux_orb)
    3527              :             ! *** A*C*Y^(T)*C^(T)*A^(T) add to aux_aux, minus sign cancels
    3528              :             CALL parallel_gemm('N', 'T', nao_aux_fit, nao_aux_fit, nao_orb, &
    3529              :                                1.0_dp, admm_env%work_aux_orb, admm_env%A, 1.0_dp, &
    3530           68 :                                admm_env%work_aux_aux)
    3531              :          END IF
    3532              : 
    3533              :          ! *** copy to sparse matrix
    3534          298 :          CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, matrix_w_s, keep_sparsity=.TRUE.)
    3535              : 
    3536              :          ! Add derivative of Eq. (33) with respect to s_aux Merlot2014 to the force
    3537          298 :          IF (admm_env%do_admmp .OR. admm_env%do_admmq .OR. admm_env%do_admms) THEN
    3538              : 
    3539              :             !Create desymmetrized auxiliary density matrix
    3540              :             NULLIFY (matrix_rho_aux_desymm_tmp)
    3541           40 :             ALLOCATE (matrix_rho_aux_desymm_tmp)
    3542              :             CALL dbcsr_create(matrix_rho_aux_desymm_tmp, template=matrix_s_aux_fit(1)%matrix, &
    3543              :                               name='Rho_aux non-symm', &
    3544           40 :                               matrix_type=dbcsr_type_no_symmetry)
    3545              : 
    3546           40 :             CALL dbcsr_desymmetrize(rho_ao_aux(ispin)%matrix, matrix_rho_aux_desymm_tmp)
    3547              : 
    3548              :             ! ADMMS/Q 1. scale original matrix_w_s by gsi due to inner deriv.
    3549              :             !       2. add derivative of variational term with resp. to s
    3550           40 :             IF (admm_env%do_admms .OR. admm_env%do_admmq) THEN
    3551           24 :                CALL dbcsr_scale(matrix_w_s, admm_env%gsi(ispin))
    3552              :                CALL dbcsr_add(matrix_w_s, matrix_rho_aux_desymm_tmp, 1.0_dp, &
    3553           24 :                               -admm_env%lambda_merlot(ispin))
    3554              : 
    3555              :                ! ADMMP scale by gsi^2 and add derivative of variational term with resp. to s
    3556           16 :             ELSE IF (admm_env%do_admmp) THEN
    3557              : 
    3558           16 :                CALL dbcsr_scale(matrix_w_s, admm_env%gsi(ispin)**2)
    3559              :                CALL dbcsr_add(matrix_w_s, matrix_rho_aux_desymm_tmp, 1.0_dp, &
    3560           16 :                               (-admm_env%gsi(ispin))*admm_env%lambda_merlot(ispin))
    3561              : 
    3562              :             END IF
    3563              : 
    3564           40 :             CALL dbcsr_deallocate_matrix(matrix_rho_aux_desymm_tmp)
    3565              : 
    3566              :          END IF
    3567              : 
    3568              :          ! allocate force vector
    3569          298 :          CALL get_qs_env(qs_env=qs_env, natom=natom)
    3570          894 :          ALLOCATE (admm_force(3, natom))
    3571          298 :          admm_force = 0.0_dp
    3572              :          CALL build_overlap_force(ks_env, admm_force, &
    3573              :                                   basis_type_a="AUX_FIT", basis_type_b="AUX_FIT", &
    3574          298 :                                   sab_nl=admm_env%sab_aux_fit_asymm, matrix_p=matrix_w_s)
    3575              :          CALL build_overlap_force(ks_env, admm_force, &
    3576              :                                   basis_type_a="AUX_FIT", basis_type_b="ORB", &
    3577          298 :                                   sab_nl=admm_env%sab_aux_fit_vs_orb, matrix_p=matrix_w_q)
    3578              : 
    3579              :          ! Add contribution of original basis set for ADMMQ, P, S
    3580          298 :          IF (admm_env%do_admmq .OR. admm_env%do_admmp .OR. admm_env%do_admms) THEN
    3581           40 :             CALL dbcsr_scale(rho_ao(ispin)%matrix, -admm_env%lambda_merlot(ispin))
    3582              :             CALL build_overlap_force(ks_env, admm_force, &
    3583              :                                      basis_type_a="ORB", basis_type_b="ORB", &
    3584           40 :                                      sab_nl=sab_orb, matrix_p=rho_ao(ispin)%matrix)
    3585           40 :             CALL dbcsr_scale(rho_ao(ispin)%matrix, -1.0_dp/admm_env%lambda_merlot(ispin))
    3586              :          END IF
    3587              : 
    3588              :          ! add forces
    3589              :          CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, &
    3590          298 :                          force=force)
    3591          298 :          CALL add_qs_force(admm_force, force, "overlap_admm", atomic_kind_set)
    3592          298 :          DEALLOCATE (admm_force)
    3593              : 
    3594          298 :          CALL section_vals_val_get(qs_env%input, "DFT%PRINT%AO_MATRICES%OMIT_HEADERS", l_val=omit_headers)
    3595          298 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, &
    3596              :                                               qs_env%input, "DFT%PRINT%AO_MATRICES/W_MATRIX_AUX_FIT"), cp_p_file)) THEN
    3597              :             iw = cp_print_key_unit_nr(logger, qs_env%input, "DFT%PRINT%AO_MATRICES/W_MATRIX_AUX_FIT", &
    3598            0 :                                       extension=".Log")
    3599              :             CALL cp_dbcsr_write_sparse_matrix(matrix_w_s, 4, 6, qs_env, &
    3600            0 :                                               para_env, output_unit=iw, omit_headers=omit_headers)
    3601              :             CALL cp_print_key_finished_output(iw, logger, qs_env%input, &
    3602            0 :                                               "DFT%PRINT%AO_MATRICES/W_MATRIX_AUX_FIT")
    3603              :          END IF
    3604          298 :          IF (BTEST(cp_print_key_should_output(logger%iter_info, &
    3605          554 :                                               qs_env%input, "DFT%PRINT%AO_MATRICES/W_MATRIX_AUX_FIT"), cp_p_file)) THEN
    3606              :             iw = cp_print_key_unit_nr(logger, qs_env%input, "DFT%PRINT%AO_MATRICES/W_MATRIX_AUX_FIT", &
    3607            0 :                                       extension=".Log")
    3608              :             CALL cp_dbcsr_write_sparse_matrix(matrix_w_q, 4, 6, qs_env, &
    3609            0 :                                               para_env, output_unit=iw, omit_headers=omit_headers)
    3610              :             CALL cp_print_key_finished_output(iw, logger, qs_env%input, &
    3611            0 :                                               "DFT%PRINT%AO_MATRICES/W_MATRIX_AUX_FIT")
    3612              :          END IF
    3613              : 
    3614              :       END DO !spin loop
    3615              : 
    3616              :       ! *** Deallocated weighted density matrices
    3617          256 :       CALL dbcsr_deallocate_matrix(matrix_w_s)
    3618          256 :       CALL dbcsr_deallocate_matrix(matrix_w_q)
    3619              : 
    3620          256 :       CALL timestop(handle)
    3621              : 
    3622          512 :    END SUBROUTINE calc_mixed_overlap_force
    3623              : 
    3624              : ! **************************************************************************************************
    3625              : !> \brief ...
    3626              : !> \param admm_env environment of auxiliary DM
    3627              : !> \param mo_set ...
    3628              : !> \param density_matrix auxiliary DM
    3629              : !> \param overlap_matrix auxiliary OM
    3630              : !> \param density_matrix_large DM of the original basis
    3631              : !> \param overlap_matrix_large overlap matrix of original basis
    3632              : !> \param ispin ...
    3633              : ! **************************************************************************************************
    3634        14982 :    SUBROUTINE calculate_dm_mo_no_diag(admm_env, mo_set, density_matrix, overlap_matrix, &
    3635              :                                       density_matrix_large, overlap_matrix_large, ispin)
    3636              :       TYPE(admm_type), POINTER                           :: admm_env
    3637              :       TYPE(mo_set_type), INTENT(IN)                      :: mo_set
    3638              :       TYPE(dbcsr_type), POINTER                          :: density_matrix, overlap_matrix, &
    3639              :                                                             density_matrix_large, &
    3640              :                                                             overlap_matrix_large
    3641              :       INTEGER                                            :: ispin
    3642              : 
    3643              :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_dm_mo_no_diag'
    3644              : 
    3645              :       INTEGER                                            :: handle, nao_aux_fit, nmo
    3646              :       REAL(KIND=dp)                                      :: alpha, nel_tmp_aux
    3647              : 
    3648              : ! Number of electrons in the aux. DM
    3649              : 
    3650        14982 :       CALL timeset(routineN, handle)
    3651              : 
    3652        14982 :       CALL dbcsr_set(density_matrix, 0.0_dp)
    3653        14982 :       nao_aux_fit = admm_env%nao_aux_fit
    3654        14982 :       nmo = admm_env%nmo(ispin)
    3655        14982 :       CALL cp_fm_to_fm(admm_env%C_hat(ispin), admm_env%work_aux_nmo(ispin))
    3656        14982 :       CALL cp_fm_column_scale(admm_env%work_aux_nmo(ispin), mo_set%occupation_numbers(1:mo_set%homo))
    3657              : 
    3658              :       CALL parallel_gemm('N', 'N', nao_aux_fit, nmo, nmo, &
    3659              :                          1.0_dp, admm_env%work_aux_nmo(ispin), admm_env%lambda_inv(ispin), 0.0_dp, &
    3660        14982 :                          admm_env%work_aux_nmo2(ispin))
    3661              : 
    3662              :       ! The following IF doesn't do anything unless !alpha=mo_set%maxocc is uncommented.
    3663        14982 :       IF (.NOT. mo_set%uniform_occupation) THEN ! not all orbitals 1..homo are equally occupied
    3664          360 :          alpha = 1.0_dp
    3665              :          CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=density_matrix, &
    3666              :                                     matrix_v=admm_env%C_hat(ispin), &
    3667              :                                     matrix_g=admm_env%work_aux_nmo2(ispin), &
    3668              :                                     ncol=mo_set%homo, &
    3669          360 :                                     alpha=alpha)
    3670              :       ELSE
    3671        14622 :          alpha = 1.0_dp
    3672              :          !alpha=mo_set%maxocc
    3673              :          CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=density_matrix, &
    3674              :                                     matrix_v=admm_env%C_hat(ispin), &
    3675              :                                     matrix_g=admm_env%work_aux_nmo2(ispin), &
    3676              :                                     ncol=mo_set%homo, &
    3677        14622 :                                     alpha=alpha)
    3678              :       END IF
    3679              : 
    3680              :       !  The following IF checks whether gsi needs to be calculated. This is the case if
    3681              :       !   the auxiliary density matrix gets scaled
    3682              :       !   according to Eq. 22 (Merlot) or a scaling of exchange_correction is employed, Eq. 35 (Merlot).
    3683        14982 :       IF (admm_env%do_admmp .OR. admm_env%do_admmq .OR. admm_env%do_admms) THEN
    3684              : 
    3685         1028 :          CALL cite_reference(Merlot2014)
    3686              : 
    3687         1028 :          admm_env%n_large_basis(3) = 0.0_dp
    3688              : 
    3689              :          ! Calculate number of electrons in the original density matrix, transposing doesn't matter
    3690              :          ! since both matrices are symmetric
    3691         1028 :          CALL dbcsr_dot(density_matrix_large, overlap_matrix_large, admm_env%n_large_basis(ispin))
    3692         1028 :          admm_env%n_large_basis(3) = admm_env%n_large_basis(3) + admm_env%n_large_basis(ispin)
    3693              :          ! Calculate number of electrons in the auxiliary density matrix
    3694         1028 :          CALL dbcsr_dot(density_matrix, overlap_matrix, nel_tmp_aux)
    3695         1028 :          admm_env%gsi(ispin) = admm_env%n_large_basis(ispin)/nel_tmp_aux
    3696              : 
    3697         1028 :          IF (admm_env%do_admmq .OR. admm_env%do_admms) THEN
    3698              :             ! multiply aux. DM with gsi to get the scaled DM (Merlot, Eq. 21)
    3699          600 :             CALL dbcsr_scale(density_matrix, admm_env%gsi(ispin))
    3700              :          END IF
    3701              : 
    3702              :       END IF
    3703              : 
    3704        14982 :       CALL timestop(handle)
    3705              : 
    3706        14982 :    END SUBROUTINE calculate_dm_mo_no_diag
    3707              : 
    3708              : ! **************************************************************************************************
    3709              : !> \brief ...
    3710              : !> \param admm_env ...
    3711              : !> \param density_matrix ...
    3712              : !> \param density_matrix_aux ...
    3713              : !> \param ispin ...
    3714              : !> \param nspins ...
    3715              : ! **************************************************************************************************
    3716          708 :    SUBROUTINE blockify_density_matrix(admm_env, density_matrix, density_matrix_aux, &
    3717              :                                       ispin, nspins)
    3718              :       TYPE(admm_type), POINTER                           :: admm_env
    3719              :       TYPE(dbcsr_type), POINTER                          :: density_matrix, density_matrix_aux
    3720              :       INTEGER                                            :: ispin, nspins
    3721              : 
    3722              :       CHARACTER(len=*), PARAMETER :: routineN = 'blockify_density_matrix'
    3723              : 
    3724              :       INTEGER                                            :: handle, iatom, jatom
    3725              :       LOGICAL                                            :: found
    3726          354 :       REAL(dp), DIMENSION(:, :), POINTER                 :: sparse_block, sparse_block_aux
    3727              :       TYPE(dbcsr_iterator_type)                          :: iter
    3728              : 
    3729          354 :       CALL timeset(routineN, handle)
    3730              : 
    3731              :       ! ** set blocked density matrix to 0
    3732          354 :       CALL dbcsr_set(density_matrix_aux, 0.0_dp)
    3733              : 
    3734              :       ! ** now loop through the list and copy corresponding blocks
    3735          354 :       CALL dbcsr_iterator_start(iter, density_matrix)
    3736         1683 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    3737         1329 :          CALL dbcsr_iterator_next_block(iter, iatom, jatom, sparse_block)
    3738         1683 :          IF (admm_env%block_map(iatom, jatom) == 1) THEN
    3739              :             CALL dbcsr_get_block_p(density_matrix_aux, &
    3740          924 :                                    row=iatom, col=jatom, block=sparse_block_aux, found=found)
    3741          924 :             IF (found) THEN
    3742        11016 :                sparse_block_aux = sparse_block
    3743              :             END IF
    3744              : 
    3745              :          END IF
    3746              :       END DO
    3747          354 :       CALL dbcsr_iterator_stop(iter)
    3748              : 
    3749          354 :       CALL copy_dbcsr_to_fm(density_matrix_aux, admm_env%P_to_be_purified(ispin))
    3750          354 :       CALL cp_fm_uplo_to_full(admm_env%P_to_be_purified(ispin), admm_env%work_orb_orb2)
    3751              : 
    3752          354 :       IF (nspins == 1) THEN
    3753          114 :          CALL cp_fm_scale(0.5_dp, admm_env%P_to_be_purified(ispin))
    3754              :       END IF
    3755              : 
    3756          354 :       CALL timestop(handle)
    3757          354 :    END SUBROUTINE blockify_density_matrix
    3758              : 
    3759              : ! **************************************************************************************************
    3760              : !> \brief ...
    3761              : !> \param x ...
    3762              : !> \return ...
    3763              : ! **************************************************************************************************
    3764         2754 :    ELEMENTAL FUNCTION delta(x)
    3765              :       REAL(KIND=dp), INTENT(IN)                          :: x
    3766              :       REAL(KIND=dp)                                      :: delta
    3767              : 
    3768         2754 :       IF (x == 0.0_dp) THEN !TODO: exact comparison of reals?
    3769              :          delta = 1.0_dp
    3770              :       ELSE
    3771         2754 :          delta = 0.0_dp
    3772              :       END IF
    3773              : 
    3774         2754 :    END FUNCTION delta
    3775              : 
    3776              : ! **************************************************************************************************
    3777              : !> \brief ...
    3778              : !> \param x ...
    3779              : !> \return ...
    3780              : ! **************************************************************************************************
    3781        19180 :    ELEMENTAL FUNCTION Heaviside(x)
    3782              :       REAL(KIND=dp), INTENT(IN)                          :: x
    3783              :       REAL(KIND=dp)                                      :: Heaviside
    3784              : 
    3785        19180 :       IF (x < 0.0_dp) THEN
    3786              :          Heaviside = 0.0_dp
    3787              :       ELSE
    3788        10404 :          Heaviside = 1.0_dp
    3789              :       END IF
    3790        19180 :    END FUNCTION Heaviside
    3791              : 
    3792              : ! **************************************************************************************************
    3793              : !> \brief Calculate ADMM auxiliary response density
    3794              : !> \param qs_env ...
    3795              : !> \param dm ...
    3796              : !> \param dm_admm ...
    3797              : ! **************************************************************************************************
    3798         2464 :    SUBROUTINE admm_aux_response_density(qs_env, dm, dm_admm)
    3799              :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
    3800              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN)       :: dm
    3801              :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT)    :: dm_admm
    3802              : 
    3803              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'admm_aux_response_density'
    3804              : 
    3805              :       INTEGER                                            :: handle, ispin, nao, nao_aux, ncol, nspins
    3806              :       TYPE(admm_type), POINTER                           :: admm_env
    3807              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3808              : 
    3809         2464 :       CALL timeset(routineN, handle)
    3810              : 
    3811         2464 :       CALL get_qs_env(qs_env, admm_env=admm_env, dft_control=dft_control)
    3812              : 
    3813         2464 :       nspins = dft_control%nspins
    3814              : 
    3815         2464 :       CPASSERT(ASSOCIATED(admm_env%A))
    3816         2464 :       CPASSERT(ASSOCIATED(admm_env%work_orb_orb))
    3817         2464 :       CPASSERT(ASSOCIATED(admm_env%work_aux_orb))
    3818         2464 :       CPASSERT(ASSOCIATED(admm_env%work_aux_aux))
    3819         2464 :       CALL cp_fm_get_info(admm_env%A, nrow_global=nao_aux, ncol_global=nao)
    3820              : 
    3821              :       ! P1 -> AUX BASIS
    3822         2464 :       CALL cp_fm_get_info(admm_env%work_orb_orb, nrow_global=nao, ncol_global=ncol)
    3823         5228 :       DO ispin = 1, nspins
    3824         2764 :          CALL copy_dbcsr_to_fm(dm(ispin)%matrix, admm_env%work_orb_orb)
    3825              :          CALL parallel_gemm('N', 'N', nao_aux, ncol, nao, 1.0_dp, admm_env%A, &
    3826         2764 :                             admm_env%work_orb_orb, 0.0_dp, admm_env%work_aux_orb)
    3827              :          CALL parallel_gemm('N', 'T', nao_aux, nao_aux, nao, 1.0_dp, admm_env%A, &
    3828         2764 :                             admm_env%work_aux_orb, 0.0_dp, admm_env%work_aux_aux)
    3829         5228 :          CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, dm_admm(ispin)%matrix, keep_sparsity=.TRUE.)
    3830              :       END DO
    3831              : 
    3832         2464 :       CALL timestop(handle)
    3833              : 
    3834         2464 :    END SUBROUTINE admm_aux_response_density
    3835              : 
    3836              : ! **************************************************************************************************
    3837              : !> \brief Fill the ADMM overlp and basis change  matrices in the KP env based on the real-space array
    3838              : !> \param qs_env ...
    3839              : !> \param calculate_forces ...
    3840              : ! **************************************************************************************************
    3841           48 :    SUBROUTINE kpoint_calc_admm_matrices(qs_env, calculate_forces)
    3842              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3843              :       LOGICAL                                            :: calculate_forces
    3844              : 
    3845              :       INTEGER                                            :: ic, igroup, ik, ikp, indx, kplocal, &
    3846              :                                                             kpmax, nao_aux_fit, nao_orb, nc, nkp, &
    3847              :                                                             nkp_groups
    3848              :       INTEGER, DIMENSION(2)                              :: kp_range
    3849           48 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    3850           48 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    3851              :       LOGICAL                                            :: my_kpgrp, use_real_wfn
    3852           48 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    3853              :       TYPE(admm_type), POINTER                           :: admm_env
    3854           48 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:, :) :: info
    3855              :       TYPE(cp_cfm_type)                                  :: cmat_aux_fit, cmat_aux_fit_vs_orb, &
    3856              :                                                             cwork_aux_fit, cwork_aux_fit_vs_orb
    3857              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct_aux_fit, &
    3858              :                                                             matrix_struct_aux_fit_vs_orb
    3859              :       TYPE(cp_fm_type)                                   :: fmdummy, imat_aux_fit, &
    3860              :                                                             imat_aux_fit_vs_orb, rmat_aux_fit, &
    3861              :                                                             rmat_aux_fit_vs_orb, work_aux_fit
    3862           48 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: fmwork
    3863           48 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s_aux_fit, matrix_s_aux_fit_vs_orb
    3864           48 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: dbcsr_aux_fit, dbcsr_aux_fit_vs_orb
    3865              :       TYPE(kpoint_env_type), POINTER                     :: kp
    3866              :       TYPE(kpoint_type), POINTER                         :: kpoints
    3867              :       TYPE(mp_para_env_type), POINTER                    :: para_env_global, para_env_local
    3868              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3869           48 :          POINTER                                         :: sab_aux_fit, sab_aux_fit_vs_orb
    3870              : 
    3871           48 :       NULLIFY (xkp, kp_dist, para_env_local, cell_to_index, admm_env, kp, &
    3872           48 :                kpoints, matrix_s_aux_fit, matrix_s_aux_fit_vs_orb, sab_aux_fit, sab_aux_fit_vs_orb, &
    3873           48 :                para_env_global, matrix_struct_aux_fit, matrix_struct_aux_fit_vs_orb)
    3874              : 
    3875           48 :       CALL get_qs_env(qs_env, kpoints=kpoints, admm_env=admm_env)
    3876              : 
    3877              :       CALL get_admm_env(admm_env, matrix_s_aux_fit_kp=matrix_s_aux_fit, &
    3878              :                         matrix_s_aux_fit_vs_orb_kp=matrix_s_aux_fit_vs_orb, &
    3879              :                         sab_aux_fit=sab_aux_fit, &
    3880           48 :                         sab_aux_fit_vs_orb=sab_aux_fit_vs_orb)
    3881              : 
    3882              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
    3883           48 :                            nkp_groups=nkp_groups, kp_dist=kp_dist, cell_to_index=cell_to_index)
    3884           48 :       kplocal = kp_range(2) - kp_range(1) + 1
    3885          144 :       kpmax = MAXVAL(kp_dist(2, :) - kp_dist(1, :) + 1)
    3886           48 :       nc = 1
    3887           48 :       IF (.NOT. use_real_wfn) nc = 2
    3888              : 
    3889          192 :       ALLOCATE (dbcsr_aux_fit(3))
    3890           48 :       CALL dbcsr_create(dbcsr_aux_fit(1), template=matrix_s_aux_fit(1, 1)%matrix, matrix_type=dbcsr_type_symmetric)
    3891           48 :       CALL dbcsr_create(dbcsr_aux_fit(2), template=matrix_s_aux_fit(1, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
    3892           48 :       CALL dbcsr_create(dbcsr_aux_fit(3), template=matrix_s_aux_fit(1, 1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    3893           48 :       CALL cp_dbcsr_alloc_block_from_nbl(dbcsr_aux_fit(1), sab_aux_fit)
    3894           48 :       CALL cp_dbcsr_alloc_block_from_nbl(dbcsr_aux_fit(2), sab_aux_fit)
    3895              : 
    3896          144 :       ALLOCATE (dbcsr_aux_fit_vs_orb(2))
    3897              :       CALL dbcsr_create(dbcsr_aux_fit_vs_orb(1), template=matrix_s_aux_fit_vs_orb(1, 1)%matrix, &
    3898           48 :                         matrix_type=dbcsr_type_no_symmetry)
    3899              :       CALL dbcsr_create(dbcsr_aux_fit_vs_orb(2), template=matrix_s_aux_fit_vs_orb(1, 1)%matrix, &
    3900           48 :                         matrix_type=dbcsr_type_no_symmetry)
    3901           48 :       CALL cp_dbcsr_alloc_block_from_nbl(dbcsr_aux_fit_vs_orb(1), sab_aux_fit_vs_orb)
    3902           48 :       CALL cp_dbcsr_alloc_block_from_nbl(dbcsr_aux_fit_vs_orb(2), sab_aux_fit_vs_orb)
    3903              : 
    3904              :       !Create global work fm
    3905           48 :       nao_aux_fit = admm_env%nao_aux_fit
    3906           48 :       nao_orb = admm_env%nao_orb
    3907           48 :       para_env_global => kpoints%blacs_env_all%para_env
    3908              : 
    3909          240 :       ALLOCATE (fmwork(4))
    3910              :       CALL cp_fm_struct_create(matrix_struct_aux_fit, context=kpoints%blacs_env_all, para_env=para_env_global, &
    3911           48 :                                nrow_global=nao_aux_fit, ncol_global=nao_aux_fit)
    3912           48 :       CALL cp_fm_create(fmwork(1), matrix_struct_aux_fit)
    3913           48 :       CALL cp_fm_create(fmwork(2), matrix_struct_aux_fit)
    3914           48 :       CALL cp_fm_struct_release(matrix_struct_aux_fit)
    3915              : 
    3916              :       CALL cp_fm_struct_create(matrix_struct_aux_fit_vs_orb, context=kpoints%blacs_env_all, para_env=para_env_global, &
    3917           48 :                                nrow_global=nao_aux_fit, ncol_global=nao_orb)
    3918           48 :       CALL cp_fm_create(fmwork(3), matrix_struct_aux_fit_vs_orb)
    3919           48 :       CALL cp_fm_create(fmwork(4), matrix_struct_aux_fit_vs_orb)
    3920           48 :       CALL cp_fm_struct_release(matrix_struct_aux_fit_vs_orb)
    3921              : 
    3922              :       !Create fm local to the KP groups
    3923           48 :       nao_aux_fit = admm_env%nao_aux_fit
    3924           48 :       nao_orb = admm_env%nao_orb
    3925           48 :       para_env_local => kpoints%blacs_env%para_env
    3926              : 
    3927              :       CALL cp_fm_struct_create(matrix_struct_aux_fit, context=kpoints%blacs_env, para_env=para_env_local, &
    3928           48 :                                nrow_global=nao_aux_fit, ncol_global=nao_aux_fit)
    3929           48 :       CALL cp_fm_create(rmat_aux_fit, matrix_struct_aux_fit)
    3930           48 :       CALL cp_fm_create(imat_aux_fit, matrix_struct_aux_fit)
    3931           48 :       CALL cp_fm_create(work_aux_fit, matrix_struct_aux_fit)
    3932           48 :       CALL cp_cfm_create(cwork_aux_fit, matrix_struct_aux_fit)
    3933           48 :       CALL cp_cfm_create(cmat_aux_fit, matrix_struct_aux_fit)
    3934              : 
    3935              :       CALL cp_fm_struct_create(matrix_struct_aux_fit_vs_orb, context=kpoints%blacs_env, para_env=para_env_local, &
    3936           48 :                                nrow_global=nao_aux_fit, ncol_global=nao_orb)
    3937           48 :       CALL cp_fm_create(rmat_aux_fit_vs_orb, matrix_struct_aux_fit_vs_orb)
    3938           48 :       CALL cp_fm_create(imat_aux_fit_vs_orb, matrix_struct_aux_fit_vs_orb)
    3939           48 :       CALL cp_cfm_create(cwork_aux_fit_vs_orb, matrix_struct_aux_fit_vs_orb)
    3940           48 :       CALL cp_cfm_create(cmat_aux_fit_vs_orb, matrix_struct_aux_fit_vs_orb)
    3941              : 
    3942         2960 :       ALLOCATE (info(nkp, 4))
    3943              : 
    3944              :       ! Steup and start all the communication
    3945           48 :       indx = 0
    3946          336 :       DO ikp = 1, kpmax
    3947          912 :          DO igroup = 1, nkp_groups
    3948          576 :             ik = kp_dist(1, igroup) + ikp - 1
    3949          576 :             IF (ik > kp_dist(2, igroup)) CYCLE
    3950          560 :             my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    3951          560 :             indx = indx + 1
    3952              : 
    3953          560 :             IF (use_real_wfn) THEN
    3954              :                !AUX-AUX overlap
    3955            0 :                CALL dbcsr_set(dbcsr_aux_fit(1), 0.0_dp)
    3956              :                CALL rskp_transform(rmatrix=dbcsr_aux_fit(1), rsmat=matrix_s_aux_fit, ispin=1, &
    3957            0 :                                    xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_aux_fit)
    3958            0 :                CALL dbcsr_desymmetrize(dbcsr_aux_fit(1), dbcsr_aux_fit(3))
    3959            0 :                CALL copy_dbcsr_to_fm(dbcsr_aux_fit(3), fmwork(1))
    3960              : 
    3961              :                !AUX-ORB overlap
    3962            0 :                CALL dbcsr_set(dbcsr_aux_fit_vs_orb(1), 0.0_dp)
    3963              :                CALL rskp_transform(rmatrix=dbcsr_aux_fit_vs_orb(1), rsmat=matrix_s_aux_fit_vs_orb, ispin=1, &
    3964            0 :                                    xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_aux_fit_vs_orb)
    3965            0 :                CALL copy_dbcsr_to_fm(dbcsr_aux_fit_vs_orb(1), fmwork(3))
    3966              :             ELSE
    3967              :                !AUX-AUX overlap
    3968          560 :                CALL dbcsr_set(dbcsr_aux_fit(1), 0.0_dp)
    3969          560 :                CALL dbcsr_set(dbcsr_aux_fit(2), 0.0_dp)
    3970              :                CALL rskp_transform(rmatrix=dbcsr_aux_fit(1), cmatrix=dbcsr_aux_fit(2), rsmat=matrix_s_aux_fit, &
    3971          560 :                                    ispin=1, xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_aux_fit)
    3972          560 :                CALL dbcsr_desymmetrize(dbcsr_aux_fit(1), dbcsr_aux_fit(3))
    3973          560 :                CALL copy_dbcsr_to_fm(dbcsr_aux_fit(3), fmwork(1))
    3974          560 :                CALL dbcsr_desymmetrize(dbcsr_aux_fit(2), dbcsr_aux_fit(3))
    3975          560 :                CALL copy_dbcsr_to_fm(dbcsr_aux_fit(3), fmwork(2))
    3976              : 
    3977              :                !AUX-ORB overlap
    3978          560 :                CALL dbcsr_set(dbcsr_aux_fit_vs_orb(1), 0.0_dp)
    3979          560 :                CALL dbcsr_set(dbcsr_aux_fit_vs_orb(2), 0.0_dp)
    3980              :                CALL rskp_transform(rmatrix=dbcsr_aux_fit_vs_orb(1), cmatrix=dbcsr_aux_fit_vs_orb(2), &
    3981              :                                    rsmat=matrix_s_aux_fit_vs_orb, ispin=1, xkp=xkp(1:3, ik), &
    3982          560 :                                    cell_to_index=cell_to_index, sab_nl=sab_aux_fit_vs_orb)
    3983          560 :                CALL copy_dbcsr_to_fm(dbcsr_aux_fit_vs_orb(1), fmwork(3))
    3984          560 :                CALL copy_dbcsr_to_fm(dbcsr_aux_fit_vs_orb(2), fmwork(4))
    3985              :             END IF
    3986              : 
    3987          848 :             IF (my_kpgrp) THEN
    3988          280 :                CALL cp_fm_start_copy_general(fmwork(1), rmat_aux_fit, para_env_global, info(indx, 1))
    3989          280 :                CALL cp_fm_start_copy_general(fmwork(3), rmat_aux_fit_vs_orb, para_env_global, info(indx, 3))
    3990          280 :                IF (.NOT. use_real_wfn) THEN
    3991          280 :                   CALL cp_fm_start_copy_general(fmwork(2), imat_aux_fit, para_env_global, info(indx, 2))
    3992          280 :                   CALL cp_fm_start_copy_general(fmwork(4), imat_aux_fit_vs_orb, para_env_global, info(indx, 4))
    3993              :                END IF
    3994              :             ELSE
    3995          280 :                CALL cp_fm_start_copy_general(fmwork(1), fmdummy, para_env_global, info(indx, 1))
    3996          280 :                CALL cp_fm_start_copy_general(fmwork(3), fmdummy, para_env_global, info(indx, 3))
    3997          280 :                IF (.NOT. use_real_wfn) THEN
    3998          280 :                   CALL cp_fm_start_copy_general(fmwork(2), fmdummy, para_env_global, info(indx, 2))
    3999          280 :                   CALL cp_fm_start_copy_general(fmwork(4), fmdummy, para_env_global, info(indx, 4))
    4000              :                END IF
    4001              :             END IF
    4002              : 
    4003              :          END DO
    4004              :       END DO
    4005              : 
    4006              :       ! Finish communication and store
    4007              :       indx = 0
    4008          336 :       DO ikp = 1, kpmax
    4009          864 :          DO igroup = 1, nkp_groups
    4010          576 :             ik = kp_dist(1, igroup) + ikp - 1
    4011          576 :             IF (ik > kp_dist(2, igroup)) CYCLE
    4012          560 :             my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    4013          280 :             indx = indx + 1
    4014              : 
    4015          288 :             IF (my_kpgrp) THEN
    4016          280 :                CALL cp_fm_finish_copy_general(rmat_aux_fit, info(indx, 1))
    4017          280 :                CALL cp_fm_finish_copy_general(rmat_aux_fit_vs_orb, info(indx, 3))
    4018          280 :                IF (.NOT. use_real_wfn) THEN
    4019          280 :                   CALL cp_fm_finish_copy_general(imat_aux_fit, info(indx, 2))
    4020          280 :                   CALL cp_fm_finish_copy_general(imat_aux_fit_vs_orb, info(indx, 4))
    4021              :                END IF
    4022              :             END IF
    4023              :          END DO
    4024              : 
    4025          288 :          IF (ikp > kplocal) CYCLE
    4026          280 :          kp => kpoints%kp_aux_env(ikp)%kpoint_env
    4027              : 
    4028              :          !Allocate local KP matrices
    4029          280 :          CALL cp_fm_release(kp%amat)
    4030         1400 :          ALLOCATE (kp%amat(nc, 1))
    4031          840 :          DO ic = 1, nc
    4032          840 :             CALL cp_fm_create(kp%amat(ic, 1), matrix_struct_aux_fit_vs_orb)
    4033              :          END DO
    4034              : 
    4035              :          !Only need the overlap in case of ADMMP, ADMMQ or ADMMS, or for forces
    4036          280 :          IF (admm_env%do_admmp .OR. admm_env%do_admmq .OR. admm_env%do_admms .OR. calculate_forces) THEN
    4037          280 :             CALL cp_fm_release(kp%smat)
    4038         1400 :             ALLOCATE (kp%smat(nc, 1))
    4039          840 :             DO ic = 1, nc
    4040          840 :                CALL cp_fm_create(kp%smat(ic, 1), matrix_struct_aux_fit)
    4041              :             END DO
    4042          280 :             CALL cp_fm_to_fm(rmat_aux_fit, kp%smat(1, 1))
    4043          280 :             IF (.NOT. use_real_wfn) CALL cp_fm_to_fm(imat_aux_fit, kp%smat(2, 1))
    4044              :          END IF
    4045              : 
    4046          328 :          IF (use_real_wfn) THEN
    4047              :             !Invert S_aux
    4048            0 :             CALL cp_fm_cholesky_decompose(rmat_aux_fit)
    4049            0 :             CALL cp_fm_cholesky_invert(rmat_aux_fit)
    4050            0 :             CALL cp_fm_uplo_to_full(rmat_aux_fit, work_aux_fit)
    4051              : 
    4052              :             !A = S^-1 * Q
    4053              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, 1.0_dp, &
    4054            0 :                                rmat_aux_fit, rmat_aux_fit_vs_orb, 0.0_dp, kp%amat(1, 1))
    4055              :          ELSE
    4056              : 
    4057              :             !Invert S_aux
    4058          280 :             CALL cp_fm_to_cfm(rmat_aux_fit, imat_aux_fit, cmat_aux_fit)
    4059          280 :             CALL cp_cfm_cholesky_decompose(cmat_aux_fit)
    4060          280 :             CALL cp_cfm_cholesky_invert(cmat_aux_fit)
    4061          280 :             CALL cp_cfm_uplo_to_full(cmat_aux_fit, cwork_aux_fit)
    4062              : 
    4063              :             !A = S^-1 * Q
    4064          280 :             CALL cp_fm_to_cfm(rmat_aux_fit_vs_orb, imat_aux_fit_vs_orb, cmat_aux_fit_vs_orb)
    4065              :             CALL parallel_gemm('N', 'N', nao_aux_fit, nao_orb, nao_aux_fit, z_one, &
    4066          280 :                                cmat_aux_fit, cmat_aux_fit_vs_orb, z_zero, cwork_aux_fit_vs_orb)
    4067          280 :             CALL cp_cfm_to_fm(cwork_aux_fit_vs_orb, kp%amat(1, 1), kp%amat(2, 1))
    4068              :          END IF
    4069              :       END DO
    4070              : 
    4071              :       ! Clean up communication
    4072          608 :       DO indx = 1, SIZE(info, 1)
    4073          560 :          CALL cp_fm_cleanup_copy_general(info(indx, 1))
    4074          560 :          CALL cp_fm_cleanup_copy_general(info(indx, 3))
    4075          608 :          IF (.NOT. use_real_wfn) THEN
    4076          560 :             CALL cp_fm_cleanup_copy_general(info(indx, 2))
    4077          560 :             CALL cp_fm_cleanup_copy_general(info(indx, 4))
    4078              :          END IF
    4079              :       END DO
    4080              : 
    4081           48 :       CALL cp_fm_release(rmat_aux_fit)
    4082           48 :       CALL cp_fm_release(imat_aux_fit)
    4083           48 :       CALL cp_fm_release(work_aux_fit)
    4084           48 :       CALL cp_cfm_release(cwork_aux_fit)
    4085           48 :       CALL cp_cfm_release(cmat_aux_fit)
    4086           48 :       CALL cp_fm_release(rmat_aux_fit_vs_orb)
    4087           48 :       CALL cp_fm_release(imat_aux_fit_vs_orb)
    4088           48 :       CALL cp_cfm_release(cwork_aux_fit_vs_orb)
    4089           48 :       CALL cp_cfm_release(cmat_aux_fit_vs_orb)
    4090           48 :       CALL cp_fm_struct_release(matrix_struct_aux_fit)
    4091           48 :       CALL cp_fm_struct_release(matrix_struct_aux_fit_vs_orb)
    4092              : 
    4093           48 :       CALL cp_fm_release(fmwork(1))
    4094           48 :       CALL cp_fm_release(fmwork(2))
    4095           48 :       CALL cp_fm_release(fmwork(3))
    4096           48 :       CALL cp_fm_release(fmwork(4))
    4097              : 
    4098           48 :       CALL dbcsr_release(dbcsr_aux_fit(1))
    4099           48 :       CALL dbcsr_release(dbcsr_aux_fit(2))
    4100           48 :       CALL dbcsr_release(dbcsr_aux_fit(3))
    4101           48 :       CALL dbcsr_release(dbcsr_aux_fit_vs_orb(1))
    4102           48 :       CALL dbcsr_release(dbcsr_aux_fit_vs_orb(2))
    4103              : 
    4104         2480 :    END SUBROUTINE kpoint_calc_admm_matrices
    4105              : 
    4106              : END MODULE admm_methods
        

Generated by: LCOV version 2.0-1