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

Generated by: LCOV version 2.0-1