LCOV - code coverage report
Current view: top level - src - kpoint_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 81.6 % 1316 1074
Test Date: 2026-07-25 06:35:44 Functions: 82.4 % 17 14

            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 Routines needed for kpoint calculation
      10              : !> \par History
      11              : !>       2014.07 created [JGH]
      12              : !>       2014.11 unified k-point and gamma-point code [Ole Schuett]
      13              : !> \author JGH
      14              : ! **************************************************************************************************
      15              : MODULE kpoint_methods
      16              :    USE atomic_kind_types,               ONLY: get_atomic_kind
      17              :    USE cell_types,                      ONLY: cell_type,&
      18              :                                               pbc,&
      19              :                                               real_to_scaled
      20              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_create,&
      21              :                                               cp_blacs_env_type
      22              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      23              :                                               cp_cfm_get_info,&
      24              :                                               cp_cfm_release,&
      25              :                                               cp_cfm_to_fm,&
      26              :                                               cp_cfm_type,&
      27              :                                               cp_fm_to_cfm
      28              :    USE cp_control_types,                ONLY: hairy_probes_type
      29              :    USE cp_dbcsr_api,                    ONLY: &
      30              :         dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_distribute, &
      31              :         dbcsr_distribution_get, dbcsr_distribution_type, dbcsr_get_block_p, dbcsr_get_info, &
      32              :         dbcsr_get_stored_coordinates, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      33              :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, &
      34              :         dbcsr_replicate_all, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, &
      35              :         dbcsr_type_no_symmetry, dbcsr_type_symmetric
      36              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_dot
      37              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      38              :    USE cp_dbcsr_operations,             ONLY: copy_fm_to_dbcsr
      39              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale
      40              :    USE cp_fm_pool_types,                ONLY: cp_fm_pool_p_type,&
      41              :                                               fm_pool_create_fm,&
      42              :                                               fm_pool_give_back_fm
      43              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_type
      44              :    USE cp_fm_types,                     ONLY: &
      45              :         copy_info_type, cp_fm_cleanup_copy_general, cp_fm_create, cp_fm_finish_copy_general, &
      46              :         cp_fm_get_diag, cp_fm_get_info, cp_fm_get_submatrix, cp_fm_release, &
      47              :         cp_fm_start_copy_general, cp_fm_to_fm, cp_fm_type
      48              :    USE cp_log_handling,                 ONLY: cp_logger_get_default_io_unit
      49              :    USE cryssym,                         ONLY: crys_sym_gen,&
      50              :                                               csym_type,&
      51              :                                               kpoint_gen,&
      52              :                                               kpoint_gen_general,&
      53              :                                               print_crys_symmetry,&
      54              :                                               print_kp_symmetry,&
      55              :                                               release_csym_type
      56              :    USE hairy_probes,                    ONLY: probe_occupancy_kp
      57              :    USE input_constants,                 ONLY: smear_fermi_dirac,&
      58              :                                               smear_gaussian,&
      59              :                                               smear_mp,&
      60              :                                               smear_mv
      61              :    USE input_cp2k_kpoints,              ONLY: use_spglib_kpoint_backend,&
      62              :                                               use_spglib_kpoint_symmetry
      63              :    USE kinds,                           ONLY: dp
      64              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      65              :                                               kind_rotmat_type,&
      66              :                                               kpoint_env_create,&
      67              :                                               kpoint_env_p_type,&
      68              :                                               kpoint_env_type,&
      69              :                                               kpoint_sym_create,&
      70              :                                               kpoint_sym_type,&
      71              :                                               kpoint_type
      72              :    USE mathconstants,                   ONLY: twopi
      73              :    USE mathlib,                         ONLY: inv_3x3
      74              :    USE memory_utilities,                ONLY: reallocate
      75              :    USE message_passing,                 ONLY: mp_cart_type,&
      76              :                                               mp_para_env_type
      77              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      78              :    USE particle_types,                  ONLY: particle_type
      79              :    USE qs_matrix_pools,                 ONLY: mpools_create,&
      80              :                                               mpools_get,&
      81              :                                               mpools_rebuild_fm_pools,&
      82              :                                               qs_matrix_pools_type
      83              :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
      84              :                                               get_mo_set,&
      85              :                                               init_mo_set,&
      86              :                                               mo_set_type,&
      87              :                                               set_mo_set
      88              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      89              :                                               get_neighbor_list_set_p,&
      90              :                                               neighbor_list_iterate,&
      91              :                                               neighbor_list_iterator_create,&
      92              :                                               neighbor_list_iterator_p_type,&
      93              :                                               neighbor_list_iterator_release,&
      94              :                                               neighbor_list_set_p_type
      95              :    USE scf_control_types,               ONLY: smear_type
      96              :    USE smearing_utils,                  ONLY: Smearkp,&
      97              :                                               Smearkp2
      98              :    USE util,                            ONLY: get_limit
      99              : #include "./base/base_uses.f90"
     100              : 
     101              :    IMPLICIT NONE
     102              : 
     103              :    PRIVATE
     104              : 
     105              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'kpoint_methods'
     106              : 
     107              :    PUBLIC :: kpoint_initialize, kpoint_env_initialize, kpoint_initialize_mos, kpoint_initialize_mo_set
     108              :    PUBLIC :: kpoint_init_cell_index, kpoint_set_mo_occupation
     109              :    PUBLIC :: kpoint_density_matrices, kpoint_density_transform
     110              :    PUBLIC :: rskp_transform, lowdin_kp_trans, lowdin_kp_mo_coeff
     111              : 
     112              : ! **************************************************************************************************
     113              : 
     114              : CONTAINS
     115              : 
     116              : ! **************************************************************************************************
     117              : !> \brief Generate the kpoints and initialize the kpoint environment
     118              : !> \param kpoint       The kpoint environment
     119              : !> \param particle_set Particle types and coordinates
     120              : !> \param cell         Computational cell information
     121              : ! **************************************************************************************************
     122        11380 :    SUBROUTINE kpoint_initialize(kpoint, particle_set, cell)
     123              : 
     124              :       TYPE(kpoint_type), POINTER                         :: kpoint
     125              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     126              :       TYPE(cell_type), POINTER                           :: cell
     127              : 
     128              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'kpoint_initialize'
     129              : 
     130              :       INTEGER                                            :: handle, i, ic, ik, iounit, ir, ira, is, &
     131              :                                                             isign, j, natom, nkind, nr, ns
     132        11380 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atype
     133        11380 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: agauge
     134              :       INTEGER, DIMENSION(3, 3)                           :: frot, krot
     135              :       LOGICAL                                            :: spez
     136              :       REAL(KIND=dp)                                      :: eps_kpoint, wsum
     137        11380 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: coord, scoord
     138              :       REAL(KIND=dp), DIMENSION(3)                        :: diff, kgvec, r_pbc, scoord_pbc, srot
     139              :       REAL(KIND=dp), DIMENSION(3, 3)                     :: srotmat
     140        11380 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp_full
     141        11380 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp_full
     142       216220 :       TYPE(csym_type)                                    :: crys_sym
     143              :       TYPE(kpoint_sym_type), POINTER                     :: kpsym
     144              : 
     145        11380 :       CALL timeset(routineN, handle)
     146              : 
     147        11380 :       CPASSERT(ASSOCIATED(kpoint))
     148              : 
     149        11398 :       SELECT CASE (kpoint%kp_scheme)
     150              :       CASE ("NONE")
     151              :          ! do nothing
     152              :       CASE ("GAMMA")
     153           18 :          kpoint%nkp = 1
     154           18 :          ALLOCATE (kpoint%xkp(3, 1), kpoint%wkp(1))
     155           72 :          kpoint%xkp(1:3, 1) = 0.0_dp
     156           18 :          kpoint%wkp(1) = 1.0_dp
     157           36 :          ALLOCATE (kpoint%kp_sym(1))
     158           18 :          NULLIFY (kpoint%kp_sym(1)%kpoint_sym)
     159           18 :          CALL kpoint_sym_create(kpoint%kp_sym(1)%kpoint_sym)
     160              :       CASE ("MONKHORST-PACK", "MACDONALD")
     161              : 
     162         3180 :          IF (.NOT. kpoint%symmetry) THEN
     163              :             ! we set up a random molecule to avoid any possible symmetry
     164          172 :             natom = 10
     165          172 :             ALLOCATE (coord(3, natom), scoord(3, natom), atype(natom))
     166         1892 :             DO i = 1, natom
     167         1720 :                atype(i) = i
     168         1720 :                coord(1, i) = SIN(i*0.12345_dp)
     169         1720 :                coord(2, i) = COS(i*0.23456_dp)
     170         1720 :                coord(3, i) = SIN(i*0.34567_dp)
     171         1892 :                CALL real_to_scaled(scoord(1:3, i), coord(1:3, i), cell)
     172              :             END DO
     173              :          ELSE
     174         3008 :             natom = SIZE(particle_set)
     175        15040 :             ALLOCATE (scoord(3, natom), atype(natom))
     176        16908 :             DO i = 1, natom
     177        13900 :                CALL get_atomic_kind(atomic_kind=particle_set(i)%atomic_kind, kind_number=atype(i))
     178        16908 :                CALL real_to_scaled(scoord(1:3, i), particle_set(i)%r(1:3), cell)
     179              :             END DO
     180              :          END IF
     181         3180 :          IF (kpoint%verbose) THEN
     182         2348 :             iounit = cp_logger_get_default_io_unit()
     183              :          ELSE
     184          832 :             iounit = -1
     185              :          END IF
     186              :          ! kind type list
     187         9540 :          ALLOCATE (kpoint%atype(natom))
     188        18800 :          kpoint%atype = atype
     189              :          ! Match the atom images used by CP2K's periodic neighbor lists.
     190         9540 :          ALLOCATE (agauge(3, natom))
     191         3180 :          agauge = 0
     192         3180 :          IF (kpoint%symmetry) THEN
     193        16908 :             DO i = 1, natom
     194        13900 :                r_pbc(1:3) = pbc(particle_set(i)%r(1:3), cell)
     195        13900 :                CALL real_to_scaled(scoord_pbc, r_pbc, cell)
     196        58608 :                agauge(1:3, i) = NINT(scoord_pbc(1:3) - scoord(1:3, i))
     197              :             END DO
     198              :          END IF
     199              : 
     200              :          CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit, &
     201         3180 :                            use_spglib=kpoint%symmetry)
     202              :          CALL kpoint_gen(crys_sym, kpoint%nkp_grid, symm=kpoint%symmetry, shift=kpoint%kp_shift, &
     203              :                          full_grid=kpoint%full_grid, gamma_centered=kpoint%gamma_centered, &
     204              :                          inversion_symmetry_only=kpoint%inversion_symmetry_only, &
     205              :                          use_spglib_reduction= &
     206              :                          kpoint%symmetry_reduction_method == use_spglib_kpoint_symmetry, &
     207         3180 :                          use_spglib_backend=kpoint%symmetry_backend == use_spglib_kpoint_backend)
     208         3180 :          IF (crys_sym%inversion_only) kpoint%inversion_symmetry_only = .TRUE.
     209         3180 :          kpoint%nkp = crys_sym%nkpoint
     210        15900 :          ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp))
     211        14622 :          wsum = SUM(crys_sym%wkpoint)
     212        14622 :          DO ik = 1, kpoint%nkp
     213        45768 :             kpoint%xkp(1:3, ik) = crys_sym%xkpoint(1:3, ik)
     214        14622 :             kpoint%wkp(ik) = crys_sym%wkpoint(ik)/wsum
     215              :          END DO
     216              : 
     217         3180 :          eps_kpoint = MAX(1.e-12_dp, 10.0_dp*kpoint%eps_geo)
     218              :          ! print output
     219         3180 :          IF (kpoint%symmetry) CALL print_crys_symmetry(crys_sym)
     220         3180 :          IF (kpoint%symmetry) CALL print_kp_symmetry(crys_sym)
     221              : 
     222              :          ! transfer symmetry information
     223        20982 :          ALLOCATE (kpoint%kp_sym(kpoint%nkp))
     224        14622 :          DO ik = 1, kpoint%nkp
     225        11442 :             NULLIFY (kpoint%kp_sym(ik)%kpoint_sym)
     226        11442 :             CALL kpoint_sym_create(kpoint%kp_sym(ik)%kpoint_sym)
     227        11442 :             kpsym => kpoint%kp_sym(ik)%kpoint_sym
     228              :             IF (crys_sym%nrtot > 0 .AND. .NOT. crys_sym%fullgrid .AND. &
     229        14622 :                 crys_sym%istriz == 1 .AND. .NOT. crys_sym%inversion_only) THEN
     230              :                ! set up the symmetrization information
     231         3324 :                kpsym%nwght = NINT(crys_sym%wkpoint(ik))
     232         3324 :                ns = kpsym%nwght
     233              :                !
     234         3324 :                IF (ns > 1) THEN
     235        71936 :                   DO is = 1, SIZE(crys_sym%kplink, 2)
     236        71936 :                      IF (crys_sym%kplink(2, is) == ik) THEN
     237       420772 :                         DO ic = 1, crys_sym%nrtot
     238     31996580 :                            srotmat = MATMUL(cell%h_inv, MATMUL(crys_sym%rt(1:3, 1:3, ic), cell%hmat))
     239      5265260 :                            frot(1:3, 1:3) = NINT(srotmat(1:3, 1:3))
     240     10530520 :                            krot(1:3, 1:3) = NINT(TRANSPOSE(inv_3x3(REAL(frot(1:3, 1:3), KIND=dp))))
     241      1230812 :                            DO isign = 1, 2
     242       810040 :                               ir = MERGE(crys_sym%ibrot(ic), -crys_sym%ibrot(ic), isign == 1)
     243       810040 :                               IF (ir == crys_sym%kpop(is)) CYCLE
     244              :                               kgvec(1:3) = crys_sym%kpmesh(1:3, is) - &
     245              :                                            MATMUL(REAL(MERGE(krot(1:3, 1:3), -krot(1:3, 1:3), &
     246              :                                                              isign == 1), KIND=dp), &
     247     22240064 :                                                   kpoint%xkp(1:3, ik))
     248      3177152 :                               diff(1:3) = kgvec(1:3) - ANINT(kgvec(1:3))
     249      1632124 :                               IF (ALL(ABS(diff(1:3)) < eps_kpoint)) ns = ns + 1
     250              :                            END DO
     251              :                         END DO
     252              :                      END IF
     253              :                   END DO
     254         3044 :                   kpsym%apply_symmetry = .TRUE.
     255         3044 :                   natom = SIZE(particle_set)
     256         9132 :                   ALLOCATE (kpsym%rot(3, 3, ns))
     257         9132 :                   ALLOCATE (kpsym%xkp(3, ns))
     258         9132 :                   ALLOCATE (kpsym%rotp(ns))
     259        12176 :                   ALLOCATE (kpsym%f0(natom, ns))
     260        12176 :                   ALLOCATE (kpsym%fcell(3, natom, ns))
     261         9132 :                   ALLOCATE (kpsym%fcell_gauge(3, natom, ns))
     262         6088 :                   ALLOCATE (kpsym%phase_mode(ns))
     263        69572 :                   kpsym%phase_mode = 0
     264        12176 :                   ALLOCATE (kpsym%kgphase(natom, ns))
     265         3044 :                   nr = 0
     266        71936 :                   DO is = 1, SIZE(crys_sym%kplink, 2)
     267        71936 :                      IF (crys_sym%kplink(2, is) == ik) THEN
     268        15752 :                         nr = nr + 1
     269        15752 :                         ir = crys_sym%kpop(is)
     270        15752 :                         ira = ABS(ir)
     271        87480 :                         DO ic = 1, crys_sym%nrtot
     272        87480 :                            IF (crys_sym%ibrot(ic) == ira) THEN
     273        15752 :                               kpsym%rotp(nr) = ir
     274       204776 :                               kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ic)
     275      1244408 :                               srotmat = MATMUL(cell%h_inv, MATMUL(crys_sym%rt(1:3, 1:3, ic), cell%hmat))
     276       204776 :                               frot(1:3, 1:3) = NINT(srotmat(1:3, 1:3))
     277        63008 :                               kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
     278       409552 :                               krot(1:3, 1:3) = NINT(TRANSPOSE(inv_3x3(REAL(frot(1:3, 1:3), KIND=dp))))
     279       108176 :                               IF (ir < 0) krot(1:3, 1:3) = -krot(1:3, 1:3)
     280              :                               kgvec(1:3) = kpsym%xkp(1:3, nr) - &
     281              :                                            MATMUL(REAL(krot(1:3, 1:3), KIND=dp), &
     282       441056 :                                                   kpoint%xkp(1:3, ik))
     283        63008 :                               kgvec(1:3) = ANINT(kgvec(1:3))
     284       126356 :                               kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
     285       126356 :                               DO j = 1, natom
     286      1769664 :                                  srot(1:3) = MATMUL(srotmat, scoord(1:3, j)) + crys_sym%vt(1:3, ic)
     287              :                                  kpsym%fcell(1:3, j, nr) = &
     288       442416 :                                     NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr)))
     289              :                                  kpsym%fcell_gauge(1:3, j, nr) = &
     290              :                                     NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr))) + &
     291              :                                     MATMUL(frot(1:3, 1:3), agauge(1:3, j)) - &
     292      2101476 :                                     agauge(1:3, kpsym%f0(j, nr))
     293              :                                  kpsym%kgphase(j, nr) = DOT_PRODUCT(kgvec(1:3), &
     294              :                                                                     scoord(1:3, j) + &
     295       458168 :                                                                     REAL(agauge(1:3, j), KIND=dp))
     296              :                               END DO
     297              :                               EXIT
     298              :                            END IF
     299              :                         END DO
     300        15752 :                         CPASSERT(ic <= crys_sym%nrtot)
     301              :                      END IF
     302              :                   END DO
     303        71936 :                   DO is = 1, SIZE(crys_sym%kplink, 2)
     304        71936 :                      IF (crys_sym%kplink(2, is) == ik) THEN
     305       420772 :                         DO ic = 1, crys_sym%nrtot
     306     31996580 :                            srotmat = MATMUL(cell%h_inv, MATMUL(crys_sym%rt(1:3, 1:3, ic), cell%hmat))
     307      5265260 :                            frot(1:3, 1:3) = NINT(srotmat(1:3, 1:3))
     308     10530520 :                            krot(1:3, 1:3) = NINT(TRANSPOSE(inv_3x3(REAL(frot(1:3, 1:3), KIND=dp))))
     309      1230812 :                            DO isign = 1, 2
     310       810040 :                               ir = MERGE(crys_sym%ibrot(ic), -crys_sym%ibrot(ic), isign == 1)
     311       810040 :                               IF (ir == crys_sym%kpop(is)) CYCLE
     312              :                               kgvec(1:3) = crys_sym%kpmesh(1:3, is) - &
     313              :                                            MATMUL(REAL(MERGE(krot(1:3, 1:3), -krot(1:3, 1:3), &
     314              :                                                              isign == 1), KIND=dp), &
     315     22240064 :                                                   kpoint%xkp(1:3, ik))
     316      3177152 :                               diff(1:3) = kgvec(1:3) - ANINT(kgvec(1:3))
     317      1632124 :                               IF (ALL(ABS(diff(1:3)) < eps_kpoint)) THEN
     318        50776 :                                  nr = nr + 1
     319        50776 :                                  kpsym%rotp(nr) = ir
     320       660088 :                                  kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ic)
     321       203104 :                                  kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
     322       203104 :                                  kgvec(1:3) = ANINT(kgvec(1:3))
     323       430728 :                                  kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
     324       430728 :                                  DO j = 1, natom
     325      6079232 :                                     srot(1:3) = MATMUL(srotmat, scoord(1:3, j)) + crys_sym%vt(1:3, ic)
     326              :                                     kpsym%fcell(1:3, j, nr) = &
     327      1519808 :                                        NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr)))
     328              :                                     kpsym%fcell_gauge(1:3, j, nr) = &
     329              :                                        NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr))) + &
     330              :                                        MATMUL(frot(1:3, 1:3), agauge(1:3, j)) - &
     331      7219088 :                                        agauge(1:3, kpsym%f0(j, nr))
     332              :                                     kpsym%kgphase(j, nr) = DOT_PRODUCT(kgvec(1:3), &
     333              :                                                                        scoord(1:3, j) + &
     334      1570584 :                                                                        REAL(agauge(1:3, j), KIND=dp))
     335              :                                  END DO
     336              :                               END IF
     337              :                            END DO
     338              :                         END DO
     339              :                      END IF
     340              :                   END DO
     341         3044 :                   kpsym%nwred = nr
     342              :                END IF
     343              :             END IF
     344              :          END DO
     345         3180 :          IF (kpoint%symmetry) THEN
     346        16908 :             nkind = MAXVAL(atype)
     347         3008 :             ns = crys_sym%nrtot
     348        31550 :             ALLOCATE (kpoint%kind_rotmat(ns, nkind))
     349        17806 :             DO i = 1, ns
     350        34644 :                DO j = 1, nkind
     351        31636 :                   NULLIFY (kpoint%kind_rotmat(i, j)%rmat)
     352              :                END DO
     353              :             END DO
     354         7454 :             ALLOCATE (kpoint%ibrot(ns))
     355        17806 :             kpoint%ibrot(1:ns) = crys_sym%ibrot(1:ns)
     356              :          END IF
     357              : 
     358         3180 :          CALL release_csym_type(crys_sym)
     359         3180 :          DEALLOCATE (scoord, atype)
     360         3180 :          DEALLOCATE (agauge)
     361              : 
     362              :       CASE ("GENERAL")
     363              :          NULLIFY (xkp_full, wkp_full)
     364           36 :          IF (ASSOCIATED(kpoint%xkp_input)) THEN
     365           36 :             xkp_full => kpoint%xkp_input
     366           36 :             wkp_full => kpoint%wkp_input
     367              :          ELSE
     368            0 :             xkp_full => kpoint%xkp
     369            0 :             wkp_full => kpoint%wkp
     370              :          END IF
     371           36 :          CPASSERT(ASSOCIATED(xkp_full))
     372           36 :          CPASSERT(ASSOCIATED(wkp_full))
     373           36 :          IF (.NOT. ASSOCIATED(kpoint%xkp_input)) THEN
     374            0 :             ALLOCATE (kpoint%xkp_input(3, SIZE(wkp_full)), kpoint%wkp_input(SIZE(wkp_full)))
     375            0 :             kpoint%xkp_input(1:3, 1:SIZE(wkp_full)) = xkp_full(1:3, 1:SIZE(wkp_full))
     376            0 :             kpoint%wkp_input(1:SIZE(wkp_full)) = wkp_full(1:SIZE(wkp_full))
     377            0 :             xkp_full => kpoint%xkp_input
     378            0 :             wkp_full => kpoint%wkp_input
     379              :          END IF
     380           36 :          IF (.NOT. kpoint%symmetry) THEN
     381           10 :             IF (.NOT. ASSOCIATED(kpoint%xkp)) THEN
     382            0 :                kpoint%nkp = SIZE(wkp_full)
     383            0 :                ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp))
     384            0 :                kpoint%xkp(1:3, 1:kpoint%nkp) = xkp_full(1:3, 1:kpoint%nkp)
     385            0 :                kpoint%wkp(1:kpoint%nkp) = wkp_full(1:kpoint%nkp)
     386              :             END IF
     387              :             ! default: no symmetry settings
     388           74 :             ALLOCATE (kpoint%kp_sym(kpoint%nkp))
     389           54 :             DO i = 1, kpoint%nkp
     390           44 :                NULLIFY (kpoint%kp_sym(i)%kpoint_sym)
     391           54 :                CALL kpoint_sym_create(kpoint%kp_sym(i)%kpoint_sym)
     392              :             END DO
     393              :          ELSE
     394           26 :             IF (kpoint%verbose) THEN
     395           16 :                iounit = cp_logger_get_default_io_unit()
     396              :             ELSE
     397           10 :                iounit = -1
     398              :             END IF
     399           26 :             natom = SIZE(particle_set)
     400          130 :             ALLOCATE (scoord(3, natom), atype(natom))
     401          234 :             DO i = 1, natom
     402          208 :                CALL get_atomic_kind(atomic_kind=particle_set(i)%atomic_kind, kind_number=atype(i))
     403          234 :                CALL real_to_scaled(scoord(1:3, i), particle_set(i)%r(1:3), cell)
     404              :             END DO
     405           52 :             ALLOCATE (kpoint%atype(natom))
     406          234 :             kpoint%atype = atype
     407           78 :             ALLOCATE (agauge(3, natom))
     408          234 :             DO i = 1, natom
     409          208 :                r_pbc(1:3) = pbc(particle_set(i)%r(1:3), cell)
     410          208 :                CALL real_to_scaled(scoord_pbc, r_pbc, cell)
     411          858 :                agauge(1:3, i) = NINT(scoord_pbc(1:3) - scoord(1:3, i))
     412              :             END DO
     413              : 
     414              :             CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit, &
     415              :                               use_spglib=(kpoint%symmetry_backend == use_spglib_kpoint_backend .OR. &
     416           30 :                                           kpoint%symmetry_reduction_method == use_spglib_kpoint_symmetry))
     417              :             CALL kpoint_gen_general(crys_sym, xkp_full, wkp_full, symm=kpoint%symmetry, &
     418              :                                     full_grid=kpoint%full_grid, &
     419              :                                     inversion_symmetry_only=kpoint%inversion_symmetry_only, &
     420              :                                     use_spglib_reduction= &
     421              :                                     kpoint%symmetry_reduction_method == use_spglib_kpoint_symmetry, &
     422           26 :                                     use_spglib_backend=kpoint%symmetry_backend == use_spglib_kpoint_backend)
     423           26 :             IF (crys_sym%inversion_only) kpoint%inversion_symmetry_only = .TRUE.
     424           26 :             IF (ASSOCIATED(kpoint%xkp)) THEN
     425           26 :                DEALLOCATE (kpoint%xkp)
     426           26 :                NULLIFY (kpoint%xkp)
     427              :             END IF
     428           26 :             IF (ASSOCIATED(kpoint%wkp)) THEN
     429           26 :                DEALLOCATE (kpoint%wkp)
     430           26 :                NULLIFY (kpoint%wkp)
     431              :             END IF
     432           26 :             kpoint%nkp = crys_sym%nkpoint
     433          130 :             ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp))
     434           52 :             wsum = SUM(crys_sym%wkpoint)
     435           52 :             DO ik = 1, kpoint%nkp
     436          104 :                kpoint%xkp(1:3, ik) = crys_sym%xkpoint(1:3, ik)
     437           52 :                kpoint%wkp(ik) = crys_sym%wkpoint(ik)/wsum
     438              :             END DO
     439              : 
     440           26 :             eps_kpoint = MAX(1.e-12_dp, 10.0_dp*kpoint%eps_geo)
     441           26 :             CALL print_crys_symmetry(crys_sym)
     442           26 :             CALL print_kp_symmetry(crys_sym)
     443              : 
     444          104 :             ALLOCATE (kpoint%kp_sym(kpoint%nkp))
     445           52 :             DO ik = 1, kpoint%nkp
     446           26 :                NULLIFY (kpoint%kp_sym(ik)%kpoint_sym)
     447           26 :                CALL kpoint_sym_create(kpoint%kp_sym(ik)%kpoint_sym)
     448           26 :                kpsym => kpoint%kp_sym(ik)%kpoint_sym
     449              :                IF (crys_sym%nrtot > 0 .AND. .NOT. crys_sym%fullgrid .AND. &
     450           52 :                    crys_sym%istriz == 1 .AND. .NOT. crys_sym%inversion_only) THEN
     451           26 :                   kpsym%nwght = NINT(crys_sym%wkpoint(ik))
     452           26 :                   ns = kpsym%nwght
     453           26 :                   IF (ns > 1) THEN
     454          234 :                      DO is = 1, SIZE(crys_sym%kplink, 2)
     455          234 :                         IF (crys_sym%kplink(2, is) == ik) THEN
     456        10192 :                            DO ic = 1, crys_sym%nrtot
     457       788736 :                               srotmat = MATMUL(cell%h_inv, MATMUL(crys_sym%rt(1:3, 1:3, ic), cell%hmat))
     458       129792 :                               frot(1:3, 1:3) = NINT(srotmat(1:3, 1:3))
     459       259584 :                               krot(1:3, 1:3) = NINT(TRANSPOSE(inv_3x3(REAL(frot(1:3, 1:3), KIND=dp))))
     460        30160 :                               DO isign = 1, 2
     461        19968 :                                  ir = MERGE(crys_sym%ibrot(ic), -crys_sym%ibrot(ic), isign == 1)
     462        19968 :                                  IF (ir == crys_sym%kpop(is)) CYCLE
     463              :                                  kgvec(1:3) = crys_sym%kpmesh(1:3, is) - &
     464              :                                               MATMUL(REAL(MERGE(krot(1:3, 1:3), -krot(1:3, 1:3), &
     465              :                                                                 isign == 1), KIND=dp), &
     466       553280 :                                                      kpoint%xkp(1:3, ik))
     467        79040 :                                  diff(1:3) = kgvec(1:3) - ANINT(kgvec(1:3))
     468        46592 :                                  IF (ALL(ABS(diff(1:3)) < eps_kpoint)) ns = ns + 1
     469              :                               END DO
     470              :                            END DO
     471              :                         END IF
     472              :                      END DO
     473           26 :                      kpsym%apply_symmetry = .TRUE.
     474           78 :                      ALLOCATE (kpsym%rot(3, 3, ns))
     475           78 :                      ALLOCATE (kpsym%xkp(3, ns))
     476           78 :                      ALLOCATE (kpsym%rotp(ns))
     477          104 :                      ALLOCATE (kpsym%f0(natom, ns))
     478          104 :                      ALLOCATE (kpsym%fcell(3, natom, ns))
     479           78 :                      ALLOCATE (kpsym%fcell_gauge(3, natom, ns))
     480           52 :                      ALLOCATE (kpsym%phase_mode(ns))
     481         2522 :                      kpsym%phase_mode = 0
     482          104 :                      ALLOCATE (kpsym%kgphase(natom, ns))
     483           26 :                      nr = 0
     484          234 :                      DO is = 1, SIZE(crys_sym%kplink, 2)
     485          234 :                         IF (crys_sym%kplink(2, is) == ik) THEN
     486          208 :                            nr = nr + 1
     487          208 :                            ir = crys_sym%kpop(is)
     488          208 :                            ira = ABS(ir)
     489          628 :                            DO ic = 1, crys_sym%nrtot
     490          628 :                               IF (crys_sym%ibrot(ic) == ira) THEN
     491          208 :                                  kpsym%rotp(nr) = ir
     492         2704 :                                  kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ic)
     493        16432 :                                  srotmat = MATMUL(cell%h_inv, MATMUL(crys_sym%rt(1:3, 1:3, ic), cell%hmat))
     494         2704 :                                  frot(1:3, 1:3) = NINT(srotmat(1:3, 1:3))
     495          832 :                                  kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
     496         5408 :                                  krot(1:3, 1:3) = NINT(TRANSPOSE(inv_3x3(REAL(frot(1:3, 1:3), KIND=dp))))
     497         1456 :                                  IF (ir < 0) krot(1:3, 1:3) = -krot(1:3, 1:3)
     498              :                                  kgvec(1:3) = kpsym%xkp(1:3, nr) - &
     499              :                                               MATMUL(REAL(krot(1:3, 1:3), KIND=dp), &
     500         5824 :                                                      kpoint%xkp(1:3, ik))
     501          832 :                                  kgvec(1:3) = ANINT(kgvec(1:3))
     502         1872 :                                  kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
     503         1872 :                                  DO j = 1, natom
     504        26624 :                                     srot(1:3) = MATMUL(srotmat, scoord(1:3, j)) + crys_sym%vt(1:3, ic)
     505              :                                     kpsym%fcell(1:3, j, nr) = &
     506         6656 :                                        NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr)))
     507              :                                     kpsym%fcell_gauge(1:3, j, nr) = &
     508              :                                        NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr))) + &
     509              :                                        MATMUL(frot(1:3, 1:3), agauge(1:3, j)) - &
     510        31616 :                                        agauge(1:3, kpsym%f0(j, nr))
     511              :                                     kpsym%kgphase(j, nr) = DOT_PRODUCT(kgvec(1:3), &
     512              :                                                                        scoord(1:3, j) + &
     513         6864 :                                                                        REAL(agauge(1:3, j), KIND=dp))
     514              :                                  END DO
     515              :                                  EXIT
     516              :                               END IF
     517              :                            END DO
     518          208 :                            CPASSERT(ic <= crys_sym%nrtot)
     519              :                         END IF
     520              :                      END DO
     521          234 :                      DO is = 1, SIZE(crys_sym%kplink, 2)
     522          234 :                         IF (crys_sym%kplink(2, is) == ik) THEN
     523        10192 :                            DO ic = 1, crys_sym%nrtot
     524       788736 :                               srotmat = MATMUL(cell%h_inv, MATMUL(crys_sym%rt(1:3, 1:3, ic), cell%hmat))
     525       129792 :                               frot(1:3, 1:3) = NINT(srotmat(1:3, 1:3))
     526       259584 :                               krot(1:3, 1:3) = NINT(TRANSPOSE(inv_3x3(REAL(frot(1:3, 1:3), KIND=dp))))
     527        30160 :                               DO isign = 1, 2
     528        19968 :                                  ir = MERGE(crys_sym%ibrot(ic), -crys_sym%ibrot(ic), isign == 1)
     529        19968 :                                  IF (ir == crys_sym%kpop(is)) CYCLE
     530              :                                  kgvec(1:3) = crys_sym%kpmesh(1:3, is) - &
     531              :                                               MATMUL(REAL(MERGE(krot(1:3, 1:3), -krot(1:3, 1:3), &
     532              :                                                                 isign == 1), KIND=dp), &
     533       553280 :                                                      kpoint%xkp(1:3, ik))
     534        79040 :                                  diff(1:3) = kgvec(1:3) - ANINT(kgvec(1:3))
     535        46592 :                                  IF (ALL(ABS(diff(1:3)) < eps_kpoint)) THEN
     536         2288 :                                     nr = nr + 1
     537         2288 :                                     kpsym%rotp(nr) = ir
     538        29744 :                                     kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ic)
     539         9152 :                                     kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
     540         9152 :                                     kgvec(1:3) = ANINT(kgvec(1:3))
     541        20592 :                                     kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
     542        20592 :                                     DO j = 1, natom
     543       292864 :                                        srot(1:3) = MATMUL(srotmat, scoord(1:3, j)) + crys_sym%vt(1:3, ic)
     544              :                                        kpsym%fcell(1:3, j, nr) = &
     545        73216 :                                           NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr)))
     546              :                                        kpsym%fcell_gauge(1:3, j, nr) = &
     547              :                                           NINT(srot(1:3) - scoord(1:3, kpsym%f0(j, nr))) + &
     548              :                                           MATMUL(frot(1:3, 1:3), agauge(1:3, j)) - &
     549       347776 :                                           agauge(1:3, kpsym%f0(j, nr))
     550              :                                        kpsym%kgphase(j, nr) = DOT_PRODUCT(kgvec(1:3), &
     551              :                                                                           scoord(1:3, j) + &
     552        75504 :                                                                           REAL(agauge(1:3, j), KIND=dp))
     553              :                                     END DO
     554              :                                  END IF
     555              :                               END DO
     556              :                            END DO
     557              :                         END IF
     558              :                      END DO
     559           26 :                      kpsym%nwred = nr
     560              :                   END IF
     561              :                END IF
     562              :             END DO
     563          234 :             nkind = MAXVAL(atype)
     564           26 :             ns = crys_sym%nrtot
     565         1378 :             ALLOCATE (kpoint%kind_rotmat(ns, nkind))
     566         1274 :             DO i = 1, ns
     567         2522 :                DO j = 1, nkind
     568         2496 :                   NULLIFY (kpoint%kind_rotmat(i, j)%rmat)
     569              :                END DO
     570              :             END DO
     571           78 :             ALLOCATE (kpoint%ibrot(ns))
     572         1274 :             kpoint%ibrot(1:ns) = crys_sym%ibrot(1:ns)
     573              : 
     574           26 :             CALL release_csym_type(crys_sym)
     575           26 :             DEALLOCATE (scoord, atype)
     576           26 :             DEALLOCATE (agauge)
     577              :          END IF
     578              :       CASE DEFAULT
     579        11380 :          CPABORT("Option invalid or unavailable for kpoint%kp_scheme")
     580              :       END SELECT
     581              : 
     582              :       ! check for consistency of options
     583        11398 :       SELECT CASE (kpoint%kp_scheme)
     584              :       CASE ("NONE")
     585              :          ! don't use k-point code
     586              :       CASE ("GAMMA")
     587           18 :          CPASSERT(kpoint%nkp == 1)
     588           90 :          CPASSERT(SUM(ABS(kpoint%xkp)) <= 1.e-12_dp)
     589           18 :          CPASSERT(kpoint%wkp(1) == 1.0_dp)
     590           18 :          CPASSERT(.NOT. kpoint%symmetry)
     591              :       CASE ("GENERAL")
     592           36 :          CPASSERT(kpoint%nkp >= 1)
     593              :       CASE ("MONKHORST-PACK", "MACDONALD")
     594        11380 :          CPASSERT(kpoint%nkp >= 1)
     595              :       END SELECT
     596        11380 :       IF (kpoint%use_real_wfn) THEN
     597              :          ! what about inversion symmetry?
     598           40 :          ikloop: DO ik = 1, kpoint%nkp
     599          100 :             DO i = 1, 3
     600           60 :                spez = (kpoint%xkp(i, ik) == 0.0_dp .OR. kpoint%xkp(i, ik) == 0.5_dp)
     601           20 :                IF (.NOT. spez) EXIT ikloop
     602              :             END DO
     603              :          END DO ikloop
     604           20 :          IF (.NOT. spez) THEN
     605              :             ! Warning: real wfn might be wrong for this system
     606              :             CALL cp_warn(__LOCATION__, &
     607              :                          "A calculation using real wavefunctions is requested. "// &
     608            0 :                          "We could not determine if the symmetry of the system allows real wavefunctions. ")
     609              :          END IF
     610              :       END IF
     611              : 
     612        11380 :       CALL timestop(handle)
     613              : 
     614        22760 :    END SUBROUTINE kpoint_initialize
     615              : 
     616              : ! **************************************************************************************************
     617              : !> \brief Initialize the kpoint environment
     618              : !> \param kpoint       Kpoint environment
     619              : !> \param para_env ...
     620              : !> \param blacs_env ...
     621              : !> \param with_aux_fit ...
     622              : ! **************************************************************************************************
     623         3054 :    SUBROUTINE kpoint_env_initialize(kpoint, para_env, blacs_env, with_aux_fit)
     624              : 
     625              :       TYPE(kpoint_type), INTENT(INOUT)                   :: kpoint
     626              :       TYPE(mp_para_env_type), INTENT(IN), TARGET         :: para_env
     627              :       TYPE(cp_blacs_env_type), INTENT(IN), TARGET        :: blacs_env
     628              :       LOGICAL, INTENT(IN), OPTIONAL                      :: with_aux_fit
     629              : 
     630              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_env_initialize'
     631              : 
     632              :       INTEGER                                            :: handle, igr, ik, ikk, ngr, niogrp, nkp, &
     633              :                                                             nkp_grp, nkp_loc, npe, unit_nr
     634              :       INTEGER, DIMENSION(2)                              :: dims, pos
     635              :       LOGICAL                                            :: aux_fit
     636         3054 :       TYPE(kpoint_env_p_type), DIMENSION(:), POINTER     :: kp_aux_env, kp_env
     637              :       TYPE(kpoint_env_type), POINTER                     :: kp
     638         3054 :       TYPE(mp_cart_type)                                 :: comm_cart
     639              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp, para_env_kp
     640              : 
     641         3054 :       CALL timeset(routineN, handle)
     642              : 
     643         3054 :       IF (PRESENT(with_aux_fit)) THEN
     644         2948 :          aux_fit = with_aux_fit
     645              :       ELSE
     646              :          aux_fit = .FALSE.
     647              :       END IF
     648              : 
     649         3054 :       kpoint%para_env => para_env
     650         3054 :       CALL kpoint%para_env%retain()
     651         3054 :       kpoint%blacs_env_all => blacs_env
     652         3054 :       CALL kpoint%blacs_env_all%retain()
     653              : 
     654         3054 :       CPASSERT(.NOT. ASSOCIATED(kpoint%kp_env))
     655         3054 :       IF (aux_fit) THEN
     656           32 :          CPASSERT(.NOT. ASSOCIATED(kpoint%kp_aux_env))
     657              :       END IF
     658              : 
     659         3054 :       NULLIFY (kp_env, kp_aux_env)
     660         3054 :       nkp = kpoint%nkp
     661         3054 :       npe = para_env%num_pe
     662         3054 :       IF (npe == 1) THEN
     663              :          ! only one process available -> owns all kpoints
     664            0 :          ALLOCATE (kp_env(nkp))
     665            0 :          DO ik = 1, nkp
     666            0 :             NULLIFY (kp_env(ik)%kpoint_env)
     667            0 :             CALL kpoint_env_create(kp_env(ik)%kpoint_env)
     668            0 :             kp => kp_env(ik)%kpoint_env
     669            0 :             kp%nkpoint = ik
     670            0 :             kp%wkp = kpoint%wkp(ik)
     671            0 :             kp%xkp(1:3) = kpoint%xkp(1:3, ik)
     672            0 :             kp%is_local = .TRUE.
     673              :          END DO
     674            0 :          kpoint%kp_env => kp_env
     675              : 
     676            0 :          IF (aux_fit) THEN
     677            0 :             ALLOCATE (kp_aux_env(nkp))
     678            0 :             DO ik = 1, nkp
     679            0 :                NULLIFY (kp_aux_env(ik)%kpoint_env)
     680            0 :                CALL kpoint_env_create(kp_aux_env(ik)%kpoint_env)
     681            0 :                kp => kp_aux_env(ik)%kpoint_env
     682            0 :                kp%nkpoint = ik
     683            0 :                kp%wkp = kpoint%wkp(ik)
     684            0 :                kp%xkp(1:3) = kpoint%xkp(1:3, ik)
     685            0 :                kp%is_local = .TRUE.
     686              :             END DO
     687              : 
     688            0 :             kpoint%kp_aux_env => kp_aux_env
     689              :          END IF
     690              : 
     691            0 :          ALLOCATE (kpoint%kp_dist(2, 1))
     692            0 :          kpoint%kp_dist(1, 1) = 1
     693            0 :          kpoint%kp_dist(2, 1) = nkp
     694            0 :          kpoint%kp_range(1) = 1
     695            0 :          kpoint%kp_range(2) = nkp
     696              : 
     697              :          ! parallel environments
     698            0 :          kpoint%para_env_kp => para_env
     699            0 :          CALL kpoint%para_env_kp%retain()
     700            0 :          kpoint%para_env_inter_kp => para_env
     701            0 :          CALL kpoint%para_env_inter_kp%retain()
     702            0 :          kpoint%iogrp = .TRUE.
     703            0 :          kpoint%nkp_groups = 1
     704              :       ELSE
     705         3054 :          IF (kpoint%parallel_group_size == -1) THEN
     706              :             ! maximum parallelization over kpoints
     707              :             ! making sure that the group size divides the npe and the nkp_grp the nkp
     708              :             ! in the worst case, there will be no parallelism over kpoints.
     709         8220 :             DO igr = npe, 1, -1
     710         5480 :                IF (MOD(npe, igr) /= 0) CYCLE
     711         5480 :                nkp_grp = npe/igr
     712         5480 :                IF (MOD(nkp, nkp_grp) /= 0) CYCLE
     713         8220 :                ngr = igr
     714              :             END DO
     715          314 :          ELSE IF (kpoint%parallel_group_size == 0) THEN
     716              :             ! no parallelization over kpoints
     717          230 :             ngr = npe
     718           84 :          ELSE IF (kpoint%parallel_group_size > 0) THEN
     719           84 :             ngr = MIN(kpoint%parallel_group_size, npe)
     720              :          ELSE
     721            0 :             CPABORT("kpoint%parallel_group_size cannot be smaller than -1")
     722              :          END IF
     723         3054 :          nkp_grp = npe/ngr
     724              :          ! processor dimensions
     725         3054 :          dims(1) = ngr
     726         3054 :          dims(2) = nkp_grp
     727         3054 :          CPASSERT(MOD(nkp, nkp_grp) == 0)
     728         3054 :          nkp_loc = nkp/nkp_grp
     729              : 
     730         3054 :          IF ((dims(1)*dims(2) /= npe)) THEN
     731            0 :             CPABORT("Number of processors is not divisible by the kpoint group size.")
     732              :          END IF
     733              : 
     734              :          ! Create the subgroups, one for each k-point group and one interconnecting group
     735         3054 :          CALL comm_cart%create(comm_old=para_env, ndims=2, dims=dims)
     736         9162 :          pos = comm_cart%mepos_cart
     737         3054 :          ALLOCATE (para_env_kp)
     738         3054 :          CALL para_env_kp%from_split(comm_cart, pos(2))
     739         3054 :          ALLOCATE (para_env_inter_kp)
     740         3054 :          CALL para_env_inter_kp%from_split(comm_cart, pos(1))
     741         3054 :          CALL comm_cart%free()
     742              : 
     743         3054 :          niogrp = 0
     744         3054 :          IF (para_env%is_source()) niogrp = 1
     745         3054 :          CALL para_env_kp%sum(niogrp)
     746         3054 :          kpoint%iogrp = (niogrp == 1)
     747              : 
     748              :          ! parallel groups
     749         3054 :          kpoint%para_env_kp => para_env_kp
     750         3054 :          kpoint%para_env_inter_kp => para_env_inter_kp
     751              : 
     752              :          ! distribution of kpoints
     753         9162 :          ALLOCATE (kpoint%kp_dist(2, nkp_grp))
     754         8096 :          DO igr = 1, nkp_grp
     755        18180 :             kpoint%kp_dist(1:2, igr) = get_limit(nkp, nkp_grp, igr - 1)
     756              :          END DO
     757              :          ! local kpoints
     758         9162 :          kpoint%kp_range(1:2) = kpoint%kp_dist(1:2, para_env_inter_kp%mepos + 1)
     759              : 
     760        16078 :          ALLOCATE (kp_env(nkp_loc))
     761         9970 :          DO ik = 1, nkp_loc
     762         6916 :             NULLIFY (kp_env(ik)%kpoint_env)
     763         6916 :             ikk = kpoint%kp_range(1) + ik - 1
     764         6916 :             CALL kpoint_env_create(kp_env(ik)%kpoint_env)
     765         6916 :             kp => kp_env(ik)%kpoint_env
     766         6916 :             kp%nkpoint = ikk
     767         6916 :             kp%wkp = kpoint%wkp(ikk)
     768        27664 :             kp%xkp(1:3) = kpoint%xkp(1:3, ikk)
     769         9970 :             kp%is_local = (ngr == 1)
     770              :          END DO
     771         3054 :          kpoint%kp_env => kp_env
     772              : 
     773         3054 :          IF (aux_fit) THEN
     774          282 :             ALLOCATE (kp_aux_env(nkp_loc))
     775          250 :             DO ik = 1, nkp_loc
     776          218 :                NULLIFY (kp_aux_env(ik)%kpoint_env)
     777          218 :                ikk = kpoint%kp_range(1) + ik - 1
     778          218 :                CALL kpoint_env_create(kp_aux_env(ik)%kpoint_env)
     779          218 :                kp => kp_aux_env(ik)%kpoint_env
     780          218 :                kp%nkpoint = ikk
     781          218 :                kp%wkp = kpoint%wkp(ikk)
     782          872 :                kp%xkp(1:3) = kpoint%xkp(1:3, ikk)
     783          250 :                kp%is_local = (ngr == 1)
     784              :             END DO
     785           32 :             kpoint%kp_aux_env => kp_aux_env
     786              :          END IF
     787              : 
     788         3054 :          unit_nr = cp_logger_get_default_io_unit()
     789              : 
     790         3054 :          IF (unit_nr > 0 .AND. kpoint%verbose) THEN
     791         1183 :             WRITE (unit_nr, *)
     792         1183 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Number of kpoint groups ", nkp_grp
     793         1183 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Size of each kpoint group", ngr
     794         1183 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Number of kpoints per group", nkp_loc
     795              :          END IF
     796         3054 :          kpoint%nkp_groups = nkp_grp
     797              : 
     798              :       END IF
     799              : 
     800         3054 :       CALL timestop(handle)
     801              : 
     802         6108 :    END SUBROUTINE kpoint_env_initialize
     803              : 
     804              : ! **************************************************************************************************
     805              : !> \brief Initialize a set of MOs and density matrix for each kpoint (kpoint group)
     806              : !> \param kpoint  Kpoint environment
     807              : !> \param mos     Reference MOs (global)
     808              : !> \param added_mos ...
     809              : !> \param for_aux_fit ...
     810              : ! **************************************************************************************************
     811         3086 :    SUBROUTINE kpoint_initialize_mos(kpoint, mos, added_mos, for_aux_fit)
     812              : 
     813              :       TYPE(kpoint_type), POINTER                         :: kpoint
     814              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
     815              :       INTEGER, INTENT(IN), OPTIONAL                      :: added_mos
     816              :       LOGICAL, OPTIONAL                                  :: for_aux_fit
     817              : 
     818              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_initialize_mos'
     819              : 
     820              :       INTEGER                                            :: handle, ic, ik, is, nadd, nao, nc, &
     821              :                                                             nelectron, nkp_loc, nmo, nmorig(2), &
     822              :                                                             nspin
     823              :       LOGICAL                                            :: aux_fit
     824              :       REAL(KIND=dp)                                      :: flexible_electron_count, maxocc, n_el_f
     825              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     826         3086 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_ao_fm_pools
     827              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     828              :       TYPE(cp_fm_type), POINTER                          :: fmlocal
     829              :       TYPE(kpoint_env_type), POINTER                     :: kp
     830              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
     831              : 
     832         3086 :       CALL timeset(routineN, handle)
     833              : 
     834         3086 :       IF (PRESENT(for_aux_fit)) THEN
     835           32 :          aux_fit = for_aux_fit
     836              :       ELSE
     837              :          aux_fit = .FALSE.
     838              :       END IF
     839              : 
     840         3086 :       CPASSERT(ASSOCIATED(kpoint))
     841              : 
     842              :       IF (.TRUE. .OR. ASSOCIATED(mos(1)%mo_coeff)) THEN
     843         3086 :          IF (aux_fit) THEN
     844           32 :             CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
     845              :          END IF
     846              : 
     847         3086 :          IF (PRESENT(added_mos)) THEN
     848           90 :             nadd = added_mos
     849              :          ELSE
     850              :             nadd = 0
     851              :          END IF
     852              : 
     853         3086 :          IF (kpoint%use_real_wfn) THEN
     854              :             nc = 1
     855              :          ELSE
     856         3068 :             nc = 2
     857              :          END IF
     858         3086 :          nspin = SIZE(mos, 1)
     859         3086 :          nkp_loc = kpoint%kp_range(2) - kpoint%kp_range(1) + 1
     860         3086 :          IF (nkp_loc > 0) THEN
     861         3086 :             IF (aux_fit) THEN
     862           32 :                CPASSERT(SIZE(kpoint%kp_aux_env) == nkp_loc)
     863              :             ELSE
     864         3054 :                CPASSERT(SIZE(kpoint%kp_env) == nkp_loc)
     865              :             END IF
     866              :             ! allocate the mo sets, correct number of kpoints (local), real/complex, spin
     867        10220 :             DO ik = 1, nkp_loc
     868         7134 :                IF (aux_fit) THEN
     869          218 :                   kp => kpoint%kp_aux_env(ik)%kpoint_env
     870              :                ELSE
     871         6916 :                   kp => kpoint%kp_env(ik)%kpoint_env
     872              :                END IF
     873        51760 :                ALLOCATE (kp%mos(nc, nspin))
     874        17968 :                DO is = 1, nspin
     875              :                   CALL get_mo_set(mos(is), nao=nao, nmo=nmo, nelectron=nelectron, &
     876         7748 :                                   n_el_f=n_el_f, maxocc=maxocc, flexible_electron_count=flexible_electron_count)
     877         7748 :                   nmo = MIN(nao, nmo + nadd)
     878        30358 :                   DO ic = 1, nc
     879              :                      CALL allocate_mo_set(kp%mos(ic, is), nao, nmo, nelectron, n_el_f, maxocc, &
     880        23224 :                                           flexible_electron_count)
     881              :                   END DO
     882              :                END DO
     883              :             END DO
     884              : 
     885              :             ! generate the blacs environment for the kpoint group
     886              :             ! we generate a blacs env for each kpoint group in parallel
     887              :             ! we assume here that the group para_env_inter_kp will connect
     888              :             ! equivalent parts of fm matrices, i.e. no reshuffeling of processors
     889         3086 :             NULLIFY (blacs_env)
     890         3086 :             IF (ASSOCIATED(kpoint%blacs_env)) THEN
     891           32 :                blacs_env => kpoint%blacs_env
     892              :             ELSE
     893         3054 :                CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=kpoint%para_env_kp)
     894         3054 :                kpoint%blacs_env => blacs_env
     895              :             END IF
     896              : 
     897              :             ! set possible new number of MOs
     898         6330 :             DO is = 1, nspin
     899         3244 :                CALL get_mo_set(mos(is), nmo=nmorig(is))
     900         3244 :                nmo = MIN(nao, nmorig(is) + nadd)
     901         6330 :                CALL set_mo_set(mos(is), nmo=nmo)
     902              :             END DO
     903              :             ! matrix pools for the kpoint group, information on MOs is transferred using
     904              :             ! generic mos structure
     905         3086 :             NULLIFY (mpools)
     906         3086 :             CALL mpools_create(mpools=mpools)
     907              :             CALL mpools_rebuild_fm_pools(mpools=mpools, mos=mos, &
     908         3086 :                                          blacs_env=blacs_env, para_env=kpoint%para_env_kp)
     909              : 
     910         3086 :             IF (aux_fit) THEN
     911           32 :                kpoint%mpools_aux_fit => mpools
     912              :             ELSE
     913         3054 :                kpoint%mpools => mpools
     914              :             END IF
     915              : 
     916              :             ! reset old number of MOs
     917         6330 :             DO is = 1, nspin
     918         6330 :                CALL set_mo_set(mos(is), nmo=nmorig(is))
     919              :             END DO
     920              : 
     921              :             ! allocate density matrices
     922         3086 :             CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
     923         3086 :             ALLOCATE (fmlocal)
     924         3086 :             CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
     925         3086 :             CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
     926        10220 :             DO ik = 1, nkp_loc
     927         7134 :                IF (aux_fit) THEN
     928          218 :                   kp => kpoint%kp_aux_env(ik)%kpoint_env
     929              :                ELSE
     930         6916 :                   kp => kpoint%kp_env(ik)%kpoint_env
     931              :                END IF
     932              :                ! density matrix
     933         7134 :                CALL cp_fm_release(kp%pmat)
     934        51760 :                ALLOCATE (kp%pmat(nc, nspin))
     935        14882 :                DO is = 1, nspin
     936        30358 :                   DO ic = 1, nc
     937        23224 :                      CALL cp_fm_create(kp%pmat(ic, is), matrix_struct)
     938              :                   END DO
     939              :                END DO
     940              :                ! energy weighted density matrix
     941         7134 :                CALL cp_fm_release(kp%wmat)
     942        44626 :                ALLOCATE (kp%wmat(nc, nspin))
     943        17968 :                DO is = 1, nspin
     944        30358 :                   DO ic = 1, nc
     945        23224 :                      CALL cp_fm_create(kp%wmat(ic, is), matrix_struct)
     946              :                   END DO
     947              :                END DO
     948              :             END DO
     949         3086 :             CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
     950         3086 :             DEALLOCATE (fmlocal)
     951              : 
     952              :          END IF
     953              : 
     954              :       END IF
     955              : 
     956         3086 :       CALL timestop(handle)
     957              : 
     958         3086 :    END SUBROUTINE kpoint_initialize_mos
     959              : 
     960              : ! **************************************************************************************************
     961              : !> \brief ...
     962              : !> \param kpoint ...
     963              : ! **************************************************************************************************
     964          106 :    SUBROUTINE kpoint_initialize_mo_set(kpoint)
     965              :       TYPE(kpoint_type), POINTER                         :: kpoint
     966              : 
     967              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_initialize_mo_set'
     968              : 
     969              :       INTEGER                                            :: handle, ic, ik, ikk, ispin
     970          106 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_mo_fm_pools
     971              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     972          106 :       TYPE(mo_set_type), DIMENSION(:, :), POINTER        :: moskp
     973              : 
     974          106 :       CALL timeset(routineN, handle)
     975              : 
     976          988 :       DO ik = 1, SIZE(kpoint%kp_env)
     977          882 :          CALL mpools_get(kpoint%mpools, ao_mo_fm_pools=ao_mo_fm_pools)
     978          882 :          moskp => kpoint%kp_env(ik)%kpoint_env%mos
     979          882 :          ikk = kpoint%kp_range(1) + ik - 1
     980          882 :          CPASSERT(ASSOCIATED(moskp))
     981         1904 :          DO ispin = 1, SIZE(moskp, 2)
     982         3630 :             DO ic = 1, SIZE(moskp, 1)
     983         1832 :                CALL get_mo_set(moskp(ic, ispin), mo_coeff=mo_coeff)
     984         2748 :                IF (.NOT. ASSOCIATED(mo_coeff)) THEN
     985              :                   CALL init_mo_set(moskp(ic, ispin), &
     986         1832 :                                    fm_pool=ao_mo_fm_pools(ispin)%pool, name="kpoints")
     987              :                END IF
     988              :             END DO
     989              :          END DO
     990              :       END DO
     991              : 
     992          106 :       CALL timestop(handle)
     993              : 
     994          106 :    END SUBROUTINE kpoint_initialize_mo_set
     995              : 
     996              : ! **************************************************************************************************
     997              : !> \brief Generates the mapping of cell indices and linear RS index
     998              : !>        CELL (0,0,0) is always mapped to index 1
     999              : !> \param kpoint    Kpoint environment
    1000              : !> \param sab_nl    Defining neighbour list
    1001              : !> \param para_env  Parallel environment
    1002              : !> \param nimages   [output]
    1003              : ! **************************************************************************************************
    1004         3926 :    SUBROUTINE kpoint_init_cell_index(kpoint, sab_nl, para_env, nimages)
    1005              : 
    1006              :       TYPE(kpoint_type), POINTER                         :: kpoint
    1007              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1008              :          POINTER                                         :: sab_nl
    1009              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1010              :       INTEGER, INTENT(OUT)                               :: nimages
    1011              : 
    1012              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_init_cell_index'
    1013              : 
    1014              :       INTEGER                                            :: handle, i1, i2, i3, ic, icount, it, &
    1015              :                                                             ncount
    1016              :       INTEGER, DIMENSION(3)                              :: cell, itm
    1017         3926 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell, list
    1018         3926 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index, cti
    1019              :       LOGICAL                                            :: new
    1020              :       TYPE(neighbor_list_iterator_p_type), &
    1021         3926 :          DIMENSION(:), POINTER                           :: nl_iterator
    1022              : 
    1023         3926 :       NULLIFY (cell_to_index, index_to_cell)
    1024              : 
    1025         3926 :       CALL timeset(routineN, handle)
    1026              : 
    1027         3926 :       CPASSERT(ASSOCIATED(kpoint))
    1028              : 
    1029         3926 :       ALLOCATE (list(3, 125))
    1030      1966926 :       list = 0
    1031         3926 :       icount = 1
    1032              : 
    1033         3926 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
    1034      1346860 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1035      1342934 :          CALL get_iterator_info(nl_iterator, cell=cell)
    1036              : 
    1037      1342934 :          new = .TRUE.
    1038     73230960 :          DO ic = 1, icount
    1039     73018697 :             IF (cell(1) == list(1, ic) .AND. cell(2) == list(2, ic) .AND. &
    1040       212263 :                 cell(3) == list(3, ic)) THEN
    1041              :                new = .FALSE.
    1042              :                EXIT
    1043              :             END IF
    1044              :          END DO
    1045      1346860 :          IF (new) THEN
    1046       212263 :             icount = icount + 1
    1047       212263 :             IF (icount > SIZE(list, 2)) THEN
    1048          555 :                CALL reallocate(list, 1, 3, 1, 2*SIZE(list, 2))
    1049              :             END IF
    1050       849052 :             list(1:3, icount) = cell(1:3)
    1051              :          END IF
    1052              : 
    1053              :       END DO
    1054         3926 :       CALL neighbor_list_iterator_release(nl_iterator)
    1055              : 
    1056       220115 :       itm(1) = MAXVAL(ABS(list(1, 1:icount)))
    1057       220115 :       itm(2) = MAXVAL(ABS(list(2, 1:icount)))
    1058       220115 :       itm(3) = MAXVAL(ABS(list(3, 1:icount)))
    1059         3926 :       CALL para_env%max(itm)
    1060        15704 :       it = MAXVAL(itm(1:3))
    1061         3926 :       IF (ASSOCIATED(kpoint%cell_to_index)) THEN
    1062         3922 :          DEALLOCATE (kpoint%cell_to_index)
    1063              :       END IF
    1064        19630 :       ALLOCATE (kpoint%cell_to_index(-itm(1):itm(1), -itm(2):itm(2), -itm(3):itm(3)))
    1065         3926 :       cell_to_index => kpoint%cell_to_index
    1066         3926 :       cti => cell_to_index
    1067       544388 :       cti(:, :, :) = 0
    1068       220115 :       DO ic = 1, icount
    1069       216189 :          i1 = list(1, ic)
    1070       216189 :          i2 = list(2, ic)
    1071       216189 :          i3 = list(3, ic)
    1072       220115 :          cti(i1, i2, i3) = ic
    1073              :       END DO
    1074      1084850 :       CALL para_env%sum(cti)
    1075         3926 :       ncount = 0
    1076        22504 :       DO i1 = -itm(1), itm(1)
    1077       137190 :          DO i2 = -itm(2), itm(2)
    1078       579974 :             DO i3 = -itm(3), itm(3)
    1079       561396 :                IF (cti(i1, i2, i3) == 0) THEN
    1080       200134 :                   cti(i1, i2, i3) = 1000000
    1081              :                ELSE
    1082       246576 :                   ncount = ncount + 1
    1083       246576 :                   cti(i1, i2, i3) = (ABS(i1) + ABS(i2) + ABS(i3))*1000 + ABS(i3)*100 + ABS(i2)*10 + ABS(i1)
    1084       246576 :                   cti(i1, i2, i3) = cti(i1, i2, i3) + (i1 + i2 + i3)
    1085              :                END IF
    1086              :             END DO
    1087              :          END DO
    1088              :       END DO
    1089              : 
    1090         3926 :       IF (ASSOCIATED(kpoint%index_to_cell)) THEN
    1091         3926 :          DEALLOCATE (kpoint%index_to_cell)
    1092              :       END IF
    1093        11778 :       ALLOCATE (kpoint%index_to_cell(3, ncount))
    1094         3926 :       index_to_cell => kpoint%index_to_cell
    1095       250502 :       DO ic = 1, ncount
    1096     82565256 :          cell = MINLOC(cti)
    1097       246576 :          i1 = cell(1) - 1 - itm(1)
    1098       246576 :          i2 = cell(2) - 1 - itm(2)
    1099       246576 :          i3 = cell(3) - 1 - itm(3)
    1100       246576 :          cti(i1, i2, i3) = 1000000
    1101       246576 :          index_to_cell(1, ic) = i1
    1102       246576 :          index_to_cell(2, ic) = i2
    1103       250502 :          index_to_cell(3, ic) = i3
    1104              :       END DO
    1105       544388 :       cti(:, :, :) = 0
    1106       250502 :       DO ic = 1, ncount
    1107       246576 :          i1 = index_to_cell(1, ic)
    1108       246576 :          i2 = index_to_cell(2, ic)
    1109       246576 :          i3 = index_to_cell(3, ic)
    1110       250502 :          cti(i1, i2, i3) = ic
    1111              :       END DO
    1112              : 
    1113              :       ! keep pointer to this neighborlist
    1114         3926 :       kpoint%sab_nl => sab_nl
    1115              : 
    1116              :       ! set number of images
    1117         3926 :       nimages = SIZE(index_to_cell, 2)
    1118              : 
    1119         3926 :       DEALLOCATE (list)
    1120              : 
    1121         3926 :       CALL timestop(handle)
    1122              : 
    1123         3926 :    END SUBROUTINE kpoint_init_cell_index
    1124              : 
    1125              : ! **************************************************************************************************
    1126              : !> \brief Transformation of real space matrices to a kpoint
    1127              : !> \param rmatrix  Real part of kpoint matrix
    1128              : !> \param cmatrix  Complex part of kpoint matrix (optional)
    1129              : !> \param rsmat    Real space matrices
    1130              : !> \param ispin    Spin index
    1131              : !> \param xkp      Kpoint coordinates
    1132              : !> \param cell_to_index   mapping of cell indices to RS index
    1133              : !> \param sab_nl   Defining neighbor list
    1134              : !> \param is_complex  Matrix to be transformed is imaginary
    1135              : !> \param rs_sign  Matrix to be transformed is csaled by rs_sign
    1136              : ! **************************************************************************************************
    1137       558116 :    SUBROUTINE rskp_transform(rmatrix, cmatrix, rsmat, ispin, &
    1138              :                              xkp, cell_to_index, sab_nl, is_complex, rs_sign)
    1139              : 
    1140              :       TYPE(dbcsr_type)                                   :: rmatrix
    1141              :       TYPE(dbcsr_type), OPTIONAL                         :: cmatrix
    1142              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rsmat
    1143              :       INTEGER, INTENT(IN)                                :: ispin
    1144              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xkp
    1145              :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1146              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1147              :          POINTER                                         :: sab_nl
    1148              :       LOGICAL, INTENT(IN), OPTIONAL                      :: is_complex
    1149              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: rs_sign
    1150              : 
    1151              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'rskp_transform'
    1152              : 
    1153              :       INTEGER                                            :: handle, iatom, ic, icol, irow, jatom, &
    1154              :                                                             nimg
    1155              :       INTEGER, DIMENSION(3)                              :: cell
    1156              :       LOGICAL                                            :: do_symmetric, found, my_complex, &
    1157              :                                                             wfn_real_only
    1158              :       REAL(KIND=dp)                                      :: arg, coskl, fsign, fsym, sinkl
    1159       279058 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, rblock, rsblock
    1160              :       TYPE(neighbor_list_iterator_p_type), &
    1161       279058 :          DIMENSION(:), POINTER                           :: nl_iterator
    1162              : 
    1163       279058 :       CALL timeset(routineN, handle)
    1164              : 
    1165       279058 :       my_complex = .FALSE.
    1166       279058 :       IF (PRESENT(is_complex)) my_complex = is_complex
    1167              : 
    1168       279058 :       fsign = 1.0_dp
    1169       279058 :       IF (PRESENT(rs_sign)) fsign = rs_sign
    1170              : 
    1171       279058 :       wfn_real_only = .TRUE.
    1172       279058 :       IF (PRESENT(cmatrix)) wfn_real_only = .FALSE.
    1173              : 
    1174       279058 :       nimg = SIZE(rsmat, 2)
    1175              : 
    1176       279058 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    1177              : 
    1178       279058 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
    1179     99942176 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1180     99663118 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom, cell=cell)
    1181              : 
    1182              :          ! fsym = +- 1 is due to real space matrices being non-symmetric (although in a symmtric type)
    1183              :          ! with the link S_mu^0,nu^b = S_nu^0,mu^-b, and the KP matrices beeing Hermitian
    1184     99663118 :          fsym = 1.0_dp
    1185     99663118 :          irow = iatom
    1186     99663118 :          icol = jatom
    1187     99663118 :          IF (do_symmetric .AND. (iatom > jatom)) THEN
    1188     43023423 :             irow = jatom
    1189     43023423 :             icol = iatom
    1190     43023423 :             fsym = -1.0_dp
    1191              :          END IF
    1192              : 
    1193     99663118 :          ic = cell_to_index(cell(1), cell(2), cell(3))
    1194     99663118 :          IF (ic < 1 .OR. ic > nimg) CYCLE
    1195              : 
    1196     99662374 :          arg = REAL(cell(1), dp)*xkp(1) + REAL(cell(2), dp)*xkp(2) + REAL(cell(3), dp)*xkp(3)
    1197     99662374 :          IF (my_complex) THEN
    1198      3466896 :             coskl = fsign*fsym*COS(twopi*arg)
    1199      3466896 :             sinkl = fsign*SIN(twopi*arg)
    1200              :          ELSE
    1201     96195478 :             coskl = fsign*COS(twopi*arg)
    1202     96195478 :             sinkl = fsign*fsym*SIN(twopi*arg)
    1203              :          END IF
    1204              : 
    1205              :          CALL dbcsr_get_block_p(matrix=rsmat(ispin, ic)%matrix, row=irow, col=icol, &
    1206     99662374 :                                 block=rsblock, found=found)
    1207     99662374 :          IF (.NOT. found) CYCLE
    1208              : 
    1209     99941432 :          IF (wfn_real_only) THEN
    1210              :             CALL dbcsr_get_block_p(matrix=rmatrix, row=irow, col=icol, &
    1211       529850 :                                    block=rblock, found=found)
    1212       529850 :             IF (.NOT. found) CYCLE
    1213    249444630 :             rblock = rblock + coskl*rsblock
    1214              :          ELSE
    1215              :             CALL dbcsr_get_block_p(matrix=rmatrix, row=irow, col=icol, &
    1216     99132524 :                                    block=rblock, found=found)
    1217     99132524 :             IF (.NOT. found) CYCLE
    1218              :             CALL dbcsr_get_block_p(matrix=cmatrix, row=irow, col=icol, &
    1219     99132524 :                                    block=cblock, found=found)
    1220     99132524 :             IF (.NOT. found) CYCLE
    1221  12152642924 :             rblock = rblock + coskl*rsblock
    1222  12152642924 :             cblock = cblock + sinkl*rsblock
    1223              :          END IF
    1224              : 
    1225              :       END DO
    1226       279058 :       CALL neighbor_list_iterator_release(nl_iterator)
    1227              : 
    1228       279058 :       CALL timestop(handle)
    1229              : 
    1230       279058 :    END SUBROUTINE rskp_transform
    1231              : 
    1232              : ! **************************************************************************************************
    1233              : !> \brief Given the eigenvalues of all kpoints, calculates the occupation numbers
    1234              : !> \param kpoint  Kpoint environment
    1235              : !> \param smear   Smearing information
    1236              : !> \param probe ...
    1237              : ! **************************************************************************************************
    1238        34396 :    SUBROUTINE kpoint_set_mo_occupation(kpoint, smear, probe)
    1239              : 
    1240              :       TYPE(kpoint_type), POINTER                         :: kpoint
    1241              :       TYPE(smear_type)                                   :: smear
    1242              :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
    1243              :          POINTER                                         :: probe
    1244              : 
    1245              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_set_mo_occupation'
    1246              : 
    1247              :       INTEGER                                            :: handle, ik, ikpgr, ispin, kplocal, nao, &
    1248              :                                                             nb, ncol_global, ne_a, ne_b, &
    1249              :                                                             nelectron, nkp, nmo, nrow_global, nspin
    1250              :       INTEGER, DIMENSION(2)                              :: kp_range
    1251              :       REAL(KIND=dp)                                      :: kTS, kTS_spin(2), mu, mus(2), nel
    1252        34396 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: smatrix
    1253        34396 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: weig, wocc
    1254        34396 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :)  :: icoeff, rcoeff
    1255        34396 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation, wkp
    1256              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1257              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1258              :       TYPE(mo_set_type), POINTER                         :: mo_set
    1259              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
    1260              : 
    1261        34396 :       CALL timeset(routineN, handle)
    1262              : 
    1263              :       ! first collect all the eigenvalues
    1264        34396 :       CALL get_kpoint_info(kpoint, nkp=nkp)
    1265        34396 :       kp => kpoint%kp_env(1)%kpoint_env
    1266        34396 :       nspin = SIZE(kp%mos, 2)
    1267        34396 :       mo_set => kp%mos(1, 1)
    1268        34396 :       CALL get_mo_set(mo_set, nmo=nmo, nao=nao, nelectron=nelectron)
    1269        34396 :       ne_a = nelectron
    1270        34396 :       IF (nspin == 2) THEN
    1271         1816 :          CALL get_mo_set(kp%mos(1, 2), nmo=nb, nelectron=ne_b)
    1272         1816 :          CPASSERT(nmo == nb)
    1273              :       END IF
    1274       275168 :       ALLOCATE (weig(nmo, nkp, nspin), wocc(nmo, nkp, nspin))
    1275        34396 :       weig = 0.0_dp
    1276        34396 :       wocc = 0.0_dp
    1277        34396 :       IF (PRESENT(probe)) THEN
    1278            0 :          ALLOCATE (rcoeff(nao, nmo, nkp, nspin), icoeff(nao, nmo, nkp, nspin))
    1279            0 :          rcoeff = 0.0_dp !coeff, real part
    1280            0 :          icoeff = 0.0_dp !coeff, imaginary part
    1281              :       END IF
    1282        34396 :       CALL get_kpoint_info(kpoint, kp_range=kp_range)
    1283        34396 :       kplocal = kp_range(2) - kp_range(1) + 1
    1284        99442 :       DO ikpgr = 1, kplocal
    1285        65046 :          ik = kp_range(1) + ikpgr - 1
    1286        65046 :          kp => kpoint%kp_env(ikpgr)%kpoint_env
    1287       170648 :          DO ispin = 1, nspin
    1288        71206 :             mo_set => kp%mos(1, ispin)
    1289        71206 :             CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
    1290      1374968 :             weig(1:nmo, ik, ispin) = eigenvalues(1:nmo)
    1291       136252 :             IF (PRESENT(probe)) THEN
    1292            0 :                CALL get_mo_set(mo_set, mo_coeff=mo_coeff)
    1293              :                CALL cp_fm_get_info(mo_coeff, &
    1294              :                                    nrow_global=nrow_global, &
    1295            0 :                                    ncol_global=ncol_global)
    1296            0 :                ALLOCATE (smatrix(nrow_global, ncol_global))
    1297            0 :                CALL cp_fm_get_submatrix(mo_coeff, smatrix)
    1298              : 
    1299            0 :                rcoeff(1:nao, 1:nmo, ik, ispin) = smatrix(1:nrow_global, 1:ncol_global)
    1300              : 
    1301            0 :                DEALLOCATE (smatrix)
    1302              : 
    1303            0 :                mo_set => kp%mos(2, ispin)
    1304              : 
    1305            0 :                CALL get_mo_set(mo_set, mo_coeff=mo_coeff)
    1306              :                CALL cp_fm_get_info(mo_coeff, &
    1307              :                                    nrow_global=nrow_global, &
    1308            0 :                                    ncol_global=ncol_global)
    1309            0 :                ALLOCATE (smatrix(nrow_global, ncol_global))
    1310            0 :                CALL cp_fm_get_submatrix(mo_coeff, smatrix)
    1311              : 
    1312            0 :                icoeff(1:nao, 1:nmo, ik, ispin) = smatrix(1:nrow_global, 1:ncol_global)
    1313              : 
    1314            0 :                mo_set => kp%mos(1, ispin)
    1315              : 
    1316            0 :                DEALLOCATE (smatrix)
    1317              :             END IF
    1318              :          END DO
    1319              :       END DO
    1320        34396 :       CALL get_kpoint_info(kpoint, para_env_inter_kp=para_env_inter_kp)
    1321        34396 :       CALL para_env_inter_kp%sum(weig)
    1322              : 
    1323        34396 :       IF (PRESENT(probe)) THEN
    1324            0 :          CALL para_env_inter_kp%sum(rcoeff)
    1325            0 :          CALL para_env_inter_kp%sum(icoeff)
    1326              :       END IF
    1327              : 
    1328        34396 :       CALL get_kpoint_info(kpoint, wkp=wkp)
    1329        34396 :       kTS_spin = 0.0_dp
    1330              : 
    1331              : !calling of HP module HERE, before smear
    1332        34396 :       IF (PRESENT(probe)) THEN
    1333            0 :          smear%do_smear = .FALSE. !ensures smearing is switched off
    1334              : 
    1335            0 :          IF (nspin == 1) THEN
    1336            0 :             nel = REAL(nelectron, KIND=dp)
    1337              :             CALL probe_occupancy_kp(wocc(:, :, :), mus(1), kTS, weig(:, :, :), rcoeff(:, :, :, :), icoeff(:, :, :, :), 2.0d0, &
    1338            0 :                                     probe, nel, wkp)
    1339              :          ELSE
    1340            0 :             nel = REAL(ne_a, KIND=dp) + REAL(ne_b, KIND=dp)
    1341              :             CALL probe_occupancy_kp(wocc(:, :, :), mu, kTS, weig(:, :, :), rcoeff(:, :, :, :), icoeff(:, :, :, :), 1.0d0, &
    1342            0 :                                     probe, nel, wkp)
    1343            0 :             kTS = kTS/2._dp
    1344            0 :             mus(1:2) = mu
    1345              :          END IF
    1346              : 
    1347            0 :          DO ikpgr = 1, kplocal
    1348            0 :             ik = kp_range(1) + ikpgr - 1
    1349            0 :             kp => kpoint%kp_env(ikpgr)%kpoint_env
    1350            0 :             DO ispin = 1, nspin
    1351            0 :                mo_set => kp%mos(1, ispin)
    1352            0 :                CALL get_mo_set(mo_set, eigenvalues=eigenvalues, occupation_numbers=occupation)
    1353            0 :                eigenvalues(1:nmo) = weig(1:nmo, ik, ispin)
    1354            0 :                occupation(1:nmo) = wocc(1:nmo, ik, ispin)
    1355            0 :                mo_set%kTS = kTS
    1356            0 :                mo_set%mu = mus(ispin)
    1357              : 
    1358            0 :                CALL get_mo_set(mo_set, mo_coeff=mo_coeff)
    1359              :                !get smatrix for kpoint_env ikp
    1360              :                CALL cp_fm_get_info(mo_coeff, &
    1361              :                                    nrow_global=nrow_global, &
    1362            0 :                                    ncol_global=ncol_global)
    1363            0 :                ALLOCATE (smatrix(nrow_global, ncol_global))
    1364            0 :                CALL cp_fm_get_submatrix(mo_coeff, smatrix)
    1365              : 
    1366            0 :                smatrix(1:nrow_global, 1:ncol_global) = rcoeff(1:nao, 1:nmo, ik, ispin)
    1367            0 :                DEALLOCATE (smatrix)
    1368              : 
    1369            0 :                mo_set => kp%mos(2, ispin)
    1370              : 
    1371            0 :                CALL get_mo_set(mo_set, mo_coeff=mo_coeff)
    1372              :                !get smatrix for kpoint_env ikp
    1373              :                CALL cp_fm_get_info(mo_coeff, &
    1374              :                                    nrow_global=nrow_global, &
    1375            0 :                                    ncol_global=ncol_global)
    1376            0 :                ALLOCATE (smatrix(nrow_global, ncol_global))
    1377            0 :                CALL cp_fm_get_submatrix(mo_coeff, smatrix)
    1378              : 
    1379            0 :                smatrix(1:nrow_global, 1:ncol_global) = icoeff(1:nao, 1:nmo, ik, ispin)
    1380            0 :                DEALLOCATE (smatrix)
    1381              : 
    1382            0 :                mo_set => kp%mos(1, ispin)
    1383              : 
    1384              :             END DO
    1385              :          END DO
    1386              : 
    1387            0 :          DEALLOCATE (weig, wocc, rcoeff, icoeff)
    1388              : 
    1389              :       END IF
    1390              : 
    1391              :       IF (PRESENT(probe) .EQV. .FALSE.) THEN
    1392        34396 :          IF (smear%do_smear) THEN
    1393        26896 :             SELECT CASE (smear%method)
    1394              :             CASE (smear_fermi_dirac)
    1395              :                ! finite electronic temperature
    1396        13384 :                IF (nspin == 1) THEN
    1397        12944 :                   nel = REAL(nelectron, KIND=dp)
    1398              :                   CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1399        12944 :                                smear%electronic_temperature, 2.0_dp, smear_fermi_dirac)
    1400        12944 :                   kTS_spin(1) = kTS
    1401          440 :                ELSE IF (smear%fixed_mag_mom > 0.0_dp) THEN
    1402            0 :                   nel = REAL(ne_a, KIND=dp)
    1403              :                   CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1404            0 :                                smear%electronic_temperature, 1.0_dp, smear_fermi_dirac)
    1405            0 :                   kTS_spin(1) = kTS
    1406            0 :                   nel = REAL(ne_b, KIND=dp)
    1407              :                   CALL Smearkp(wocc(:, :, 2), mus(2), kTS, weig(:, :, 2), nel, wkp, &
    1408            0 :                                smear%electronic_temperature, 1.0_dp, smear_fermi_dirac)
    1409            0 :                   kTS_spin(2) = kTS
    1410              :                ELSE
    1411          440 :                   nel = REAL(ne_a, KIND=dp) + REAL(ne_b, KIND=dp)
    1412              :                   CALL Smearkp2(wocc(:, :, :), mu, kTS, weig(:, :, :), nel, wkp, &
    1413          440 :                                 smear%electronic_temperature, smear_fermi_dirac)
    1414          440 :                   kTS = kTS/2._dp
    1415         1320 :                   kTS_spin(1:2) = kTS
    1416         1320 :                   mus(1:2) = mu
    1417              :                END IF
    1418              :             CASE (smear_gaussian, smear_mp, smear_mv)
    1419          128 :                IF (nspin == 1) THEN
    1420           96 :                   nel = REAL(nelectron, KIND=dp)
    1421              :                   CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1422           96 :                                smear%smearing_width, 2.0_dp, smear%method)
    1423           96 :                   kTS_spin(1) = kTS
    1424           32 :                ELSE IF (smear%fixed_mag_mom > 0.0_dp) THEN
    1425            0 :                   nel = REAL(ne_a, KIND=dp)
    1426              :                   CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1427            0 :                                smear%smearing_width, 1.0_dp, smear%method)
    1428            0 :                   kTS_spin(1) = kTS
    1429            0 :                   nel = REAL(ne_b, KIND=dp)
    1430              :                   CALL Smearkp(wocc(:, :, 2), mus(2), kTS, weig(:, :, 2), nel, wkp, &
    1431            0 :                                smear%smearing_width, 1.0_dp, smear%method)
    1432            0 :                   kTS_spin(2) = kTS
    1433              :                ELSE
    1434           32 :                   nel = REAL(ne_a, KIND=dp) + REAL(ne_b, KIND=dp)
    1435              :                   CALL Smearkp2(wocc(:, :, :), mu, kTS, weig(:, :, :), nel, wkp, &
    1436           32 :                                 smear%smearing_width, smear%method)
    1437           32 :                   kTS = kTS/2._dp
    1438           96 :                   kTS_spin(1:2) = kTS
    1439           96 :                   mus(1:2) = mu
    1440              :                END IF
    1441              :             CASE DEFAULT
    1442        13512 :                CPABORT("kpoints: Selected smearing not (yet) supported")
    1443              :             END SELECT
    1444              :          ELSE
    1445              :             ! fixed occupations (2/1)
    1446        20884 :             IF (nspin == 1) THEN
    1447        19540 :                nel = REAL(nelectron, KIND=dp)
    1448              :                CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1449        19540 :                             0.0_dp, 2.0_dp, smear_gaussian)
    1450        19540 :                kTS_spin(1) = kTS
    1451              :             ELSE
    1452         1344 :                nel = REAL(ne_a, KIND=dp)
    1453              :                CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1454         1344 :                             0.0_dp, 1.0_dp, smear_gaussian)
    1455         1344 :                kTS_spin(1) = kTS
    1456         1344 :                nel = REAL(ne_b, KIND=dp)
    1457              :                CALL Smearkp(wocc(:, :, 2), mus(2), kTS, weig(:, :, 2), nel, wkp, &
    1458         1344 :                             0.0_dp, 1.0_dp, smear_gaussian)
    1459         1344 :                kTS_spin(2) = kTS
    1460              :             END IF
    1461              :          END IF
    1462        99442 :          DO ikpgr = 1, kplocal
    1463        65046 :             ik = kp_range(1) + ikpgr - 1
    1464        65046 :             kp => kpoint%kp_env(ikpgr)%kpoint_env
    1465       170648 :             DO ispin = 1, nspin
    1466        71206 :                mo_set => kp%mos(1, ispin)
    1467        71206 :                CALL get_mo_set(mo_set, eigenvalues=eigenvalues, occupation_numbers=occupation)
    1468      1374968 :                eigenvalues(1:nmo) = weig(1:nmo, ik, ispin)
    1469      1374968 :                occupation(1:nmo) = wocc(1:nmo, ik, ispin)
    1470        71206 :                mo_set%kTS = kTS_spin(ispin)
    1471       136252 :                mo_set%mu = mus(ispin)
    1472              :             END DO
    1473              :          END DO
    1474              : 
    1475        34396 :          DEALLOCATE (weig, wocc)
    1476              : 
    1477              :       END IF
    1478              : 
    1479        34396 :       CALL timestop(handle)
    1480              : 
    1481       103188 :    END SUBROUTINE kpoint_set_mo_occupation
    1482              : 
    1483              : ! **************************************************************************************************
    1484              : !> \brief Calculate kpoint density matrices (rho(k), owned by kpoint groups)
    1485              : !> \param kpoint    kpoint environment
    1486              : !> \param energy_weighted  calculate energy weighted density matrix
    1487              : !> \param for_aux_fit ...
    1488              : ! **************************************************************************************************
    1489       104952 :    SUBROUTINE kpoint_density_matrices(kpoint, energy_weighted, for_aux_fit)
    1490              : 
    1491              :       TYPE(kpoint_type), POINTER                         :: kpoint
    1492              :       LOGICAL, OPTIONAL                                  :: energy_weighted, for_aux_fit
    1493              : 
    1494              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_density_matrices'
    1495              : 
    1496              :       INTEGER                                            :: handle, ikpgr, ispin, kplocal, nao, nmo, &
    1497              :                                                             nspin
    1498              :       INTEGER, DIMENSION(2)                              :: kp_range
    1499              :       LOGICAL                                            :: aux_fit, wtype
    1500        34984 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation
    1501              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1502              :       TYPE(cp_fm_type)                                   :: fwork
    1503              :       TYPE(cp_fm_type), POINTER                          :: cpmat, pmat, rpmat
    1504              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1505              :       TYPE(mo_set_type), POINTER                         :: mo_set
    1506              : 
    1507        34984 :       CALL timeset(routineN, handle)
    1508              : 
    1509        34984 :       IF (PRESENT(energy_weighted)) THEN
    1510          448 :          wtype = energy_weighted
    1511              :       ELSE
    1512              :          ! default is normal density matrix
    1513              :          wtype = .FALSE.
    1514              :       END IF
    1515              : 
    1516        34984 :       IF (PRESENT(for_aux_fit)) THEN
    1517          124 :          aux_fit = for_aux_fit
    1518              :       ELSE
    1519              :          aux_fit = .FALSE.
    1520              :       END IF
    1521              : 
    1522          124 :       IF (aux_fit) THEN
    1523          124 :          CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
    1524              :       END IF
    1525              : 
    1526              :       ! work matrix
    1527        34984 :       IF (aux_fit) THEN
    1528          124 :          mo_set => kpoint%kp_aux_env(1)%kpoint_env%mos(1, 1)
    1529              :       ELSE
    1530        34860 :          mo_set => kpoint%kp_env(1)%kpoint_env%mos(1, 1)
    1531              :       END IF
    1532        34984 :       CALL get_mo_set(mo_set, nao=nao, nmo=nmo)
    1533        34984 :       CALL cp_fm_get_info(mo_set%mo_coeff, matrix_struct=matrix_struct)
    1534        34984 :       CALL cp_fm_create(fwork, matrix_struct)
    1535              : 
    1536        34984 :       CALL get_kpoint_info(kpoint, kp_range=kp_range)
    1537        34984 :       kplocal = kp_range(2) - kp_range(1) + 1
    1538       103404 :       DO ikpgr = 1, kplocal
    1539        68420 :          IF (aux_fit) THEN
    1540         1876 :             kp => kpoint%kp_aux_env(ikpgr)%kpoint_env
    1541              :          ELSE
    1542        66544 :             kp => kpoint%kp_env(ikpgr)%kpoint_env
    1543              :          END IF
    1544        68420 :          nspin = SIZE(kp%mos, 2)
    1545       178260 :          DO ispin = 1, nspin
    1546        74856 :             mo_set => kp%mos(1, ispin)
    1547        74856 :             IF (wtype) THEN
    1548         1546 :                CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
    1549              :             END IF
    1550       143276 :             IF (kpoint%use_real_wfn) THEN
    1551          168 :                IF (wtype) THEN
    1552           12 :                   pmat => kp%wmat(1, ispin)
    1553              :                ELSE
    1554          156 :                   pmat => kp%pmat(1, ispin)
    1555              :                END IF
    1556          168 :                CALL get_mo_set(mo_set, occupation_numbers=occupation)
    1557          168 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1558          168 :                CALL cp_fm_column_scale(fwork, occupation)
    1559          168 :                IF (wtype) THEN
    1560           12 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1561              :                END IF
    1562          168 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, pmat)
    1563              :             ELSE
    1564        74688 :                IF (wtype) THEN
    1565         1534 :                   rpmat => kp%wmat(1, ispin)
    1566         1534 :                   cpmat => kp%wmat(2, ispin)
    1567              :                ELSE
    1568        73154 :                   rpmat => kp%pmat(1, ispin)
    1569        73154 :                   cpmat => kp%pmat(2, ispin)
    1570              :                END IF
    1571        74688 :                CALL get_mo_set(mo_set, occupation_numbers=occupation)
    1572        74688 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1573        74688 :                CALL cp_fm_column_scale(fwork, occupation)
    1574        74688 :                IF (wtype) THEN
    1575         1534 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1576              :                END IF
    1577              :                ! Re(c)*Re(c)
    1578        74688 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, rpmat)
    1579        74688 :                mo_set => kp%mos(2, ispin)
    1580              :                ! Im(c)*Re(c)
    1581        74688 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, cpmat)
    1582              :                ! Re(c)*Im(c)
    1583        74688 :                CALL parallel_gemm("N", "T", nao, nao, nmo, -1.0_dp, fwork, mo_set%mo_coeff, 1.0_dp, cpmat)
    1584        74688 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1585        74688 :                CALL cp_fm_column_scale(fwork, occupation)
    1586        74688 :                IF (wtype) THEN
    1587         1534 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1588              :                END IF
    1589              :                ! Im(c)*Im(c)
    1590        74688 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 1.0_dp, rpmat)
    1591              :             END IF
    1592              :          END DO
    1593              :       END DO
    1594              : 
    1595        34984 :       CALL cp_fm_release(fwork)
    1596              : 
    1597        34984 :       CALL timestop(handle)
    1598              : 
    1599        34984 :    END SUBROUTINE kpoint_density_matrices
    1600              : 
    1601              : ! **************************************************************************************************
    1602              : !> \brief Calculate Lowdin transformation of density matrix S^1/2 P S^1/2
    1603              : !>        Integrate diagonal elements over k-points to get Lowdin charges
    1604              : !> \param kpoint    kpoint environment
    1605              : !> \param pmat_diag Sum over kpoints of diagonal elements
    1606              : !> \par History
    1607              : !>      04.2026 created [JGH]
    1608              : ! **************************************************************************************************
    1609            6 :    SUBROUTINE lowdin_kp_trans(kpoint, pmat_diag)
    1610              : 
    1611              :       TYPE(kpoint_type), POINTER                         :: kpoint
    1612              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: pmat_diag
    1613              : 
    1614              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'lowdin_kp_trans'
    1615              :       COMPLEX(KIND=dp), PARAMETER                        :: cone = (1.0_dp, 0.0_dp), &
    1616              :                                                             czero = (0.0_dp, 0.0_dp)
    1617              : 
    1618              :       INTEGER                                            :: handle, ikpgr, ispin, kplocal, nao, nspin
    1619              :       INTEGER, DIMENSION(2)                              :: kp_range
    1620            6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: dele
    1621              :       TYPE(cp_cfm_type)                                  :: cf1work, cf2work
    1622              :       TYPE(cp_cfm_type), POINTER                         :: cshalf
    1623              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1624              :       TYPE(cp_fm_type)                                   :: f1work, f2work
    1625              :       TYPE(cp_fm_type), POINTER                          :: cpmat, pmat, rpmat, shalf
    1626              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1627              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
    1628              : 
    1629            6 :       CALL timeset(routineN, handle)
    1630              : 
    1631            6 :       nspin = SIZE(pmat_diag, 2)
    1632          336 :       pmat_diag = 0.0_dp
    1633              : 
    1634              :       ! work matrix
    1635              :       CALL cp_fm_get_info(kpoint%kp_env(1)%kpoint_env%pmat(1, 1), &
    1636            6 :                           matrix_struct=matrix_struct, nrow_global=nao)
    1637            6 :       IF (kpoint%use_real_wfn) THEN
    1638            0 :          CALL cp_fm_create(f1work, matrix_struct, nrow=nao, ncol=nao)
    1639            0 :          CALL cp_fm_create(f2work, matrix_struct, nrow=nao, ncol=nao)
    1640              :       ELSE
    1641            6 :          CALL cp_fm_create(f2work, matrix_struct, nrow=nao, ncol=nao)
    1642            6 :          CALL cp_cfm_create(cf1work, matrix_struct, nrow=nao, ncol=nao)
    1643            6 :          CALL cp_cfm_create(cf2work, matrix_struct, nrow=nao, ncol=nao)
    1644              :       END IF
    1645           18 :       ALLOCATE (dele(nao))
    1646              : 
    1647            6 :       CALL get_kpoint_info(kpoint, kp_range=kp_range)
    1648            6 :       kplocal = kp_range(2) - kp_range(1) + 1
    1649          238 :       DO ikpgr = 1, kplocal
    1650          232 :          kp => kpoint%kp_env(ikpgr)%kpoint_env
    1651          486 :          DO ispin = 1, nspin
    1652          248 :             IF (kpoint%use_real_wfn) THEN
    1653            0 :                pmat => kp%pmat(1, ispin)
    1654            0 :                shalf => kp%shalf
    1655            0 :                CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, pmat, shalf, 0.0_dp, f1work)
    1656            0 :                CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, shalf, f1work, 0.0_dp, f2work)
    1657              :             ELSE
    1658          248 :                rpmat => kp%pmat(1, ispin)
    1659          248 :                cpmat => kp%pmat(2, ispin)
    1660          248 :                cshalf => kp%cshalf
    1661          248 :                CALL cp_fm_to_cfm(rpmat, cpmat, cf1work)
    1662          248 :                CALL parallel_gemm("N", "N", nao, nao, nao, cone, cf1work, cshalf, czero, cf2work)
    1663          248 :                CALL parallel_gemm("N", "N", nao, nao, nao, cone, cshalf, cf2work, czero, cf1work)
    1664          248 :                CALL cp_cfm_to_fm(cf1work, mtargetr=f2work)
    1665              :             END IF
    1666          248 :             CALL cp_fm_get_diag(f2work, dele)
    1667         2592 :             pmat_diag(1:nao, ispin) = pmat_diag(1:nao, ispin) + kp%wkp*dele(1:nao)
    1668              :          END DO
    1669              :       END DO
    1670              : 
    1671            6 :       CALL get_kpoint_info(kpoint, para_env_inter_kp=para_env_inter_kp)
    1672          666 :       CALL para_env_inter_kp%sum(pmat_diag)
    1673              : 
    1674            6 :       IF (kpoint%use_real_wfn) THEN
    1675            0 :          CALL cp_fm_release(f1work)
    1676            0 :          CALL cp_fm_release(f2work)
    1677              :       ELSE
    1678            6 :          CALL cp_fm_release(f2work)
    1679            6 :          CALL cp_cfm_release(cf1work)
    1680            6 :          CALL cp_cfm_release(cf2work)
    1681              :       END IF
    1682            6 :       DEALLOCATE (dele)
    1683              : 
    1684            6 :       CALL timestop(handle)
    1685              : 
    1686           12 :    END SUBROUTINE lowdin_kp_trans
    1687              : 
    1688              : ! **************************************************************************************************
    1689              : !> \brief Calculate S(k)^1/2 C(k) for real or complex k-point wavefunctions
    1690              : !> \param kp           K-point environment for one local k point
    1691              : !> \param ispin        Spin index
    1692              : !> \param use_real_wfn Use real k-point wavefunctions
    1693              : !> \param shalfc       Output matrix containing S(k)^1/2 C(k) for real wavefunctions
    1694              : !> \param cshalfc      Output matrix containing S(k)^1/2 C(k) for complex wavefunctions
    1695              : ! **************************************************************************************************
    1696            0 :    SUBROUTINE lowdin_kp_mo_coeff(kp, ispin, use_real_wfn, shalfc, cshalfc)
    1697              : 
    1698              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1699              :       INTEGER, INTENT(IN)                                :: ispin
    1700              :       LOGICAL, INTENT(IN)                                :: use_real_wfn
    1701              :       TYPE(cp_fm_type), INTENT(INOUT), OPTIONAL          :: shalfc
    1702              :       TYPE(cp_cfm_type), INTENT(INOUT), OPTIONAL         :: cshalfc
    1703              : 
    1704              :       INTEGER                                            :: nao, nmo
    1705              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct_mo, matrix_struct_shalf
    1706              :       TYPE(cp_fm_type)                                   :: cshalf_im, cshalf_re, shalf_im, shalf_re
    1707              :       TYPE(mo_set_type), POINTER                         :: mo_set, mo_set_im, mo_set_re
    1708              : 
    1709            0 :       IF (use_real_wfn) THEN
    1710            0 :          CPASSERT(PRESENT(shalfc))
    1711            0 :          mo_set => kp%mos(1, ispin)
    1712            0 :          CALL get_mo_set(mo_set, nao=nao, nmo=nmo)
    1713              : 
    1714              :          CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, kp%shalf, &
    1715            0 :                             mo_set%mo_coeff, 0.0_dp, shalfc)
    1716              :       ELSE
    1717            0 :          CPASSERT(PRESENT(cshalfc))
    1718            0 :          mo_set_re => kp%mos(1, ispin)
    1719            0 :          mo_set_im => kp%mos(2, ispin)
    1720            0 :          CALL get_mo_set(mo_set_re, nao=nao, nmo=nmo)
    1721            0 :          CALL cp_fm_get_info(mo_set_re%mo_coeff, matrix_struct=matrix_struct_mo)
    1722            0 :          CALL cp_cfm_get_info(kp%cshalf, matrix_struct=matrix_struct_shalf)
    1723              : 
    1724            0 :          CALL cp_fm_create(shalf_re, matrix_struct_shalf, nrow=nao, ncol=nao)
    1725            0 :          CALL cp_fm_create(shalf_im, matrix_struct_shalf, nrow=nao, ncol=nao)
    1726            0 :          CALL cp_fm_create(cshalf_re, matrix_struct_mo, nrow=nao, ncol=nmo)
    1727            0 :          CALL cp_fm_create(cshalf_im, matrix_struct_mo, nrow=nao, ncol=nmo)
    1728              : 
    1729            0 :          CALL cp_cfm_to_fm(kp%cshalf, mtargetr=shalf_re, mtargeti=shalf_im)
    1730              : 
    1731              :          ! Re[S(k)^1/2 C(k)] = Re[S(k)^1/2] C_re(k) - Im[S(k)^1/2] C_im(k)
    1732              :          CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, shalf_re, &
    1733            0 :                             mo_set_re%mo_coeff, 0.0_dp, cshalf_re)
    1734              :          CALL parallel_gemm("N", "N", nao, nmo, nao, -1.0_dp, shalf_im, &
    1735            0 :                             mo_set_im%mo_coeff, 1.0_dp, cshalf_re)
    1736              : 
    1737              :          ! Im[S(k)^1/2 C(k)] = Re[S(k)^1/2] C_im(k) + Im[S(k)^1/2] C_re(k)
    1738              :          CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, shalf_re, &
    1739            0 :                             mo_set_im%mo_coeff, 0.0_dp, cshalf_im)
    1740              :          CALL parallel_gemm("N", "N", nao, nmo, nao, 1.0_dp, shalf_im, &
    1741            0 :                             mo_set_re%mo_coeff, 1.0_dp, cshalf_im)
    1742              : 
    1743            0 :          CALL cp_fm_to_cfm(cshalf_re, cshalf_im, cshalfc)
    1744              : 
    1745            0 :          CALL cp_fm_release(shalf_re)
    1746            0 :          CALL cp_fm_release(shalf_im)
    1747            0 :          CALL cp_fm_release(cshalf_re)
    1748            0 :          CALL cp_fm_release(cshalf_im)
    1749              :       END IF
    1750              : 
    1751            0 :    END SUBROUTINE lowdin_kp_mo_coeff
    1752              : 
    1753              : ! **************************************************************************************************
    1754              : !> \brief generate real space density matrices in DBCSR format
    1755              : !> \param kpoint  Kpoint environment
    1756              : !> \param denmat  Real space (DBCSR) density matrices
    1757              : !> \param wtype   True = energy weighted density matrix
    1758              : !>                False = normal density matrix
    1759              : !> \param tempmat DBCSR matrix to be used as template
    1760              : !> \param sab_nl ...
    1761              : !> \param fmwork  FM work matrices (kpoint group)
    1762              : !> \param for_aux_fit ...
    1763              : !> \param pmat_ext ...
    1764              : !> \param overlap_rs ...
    1765              : ! **************************************************************************************************
    1766        35232 :    SUBROUTINE kpoint_density_transform(kpoint, denmat, wtype, tempmat, sab_nl, fmwork, for_aux_fit, &
    1767        35232 :                                        pmat_ext, overlap_rs)
    1768              : 
    1769              :       TYPE(kpoint_type), POINTER                         :: kpoint
    1770              :       TYPE(dbcsr_p_type), DIMENSION(:, :)                :: denmat
    1771              :       LOGICAL, INTENT(IN)                                :: wtype
    1772              :       TYPE(dbcsr_type), POINTER                          :: tempmat
    1773              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1774              :          POINTER                                         :: sab_nl
    1775              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fmwork
    1776              :       LOGICAL, OPTIONAL                                  :: for_aux_fit
    1777              :       TYPE(cp_fm_type), DIMENSION(:, :, :), INTENT(IN), &
    1778              :          OPTIONAL                                        :: pmat_ext
    1779              :       TYPE(dbcsr_p_type), DIMENSION(:, :), OPTIONAL, &
    1780              :          POINTER                                         :: overlap_rs
    1781              : 
    1782              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_density_transform'
    1783              : 
    1784              :       INTEGER                                            :: handle, ic, ik, ikk, indx, ir, ira, is, &
    1785              :                                                             ispin, jr, nc, nimg, nkp, nspin
    1786        35232 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1787              :       LOGICAL                                            :: aux_fit, do_ext, do_symmetric, my_kpgrp, &
    1788              :                                                             real_only, reverse_phase
    1789              :       REAL(KIND=dp)                                      :: wkpx
    1790        35232 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    1791        35232 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1792        35232 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:)    :: info
    1793              :       TYPE(cp_fm_type)                                   :: fmdummy
    1794              :       TYPE(dbcsr_type), POINTER                          :: cpmat, rpmat, scpmat, srpmat
    1795        35232 :       TYPE(kind_rotmat_type), DIMENSION(:), POINTER      :: kind_rot
    1796              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1797              :       TYPE(kpoint_sym_type), POINTER                     :: kpsym
    1798              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1799              : 
    1800        35232 :       CALL timeset(routineN, handle)
    1801              : 
    1802        35232 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    1803              : 
    1804        35232 :       IF (PRESENT(for_aux_fit)) THEN
    1805          372 :          aux_fit = for_aux_fit
    1806              :       ELSE
    1807              :          aux_fit = .FALSE.
    1808              :       END IF
    1809              : 
    1810        35232 :       do_ext = .FALSE.
    1811        35232 :       IF (PRESENT(pmat_ext)) do_ext = .TRUE.
    1812              : 
    1813        35232 :       IF (aux_fit) THEN
    1814          216 :          CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
    1815              :       END IF
    1816              : 
    1817              :       ! work storage
    1818        35232 :       ALLOCATE (rpmat)
    1819              :       CALL dbcsr_create(rpmat, template=tempmat, &
    1820        35292 :                         matrix_type=MERGE(dbcsr_type_symmetric, dbcsr_type_no_symmetry, do_symmetric))
    1821        35232 :       CALL cp_dbcsr_alloc_block_from_nbl(rpmat, sab_nl)
    1822        35232 :       CALL dbcsr_set(rpmat, 0.0_dp)
    1823        35232 :       ALLOCATE (cpmat)
    1824              :       CALL dbcsr_create(cpmat, template=tempmat, &
    1825        35292 :                         matrix_type=MERGE(dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, do_symmetric))
    1826        35232 :       CALL cp_dbcsr_alloc_block_from_nbl(cpmat, sab_nl)
    1827        35232 :       CALL dbcsr_set(cpmat, 0.0_dp)
    1828        35232 :       IF (.NOT. kpoint%full_grid) THEN
    1829        32074 :          ALLOCATE (srpmat)
    1830        32074 :          CALL dbcsr_create(srpmat, template=rpmat)
    1831        32074 :          CALL cp_dbcsr_alloc_block_from_nbl(srpmat, sab_nl)
    1832        32074 :          CALL dbcsr_set(srpmat, 0.0_dp)
    1833        32074 :          ALLOCATE (scpmat)
    1834        32074 :          CALL dbcsr_create(scpmat, template=cpmat)
    1835        32074 :          CALL cp_dbcsr_alloc_block_from_nbl(scpmat, sab_nl)
    1836        32074 :          CALL dbcsr_set(scpmat, 0.0_dp)
    1837              :       END IF
    1838              : 
    1839              :       CALL get_kpoint_info(kpoint, nkp=nkp, xkp=xkp, wkp=wkp, &
    1840        35232 :                            cell_to_index=cell_to_index)
    1841        35232 :       IF (PRESENT(overlap_rs)) THEN
    1842        33974 :          CALL calibrate_symmetry_phases(kpoint, overlap_rs, tempmat, sab_nl, cell_to_index)
    1843              :       END IF
    1844              :       ! initialize real space density matrices
    1845        35232 :       IF (aux_fit) THEN
    1846          216 :          kp => kpoint%kp_aux_env(1)%kpoint_env
    1847              :       ELSE
    1848        35016 :          kp => kpoint%kp_env(1)%kpoint_env
    1849              :       END IF
    1850        35232 :       nspin = SIZE(kp%mos, 2)
    1851        35232 :       nc = SIZE(kp%mos, 1)
    1852        35232 :       nimg = SIZE(denmat, 2)
    1853        35232 :       real_only = (nc == 1)
    1854              : 
    1855        35232 :       para_env => kpoint%blacs_env_all%para_env
    1856       633812 :       ALLOCATE (info(nspin*nkp*nc))
    1857              : 
    1858              :       ! Start all the communication
    1859        35232 :       indx = 0
    1860        72370 :       DO ispin = 1, nspin
    1861      1746098 :          DO ic = 1, nimg
    1862      1746098 :             CALL dbcsr_set(denmat(ispin, ic)%matrix, 0.0_dp)
    1863              :          END DO
    1864              :          !
    1865       195584 :          DO ik = 1, nkp
    1866       123214 :             my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
    1867              :             IF (my_kpgrp) THEN
    1868        77836 :                ikk = ik - kpoint%kp_range(1) + 1
    1869        77836 :                IF (aux_fit) THEN
    1870         2714 :                   kp => kpoint%kp_aux_env(ikk)%kpoint_env
    1871              :                ELSE
    1872        75122 :                   kp => kpoint%kp_env(ikk)%kpoint_env
    1873              :                END IF
    1874              :             ELSE
    1875              :                NULLIFY (kp)
    1876              :             END IF
    1877              :             ! collect this density matrix on all processors
    1878       123214 :             CPASSERT(SIZE(fmwork) >= nc)
    1879              : 
    1880       160352 :             IF (my_kpgrp) THEN
    1881       233340 :                DO ic = 1, nc
    1882       155504 :                   indx = indx + 1
    1883       233340 :                   IF (do_ext) THEN
    1884         5428 :                      CALL cp_fm_start_copy_general(pmat_ext(ikk, ic, ispin), fmwork(ic), para_env, info(indx))
    1885              :                   ELSE
    1886       150076 :                      IF (wtype) THEN
    1887         3080 :                         CALL cp_fm_start_copy_general(kp%wmat(ic, ispin), fmwork(ic), para_env, info(indx))
    1888              :                      ELSE
    1889       146996 :                         CALL cp_fm_start_copy_general(kp%pmat(ic, ispin), fmwork(ic), para_env, info(indx))
    1890              :                      END IF
    1891              :                   END IF
    1892              :                END DO
    1893              :             ELSE
    1894       136134 :                DO ic = 1, nc
    1895        90756 :                   indx = indx + 1
    1896       136134 :                   CALL cp_fm_start_copy_general(fmdummy, fmwork(ic), para_env, info(indx))
    1897              :                END DO
    1898              :             END IF
    1899              :          END DO
    1900              :       END DO
    1901              : 
    1902              :       ! Finish communication and transform the received matrices
    1903        35232 :       indx = 0
    1904        72370 :       DO ispin = 1, nspin
    1905       195584 :          DO ik = 1, nkp
    1906       369474 :             DO ic = 1, nc
    1907       246260 :                indx = indx + 1
    1908       369474 :                CALL cp_fm_finish_copy_general(fmwork(ic), info(indx))
    1909              :             END DO
    1910              : 
    1911              :             ! reduce to dbcsr storage
    1912       123214 :             IF (real_only) THEN
    1913          168 :                CALL copy_fm_to_dbcsr(fmwork(1), rpmat, keep_sparsity=.TRUE.)
    1914              :             ELSE
    1915       123046 :                CALL copy_fm_to_dbcsr(fmwork(1), rpmat, keep_sparsity=.TRUE.)
    1916       123046 :                CALL copy_fm_to_dbcsr(fmwork(2), cpmat, keep_sparsity=.TRUE.)
    1917              :             END IF
    1918              : 
    1919              :             ! symmetrization
    1920       123214 :             kpsym => kpoint%kp_sym(ik)%kpoint_sym
    1921       123214 :             CPASSERT(ASSOCIATED(kpsym))
    1922              : 
    1923       160352 :             IF (kpsym%apply_symmetry) THEN
    1924        26370 :                wkpx = wkp(ik)/REAL(kpsym%nwght, KIND=dp)
    1925       124318 :                DO is = 1, kpsym%nwght
    1926        97948 :                   ir = ABS(kpsym%rotp(is))
    1927        97948 :                   ira = 0
    1928      1645808 :                   DO jr = 1, SIZE(kpoint%ibrot)
    1929      1645808 :                      IF (ir == kpoint%ibrot(jr)) ira = jr
    1930              :                   END DO
    1931        97948 :                   CPASSERT(ira > 0)
    1932        97948 :                   kind_rot => kpoint%kind_rotmat(ira, :)
    1933        97948 :                   CPASSERT(kpsym%phase_mode(is) > 0)
    1934        97948 :                   reverse_phase = kpsym%phase_mode(is) == 2
    1935              :                   CALL symtrans_phase(srpmat, scpmat, rpmat, cpmat, real_only, kind_rot, &
    1936              :                                       kpsym%rot(1:3, 1:3, is), kpsym%f0(:, is), &
    1937              :                                       kpsym%fcell_gauge(:, :, is), kpoint%atype, &
    1938        97948 :                                       kpsym%xkp(1:3, is), kpsym%rotp(is) < 0, reverse_phase)
    1939              :                   CALL transform_dmat(denmat, srpmat, scpmat, ispin, real_only, sab_nl, &
    1940       124318 :                                       cell_to_index, kpsym%xkp(1:3, is), wkpx)
    1941              :                END DO
    1942              :             ELSE
    1943              :                ! transformation
    1944              :                CALL transform_dmat(denmat, rpmat, cpmat, ispin, real_only, sab_nl, &
    1945        96844 :                                    cell_to_index, xkp(1:3, ik), wkp(ik))
    1946              :             END IF
    1947              :          END DO
    1948              :       END DO
    1949              : 
    1950              :       ! Clean up communication
    1951        35232 :       indx = 0
    1952        72370 :       DO ispin = 1, nspin
    1953       195584 :          DO ik = 1, nkp
    1954       123214 :             my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
    1955        37138 :             IF (my_kpgrp) THEN
    1956       233340 :                ikk = ik - kpoint%kp_range(1) + 1
    1957              :                IF (aux_fit) THEN
    1958       233340 :                   kp => kpoint%kp_aux_env(ikk)%kpoint_env
    1959              :                ELSE
    1960       233340 :                   kp => kpoint%kp_env(ikk)%kpoint_env
    1961              :                END IF
    1962              : 
    1963       233340 :                DO ic = 1, nc
    1964       155504 :                   indx = indx + 1
    1965       233340 :                   CALL cp_fm_cleanup_copy_general(info(indx))
    1966              :                END DO
    1967              :             ELSE
    1968              :                ! calls with dummy arguments, so not included
    1969              :                ! therefore just increment counter by trip count
    1970        45378 :                indx = indx + nc
    1971              :             END IF
    1972              :          END DO
    1973              :       END DO
    1974              : 
    1975              :       ! All done
    1976       281492 :       DEALLOCATE (info)
    1977              : 
    1978        35232 :       CALL dbcsr_deallocate_matrix(rpmat)
    1979        35232 :       CALL dbcsr_deallocate_matrix(cpmat)
    1980        35232 :       IF (.NOT. kpoint%full_grid) THEN
    1981        32074 :          CALL dbcsr_deallocate_matrix(srpmat)
    1982        32074 :          CALL dbcsr_deallocate_matrix(scpmat)
    1983              :       END IF
    1984              : 
    1985        35232 :       CALL timestop(handle)
    1986              : 
    1987        35232 :    END SUBROUTINE kpoint_density_transform
    1988              : 
    1989              : ! **************************************************************************************************
    1990              : !> \brief real space density matrices in DBCSR format
    1991              : !> \param denmat  Real space (DBCSR) density matrix
    1992              : !> \param rpmat ...
    1993              : !> \param cpmat ...
    1994              : !> \param ispin ...
    1995              : !> \param real_only ...
    1996              : !> \param sab_nl ...
    1997              : !> \param cell_to_index ...
    1998              : !> \param xkp ...
    1999              : !> \param wkp ...
    2000              : ! **************************************************************************************************
    2001       194792 :    SUBROUTINE transform_dmat(denmat, rpmat, cpmat, ispin, real_only, sab_nl, cell_to_index, xkp, wkp)
    2002              : 
    2003              :       TYPE(dbcsr_p_type), DIMENSION(:, :)                :: denmat
    2004              :       TYPE(dbcsr_type), POINTER                          :: rpmat, cpmat
    2005              :       INTEGER, INTENT(IN)                                :: ispin
    2006              :       LOGICAL, INTENT(IN)                                :: real_only
    2007              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2008              :          POINTER                                         :: sab_nl
    2009              :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    2010              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xkp
    2011              :       REAL(KIND=dp), INTENT(IN)                          :: wkp
    2012              : 
    2013              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'transform_dmat'
    2014              : 
    2015              :       INTEGER                                            :: handle, iatom, icell, icol, irow, jatom, &
    2016              :                                                             nimg
    2017              :       INTEGER, DIMENSION(3)                              :: cell
    2018              :       LOGICAL                                            :: do_symmetric, found
    2019              :       REAL(KIND=dp)                                      :: arg, coskl, fc, sinkl
    2020       194792 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, dblock, rblock
    2021              :       TYPE(neighbor_list_iterator_p_type), &
    2022       194792 :          DIMENSION(:), POINTER                           :: nl_iterator
    2023              : 
    2024       194792 :       CALL timeset(routineN, handle)
    2025              : 
    2026       194792 :       nimg = SIZE(denmat, 2)
    2027              : 
    2028              :       ! transformation
    2029       194792 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    2030       194792 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
    2031     78083997 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    2032     77889205 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom, cell=cell)
    2033              : 
    2034              :          !We have a FT from KP to real-space: S(R) = sum_k S(k)*exp(-i*k*R), with S(k) a complex number
    2035              :          !Therefore, we have: S(R) = sum_k Re(S(k))*cos(k*R) -i^2*Im(S(k))*sin(k*R)
    2036              :          !                         = sum_k Re(S(k))*cos(k*R) + Im(S(k))*sin(k*R)
    2037              :          !fc = +- 1 is due to the usual non-symmetric real-space matrices stored as symmetric ones
    2038              : 
    2039     77889205 :          irow = iatom
    2040     77889205 :          icol = jatom
    2041     77889205 :          fc = 1.0_dp
    2042     77889205 :          IF (do_symmetric .AND. iatom > jatom) THEN
    2043     33842798 :             irow = jatom
    2044     33842798 :             icol = iatom
    2045     33842798 :             fc = -1.0_dp
    2046              :          END IF
    2047              : 
    2048     77889205 :          icell = cell_to_index(cell(1), cell(2), cell(3))
    2049     77889205 :          IF (icell < 1 .OR. icell > nimg) CYCLE
    2050              : 
    2051     77887927 :          arg = REAL(cell(1), dp)*xkp(1) + REAL(cell(2), dp)*xkp(2) + REAL(cell(3), dp)*xkp(3)
    2052     77887927 :          coskl = wkp*COS(twopi*arg)
    2053     77887927 :          sinkl = wkp*fc*SIN(twopi*arg)
    2054              : 
    2055              :          CALL dbcsr_get_block_p(matrix=denmat(ispin, icell)%matrix, row=irow, col=icol, &
    2056     77887927 :                                 block=dblock, found=found)
    2057     77887927 :          IF (.NOT. found) CYCLE
    2058              : 
    2059     78082719 :          IF (real_only) THEN
    2060       294113 :             CALL dbcsr_get_block_p(matrix=rpmat, row=irow, col=icol, block=rblock, found=found)
    2061       294113 :             IF (.NOT. found) CYCLE
    2062    142452095 :             dblock = dblock + coskl*rblock
    2063              :          ELSE
    2064     77593814 :             CALL dbcsr_get_block_p(matrix=rpmat, row=irow, col=icol, block=rblock, found=found)
    2065     77593814 :             IF (.NOT. found) CYCLE
    2066     77593814 :             CALL dbcsr_get_block_p(matrix=cpmat, row=irow, col=icol, block=cblock, found=found)
    2067     77593814 :             IF (.NOT. found) CYCLE
    2068  10774781560 :             dblock = dblock + coskl*rblock
    2069  10774781560 :             dblock = dblock + sinkl*cblock
    2070              :          END IF
    2071              :       END DO
    2072       194792 :       CALL neighbor_list_iterator_release(nl_iterator)
    2073              : 
    2074       194792 :       CALL timestop(handle)
    2075              : 
    2076       194792 :    END SUBROUTINE transform_dmat
    2077              : 
    2078              : ! **************************************************************************************************
    2079              : !> \brief Allocate a dense work matrix with the requested shape
    2080              : !> \param work dense work matrix
    2081              : !> \param nrow number of rows
    2082              : !> \param ncol number of columns
    2083              : ! **************************************************************************************************
    2084      2707558 :    SUBROUTINE ensure_work_matrix(work, nrow, ncol)
    2085              : 
    2086              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
    2087              :          INTENT(INOUT)                                   :: work
    2088              :       INTEGER, INTENT(IN)                                :: nrow, ncol
    2089              : 
    2090      2707558 :       IF (ALLOCATED(work)) THEN
    2091      2619929 :          IF (SIZE(work, 1) == nrow .AND. SIZE(work, 2) == ncol) RETURN
    2092        47492 :          DEALLOCATE (work)
    2093              :       END IF
    2094       540484 :       ALLOCATE (work(nrow, ncol))
    2095              : 
    2096              :    END SUBROUTINE ensure_work_matrix
    2097              : 
    2098              : ! **************************************************************************************************
    2099              : !> \brief Select the Bloch-phase convention that preserves overlap covariance.
    2100              : !> \param kpoint ...
    2101              : !> \param overlap_rs ...
    2102              : !> \param tempmat ...
    2103              : !> \param sab_nl ...
    2104              : !> \param cell_to_index ...
    2105              : ! **************************************************************************************************
    2106        33974 :    SUBROUTINE calibrate_symmetry_phases(kpoint, overlap_rs, tempmat, sab_nl, cell_to_index)
    2107              : 
    2108              :       TYPE(kpoint_type), POINTER                         :: kpoint
    2109              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: overlap_rs
    2110              :       TYPE(dbcsr_type), POINTER                          :: tempmat
    2111              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2112              :          POINTER                                         :: sab_nl
    2113              :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    2114              : 
    2115              :       CHARACTER(LEN=256)                                 :: phase_error
    2116              :       INTEGER                                            :: best_mode, ik, ir, ira, is, jr, mode
    2117              :       LOGICAL                                            :: needs_calibration, reverse
    2118              :       REAL(KIND=dp)                                      :: best_residual, candidate_norm, &
    2119              :                                                             direct_norm, overlap_dot, &
    2120              :                                                             phase_tolerance, relative_residual
    2121              :       TYPE(dbcsr_type), POINTER                          :: direct_c, direct_r, source_c, source_r, &
    2122              :                                                             sym_c, sym_r
    2123        33974 :       TYPE(kind_rotmat_type), DIMENSION(:), POINTER      :: kind_rot
    2124              :       TYPE(kpoint_sym_type), POINTER                     :: kpsym
    2125              : 
    2126        33974 :       needs_calibration = .FALSE.
    2127       124502 :       DO ik = 1, kpoint%nkp
    2128        95544 :          kpsym => kpoint%kp_sym(ik)%kpoint_sym
    2129       124502 :          IF (kpsym%apply_symmetry) THEN
    2130        66900 :             IF (ANY(kpsym%phase_mode == 0)) THEN
    2131              :                needs_calibration = .TRUE.
    2132              :                EXIT
    2133              :             END IF
    2134              :          END IF
    2135              :       END DO
    2136        33974 :       IF (.NOT. needs_calibration) RETURN
    2137              : 
    2138         5016 :       ALLOCATE (source_r, source_c, direct_r, direct_c, sym_r, sym_c)
    2139         5016 :       CALL dbcsr_create(source_r, template=tempmat, matrix_type=dbcsr_type_symmetric)
    2140         5016 :       CALL dbcsr_create(source_c, template=tempmat, matrix_type=dbcsr_type_antisymmetric)
    2141         5016 :       CALL dbcsr_create(direct_r, template=tempmat, matrix_type=dbcsr_type_symmetric)
    2142         5016 :       CALL dbcsr_create(direct_c, template=tempmat, matrix_type=dbcsr_type_antisymmetric)
    2143         5016 :       CALL dbcsr_create(sym_r, template=tempmat, matrix_type=dbcsr_type_symmetric)
    2144         5016 :       CALL dbcsr_create(sym_c, template=tempmat, matrix_type=dbcsr_type_antisymmetric)
    2145         5016 :       CALL cp_dbcsr_alloc_block_from_nbl(source_r, sab_nl)
    2146         5016 :       CALL cp_dbcsr_alloc_block_from_nbl(source_c, sab_nl)
    2147         5016 :       CALL cp_dbcsr_alloc_block_from_nbl(direct_r, sab_nl)
    2148         5016 :       CALL cp_dbcsr_alloc_block_from_nbl(direct_c, sab_nl)
    2149         5016 :       CALL cp_dbcsr_alloc_block_from_nbl(sym_r, sab_nl)
    2150         5016 :       CALL cp_dbcsr_alloc_block_from_nbl(sym_c, sab_nl)
    2151              : 
    2152         5016 :       phase_tolerance = MAX(1.0e-6_dp, 100.0_dp*kpoint%eps_geo)
    2153        19818 :       DO ik = 1, kpoint%nkp
    2154        14802 :          kpsym => kpoint%kp_sym(ik)%kpoint_sym
    2155        14802 :          IF (.NOT. kpsym%apply_symmetry) CYCLE
    2156        64034 :          IF (ALL(kpsym%phase_mode > 0)) CYCLE
    2157              : 
    2158        11760 :          CALL dbcsr_set(source_r, 0.0_dp)
    2159        11760 :          CALL dbcsr_set(source_c, 0.0_dp)
    2160              :          CALL rskp_transform(source_r, source_c, overlap_rs, 1, kpoint%xkp(1:3, ik), &
    2161        11760 :                              cell_to_index, sab_nl)
    2162              : 
    2163        73576 :          DO is = 1, kpsym%nwght
    2164        56800 :             IF (kpsym%phase_mode(is) > 0) CYCLE
    2165        10624 :             CALL dbcsr_set(direct_r, 0.0_dp)
    2166        10624 :             CALL dbcsr_set(direct_c, 0.0_dp)
    2167              :             CALL rskp_transform(direct_r, direct_c, overlap_rs, 1, kpsym%xkp(1:3, is), &
    2168        10624 :                                 cell_to_index, sab_nl)
    2169        10624 :             CALL dbcsr_dot(direct_r, direct_r, direct_norm)
    2170        10624 :             CALL dbcsr_dot(direct_c, direct_c, candidate_norm)
    2171        10624 :             direct_norm = direct_norm + candidate_norm
    2172              : 
    2173        10624 :             ir = ABS(kpsym%rotp(is))
    2174        10624 :             ira = 0
    2175       237256 :             DO jr = 1, SIZE(kpoint%ibrot)
    2176       237256 :                IF (ir == kpoint%ibrot(jr)) ira = jr
    2177              :             END DO
    2178        10624 :             CPASSERT(ira > 0)
    2179        10624 :             kind_rot => kpoint%kind_rotmat(ira, :)
    2180              : 
    2181        10624 :             best_mode = 0
    2182        10624 :             best_residual = HUGE(1.0_dp)
    2183        31872 :             DO mode = 1, 2
    2184        21248 :                reverse = mode == 2
    2185              :                CALL symtrans_phase(sym_r, sym_c, source_r, source_c, .FALSE., kind_rot, &
    2186              :                                    kpsym%rot(1:3, 1:3, is), kpsym%f0(:, is), &
    2187              :                                    kpsym%fcell_gauge(:, :, is), kpoint%atype, &
    2188        21248 :                                    kpsym%xkp(1:3, is), kpsym%rotp(is) < 0, reverse)
    2189        21248 :                CALL dbcsr_dot(sym_r, sym_r, candidate_norm)
    2190        21248 :                CALL dbcsr_dot(sym_c, sym_c, relative_residual)
    2191        21248 :                candidate_norm = candidate_norm + relative_residual
    2192        21248 :                CALL dbcsr_dot(sym_r, direct_r, overlap_dot)
    2193        21248 :                CALL dbcsr_dot(sym_c, direct_c, relative_residual)
    2194        21248 :                overlap_dot = overlap_dot + relative_residual
    2195              :                relative_residual = SQRT(MAX(0.0_dp, candidate_norm + direct_norm - &
    2196        21248 :                                             2.0_dp*overlap_dot)/MAX(direct_norm, TINY(1.0_dp)))
    2197        31872 :                IF (relative_residual < best_residual) THEN
    2198        15032 :                   best_residual = relative_residual
    2199        15032 :                   best_mode = mode
    2200              :                END IF
    2201              :             END DO
    2202        10624 :             IF (best_residual > phase_tolerance) THEN
    2203              :                WRITE (phase_error, '(A,ES12.4,A,I0,A,I0)') &
    2204            0 :                   "No Bloch-phase direction preserves overlap covariance; residual=", &
    2205            0 :                   best_residual, ", irreducible k-point=", ik, ", operation=", is
    2206            0 :                CALL cp_abort(__LOCATION__, TRIM(phase_error))
    2207              :             END IF
    2208        82226 :             kpsym%phase_mode(is) = best_mode
    2209              :          END DO
    2210              :       END DO
    2211              : 
    2212         5016 :       CALL dbcsr_deallocate_matrix(source_r)
    2213         5016 :       CALL dbcsr_deallocate_matrix(source_c)
    2214         5016 :       CALL dbcsr_deallocate_matrix(direct_r)
    2215         5016 :       CALL dbcsr_deallocate_matrix(direct_c)
    2216         5016 :       CALL dbcsr_deallocate_matrix(sym_r)
    2217         5016 :       CALL dbcsr_deallocate_matrix(sym_c)
    2218              : 
    2219        33974 :    END SUBROUTINE calibrate_symmetry_phases
    2220              : 
    2221              : ! **************************************************************************************************
    2222              : !> \brief Symmetrize a complex k-point matrix including Bloch phase shifts
    2223              : !> \param srpmat real part of transformed matrix
    2224              : !> \param scpmat imaginary part of transformed matrix
    2225              : !> \param rpmat real part of reference matrix
    2226              : !> \param cpmat imaginary part of reference matrix
    2227              : !> \param real_only ...
    2228              : !> \param kmat kind type rotation matrix
    2229              : !> \param rot rotation matrix
    2230              : !> \param f0 atom permutation
    2231              : !> \param fcell atom cell shifts generated by the symmetry operation
    2232              : !> \param atype atom to kind pointer
    2233              : !> \param xkp target k-point coordinates
    2234              : !> \param time_reversal ...
    2235              : !> \param reverse_phase ...
    2236              : ! **************************************************************************************************
    2237       119196 :    SUBROUTINE symtrans_phase(srpmat, scpmat, rpmat, cpmat, real_only, kmat, rot, f0, fcell, atype, &
    2238              :                              xkp, time_reversal, reverse_phase)
    2239              : 
    2240              :       TYPE(dbcsr_type), POINTER                          :: srpmat, scpmat, rpmat, cpmat
    2241              :       LOGICAL, INTENT(IN)                                :: real_only
    2242              :       TYPE(kind_rotmat_type), DIMENSION(:), POINTER      :: kmat
    2243              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: rot
    2244              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: f0
    2245              :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: fcell
    2246              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: atype
    2247              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xkp
    2248              :       LOGICAL, INTENT(IN)                                :: time_reversal, reverse_phase
    2249              : 
    2250              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'symtrans_phase'
    2251              : 
    2252              :       INTEGER                                            :: handle, iatom, icol, ikind, ip, irow, &
    2253              :                                                             jcol, jkind, jp, jrow, mynode, natom, &
    2254              :                                                             numnodes, owner
    2255              :       INTEGER, DIMENSION(3)                              :: shift
    2256              :       LOGICAL                                            :: dorot, found, has_phase, perm, trans
    2257              :       REAL(KIND=dp)                                      :: arg, coskl, dr, sinkl
    2258       119196 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: cwork, rwork, twork
    2259       119196 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, kroti, krotj, rblock, scblock, &
    2260       119196 :                                                             srblock
    2261              :       TYPE(dbcsr_distribution_type)                      :: dist
    2262              :       TYPE(dbcsr_iterator_type)                          :: iter
    2263              : 
    2264       119196 :       CALL timeset(routineN, handle)
    2265              : 
    2266       119196 :       natom = SIZE(f0)
    2267       119196 :       perm = .FALSE.
    2268       534908 :       DO iatom = 1, natom
    2269       465816 :          IF (f0(iatom) == iatom) CYCLE
    2270              :          perm = .TRUE.
    2271       484804 :          EXIT
    2272              :       END DO
    2273              : 
    2274       119196 :       dorot = .FALSE.
    2275      1549548 :       IF (ABS(SUM(ABS(rot)) - 3.0_dp) > 1.e-12_dp) dorot = .TRUE.
    2276       119196 :       dr = ABS(rot(1, 1) - 1.0_dp) + ABS(rot(2, 2) - 1.0_dp) + ABS(rot(3, 3) - 1.0_dp)
    2277       119196 :       IF (ABS(dr) > 1.e-12_dp) dorot = .TRUE.
    2278      1919280 :       has_phase = ANY(fcell /= 0) .OR. time_reversal
    2279              : 
    2280       119196 :       IF (.NOT. (dorot .OR. perm .OR. has_phase)) THEN
    2281        31062 :          CALL dbcsr_copy(srpmat, rpmat)
    2282        31062 :          IF (.NOT. real_only) CALL dbcsr_copy(scpmat, cpmat)
    2283        31062 :          CALL timestop(handle)
    2284        31062 :          RETURN
    2285              :       END IF
    2286              : 
    2287        88134 :       CALL dbcsr_get_info(rpmat, distribution=dist)
    2288        88134 :       CALL dbcsr_distribution_get(dist, mynode=mynode, numnodes=numnodes)
    2289        88134 :       IF (numnodes /= 1 .AND. (perm .OR. has_phase)) THEN
    2290        84858 :          CALL dbcsr_replicate_all(rpmat)
    2291        84858 :          IF (.NOT. real_only) CALL dbcsr_replicate_all(cpmat)
    2292              :       END IF
    2293              : 
    2294        88134 :       CALL dbcsr_set(srpmat, 0.0_dp)
    2295        88134 :       IF (.NOT. real_only) CALL dbcsr_set(scpmat, 0.0_dp)
    2296              : 
    2297        88134 :       CALL dbcsr_iterator_start(iter, rpmat)
    2298      2786906 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    2299      2698772 :          CALL dbcsr_iterator_next_block(iter, irow, icol, rblock)
    2300      2698772 :          IF (.NOT. ALLOCATED(rwork)) THEN
    2301       352096 :             ALLOCATE (rwork(SIZE(rblock, 1), SIZE(rblock, 2)))
    2302      2610748 :          ELSE IF (SIZE(rwork, 1) /= SIZE(rblock, 1) .OR. SIZE(rwork, 2) /= SIZE(rblock, 2)) THEN
    2303        68248 :             DEALLOCATE (rwork)
    2304       272992 :             ALLOCATE (rwork(SIZE(rblock, 1), SIZE(rblock, 2)))
    2305              :          END IF
    2306      2698772 :          IF (.NOT. real_only) THEN
    2307      2698772 :             IF (.NOT. ALLOCATED(cwork)) THEN
    2308       352096 :                ALLOCATE (cwork(SIZE(rblock, 1), SIZE(rblock, 2)))
    2309      2610748 :             ELSE IF (SIZE(cwork, 1) /= SIZE(rblock, 1) .OR. SIZE(cwork, 2) /= SIZE(rblock, 2)) THEN
    2310        68248 :                DEALLOCATE (cwork)
    2311       272992 :                ALLOCATE (cwork(SIZE(rblock, 1), SIZE(rblock, 2)))
    2312              :             END IF
    2313              :          END IF
    2314              : 
    2315      2698772 :          ikind = atype(irow)
    2316      2698772 :          jkind = atype(icol)
    2317      2698772 :          kroti => kmat(ikind)%rmat
    2318      2698772 :          krotj => kmat(jkind)%rmat
    2319              : 
    2320      2698772 :          IF (reverse_phase) THEN
    2321      6062408 :             shift = fcell(1:3, irow) - fcell(1:3, icol)
    2322              :          ELSE
    2323      4732680 :             shift = fcell(1:3, icol) - fcell(1:3, irow)
    2324              :          END IF
    2325              :          arg = REAL(shift(1), dp)*xkp(1) + REAL(shift(2), dp)*xkp(2) + &
    2326      2698772 :                REAL(shift(3), dp)*xkp(3)
    2327      2698772 :          coskl = COS(twopi*arg)
    2328      2698772 :          sinkl = SIN(twopi*arg)
    2329      2698772 :          IF (real_only) THEN
    2330            0 :             IF (ABS(sinkl) > 1.e-12_dp) THEN
    2331            0 :                CALL cp_abort(__LOCATION__, "Real k-point wavefunctions cannot represent symmetry phases")
    2332              :             END IF
    2333            0 :             rwork(:, :) = coskl*rblock
    2334              :          ELSE
    2335      2698772 :             CALL dbcsr_get_block_p(matrix=cpmat, row=irow, col=icol, block=cblock, found=found)
    2336    137322780 :             rwork(:, :) = coskl*rblock
    2337      2698772 :             IF (time_reversal) THEN
    2338     81241550 :                cwork(:, :) = -sinkl*rblock
    2339      1481334 :                IF (found) THEN
    2340     81241550 :                   rwork(:, :) = rwork - sinkl*cblock
    2341     81241550 :                   cwork(:, :) = cwork - coskl*cblock
    2342              :                END IF
    2343              :             ELSE
    2344     56081230 :                cwork(:, :) = -sinkl*rblock
    2345      1217438 :                IF (found) THEN
    2346     56081230 :                   rwork(:, :) = rwork + sinkl*cblock
    2347     56081230 :                   cwork(:, :) = cwork + coskl*cblock
    2348              :                END IF
    2349              :             END IF
    2350              :          END IF
    2351              : 
    2352      2698772 :          ip = f0(irow)
    2353      2698772 :          jp = f0(icol)
    2354      2698772 :          IF (ip <= jp) THEN
    2355      2437540 :             jrow = ip
    2356      2437540 :             jcol = jp
    2357      2437540 :             trans = .FALSE.
    2358              :          ELSE
    2359       261232 :             jrow = jp
    2360       261232 :             jcol = ip
    2361       261232 :             trans = .TRUE.
    2362              :          END IF
    2363              : 
    2364      2698772 :          CALL dbcsr_get_block_p(matrix=srpmat, row=jrow, col=jcol, block=srblock, found=found)
    2365      2698772 :          IF (.NOT. found) THEN
    2366      1344993 :             CALL dbcsr_get_stored_coordinates(srpmat, jrow, jcol, owner)
    2367      1344993 :             CPASSERT(owner /= mynode)
    2368              :             CYCLE
    2369              :          END IF
    2370      1353779 :          IF (trans) THEN
    2371       130616 :             CALL ensure_work_matrix(twork, SIZE(krotj, 1), SIZE(rwork, 1))
    2372              :             CALL dgemm('N', 'T', SIZE(krotj, 1), SIZE(rwork, 1), SIZE(krotj, 2), &
    2373              :                        1.0_dp, krotj, SIZE(krotj, 1), rwork, SIZE(rwork, 1), &
    2374       130616 :                        0.0_dp, twork, SIZE(twork, 1))
    2375              :             CALL dgemm('N', 'T', SIZE(twork, 1), SIZE(kroti, 1), SIZE(twork, 2), &
    2376              :                        1.0_dp, twork, SIZE(twork, 1), kroti, SIZE(kroti, 1), &
    2377       130616 :                        1.0_dp, srblock, SIZE(srblock, 1))
    2378              :          ELSE
    2379      1223163 :             CALL ensure_work_matrix(twork, SIZE(kroti, 1), SIZE(rwork, 2))
    2380              :             CALL dgemm('N', 'N', SIZE(kroti, 1), SIZE(rwork, 2), SIZE(kroti, 2), &
    2381              :                        1.0_dp, kroti, SIZE(kroti, 1), rwork, SIZE(rwork, 1), &
    2382      1223163 :                        0.0_dp, twork, SIZE(twork, 1))
    2383              :             CALL dgemm('N', 'T', SIZE(twork, 1), SIZE(krotj, 1), SIZE(twork, 2), &
    2384              :                        1.0_dp, twork, SIZE(twork, 1), krotj, SIZE(krotj, 1), &
    2385      1223163 :                        1.0_dp, srblock, SIZE(srblock, 1))
    2386              :          END IF
    2387              : 
    2388      1441913 :          IF (.NOT. real_only) THEN
    2389      1353779 :             CALL dbcsr_get_block_p(matrix=scpmat, row=jrow, col=jcol, block=scblock, found=found)
    2390      1353779 :             CPASSERT(found)
    2391      1353779 :             IF (trans) THEN
    2392       130616 :                CALL ensure_work_matrix(twork, SIZE(krotj, 1), SIZE(cwork, 1))
    2393              :                CALL dgemm('N', 'T', SIZE(krotj, 1), SIZE(cwork, 1), SIZE(krotj, 2), &
    2394              :                           1.0_dp, krotj, SIZE(krotj, 1), cwork, SIZE(cwork, 1), &
    2395       130616 :                           0.0_dp, twork, SIZE(twork, 1))
    2396              :                CALL dgemm('N', 'T', SIZE(twork, 1), SIZE(kroti, 1), SIZE(twork, 2), &
    2397              :                           -1.0_dp, twork, SIZE(twork, 1), kroti, SIZE(kroti, 1), &
    2398       130616 :                           1.0_dp, scblock, SIZE(scblock, 1))
    2399              :             ELSE
    2400      1223163 :                CALL ensure_work_matrix(twork, SIZE(kroti, 1), SIZE(cwork, 2))
    2401              :                CALL dgemm('N', 'N', SIZE(kroti, 1), SIZE(cwork, 2), SIZE(kroti, 2), &
    2402              :                           1.0_dp, kroti, SIZE(kroti, 1), cwork, SIZE(cwork, 1), &
    2403      1223163 :                           0.0_dp, twork, SIZE(twork, 1))
    2404              :                CALL dgemm('N', 'T', SIZE(twork, 1), SIZE(krotj, 1), SIZE(twork, 2), &
    2405              :                           1.0_dp, twork, SIZE(twork, 1), krotj, SIZE(krotj, 1), &
    2406      1223163 :                           1.0_dp, scblock, SIZE(scblock, 1))
    2407              :             END IF
    2408              :          END IF
    2409              :       END DO
    2410        88134 :       CALL dbcsr_iterator_stop(iter)
    2411        88134 :       IF (numnodes /= 1 .AND. (perm .OR. has_phase)) THEN
    2412        84858 :          CALL dbcsr_distribute(rpmat)
    2413        84858 :          IF (.NOT. real_only) CALL dbcsr_distribute(cpmat)
    2414              :       END IF
    2415              : 
    2416        88134 :       CALL timestop(handle)
    2417              : 
    2418       238392 :    END SUBROUTINE symtrans_phase
    2419              : 
    2420              : ! **************************************************************************************************
    2421              : !> \brief Symmetrization of density matrix - transform to new k-point
    2422              : !> \param smat density matrix at new kpoint
    2423              : !> \param pmat reference density matrix
    2424              : !> \param kmat Kind type rotation matrix
    2425              : !> \param rot Rotation matrix
    2426              : !> \param f0 Permutation of atoms under transformation
    2427              : !> \param atype Atom to kind pointer
    2428              : !> \param symmetric Symmetric matrix
    2429              : !> \param antisymmetric Anti-Symmetric matrix
    2430              : ! **************************************************************************************************
    2431            0 :    SUBROUTINE symtrans(smat, pmat, kmat, rot, f0, atype, symmetric, antisymmetric)
    2432              :       TYPE(dbcsr_type), POINTER                          :: smat, pmat
    2433              :       TYPE(kind_rotmat_type), DIMENSION(:), POINTER      :: kmat
    2434              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: rot
    2435              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: f0, atype
    2436              :       LOGICAL, INTENT(IN), OPTIONAL                      :: symmetric, antisymmetric
    2437              : 
    2438              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'symtrans'
    2439              : 
    2440              :       INTEGER                                            :: handle, iatom, icol, ikind, ip, irow, &
    2441              :                                                             jcol, jkind, jp, jrow, natom, numnodes
    2442              :       LOGICAL                                            :: asym, dorot, found, perm, sym, trans
    2443              :       REAL(KIND=dp)                                      :: dr, fsign
    2444            0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: work
    2445            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: kroti, krotj, pblock, sblock
    2446              :       TYPE(dbcsr_distribution_type)                      :: dist
    2447              :       TYPE(dbcsr_iterator_type)                          :: iter
    2448              : 
    2449            0 :       CALL timeset(routineN, handle)
    2450              : 
    2451              :       ! check symmetry options
    2452            0 :       sym = .FALSE.
    2453            0 :       IF (PRESENT(symmetric)) sym = symmetric
    2454            0 :       asym = .FALSE.
    2455            0 :       IF (PRESENT(antisymmetric)) asym = antisymmetric
    2456              : 
    2457            0 :       CPASSERT(.NOT. (sym .AND. asym))
    2458            0 :       CPASSERT((sym .OR. asym))
    2459              : 
    2460              :       ! do we have permutation of atoms
    2461            0 :       natom = SIZE(f0)
    2462            0 :       perm = .FALSE.
    2463            0 :       DO iatom = 1, natom
    2464            0 :          IF (f0(iatom) == iatom) CYCLE
    2465              :          perm = .TRUE.
    2466            0 :          EXIT
    2467              :       END DO
    2468              : 
    2469              :       ! do we have a real rotation
    2470            0 :       dorot = .FALSE.
    2471            0 :       IF (ABS(SUM(ABS(rot)) - 3.0_dp) > 1.e-12_dp) dorot = .TRUE.
    2472            0 :       dr = ABS(rot(1, 1) - 1.0_dp) + ABS(rot(2, 2) - 1.0_dp) + ABS(rot(3, 3) - 1.0_dp)
    2473            0 :       IF (ABS(dr) > 1.e-12_dp) dorot = .TRUE.
    2474              : 
    2475            0 :       fsign = 1.0_dp
    2476            0 :       IF (asym) fsign = -1.0_dp
    2477              : 
    2478            0 :       IF (dorot .OR. perm) THEN
    2479              :          CALL cp_abort(__LOCATION__, "k-points need FULL_GRID currently. "// &
    2480            0 :                        "Reduced grids not yet working correctly")
    2481            0 :          CALL dbcsr_set(smat, 0.0_dp)
    2482            0 :          IF (perm) THEN
    2483            0 :             CALL dbcsr_get_info(pmat, distribution=dist)
    2484            0 :             CALL dbcsr_distribution_get(dist, numnodes=numnodes)
    2485            0 :             IF (numnodes == 1) THEN
    2486              :                ! the matrices are local to this process
    2487            0 :                CALL dbcsr_iterator_start(iter, pmat)
    2488            0 :                DO WHILE (dbcsr_iterator_blocks_left(iter))
    2489            0 :                   CALL dbcsr_iterator_next_block(iter, irow, icol, pblock)
    2490            0 :                   ip = f0(irow)
    2491            0 :                   jp = f0(icol)
    2492            0 :                   IF (ip <= jp) THEN
    2493            0 :                      jrow = ip
    2494            0 :                      jcol = jp
    2495            0 :                      trans = .FALSE.
    2496              :                   ELSE
    2497            0 :                      jrow = jp
    2498            0 :                      jcol = ip
    2499            0 :                      trans = .TRUE.
    2500              :                   END IF
    2501            0 :                   CALL dbcsr_get_block_p(matrix=smat, row=jrow, col=jcol, BLOCK=sblock, found=found)
    2502            0 :                   CPASSERT(found)
    2503            0 :                   ikind = atype(irow)
    2504            0 :                   jkind = atype(icol)
    2505            0 :                   kroti => kmat(ikind)%rmat
    2506            0 :                   krotj => kmat(jkind)%rmat
    2507              :                   ! rotation
    2508            0 :                   IF (trans) THEN
    2509            0 :                      CALL ensure_work_matrix(work, SIZE(krotj, 2), SIZE(pblock, 1))
    2510              :                      CALL dgemm('T', 'T', SIZE(krotj, 2), SIZE(pblock, 1), SIZE(krotj, 1), &
    2511              :                                 1.0_dp, krotj, SIZE(krotj, 1), pblock, SIZE(pblock, 1), &
    2512            0 :                                 0.0_dp, work, SIZE(work, 1))
    2513              :                      CALL dgemm('N', 'N', SIZE(work, 1), SIZE(kroti, 2), SIZE(work, 2), &
    2514              :                                 fsign, work, SIZE(work, 1), kroti, SIZE(kroti, 1), &
    2515            0 :                                 0.0_dp, sblock, SIZE(sblock, 1))
    2516              :                   ELSE
    2517            0 :                      CALL ensure_work_matrix(work, SIZE(kroti, 2), SIZE(pblock, 2))
    2518              :                      CALL dgemm('T', 'N', SIZE(kroti, 2), SIZE(pblock, 2), SIZE(kroti, 1), &
    2519              :                                 1.0_dp, kroti, SIZE(kroti, 1), pblock, SIZE(pblock, 1), &
    2520            0 :                                 0.0_dp, work, SIZE(work, 1))
    2521              :                      CALL dgemm('N', 'N', SIZE(work, 1), SIZE(krotj, 2), SIZE(work, 2), &
    2522              :                                 fsign, work, SIZE(work, 1), krotj, SIZE(krotj, 1), &
    2523            0 :                                 0.0_dp, sblock, SIZE(sblock, 1))
    2524              :                   END IF
    2525              :                END DO
    2526            0 :                CALL dbcsr_iterator_stop(iter)
    2527              :                !
    2528              :             ELSE
    2529              :                ! distributed matrices, most general code needed
    2530              :                CALL cp_abort(__LOCATION__, "k-points need FULL_GRID currently. "// &
    2531            0 :                              "Reduced grids not yet working correctly")
    2532              :             END IF
    2533              :          ELSE
    2534              :             ! no atom permutations, this is always local
    2535            0 :             CALL dbcsr_copy(smat, pmat)
    2536            0 :             CALL dbcsr_iterator_start(iter, smat)
    2537            0 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
    2538            0 :                CALL dbcsr_iterator_next_block(iter, irow, icol, sblock)
    2539            0 :                ip = f0(irow)
    2540            0 :                jp = f0(icol)
    2541            0 :                IF (ip <= jp) THEN
    2542              :                   jrow = ip
    2543              :                   jcol = jp
    2544            0 :                   trans = .FALSE.
    2545              :                ELSE
    2546              :                   jrow = jp
    2547              :                   jcol = ip
    2548            0 :                   trans = .TRUE.
    2549              :                END IF
    2550            0 :                ikind = atype(irow)
    2551            0 :                jkind = atype(icol)
    2552            0 :                kroti => kmat(ikind)%rmat
    2553            0 :                krotj => kmat(jkind)%rmat
    2554              :                ! rotation
    2555            0 :                IF (trans) THEN
    2556            0 :                   CALL ensure_work_matrix(work, SIZE(krotj, 2), SIZE(sblock, 1))
    2557              :                   CALL dgemm('T', 'T', SIZE(krotj, 2), SIZE(sblock, 1), SIZE(krotj, 1), &
    2558              :                              1.0_dp, krotj, SIZE(krotj, 1), sblock, SIZE(sblock, 1), &
    2559            0 :                              0.0_dp, work, SIZE(work, 1))
    2560              :                   CALL dgemm('N', 'N', SIZE(work, 1), SIZE(kroti, 2), SIZE(work, 2), &
    2561              :                              fsign, work, SIZE(work, 1), kroti, SIZE(kroti, 1), &
    2562            0 :                              0.0_dp, sblock, SIZE(sblock, 1))
    2563              :                ELSE
    2564            0 :                   CALL ensure_work_matrix(work, SIZE(kroti, 2), SIZE(sblock, 2))
    2565              :                   CALL dgemm('T', 'N', SIZE(kroti, 2), SIZE(sblock, 2), SIZE(kroti, 1), &
    2566              :                              1.0_dp, kroti, SIZE(kroti, 1), sblock, SIZE(sblock, 1), &
    2567            0 :                              0.0_dp, work, SIZE(work, 1))
    2568              :                   CALL dgemm('N', 'N', SIZE(work, 1), SIZE(krotj, 2), SIZE(work, 2), &
    2569              :                              fsign, work, SIZE(work, 1), krotj, SIZE(krotj, 1), &
    2570            0 :                              0.0_dp, sblock, SIZE(sblock, 1))
    2571              :                END IF
    2572              :             END DO
    2573            0 :             CALL dbcsr_iterator_stop(iter)
    2574              :             !
    2575              :          END IF
    2576              :       ELSE
    2577              :          ! this is the identity operation, just copy the matrix
    2578            0 :          CALL dbcsr_copy(smat, pmat)
    2579              :       END IF
    2580              : 
    2581            0 :       CALL timestop(handle)
    2582              : 
    2583            0 :    END SUBROUTINE symtrans
    2584              : 
    2585              : ! **************************************************************************************************
    2586              : !> \brief ...
    2587              : !> \param mat ...
    2588              : ! **************************************************************************************************
    2589            0 :    SUBROUTINE matprint(mat)
    2590              :       TYPE(dbcsr_type), POINTER                          :: mat
    2591              : 
    2592              :       INTEGER                                            :: i, icol, iounit, irow
    2593            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: mblock
    2594              :       TYPE(dbcsr_iterator_type)                          :: iter
    2595              : 
    2596            0 :       iounit = cp_logger_get_default_io_unit()
    2597            0 :       CALL dbcsr_iterator_start(iter, mat)
    2598            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    2599            0 :          CALL dbcsr_iterator_next_block(iter, irow, icol, mblock)
    2600              :          !
    2601            0 :          IF (iounit > 0) THEN
    2602            0 :             WRITE (iounit, '(A,2I4)') 'BLOCK  ', irow, icol
    2603            0 :             DO i = 1, SIZE(mblock, 1)
    2604            0 :                WRITE (iounit, '(8F12.6)') mblock(i, :)
    2605              :             END DO
    2606              :          END IF
    2607              :          !
    2608              :       END DO
    2609            0 :       CALL dbcsr_iterator_stop(iter)
    2610              : 
    2611            0 :    END SUBROUTINE matprint
    2612              : ! **************************************************************************************************
    2613              : 
    2614              : END MODULE kpoint_methods
        

Generated by: LCOV version 2.0-1