LCOV - code coverage report
Current view: top level - src - kpoint_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:3130539) Lines: 615 777 79.2 %
Date: 2025-05-14 06:57:18 Functions: 10 12 83.3 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 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             :                                               real_to_scaled
      19             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_create,&
      20             :                                               cp_blacs_env_type
      21             :    USE cp_control_types,                ONLY: dft_control_type
      22             :    USE cp_dbcsr_api,                    ONLY: &
      23             :         dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_distribution_get, &
      24             :         dbcsr_distribution_type, dbcsr_get_block_p, dbcsr_get_info, dbcsr_iterator_blocks_left, &
      25             :         dbcsr_iterator_next_block, dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, &
      26             :         dbcsr_p_type, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, &
      27             :         dbcsr_type_symmetric
      28             :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      29             :    USE cp_dbcsr_operations,             ONLY: copy_fm_to_dbcsr
      30             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale
      31             :    USE cp_fm_pool_types,                ONLY: cp_fm_pool_p_type,&
      32             :                                               fm_pool_create_fm,&
      33             :                                               fm_pool_give_back_fm
      34             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_type
      35             :    USE cp_fm_types,                     ONLY: &
      36             :         copy_info_type, cp_fm_cleanup_copy_general, cp_fm_create, cp_fm_finish_copy_general, &
      37             :         cp_fm_get_info, cp_fm_release, cp_fm_start_copy_general, cp_fm_to_fm, cp_fm_type
      38             :    USE cp_log_handling,                 ONLY: cp_logger_get_default_io_unit
      39             :    USE cryssym,                         ONLY: crys_sym_gen,&
      40             :                                               csym_type,&
      41             :                                               kpoint_gen,&
      42             :                                               print_crys_symmetry,&
      43             :                                               print_kp_symmetry,&
      44             :                                               release_csym_type
      45             :    USE fermi_utils,                     ONLY: fermikp,&
      46             :                                               fermikp2
      47             :    USE input_constants,                 ONLY: smear_fermi_dirac
      48             :    USE kinds,                           ONLY: dp
      49             :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      50             :                                               kind_rotmat_type,&
      51             :                                               kpoint_env_create,&
      52             :                                               kpoint_env_p_type,&
      53             :                                               kpoint_env_type,&
      54             :                                               kpoint_sym_create,&
      55             :                                               kpoint_sym_type,&
      56             :                                               kpoint_type
      57             :    USE mathconstants,                   ONLY: twopi
      58             :    USE memory_utilities,                ONLY: reallocate
      59             :    USE message_passing,                 ONLY: mp_cart_type,&
      60             :                                               mp_para_env_type
      61             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      62             :    USE particle_types,                  ONLY: particle_type
      63             :    USE qs_matrix_pools,                 ONLY: mpools_create,&
      64             :                                               mpools_get,&
      65             :                                               mpools_rebuild_fm_pools,&
      66             :                                               qs_matrix_pools_type
      67             :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
      68             :                                               get_mo_set,&
      69             :                                               init_mo_set,&
      70             :                                               mo_set_type,&
      71             :                                               set_mo_set
      72             :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      73             :                                               get_neighbor_list_set_p,&
      74             :                                               neighbor_list_iterate,&
      75             :                                               neighbor_list_iterator_create,&
      76             :                                               neighbor_list_iterator_p_type,&
      77             :                                               neighbor_list_iterator_release,&
      78             :                                               neighbor_list_set_p_type
      79             :    USE scf_control_types,               ONLY: smear_type
      80             :    USE util,                            ONLY: get_limit
      81             : #include "./base/base_uses.f90"
      82             : 
      83             :    IMPLICIT NONE
      84             : 
      85             :    PRIVATE
      86             : 
      87             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'kpoint_methods'
      88             : 
      89             :    PUBLIC :: kpoint_initialize, kpoint_env_initialize, kpoint_initialize_mos, kpoint_initialize_mo_set
      90             :    PUBLIC :: kpoint_init_cell_index, kpoint_set_mo_occupation
      91             :    PUBLIC :: kpoint_density_matrices, kpoint_density_transform
      92             :    PUBLIC :: rskp_transform
      93             : 
      94             : ! **************************************************************************************************
      95             : 
      96             : CONTAINS
      97             : 
      98             : ! **************************************************************************************************
      99             : !> \brief Generate the kpoints and initialize the kpoint environment
     100             : !> \param kpoint       The kpoint environment
     101             : !> \param particle_set Particle types and coordinates
     102             : !> \param cell         Computational cell information
     103             : ! **************************************************************************************************
     104        7324 :    SUBROUTINE kpoint_initialize(kpoint, particle_set, cell)
     105             : 
     106             :       TYPE(kpoint_type), POINTER                         :: kpoint
     107             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     108             :       TYPE(cell_type), POINTER                           :: cell
     109             : 
     110             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'kpoint_initialize'
     111             : 
     112             :       INTEGER                                            :: handle, i, ic, ik, iounit, ir, ira, is, &
     113             :                                                             j, natom, nkind, nr, ns
     114        7324 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atype
     115             :       LOGICAL                                            :: spez
     116             :       REAL(KIND=dp)                                      :: wsum
     117        7324 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: coord, scoord
     118     6467092 :       TYPE(csym_type)                                    :: crys_sym
     119             :       TYPE(kpoint_sym_type), POINTER                     :: kpsym
     120             : 
     121        7324 :       CALL timeset(routineN, handle)
     122             : 
     123        7324 :       CPASSERT(ASSOCIATED(kpoint))
     124             : 
     125        7340 :       SELECT CASE (kpoint%kp_scheme)
     126             :       CASE ("NONE")
     127             :          ! do nothing
     128             :       CASE ("GAMMA")
     129          16 :          kpoint%nkp = 1
     130          16 :          ALLOCATE (kpoint%xkp(3, 1), kpoint%wkp(1))
     131          64 :          kpoint%xkp(1:3, 1) = 0.0_dp
     132          16 :          kpoint%wkp(1) = 1.0_dp
     133          32 :          ALLOCATE (kpoint%kp_sym(1))
     134          16 :          NULLIFY (kpoint%kp_sym(1)%kpoint_sym)
     135          16 :          CALL kpoint_sym_create(kpoint%kp_sym(1)%kpoint_sym)
     136             :       CASE ("MONKHORST-PACK", "MACDONALD")
     137             : 
     138         148 :          IF (.NOT. kpoint%symmetry) THEN
     139             :             ! we set up a random molecule to avoid any possible symmetry
     140         100 :             natom = 10
     141         100 :             ALLOCATE (coord(3, natom), scoord(3, natom), atype(natom))
     142        1100 :             DO i = 1, natom
     143        1000 :                atype(i) = i
     144        1000 :                coord(1, i) = SIN(i*0.12345_dp)
     145        1000 :                coord(2, i) = COS(i*0.23456_dp)
     146        1000 :                coord(3, i) = SIN(i*0.34567_dp)
     147        1100 :                CALL real_to_scaled(scoord(1:3, i), coord(1:3, i), cell)
     148             :             END DO
     149             :          ELSE
     150          48 :             natom = SIZE(particle_set)
     151         240 :             ALLOCATE (scoord(3, natom), atype(natom))
     152         360 :             DO i = 1, natom
     153         312 :                CALL get_atomic_kind(atomic_kind=particle_set(i)%atomic_kind, kind_number=atype(i))
     154         360 :                CALL real_to_scaled(scoord(1:3, i), particle_set(i)%r(1:3), cell)
     155             :             END DO
     156             :          END IF
     157         148 :          IF (kpoint%verbose) THEN
     158          10 :             iounit = cp_logger_get_default_io_unit()
     159             :          ELSE
     160         138 :             iounit = -1
     161             :          END IF
     162             :          ! kind type list
     163         444 :          ALLOCATE (kpoint%atype(natom))
     164        1460 :          kpoint%atype = atype
     165             : 
     166         148 :          CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit)
     167             :          CALL kpoint_gen(crys_sym, kpoint%nkp_grid, symm=kpoint%symmetry, shift=kpoint%kp_shift, &
     168         148 :                          full_grid=kpoint%full_grid)
     169         148 :          kpoint%nkp = crys_sym%nkpoint
     170         740 :          ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp))
     171        1790 :          wsum = SUM(crys_sym%wkpoint)
     172        1790 :          DO ik = 1, kpoint%nkp
     173        6568 :             kpoint%xkp(1:3, ik) = crys_sym%xkpoint(1:3, ik)
     174        1790 :             kpoint%wkp(ik) = crys_sym%wkpoint(ik)/wsum
     175             :          END DO
     176             : 
     177             :          ! print output
     178         148 :          IF (kpoint%symmetry) CALL print_crys_symmetry(crys_sym)
     179         148 :          IF (kpoint%symmetry) CALL print_kp_symmetry(crys_sym)
     180             : 
     181             :          ! transfer symmetry information
     182        2086 :          ALLOCATE (kpoint%kp_sym(kpoint%nkp))
     183        1790 :          DO ik = 1, kpoint%nkp
     184        1642 :             NULLIFY (kpoint%kp_sym(ik)%kpoint_sym)
     185        1642 :             CALL kpoint_sym_create(kpoint%kp_sym(ik)%kpoint_sym)
     186        1642 :             kpsym => kpoint%kp_sym(ik)%kpoint_sym
     187        1790 :             IF (crys_sym%symlib .AND. .NOT. crys_sym%fullgrid .AND. crys_sym%istriz == 1) THEN
     188             :                ! set up the symmetrization information
     189           0 :                kpsym%nwght = NINT(crys_sym%wkpoint(ik))
     190           0 :                ns = kpsym%nwght
     191             :                !
     192           0 :                IF (ns > 1) THEN
     193           0 :                   kpsym%apply_symmetry = .TRUE.
     194           0 :                   natom = SIZE(particle_set)
     195           0 :                   ALLOCATE (kpsym%rot(3, 3, ns))
     196           0 :                   ALLOCATE (kpsym%xkp(3, ns))
     197           0 :                   ALLOCATE (kpsym%rotp(ns))
     198           0 :                   ALLOCATE (kpsym%f0(natom, ns))
     199           0 :                   nr = 0
     200           0 :                   DO is = 1, SIZE(crys_sym%kplink, 2)
     201           0 :                      IF (crys_sym%kplink(2, is) == ik) THEN
     202           0 :                         nr = nr + 1
     203           0 :                         ir = crys_sym%kpop(is)
     204           0 :                         ira = ABS(ir)
     205           0 :                         kpsym%rotp(nr) = ir
     206           0 :                         IF (ir > 0) THEN
     207           0 :                            kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ira)
     208             :                         ELSE
     209           0 :                            kpsym%rot(1:3, 1:3, nr) = -crys_sym%rt(1:3, 1:3, ira)
     210             :                         END IF
     211           0 :                         kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
     212           0 :                         DO ic = 1, crys_sym%nrtot
     213           0 :                            IF (crys_sym%ibrot(ic) == ira) THEN
     214           0 :                               kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
     215             :                               EXIT
     216             :                            END IF
     217             :                         END DO
     218             :                      END IF
     219             :                   END DO
     220             :                   ! Reduce inversion?
     221           0 :                   kpsym%nwred = nr
     222             :                END IF
     223             :             END IF
     224             :          END DO
     225         148 :          IF (kpoint%symmetry) THEN
     226         360 :             nkind = MAXVAL(atype)
     227          48 :             ns = crys_sym%nrtot
     228         198 :             ALLOCATE (kpoint%kind_rotmat(ns, nkind))
     229          48 :             DO i = 1, ns
     230          48 :                DO j = 1, nkind
     231           0 :                   NULLIFY (kpoint%kind_rotmat(i, j)%rmat)
     232             :                END DO
     233             :             END DO
     234          96 :             ALLOCATE (kpoint%ibrot(ns))
     235          48 :             kpoint%ibrot(1:ns) = crys_sym%ibrot(1:ns)
     236             :          END IF
     237             : 
     238         148 :          CALL release_csym_type(crys_sym)
     239         148 :          DEALLOCATE (scoord, atype)
     240             : 
     241             :       CASE ("GENERAL")
     242             :          ! default: no symmetry settings
     243          12 :          ALLOCATE (kpoint%kp_sym(kpoint%nkp))
     244           8 :          DO i = 1, kpoint%nkp
     245           6 :             NULLIFY (kpoint%kp_sym(i)%kpoint_sym)
     246           8 :             CALL kpoint_sym_create(kpoint%kp_sym(i)%kpoint_sym)
     247             :          END DO
     248             :       CASE DEFAULT
     249        7324 :          CPASSERT(.FALSE.)
     250             :       END SELECT
     251             : 
     252             :       ! check for consistency of options
     253        7340 :       SELECT CASE (kpoint%kp_scheme)
     254             :       CASE ("NONE")
     255             :          ! don't use k-point code
     256             :       CASE ("GAMMA")
     257          16 :          CPASSERT(kpoint%nkp == 1)
     258          80 :          CPASSERT(SUM(ABS(kpoint%xkp)) <= 1.e-12_dp)
     259          16 :          CPASSERT(kpoint%wkp(1) == 1.0_dp)
     260          16 :          CPASSERT(.NOT. kpoint%symmetry)
     261             :       CASE ("GENERAL")
     262           2 :          CPASSERT(.NOT. kpoint%symmetry)
     263           2 :          CPASSERT(kpoint%nkp >= 1)
     264             :       CASE ("MONKHORST-PACK", "MACDONALD")
     265        7324 :          CPASSERT(kpoint%nkp >= 1)
     266             :       END SELECT
     267        7324 :       IF (kpoint%use_real_wfn) THEN
     268             :          ! what about inversion symmetry?
     269          24 :          ikloop: DO ik = 1, kpoint%nkp
     270          60 :             DO i = 1, 3
     271          36 :                spez = (kpoint%xkp(i, ik) == 0.0_dp .OR. kpoint%xkp(i, ik) == 0.5_dp)
     272          12 :                IF (.NOT. spez) EXIT ikloop
     273             :             END DO
     274             :          END DO ikloop
     275          12 :          IF (.NOT. spez) THEN
     276             :             ! Warning: real wfn might be wrong for this system
     277             :             CALL cp_warn(__LOCATION__, &
     278             :                          "A calculation using real wavefunctions is requested. "// &
     279           0 :                          "We could not determine if the symmetry of the system allows real wavefunctions. ")
     280             :          END IF
     281             :       END IF
     282             : 
     283        7324 :       CALL timestop(handle)
     284             : 
     285        7324 :    END SUBROUTINE kpoint_initialize
     286             : 
     287             : ! **************************************************************************************************
     288             : !> \brief Initialize the kpoint environment
     289             : !> \param kpoint       Kpoint environment
     290             : !> \param para_env ...
     291             : !> \param blacs_env ...
     292             : !> \param with_aux_fit ...
     293             : ! **************************************************************************************************
     294         224 :    SUBROUTINE kpoint_env_initialize(kpoint, para_env, blacs_env, with_aux_fit)
     295             : 
     296             :       TYPE(kpoint_type), INTENT(INOUT)                   :: kpoint
     297             :       TYPE(mp_para_env_type), INTENT(IN), TARGET         :: para_env
     298             :       TYPE(cp_blacs_env_type), INTENT(IN), TARGET        :: blacs_env
     299             :       LOGICAL, INTENT(IN), OPTIONAL                      :: with_aux_fit
     300             : 
     301             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_env_initialize'
     302             : 
     303             :       INTEGER                                            :: handle, igr, ik, ikk, ngr, niogrp, nkp, &
     304             :                                                             nkp_grp, nkp_loc, npe, unit_nr
     305             :       INTEGER, DIMENSION(2)                              :: dims, pos
     306             :       LOGICAL                                            :: aux_fit
     307         224 :       TYPE(kpoint_env_p_type), DIMENSION(:), POINTER     :: kp_aux_env, kp_env
     308             :       TYPE(kpoint_env_type), POINTER                     :: kp
     309         224 :       TYPE(mp_cart_type)                                 :: comm_cart
     310             :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp, para_env_kp
     311             : 
     312         224 :       CALL timeset(routineN, handle)
     313             : 
     314         224 :       IF (PRESENT(with_aux_fit)) THEN
     315         166 :          aux_fit = with_aux_fit
     316             :       ELSE
     317             :          aux_fit = .FALSE.
     318             :       END IF
     319             : 
     320         224 :       kpoint%para_env => para_env
     321         224 :       CALL kpoint%para_env%retain()
     322         224 :       kpoint%blacs_env_all => blacs_env
     323         224 :       CALL kpoint%blacs_env_all%retain()
     324             : 
     325         224 :       CPASSERT(.NOT. ASSOCIATED(kpoint%kp_env))
     326         224 :       IF (aux_fit) THEN
     327          28 :          CPASSERT(.NOT. ASSOCIATED(kpoint%kp_aux_env))
     328             :       END IF
     329             : 
     330         224 :       NULLIFY (kp_env, kp_aux_env)
     331         224 :       nkp = kpoint%nkp
     332         224 :       npe = para_env%num_pe
     333         224 :       IF (npe == 1) THEN
     334             :          ! only one process available -> owns all kpoints
     335           0 :          ALLOCATE (kp_env(nkp))
     336           0 :          DO ik = 1, nkp
     337           0 :             NULLIFY (kp_env(ik)%kpoint_env)
     338           0 :             CALL kpoint_env_create(kp_env(ik)%kpoint_env)
     339           0 :             kp => kp_env(ik)%kpoint_env
     340           0 :             kp%nkpoint = ik
     341           0 :             kp%wkp = kpoint%wkp(ik)
     342           0 :             kp%xkp(1:3) = kpoint%xkp(1:3, ik)
     343           0 :             kp%is_local = .TRUE.
     344             :          END DO
     345           0 :          kpoint%kp_env => kp_env
     346             : 
     347           0 :          IF (aux_fit) THEN
     348           0 :             ALLOCATE (kp_aux_env(nkp))
     349           0 :             DO ik = 1, nkp
     350           0 :                NULLIFY (kp_aux_env(ik)%kpoint_env)
     351           0 :                CALL kpoint_env_create(kp_aux_env(ik)%kpoint_env)
     352           0 :                kp => kp_aux_env(ik)%kpoint_env
     353           0 :                kp%nkpoint = ik
     354           0 :                kp%wkp = kpoint%wkp(ik)
     355           0 :                kp%xkp(1:3) = kpoint%xkp(1:3, ik)
     356           0 :                kp%is_local = .TRUE.
     357             :             END DO
     358             : 
     359           0 :             kpoint%kp_aux_env => kp_aux_env
     360             :          END IF
     361             : 
     362           0 :          ALLOCATE (kpoint%kp_dist(2, 1))
     363           0 :          kpoint%kp_dist(1, 1) = 1
     364           0 :          kpoint%kp_dist(2, 1) = nkp
     365           0 :          kpoint%kp_range(1) = 1
     366           0 :          kpoint%kp_range(2) = nkp
     367             : 
     368             :          ! parallel environments
     369           0 :          kpoint%para_env_kp => para_env
     370           0 :          CALL kpoint%para_env_kp%retain()
     371           0 :          kpoint%para_env_inter_kp => para_env
     372           0 :          CALL kpoint%para_env_inter_kp%retain()
     373           0 :          kpoint%iogrp = .TRUE.
     374           0 :          kpoint%nkp_groups = 1
     375             :       ELSE
     376         224 :          IF (kpoint%parallel_group_size == -1) THEN
     377             :             ! maximum parallelization over kpoints
     378             :             ! making sure that the group size divides the npe and the nkp_grp the nkp
     379             :             ! in the worst case, there will be no parallelism over kpoints.
     380         342 :             DO igr = npe, 1, -1
     381         228 :                IF (MOD(npe, igr) .NE. 0) CYCLE
     382         228 :                nkp_grp = npe/igr
     383         228 :                IF (MOD(nkp, nkp_grp) .NE. 0) CYCLE
     384         342 :                ngr = igr
     385             :             END DO
     386         110 :          ELSE IF (kpoint%parallel_group_size == 0) THEN
     387             :             ! no parallelization over kpoints
     388          62 :             ngr = npe
     389          48 :          ELSE IF (kpoint%parallel_group_size > 0) THEN
     390          48 :             ngr = MIN(kpoint%parallel_group_size, npe)
     391             :          ELSE
     392           0 :             CPASSERT(.FALSE.)
     393             :          END IF
     394         224 :          nkp_grp = npe/ngr
     395             :          ! processor dimensions
     396         224 :          dims(1) = ngr
     397         224 :          dims(2) = nkp_grp
     398         224 :          CPASSERT(MOD(nkp, nkp_grp) == 0)
     399         224 :          nkp_loc = nkp/nkp_grp
     400             : 
     401         224 :          IF ((dims(1)*dims(2) /= npe)) THEN
     402           0 :             CPABORT("Number of processors is not divisible by the kpoint group size.")
     403             :          END IF
     404             : 
     405             :          ! Create the subgroups, one for each k-point group and one interconnecting group
     406         224 :          CALL comm_cart%create(comm_old=para_env, ndims=2, dims=dims)
     407         672 :          pos = comm_cart%mepos_cart
     408         224 :          ALLOCATE (para_env_kp)
     409         224 :          CALL para_env_kp%from_split(comm_cart, pos(2))
     410         224 :          ALLOCATE (para_env_inter_kp)
     411         224 :          CALL para_env_inter_kp%from_split(comm_cart, pos(1))
     412         224 :          CALL comm_cart%free()
     413             : 
     414         224 :          niogrp = 0
     415         224 :          IF (para_env%is_source()) niogrp = 1
     416         224 :          CALL para_env_kp%sum(niogrp)
     417         224 :          kpoint%iogrp = (niogrp == 1)
     418             : 
     419             :          ! parallel groups
     420         224 :          kpoint%para_env_kp => para_env_kp
     421         224 :          kpoint%para_env_inter_kp => para_env_inter_kp
     422             : 
     423             :          ! distribution of kpoints
     424         672 :          ALLOCATE (kpoint%kp_dist(2, nkp_grp))
     425         528 :          DO igr = 1, nkp_grp
     426        1136 :             kpoint%kp_dist(1:2, igr) = get_limit(nkp, nkp_grp, igr - 1)
     427             :          END DO
     428             :          ! local kpoints
     429         672 :          kpoint%kp_range(1:2) = kpoint%kp_dist(1:2, para_env_inter_kp%mepos + 1)
     430             : 
     431        2192 :          ALLOCATE (kp_env(nkp_loc))
     432        1744 :          DO ik = 1, nkp_loc
     433        1520 :             NULLIFY (kp_env(ik)%kpoint_env)
     434        1520 :             ikk = kpoint%kp_range(1) + ik - 1
     435        1520 :             CALL kpoint_env_create(kp_env(ik)%kpoint_env)
     436        1520 :             kp => kp_env(ik)%kpoint_env
     437        1520 :             kp%nkpoint = ikk
     438        1520 :             kp%wkp = kpoint%wkp(ikk)
     439        6080 :             kp%xkp(1:3) = kpoint%xkp(1:3, ikk)
     440        1744 :             kp%is_local = (ngr == 1)
     441             :          END DO
     442         224 :          kpoint%kp_env => kp_env
     443             : 
     444         224 :          IF (aux_fit) THEN
     445         216 :             ALLOCATE (kp_aux_env(nkp_loc))
     446         188 :             DO ik = 1, nkp_loc
     447         160 :                NULLIFY (kp_aux_env(ik)%kpoint_env)
     448         160 :                ikk = kpoint%kp_range(1) + ik - 1
     449         160 :                CALL kpoint_env_create(kp_aux_env(ik)%kpoint_env)
     450         160 :                kp => kp_aux_env(ik)%kpoint_env
     451         160 :                kp%nkpoint = ikk
     452         160 :                kp%wkp = kpoint%wkp(ikk)
     453         640 :                kp%xkp(1:3) = kpoint%xkp(1:3, ikk)
     454         188 :                kp%is_local = (ngr == 1)
     455             :             END DO
     456          28 :             kpoint%kp_aux_env => kp_aux_env
     457             :          END IF
     458             : 
     459         224 :          unit_nr = cp_logger_get_default_io_unit()
     460             : 
     461         224 :          IF (unit_nr > 0 .AND. kpoint%verbose) THEN
     462           5 :             WRITE (unit_nr, *)
     463           5 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Number of kpoint groups ", nkp_grp
     464           5 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Size of each kpoint group", ngr
     465           5 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Number of kpoints per group", nkp_loc
     466             :          END IF
     467         224 :          kpoint%nkp_groups = nkp_grp
     468             : 
     469             :       END IF
     470             : 
     471         224 :       CALL timestop(handle)
     472             : 
     473         448 :    END SUBROUTINE kpoint_env_initialize
     474             : 
     475             : ! **************************************************************************************************
     476             : !> \brief Initialize a set of MOs and density matrix for each kpoint (kpoint group)
     477             : !> \param kpoint  Kpoint environment
     478             : !> \param mos     Reference MOs (global)
     479             : !> \param added_mos ...
     480             : !> \param for_aux_fit ...
     481             : ! **************************************************************************************************
     482         252 :    SUBROUTINE kpoint_initialize_mos(kpoint, mos, added_mos, for_aux_fit)
     483             : 
     484             :       TYPE(kpoint_type), POINTER                         :: kpoint
     485             :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
     486             :       INTEGER, INTENT(IN), OPTIONAL                      :: added_mos
     487             :       LOGICAL, OPTIONAL                                  :: for_aux_fit
     488             : 
     489             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_initialize_mos'
     490             : 
     491             :       INTEGER                                            :: handle, ic, ik, is, nadd, nao, nc, &
     492             :                                                             nelectron, nkp_loc, nmo, nmorig(2), &
     493             :                                                             nspin
     494             :       LOGICAL                                            :: aux_fit
     495             :       REAL(KIND=dp)                                      :: flexible_electron_count, maxocc, n_el_f
     496             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     497         252 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_ao_fm_pools
     498             :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     499             :       TYPE(cp_fm_type), POINTER                          :: fmlocal
     500             :       TYPE(kpoint_env_type), POINTER                     :: kp
     501             :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
     502             : 
     503         252 :       CALL timeset(routineN, handle)
     504             : 
     505         252 :       IF (PRESENT(for_aux_fit)) THEN
     506          28 :          aux_fit = for_aux_fit
     507             :       ELSE
     508             :          aux_fit = .FALSE.
     509             :       END IF
     510             : 
     511         252 :       CPASSERT(ASSOCIATED(kpoint))
     512             : 
     513             :       IF (.TRUE. .OR. ASSOCIATED(mos(1)%mo_coeff)) THEN
     514         252 :          IF (aux_fit) THEN
     515          28 :             CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
     516             :          END IF
     517             : 
     518         252 :          IF (PRESENT(added_mos)) THEN
     519          58 :             nadd = added_mos
     520             :          ELSE
     521             :             nadd = 0
     522             :          END IF
     523             : 
     524         252 :          IF (kpoint%use_real_wfn) THEN
     525             :             nc = 1
     526             :          ELSE
     527         240 :             nc = 2
     528             :          END IF
     529         252 :          nspin = SIZE(mos, 1)
     530         252 :          nkp_loc = kpoint%kp_range(2) - kpoint%kp_range(1) + 1
     531         252 :          IF (nkp_loc > 0) THEN
     532         252 :             IF (aux_fit) THEN
     533          28 :                CPASSERT(SIZE(kpoint%kp_aux_env) == nkp_loc)
     534             :             ELSE
     535         224 :                CPASSERT(SIZE(kpoint%kp_env) == nkp_loc)
     536             :             END IF
     537             :             ! allocate the mo sets, correct number of kpoints (local), real/complex, spin
     538        1932 :             DO ik = 1, nkp_loc
     539        1680 :                IF (aux_fit) THEN
     540         160 :                   kp => kpoint%kp_aux_env(ik)%kpoint_env
     541             :                ELSE
     542        1520 :                   kp => kpoint%kp_env(ik)%kpoint_env
     543             :                END IF
     544       12490 :                ALLOCATE (kp%mos(nc, nspin))
     545        3860 :                DO is = 1, nspin
     546             :                   CALL get_mo_set(mos(is), nao=nao, nmo=nmo, nelectron=nelectron, &
     547        1928 :                                   n_el_f=n_el_f, maxocc=maxocc, flexible_electron_count=flexible_electron_count)
     548        1928 :                   nmo = MIN(nao, nmo + nadd)
     549        7450 :                   DO ic = 1, nc
     550             :                      CALL allocate_mo_set(kp%mos(ic, is), nao, nmo, nelectron, n_el_f, maxocc, &
     551        5770 :                                           flexible_electron_count)
     552             :                   END DO
     553             :                END DO
     554             :             END DO
     555             : 
     556             :             ! generate the blacs environment for the kpoint group
     557             :             ! we generate a blacs env for each kpoint group in parallel
     558             :             ! we assume here that the group para_env_inter_kp will connect
     559             :             ! equivalent parts of fm matrices, i.e. no reshuffeling of processors
     560         252 :             NULLIFY (blacs_env)
     561         252 :             IF (ASSOCIATED(kpoint%blacs_env)) THEN
     562          28 :                blacs_env => kpoint%blacs_env
     563             :             ELSE
     564         224 :                CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=kpoint%para_env_kp)
     565         224 :                kpoint%blacs_env => blacs_env
     566             :             END IF
     567             : 
     568             :             ! set possible new number of MOs
     569         540 :             DO is = 1, nspin
     570         288 :                CALL get_mo_set(mos(is), nmo=nmorig(is))
     571         288 :                nmo = MIN(nao, nmorig(is) + nadd)
     572         540 :                CALL set_mo_set(mos(is), nmo=nmo)
     573             :             END DO
     574             :             ! matrix pools for the kpoint group, information on MOs is transferred using
     575             :             ! generic mos structure
     576         252 :             NULLIFY (mpools)
     577         252 :             CALL mpools_create(mpools=mpools)
     578             :             CALL mpools_rebuild_fm_pools(mpools=mpools, mos=mos, &
     579         252 :                                          blacs_env=blacs_env, para_env=kpoint%para_env_kp)
     580             : 
     581         252 :             IF (aux_fit) THEN
     582          28 :                kpoint%mpools_aux_fit => mpools
     583             :             ELSE
     584         224 :                kpoint%mpools => mpools
     585             :             END IF
     586             : 
     587             :             ! reset old number of MOs
     588         540 :             DO is = 1, nspin
     589         540 :                CALL set_mo_set(mos(is), nmo=nmorig(is))
     590             :             END DO
     591             : 
     592             :             ! allocate density matrices
     593         252 :             CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
     594         252 :             ALLOCATE (fmlocal)
     595         252 :             CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
     596         252 :             CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
     597        1932 :             DO ik = 1, nkp_loc
     598        1680 :                IF (aux_fit) THEN
     599         160 :                   kp => kpoint%kp_aux_env(ik)%kpoint_env
     600             :                ELSE
     601        1520 :                   kp => kpoint%kp_env(ik)%kpoint_env
     602             :                END IF
     603             :                ! density matrix
     604        1680 :                CALL cp_fm_release(kp%pmat)
     605       12490 :                ALLOCATE (kp%pmat(nc, nspin))
     606        3608 :                DO is = 1, nspin
     607        7450 :                   DO ic = 1, nc
     608        5770 :                      CALL cp_fm_create(kp%pmat(ic, is), matrix_struct)
     609             :                   END DO
     610             :                END DO
     611             :                ! energy weighted density matrix
     612        1680 :                CALL cp_fm_release(kp%wmat)
     613       10810 :                ALLOCATE (kp%wmat(nc, nspin))
     614        3860 :                DO is = 1, nspin
     615        7450 :                   DO ic = 1, nc
     616        5770 :                      CALL cp_fm_create(kp%wmat(ic, is), matrix_struct)
     617             :                   END DO
     618             :                END DO
     619             :             END DO
     620         252 :             CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
     621         252 :             DEALLOCATE (fmlocal)
     622             : 
     623             :          END IF
     624             : 
     625             :       END IF
     626             : 
     627         252 :       CALL timestop(handle)
     628             : 
     629         252 :    END SUBROUTINE kpoint_initialize_mos
     630             : 
     631             : ! **************************************************************************************************
     632             : !> \brief ...
     633             : !> \param kpoint ...
     634             : ! **************************************************************************************************
     635          58 :    SUBROUTINE kpoint_initialize_mo_set(kpoint)
     636             :       TYPE(kpoint_type), POINTER                         :: kpoint
     637             : 
     638             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_initialize_mo_set'
     639             : 
     640             :       INTEGER                                            :: handle, ic, ik, ikk, ispin
     641          58 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_mo_fm_pools
     642             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     643          58 :       TYPE(mo_set_type), DIMENSION(:, :), POINTER        :: moskp
     644             : 
     645          58 :       CALL timeset(routineN, handle)
     646             : 
     647         404 :       DO ik = 1, SIZE(kpoint%kp_env)
     648         346 :          CALL mpools_get(kpoint%mpools, ao_mo_fm_pools=ao_mo_fm_pools)
     649         346 :          moskp => kpoint%kp_env(ik)%kpoint_env%mos
     650         346 :          ikk = kpoint%kp_range(1) + ik - 1
     651         346 :          CPASSERT(ASSOCIATED(moskp))
     652         784 :          DO ispin = 1, SIZE(moskp, 2)
     653        1486 :             DO ic = 1, SIZE(moskp, 1)
     654         760 :                CALL get_mo_set(moskp(ic, ispin), mo_coeff=mo_coeff)
     655        1140 :                IF (.NOT. ASSOCIATED(mo_coeff)) THEN
     656             :                   CALL init_mo_set(moskp(ic, ispin), &
     657         760 :                                    fm_pool=ao_mo_fm_pools(ispin)%pool, name="kpoints")
     658             :                END IF
     659             :             END DO
     660             :          END DO
     661             :       END DO
     662             : 
     663          58 :       CALL timestop(handle)
     664             : 
     665          58 :    END SUBROUTINE kpoint_initialize_mo_set
     666             : 
     667             : ! **************************************************************************************************
     668             : !> \brief Generates the mapping of cell indices and linear RS index
     669             : !>        CELL (0,0,0) is always mapped to index 1
     670             : !> \param kpoint    Kpoint environment
     671             : !> \param sab_nl    Defining neighbour list
     672             : !> \param para_env  Parallel environment
     673             : !> \param dft_control ...
     674             : ! **************************************************************************************************
     675         988 :    SUBROUTINE kpoint_init_cell_index(kpoint, sab_nl, para_env, dft_control)
     676             : 
     677             :       TYPE(kpoint_type), POINTER                         :: kpoint
     678             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     679             :          POINTER                                         :: sab_nl
     680             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     681             :       TYPE(dft_control_type), POINTER                    :: dft_control
     682             : 
     683             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_init_cell_index'
     684             : 
     685             :       INTEGER                                            :: handle, i1, i2, i3, ic, icount, it, &
     686             :                                                             ncount
     687             :       INTEGER, DIMENSION(3)                              :: cell, itm
     688         988 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell, list
     689         988 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index, cti
     690             :       LOGICAL                                            :: new
     691             :       TYPE(neighbor_list_iterator_p_type), &
     692         988 :          DIMENSION(:), POINTER                           :: nl_iterator
     693             : 
     694         988 :       NULLIFY (cell_to_index, index_to_cell)
     695             : 
     696         988 :       CALL timeset(routineN, handle)
     697             : 
     698         988 :       CPASSERT(ASSOCIATED(kpoint))
     699             : 
     700         988 :       ALLOCATE (list(3, 125))
     701      494988 :       list = 0
     702         988 :       icount = 1
     703             : 
     704         988 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
     705      607386 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     706      606398 :          CALL get_iterator_info(nl_iterator, cell=cell)
     707             : 
     708      606398 :          new = .TRUE.
     709    35871597 :          DO ic = 1, icount
     710    35790766 :             IF (cell(1) == list(1, ic) .AND. cell(2) == list(2, ic) .AND. &
     711       80831 :                 cell(3) == list(3, ic)) THEN
     712             :                new = .FALSE.
     713             :                EXIT
     714             :             END IF
     715             :          END DO
     716      607386 :          IF (new) THEN
     717       80831 :             icount = icount + 1
     718       80831 :             IF (icount > SIZE(list, 2)) THEN
     719         273 :                CALL reallocate(list, 1, 3, 1, 2*SIZE(list, 2))
     720             :             END IF
     721      323324 :             list(1:3, icount) = cell(1:3)
     722             :          END IF
     723             : 
     724             :       END DO
     725         988 :       CALL neighbor_list_iterator_release(nl_iterator)
     726             : 
     727       82807 :       itm(1) = MAXVAL(ABS(list(1, 1:icount)))
     728       82807 :       itm(2) = MAXVAL(ABS(list(2, 1:icount)))
     729       82807 :       itm(3) = MAXVAL(ABS(list(3, 1:icount)))
     730         988 :       CALL para_env%max(itm)
     731        3952 :       it = MAXVAL(itm(1:3))
     732         988 :       IF (ASSOCIATED(kpoint%cell_to_index)) THEN
     733         984 :          DEALLOCATE (kpoint%cell_to_index)
     734             :       END IF
     735        4940 :       ALLOCATE (kpoint%cell_to_index(-itm(1):itm(1), -itm(2):itm(2), -itm(3):itm(3)))
     736         988 :       cell_to_index => kpoint%cell_to_index
     737         988 :       cti => cell_to_index
     738      199900 :       cti(:, :, :) = 0
     739       82807 :       DO ic = 1, icount
     740       81819 :          i1 = list(1, ic)
     741       81819 :          i2 = list(2, ic)
     742       81819 :          i3 = list(3, ic)
     743       82807 :          cti(i1, i2, i3) = ic
     744             :       END DO
     745      398812 :       CALL para_env%sum(cti)
     746         988 :       ncount = 0
     747        5748 :       DO i1 = -itm(1), itm(1)
     748       34832 :          DO i2 = -itm(2), itm(2)
     749      200472 :             DO i3 = -itm(3), itm(3)
     750      195712 :                IF (cti(i1, i2, i3) == 0) THEN
     751       76028 :                   cti(i1, i2, i3) = 1000000
     752             :                ELSE
     753       90600 :                   ncount = ncount + 1
     754       90600 :                   cti(i1, i2, i3) = (ABS(i1) + ABS(i2) + ABS(i3))*1000 + ABS(i3)*100 + ABS(i2)*10 + ABS(i1)
     755       90600 :                   cti(i1, i2, i3) = cti(i1, i2, i3) + (i1 + i2 + i3)
     756             :                END IF
     757             :             END DO
     758             :          END DO
     759             :       END DO
     760             : 
     761         988 :       IF (ASSOCIATED(kpoint%index_to_cell)) THEN
     762         988 :          DEALLOCATE (kpoint%index_to_cell)
     763             :       END IF
     764        2964 :       ALLOCATE (kpoint%index_to_cell(3, ncount))
     765         988 :       index_to_cell => kpoint%index_to_cell
     766       91588 :       DO ic = 1, ncount
     767       90600 :          cell = MINLOC(cti)
     768       90600 :          i1 = cell(1) - 1 - itm(1)
     769       90600 :          i2 = cell(2) - 1 - itm(2)
     770       90600 :          i3 = cell(3) - 1 - itm(3)
     771       90600 :          cti(i1, i2, i3) = 1000000
     772       90600 :          index_to_cell(1, ic) = i1
     773       90600 :          index_to_cell(2, ic) = i2
     774       91588 :          index_to_cell(3, ic) = i3
     775             :       END DO
     776      199900 :       cti(:, :, :) = 0
     777       91588 :       DO ic = 1, ncount
     778       90600 :          i1 = index_to_cell(1, ic)
     779       90600 :          i2 = index_to_cell(2, ic)
     780       90600 :          i3 = index_to_cell(3, ic)
     781       91588 :          cti(i1, i2, i3) = ic
     782             :       END DO
     783             : 
     784             :       ! keep pointer to this neighborlist
     785         988 :       kpoint%sab_nl => sab_nl
     786             : 
     787             :       ! set number of images
     788         988 :       dft_control%nimages = SIZE(index_to_cell, 2)
     789             : 
     790         988 :       DEALLOCATE (list)
     791             : 
     792         988 :       CALL timestop(handle)
     793         988 :    END SUBROUTINE kpoint_init_cell_index
     794             : 
     795             : ! **************************************************************************************************
     796             : !> \brief Transformation of real space matrices to a kpoint
     797             : !> \param rmatrix  Real part of kpoint matrix
     798             : !> \param cmatrix  Complex part of kpoint matrix (optional)
     799             : !> \param rsmat    Real space matrices
     800             : !> \param ispin    Spin index
     801             : !> \param xkp      Kpoint coordinates
     802             : !> \param cell_to_index   mapping of cell indices to RS index
     803             : !> \param sab_nl   Defining neighbor list
     804             : !> \param is_complex  Matrix to be transformed is imaginary
     805             : !> \param rs_sign  Matrix to be transformed is csaled by rs_sign
     806             : ! **************************************************************************************************
     807      100260 :    SUBROUTINE rskp_transform(rmatrix, cmatrix, rsmat, ispin, &
     808             :                              xkp, cell_to_index, sab_nl, is_complex, rs_sign)
     809             : 
     810             :       TYPE(dbcsr_type)                                   :: rmatrix
     811             :       TYPE(dbcsr_type), OPTIONAL                         :: cmatrix
     812             :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rsmat
     813             :       INTEGER, INTENT(IN)                                :: ispin
     814             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xkp
     815             :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     816             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     817             :          POINTER                                         :: sab_nl
     818             :       LOGICAL, INTENT(IN), OPTIONAL                      :: is_complex
     819             :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: rs_sign
     820             : 
     821             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'rskp_transform'
     822             : 
     823             :       INTEGER                                            :: handle, iatom, ic, icol, irow, jatom, &
     824             :                                                             nimg
     825             :       INTEGER, DIMENSION(3)                              :: cell
     826             :       LOGICAL                                            :: do_symmetric, found, my_complex, &
     827             :                                                             wfn_real_only
     828             :       REAL(KIND=dp)                                      :: arg, coskl, fsign, fsym, sinkl
     829       50130 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, rblock, rsblock
     830             :       TYPE(neighbor_list_iterator_p_type), &
     831       50130 :          DIMENSION(:), POINTER                           :: nl_iterator
     832             : 
     833       50130 :       CALL timeset(routineN, handle)
     834             : 
     835       50130 :       my_complex = .FALSE.
     836       50130 :       IF (PRESENT(is_complex)) my_complex = is_complex
     837             : 
     838       50130 :       fsign = 1.0_dp
     839       50130 :       IF (PRESENT(rs_sign)) fsign = rs_sign
     840             : 
     841       50130 :       wfn_real_only = .TRUE.
     842       50130 :       IF (PRESENT(cmatrix)) wfn_real_only = .FALSE.
     843             : 
     844       50130 :       nimg = SIZE(rsmat, 2)
     845             : 
     846       50130 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
     847             : 
     848       50130 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
     849    22192942 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     850    22142812 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom, cell=cell)
     851             : 
     852             :          ! fsym = +- 1 is due to real space matrices being non-symmetric (although in a symmtric type)
     853             :          ! with the link S_mu^0,nu^b = S_nu^0,mu^-b, and the KP matrices beeing Hermitian
     854    22142812 :          fsym = 1.0_dp
     855    22142812 :          irow = iatom
     856    22142812 :          icol = jatom
     857    22142812 :          IF (do_symmetric .AND. (iatom > jatom)) THEN
     858     9377774 :             irow = jatom
     859     9377774 :             icol = iatom
     860     9377774 :             fsym = -1.0_dp
     861             :          END IF
     862             : 
     863    22142812 :          ic = cell_to_index(cell(1), cell(2), cell(3))
     864    22142812 :          IF (ic < 1 .OR. ic > nimg) CYCLE
     865             : 
     866    22142068 :          arg = REAL(cell(1), dp)*xkp(1) + REAL(cell(2), dp)*xkp(2) + REAL(cell(3), dp)*xkp(3)
     867    22142068 :          IF (my_complex) THEN
     868           0 :             coskl = fsign*fsym*COS(twopi*arg)
     869           0 :             sinkl = fsign*SIN(twopi*arg)
     870             :          ELSE
     871    22142068 :             coskl = fsign*COS(twopi*arg)
     872    22142068 :             sinkl = fsign*fsym*SIN(twopi*arg)
     873             :          END IF
     874             : 
     875             :          CALL dbcsr_get_block_p(matrix=rsmat(ispin, ic)%matrix, row=irow, col=icol, &
     876    22142068 :                                 block=rsblock, found=found)
     877    22142068 :          IF (.NOT. found) CYCLE
     878             : 
     879    22192198 :          IF (wfn_real_only) THEN
     880             :             CALL dbcsr_get_block_p(matrix=rmatrix, row=irow, col=icol, &
     881      303864 :                                    block=rblock, found=found)
     882      303864 :             IF (.NOT. found) CYCLE
     883   153367320 :             rblock = rblock + coskl*rsblock
     884             :          ELSE
     885             :             CALL dbcsr_get_block_p(matrix=rmatrix, row=irow, col=icol, &
     886    21838204 :                                    block=rblock, found=found)
     887    21838204 :             IF (.NOT. found) CYCLE
     888             :             CALL dbcsr_get_block_p(matrix=cmatrix, row=irow, col=icol, &
     889    21838204 :                                    block=cblock, found=found)
     890    21838204 :             IF (.NOT. found) CYCLE
     891  4280031184 :             rblock = rblock + coskl*rsblock
     892  4280031184 :             cblock = cblock + sinkl*rsblock
     893             :          END IF
     894             : 
     895             :       END DO
     896       50130 :       CALL neighbor_list_iterator_release(nl_iterator)
     897             : 
     898       50130 :       CALL timestop(handle)
     899             : 
     900       50130 :    END SUBROUTINE rskp_transform
     901             : 
     902             : ! **************************************************************************************************
     903             : !> \brief Given the eigenvalues of all kpoints, calculates the occupation numbers
     904             : !> \param kpoint  Kpoint environment
     905             : !> \param smear   Smearing information
     906             : ! **************************************************************************************************
     907        5464 :    SUBROUTINE kpoint_set_mo_occupation(kpoint, smear)
     908             : 
     909             :       TYPE(kpoint_type), POINTER                         :: kpoint
     910             :       TYPE(smear_type), POINTER                          :: smear
     911             : 
     912             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_set_mo_occupation'
     913             : 
     914             :       INTEGER                                            :: handle, ik, ikpgr, ispin, kplocal, nb, &
     915             :                                                             ne_a, ne_b, nelectron, nkp, nmo, nspin
     916             :       INTEGER, DIMENSION(2)                              :: kp_range
     917             :       REAL(KIND=dp)                                      :: kTS, mu, mus(2), nel
     918        5464 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: weig, wocc
     919        5464 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation, wkp
     920             :       TYPE(kpoint_env_type), POINTER                     :: kp
     921             :       TYPE(mo_set_type), POINTER                         :: mo_set
     922             :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
     923             : 
     924        5464 :       CALL timeset(routineN, handle)
     925             : 
     926             :       ! first collect all the eigenvalues
     927        5464 :       CALL get_kpoint_info(kpoint, nkp=nkp)
     928        5464 :       kp => kpoint%kp_env(1)%kpoint_env
     929        5464 :       nspin = SIZE(kp%mos, 2)
     930        5464 :       mo_set => kp%mos(1, 1)
     931        5464 :       CALL get_mo_set(mo_set, nmo=nmo, nelectron=nelectron)
     932        5464 :       ne_a = nelectron
     933        5464 :       IF (nspin == 2) THEN
     934         542 :          CALL get_mo_set(kp%mos(1, 2), nmo=nb, nelectron=ne_b)
     935         542 :          CPASSERT(nmo == nb)
     936             :       END IF
     937       43712 :       ALLOCATE (weig(nmo, nkp, nspin), wocc(nmo, nkp, nspin))
     938      462772 :       weig = 0.0_dp
     939      462772 :       wocc = 0.0_dp
     940        5464 :       CALL get_kpoint_info(kpoint, kp_range=kp_range)
     941        5464 :       kplocal = kp_range(2) - kp_range(1) + 1
     942       19024 :       DO ikpgr = 1, kplocal
     943       13560 :          ik = kp_range(1) + ikpgr - 1
     944       13560 :          kp => kpoint%kp_env(ikpgr)%kpoint_env
     945       34452 :          DO ispin = 1, nspin
     946       15428 :             mo_set => kp%mos(1, ispin)
     947       15428 :             CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
     948      343256 :             weig(1:nmo, ik, ispin) = eigenvalues(1:nmo)
     949             :          END DO
     950             :       END DO
     951        5464 :       CALL get_kpoint_info(kpoint, para_env_inter_kp=para_env_inter_kp)
     952        5464 :       CALL para_env_inter_kp%sum(weig)
     953             : 
     954        5464 :       CALL get_kpoint_info(kpoint, wkp=wkp)
     955        5464 :       IF (smear%do_smear) THEN
     956             :          ! finite electronic temperature
     957        1412 :          SELECT CASE (smear%method)
     958             :          CASE (smear_fermi_dirac)
     959         706 :             IF (nspin == 1) THEN
     960         694 :                nel = REAL(nelectron, KIND=dp)
     961             :                CALL Fermikp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
     962         694 :                             smear%electronic_temperature, 2.0_dp)
     963          12 :             ELSE IF (smear%fixed_mag_mom > 0.0_dp) THEN
     964           2 :                nel = REAL(ne_a, KIND=dp)
     965             :                CALL Fermikp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
     966           2 :                             smear%electronic_temperature, 1.0_dp)
     967           2 :                nel = REAL(ne_b, KIND=dp)
     968             :                CALL Fermikp(wocc(:, :, 2), mus(2), kTS, weig(:, :, 2), nel, wkp, &
     969           2 :                             smear%electronic_temperature, 1.0_dp)
     970             :             ELSE
     971          10 :                nel = REAL(ne_a, KIND=dp) + REAL(ne_b, KIND=dp)
     972             :                CALL Fermikp2(wocc(:, :, :), mu, kTS, weig(:, :, :), nel, wkp, &
     973          10 :                              smear%electronic_temperature)
     974          10 :                kTS = kTS/2._dp
     975          30 :                mus(1:2) = mu
     976             :             END IF
     977             :          CASE DEFAULT
     978         706 :             CPABORT("kpoints: Selected smearing not (yet) supported")
     979             :          END SELECT
     980             :       ELSE
     981             :          ! fixed occupations (2/1)
     982        4758 :          IF (nspin == 1) THEN
     983        4228 :             nel = REAL(nelectron, KIND=dp)
     984        4228 :             CALL Fermikp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, 0.0_dp, 2.0_dp)
     985             :          ELSE
     986         530 :             nel = REAL(ne_a, KIND=dp)
     987         530 :             CALL Fermikp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, 0.0_dp, 1.0_dp)
     988         530 :             nel = REAL(ne_b, KIND=dp)
     989         530 :             CALL Fermikp(wocc(:, :, 2), mus(2), kTS, weig(:, :, 2), nel, wkp, 0.0_dp, 1.0_dp)
     990             :          END IF
     991             :       END IF
     992       19024 :       DO ikpgr = 1, kplocal
     993       13560 :          ik = kp_range(1) + ikpgr - 1
     994       13560 :          kp => kpoint%kp_env(ikpgr)%kpoint_env
     995       34452 :          DO ispin = 1, nspin
     996       15428 :             mo_set => kp%mos(1, ispin)
     997       15428 :             CALL get_mo_set(mo_set, eigenvalues=eigenvalues, occupation_numbers=occupation)
     998      329696 :             eigenvalues(1:nmo) = weig(1:nmo, ik, ispin)
     999      329696 :             occupation(1:nmo) = wocc(1:nmo, ik, ispin)
    1000       15428 :             mo_set%kTS = kTS
    1001       28988 :             mo_set%mu = mus(ispin)
    1002             :          END DO
    1003             :       END DO
    1004             : 
    1005        5464 :       DEALLOCATE (weig, wocc)
    1006             : 
    1007        5464 :       CALL timestop(handle)
    1008             : 
    1009       10928 :    END SUBROUTINE kpoint_set_mo_occupation
    1010             : 
    1011             : ! **************************************************************************************************
    1012             : !> \brief Calculate kpoint density matrices (rho(k), owned by kpoint groups)
    1013             : !> \param kpoint    kpoint environment
    1014             : !> \param energy_weighted  calculate energy weighted density matrix
    1015             : !> \param for_aux_fit ...
    1016             : ! **************************************************************************************************
    1017       17082 :    SUBROUTINE kpoint_density_matrices(kpoint, energy_weighted, for_aux_fit)
    1018             : 
    1019             :       TYPE(kpoint_type), POINTER                         :: kpoint
    1020             :       LOGICAL, OPTIONAL                                  :: energy_weighted, for_aux_fit
    1021             : 
    1022             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_density_matrices'
    1023             : 
    1024             :       INTEGER                                            :: handle, ikpgr, ispin, kplocal, nao, nmo, &
    1025             :                                                             nspin
    1026             :       INTEGER, DIMENSION(2)                              :: kp_range
    1027             :       LOGICAL                                            :: aux_fit, wtype
    1028        5694 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation
    1029             :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1030             :       TYPE(cp_fm_type)                                   :: fwork
    1031             :       TYPE(cp_fm_type), POINTER                          :: cpmat, pmat, rpmat
    1032             :       TYPE(kpoint_env_type), POINTER                     :: kp
    1033             :       TYPE(mo_set_type), POINTER                         :: mo_set
    1034             : 
    1035        5694 :       CALL timeset(routineN, handle)
    1036             : 
    1037        5694 :       IF (PRESENT(energy_weighted)) THEN
    1038         152 :          wtype = energy_weighted
    1039             :       ELSE
    1040             :          ! default is normal density matrix
    1041             :          wtype = .FALSE.
    1042             :       END IF
    1043             : 
    1044        5694 :       IF (PRESENT(for_aux_fit)) THEN
    1045          62 :          aux_fit = for_aux_fit
    1046             :       ELSE
    1047             :          aux_fit = .FALSE.
    1048             :       END IF
    1049             : 
    1050          62 :       IF (aux_fit) THEN
    1051          62 :          CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
    1052             :       END IF
    1053             : 
    1054             :       ! work matrix
    1055        5694 :       IF (aux_fit) THEN
    1056          62 :          mo_set => kpoint%kp_aux_env(1)%kpoint_env%mos(1, 1)
    1057             :       ELSE
    1058        5632 :          mo_set => kpoint%kp_env(1)%kpoint_env%mos(1, 1)
    1059             :       END IF
    1060        5694 :       CALL get_mo_set(mo_set, nao=nao, nmo=nmo)
    1061        5694 :       CALL cp_fm_get_info(mo_set%mo_coeff, matrix_struct=matrix_struct)
    1062        5694 :       CALL cp_fm_create(fwork, matrix_struct)
    1063             : 
    1064        5694 :       CALL get_kpoint_info(kpoint, kp_range=kp_range)
    1065        5694 :       kplocal = kp_range(2) - kp_range(1) + 1
    1066       20412 :       DO ikpgr = 1, kplocal
    1067       14718 :          IF (aux_fit) THEN
    1068         352 :             kp => kpoint%kp_aux_env(ikpgr)%kpoint_env
    1069             :          ELSE
    1070       14366 :             kp => kpoint%kp_env(ikpgr)%kpoint_env
    1071             :          END IF
    1072       14718 :          nspin = SIZE(kp%mos, 2)
    1073       37246 :          DO ispin = 1, nspin
    1074       16834 :             mo_set => kp%mos(1, ispin)
    1075       16834 :             IF (wtype) THEN
    1076         826 :                CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
    1077             :             END IF
    1078       31552 :             IF (kpoint%use_real_wfn) THEN
    1079          72 :                IF (wtype) THEN
    1080          10 :                   pmat => kp%wmat(1, ispin)
    1081             :                ELSE
    1082          62 :                   pmat => kp%pmat(1, ispin)
    1083             :                END IF
    1084          72 :                CALL get_mo_set(mo_set, occupation_numbers=occupation)
    1085          72 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1086          72 :                CALL cp_fm_column_scale(fwork, occupation)
    1087          72 :                IF (wtype) THEN
    1088          10 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1089             :                END IF
    1090          72 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, pmat)
    1091             :             ELSE
    1092       16762 :                IF (wtype) THEN
    1093         816 :                   rpmat => kp%wmat(1, ispin)
    1094         816 :                   cpmat => kp%wmat(2, ispin)
    1095             :                ELSE
    1096       15946 :                   rpmat => kp%pmat(1, ispin)
    1097       15946 :                   cpmat => kp%pmat(2, ispin)
    1098             :                END IF
    1099       16762 :                CALL get_mo_set(mo_set, occupation_numbers=occupation)
    1100       16762 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1101       16762 :                CALL cp_fm_column_scale(fwork, occupation)
    1102       16762 :                IF (wtype) THEN
    1103         816 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1104             :                END IF
    1105             :                ! Re(c)*Re(c)
    1106       16762 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, rpmat)
    1107       16762 :                mo_set => kp%mos(2, ispin)
    1108             :                ! Im(c)*Re(c)
    1109       16762 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, cpmat)
    1110             :                ! Re(c)*Im(c)
    1111       16762 :                CALL parallel_gemm("N", "T", nao, nao, nmo, -1.0_dp, fwork, mo_set%mo_coeff, 1.0_dp, cpmat)
    1112       16762 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1113       16762 :                CALL cp_fm_column_scale(fwork, occupation)
    1114       16762 :                IF (wtype) THEN
    1115         816 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1116             :                END IF
    1117             :                ! Im(c)*Im(c)
    1118       16762 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 1.0_dp, rpmat)
    1119             :             END IF
    1120             :          END DO
    1121             :       END DO
    1122             : 
    1123        5694 :       CALL cp_fm_release(fwork)
    1124             : 
    1125        5694 :       CALL timestop(handle)
    1126             : 
    1127        5694 :    END SUBROUTINE kpoint_density_matrices
    1128             : 
    1129             : ! **************************************************************************************************
    1130             : !> \brief generate real space density matrices in DBCSR format
    1131             : !> \param kpoint  Kpoint environment
    1132             : !> \param denmat  Real space (DBCSR) density matrices
    1133             : !> \param wtype   True = energy weighted density matrix
    1134             : !>                False = normal density matrix
    1135             : !> \param tempmat DBCSR matrix to be used as template
    1136             : !> \param sab_nl ...
    1137             : !> \param fmwork  FM work matrices (kpoint group)
    1138             : !> \param for_aux_fit ...
    1139             : !> \param pmat_ext ...
    1140             : ! **************************************************************************************************
    1141        5860 :    SUBROUTINE kpoint_density_transform(kpoint, denmat, wtype, tempmat, sab_nl, fmwork, for_aux_fit, pmat_ext)
    1142             : 
    1143             :       TYPE(kpoint_type), POINTER                         :: kpoint
    1144             :       TYPE(dbcsr_p_type), DIMENSION(:, :)                :: denmat
    1145             :       LOGICAL, INTENT(IN)                                :: wtype
    1146             :       TYPE(dbcsr_type), POINTER                          :: tempmat
    1147             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1148             :          POINTER                                         :: sab_nl
    1149             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fmwork
    1150             :       LOGICAL, OPTIONAL                                  :: for_aux_fit
    1151             :       TYPE(cp_fm_type), DIMENSION(:, :, :), INTENT(IN), &
    1152             :          OPTIONAL                                        :: pmat_ext
    1153             : 
    1154             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_density_transform'
    1155             : 
    1156             :       INTEGER                                            :: handle, ic, ik, ikk, indx, ir, ira, is, &
    1157             :                                                             ispin, jr, nc, nimg, nkp, nspin
    1158        5860 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1159             :       LOGICAL                                            :: aux_fit, do_ext, do_symmetric, my_kpgrp, &
    1160             :                                                             real_only
    1161             :       REAL(KIND=dp)                                      :: wkpx
    1162        5860 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    1163        5860 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1164        5860 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:)    :: info
    1165             :       TYPE(cp_fm_type)                                   :: fmdummy
    1166             :       TYPE(dbcsr_type), POINTER                          :: cpmat, rpmat, scpmat, srpmat
    1167        5860 :       TYPE(kind_rotmat_type), DIMENSION(:), POINTER      :: kind_rot
    1168             :       TYPE(kpoint_env_type), POINTER                     :: kp
    1169             :       TYPE(kpoint_sym_type), POINTER                     :: kpsym
    1170             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1171             : 
    1172        5860 :       CALL timeset(routineN, handle)
    1173             : 
    1174        5860 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    1175             : 
    1176        5860 :       IF (PRESENT(for_aux_fit)) THEN
    1177         228 :          aux_fit = for_aux_fit
    1178             :       ELSE
    1179             :          aux_fit = .FALSE.
    1180             :       END IF
    1181             : 
    1182        5860 :       do_ext = .FALSE.
    1183        5860 :       IF (PRESENT(pmat_ext)) do_ext = .TRUE.
    1184             : 
    1185        5860 :       IF (aux_fit) THEN
    1186         138 :          CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
    1187             :       END IF
    1188             : 
    1189             :       ! work storage
    1190        5860 :       ALLOCATE (rpmat)
    1191             :       CALL dbcsr_create(rpmat, template=tempmat, &
    1192        5908 :                         matrix_type=MERGE(dbcsr_type_symmetric, dbcsr_type_no_symmetry, do_symmetric))
    1193        5860 :       CALL cp_dbcsr_alloc_block_from_nbl(rpmat, sab_nl)
    1194        5860 :       CALL dbcsr_set(rpmat, 0.0_dp)
    1195        5860 :       ALLOCATE (cpmat)
    1196             :       CALL dbcsr_create(cpmat, template=tempmat, &
    1197        5908 :                         matrix_type=MERGE(dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, do_symmetric))
    1198        5860 :       CALL cp_dbcsr_alloc_block_from_nbl(cpmat, sab_nl)
    1199        5860 :       CALL dbcsr_set(cpmat, 0.0_dp)
    1200        5860 :       IF (.NOT. kpoint%full_grid) THEN
    1201        4784 :          ALLOCATE (srpmat)
    1202        4784 :          CALL dbcsr_create(srpmat, template=rpmat)
    1203        4784 :          CALL cp_dbcsr_alloc_block_from_nbl(srpmat, sab_nl)
    1204        4784 :          CALL dbcsr_set(srpmat, 0.0_dp)
    1205        4784 :          ALLOCATE (scpmat)
    1206        4784 :          CALL dbcsr_create(scpmat, template=cpmat)
    1207        4784 :          CALL cp_dbcsr_alloc_block_from_nbl(scpmat, sab_nl)
    1208        4784 :          CALL dbcsr_set(scpmat, 0.0_dp)
    1209             :       END IF
    1210             : 
    1211             :       CALL get_kpoint_info(kpoint, nkp=nkp, xkp=xkp, wkp=wkp, &
    1212        5860 :                            cell_to_index=cell_to_index)
    1213             :       ! initialize real space density matrices
    1214        5860 :       IF (aux_fit) THEN
    1215         138 :          kp => kpoint%kp_aux_env(1)%kpoint_env
    1216             :       ELSE
    1217        5722 :          kp => kpoint%kp_env(1)%kpoint_env
    1218             :       END IF
    1219        5860 :       nspin = SIZE(kp%mos, 2)
    1220        5860 :       nc = SIZE(kp%mos, 1)
    1221        5860 :       nimg = SIZE(denmat, 2)
    1222        5860 :       real_only = (nc == 1)
    1223             : 
    1224        5860 :       para_env => kpoint%blacs_env_all%para_env
    1225      118840 :       ALLOCATE (info(nspin*nkp*nc))
    1226             : 
    1227             :       ! Start all the communication
    1228        5860 :       indx = 0
    1229       12342 :       DO ispin = 1, nspin
    1230      535528 :          DO ic = 1, nimg
    1231      535528 :             CALL dbcsr_set(denmat(ispin, ic)%matrix, 0.0_dp)
    1232             :          END DO
    1233             :          !
    1234       39568 :          DO ik = 1, nkp
    1235       27226 :             my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
    1236             :             IF (my_kpgrp) THEN
    1237       18050 :                ikk = ik - kpoint%kp_range(1) + 1
    1238       18050 :                IF (aux_fit) THEN
    1239        1008 :                   kp => kpoint%kp_aux_env(ikk)%kpoint_env
    1240             :                ELSE
    1241       17042 :                   kp => kpoint%kp_env(ikk)%kpoint_env
    1242             :                END IF
    1243             :             ELSE
    1244             :                NULLIFY (kp)
    1245             :             END IF
    1246             :             ! collect this density matrix on all processors
    1247       27226 :             CPASSERT(SIZE(fmwork) >= nc)
    1248             : 
    1249       33708 :             IF (my_kpgrp) THEN
    1250       54078 :                DO ic = 1, nc
    1251       36028 :                   indx = indx + 1
    1252       54078 :                   IF (do_ext) THEN
    1253        2016 :                      CALL cp_fm_start_copy_general(pmat_ext(ikk, ic, ispin), fmwork(ic), para_env, info(indx))
    1254             :                   ELSE
    1255       34012 :                      IF (wtype) THEN
    1256        1642 :                         CALL cp_fm_start_copy_general(kp%wmat(ic, ispin), fmwork(ic), para_env, info(indx))
    1257             :                      ELSE
    1258       32370 :                         CALL cp_fm_start_copy_general(kp%pmat(ic, ispin), fmwork(ic), para_env, info(indx))
    1259             :                      END IF
    1260             :                   END IF
    1261             :                END DO
    1262             :             ELSE
    1263       27528 :                DO ic = 1, nc
    1264       18352 :                   indx = indx + 1
    1265       27528 :                   CALL cp_fm_start_copy_general(fmdummy, fmwork(ic), para_env, info(indx))
    1266             :                END DO
    1267             :             END IF
    1268             :          END DO
    1269             :       END DO
    1270             : 
    1271             :       ! Finish communication and transform the received matrices
    1272        5860 :       indx = 0
    1273       12342 :       DO ispin = 1, nspin
    1274       39568 :          DO ik = 1, nkp
    1275       81606 :             DO ic = 1, nc
    1276       54380 :                indx = indx + 1
    1277       81606 :                CALL cp_fm_finish_copy_general(fmwork(ic), info(indx))
    1278             :             END DO
    1279             : 
    1280             :             ! reduce to dbcsr storage
    1281       27226 :             IF (real_only) THEN
    1282          72 :                CALL copy_fm_to_dbcsr(fmwork(1), rpmat, keep_sparsity=.TRUE.)
    1283             :             ELSE
    1284       27154 :                CALL copy_fm_to_dbcsr(fmwork(1), rpmat, keep_sparsity=.TRUE.)
    1285       27154 :                CALL copy_fm_to_dbcsr(fmwork(2), cpmat, keep_sparsity=.TRUE.)
    1286             :             END IF
    1287             : 
    1288             :             ! symmetrization
    1289       27226 :             kpsym => kpoint%kp_sym(ik)%kpoint_sym
    1290       27226 :             CPASSERT(ASSOCIATED(kpsym))
    1291             : 
    1292       33708 :             IF (kpsym%apply_symmetry) THEN
    1293           0 :                wkpx = wkp(ik)/REAL(kpsym%nwght, KIND=dp)
    1294           0 :                DO is = 1, kpsym%nwght
    1295           0 :                   ir = ABS(kpsym%rotp(is))
    1296           0 :                   ira = 0
    1297           0 :                   DO jr = 1, SIZE(kpoint%ibrot)
    1298           0 :                      IF (ir == kpoint%ibrot(jr)) ira = jr
    1299             :                   END DO
    1300           0 :                   CPASSERT(ira > 0)
    1301           0 :                   kind_rot => kpoint%kind_rotmat(ira, :)
    1302           0 :                   IF (real_only) THEN
    1303             :                      CALL symtrans(srpmat, rpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
    1304           0 :                                    kpsym%f0(:, is), kpoint%atype, symmetric=.TRUE.)
    1305             :                   ELSE
    1306             :                      CALL symtrans(srpmat, rpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
    1307           0 :                                    kpsym%f0(:, is), kpoint%atype, symmetric=.TRUE.)
    1308             :                      CALL symtrans(scpmat, cpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
    1309           0 :                                    kpsym%f0(:, is), kpoint%atype, antisymmetric=.TRUE.)
    1310             :                   END IF
    1311             :                   CALL transform_dmat(denmat, srpmat, scpmat, ispin, real_only, sab_nl, &
    1312           0 :                                       cell_to_index, kpsym%xkp(1:3, is), wkpx)
    1313             :                END DO
    1314             :             ELSE
    1315             :                ! transformation
    1316             :                CALL transform_dmat(denmat, rpmat, cpmat, ispin, real_only, sab_nl, &
    1317       27226 :                                    cell_to_index, xkp(1:3, ik), wkp(ik))
    1318             :             END IF
    1319             :          END DO
    1320             :       END DO
    1321             : 
    1322             :       ! Clean up communication
    1323        5860 :       indx = 0
    1324       12342 :       DO ispin = 1, nspin
    1325       39568 :          DO ik = 1, nkp
    1326       27226 :             my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
    1327        6482 :             IF (my_kpgrp) THEN
    1328       18050 :                ikk = ik - kpoint%kp_range(1) + 1
    1329             :                IF (aux_fit) THEN
    1330       18050 :                   kp => kpoint%kp_aux_env(ikk)%kpoint_env
    1331             :                ELSE
    1332       18050 :                   kp => kpoint%kp_env(ikk)%kpoint_env
    1333             :                END IF
    1334             : 
    1335       54078 :                DO ic = 1, nc
    1336       36028 :                   indx = indx + 1
    1337       54078 :                   CALL cp_fm_cleanup_copy_general(info(indx))
    1338             :                END DO
    1339             :             ELSE
    1340             :                ! calls with dummy arguments, so not included
    1341             :                ! therefore just increment counter by trip count
    1342        9176 :                indx = indx + nc
    1343             :             END IF
    1344             :          END DO
    1345             :       END DO
    1346             : 
    1347             :       ! All done
    1348       60240 :       DEALLOCATE (info)
    1349             : 
    1350        5860 :       CALL dbcsr_deallocate_matrix(rpmat)
    1351        5860 :       CALL dbcsr_deallocate_matrix(cpmat)
    1352        5860 :       IF (.NOT. kpoint%full_grid) THEN
    1353        4784 :          CALL dbcsr_deallocate_matrix(srpmat)
    1354        4784 :          CALL dbcsr_deallocate_matrix(scpmat)
    1355             :       END IF
    1356             : 
    1357        5860 :       CALL timestop(handle)
    1358             : 
    1359        5860 :    END SUBROUTINE kpoint_density_transform
    1360             : 
    1361             : ! **************************************************************************************************
    1362             : !> \brief real space density matrices in DBCSR format
    1363             : !> \param denmat  Real space (DBCSR) density matrix
    1364             : !> \param rpmat ...
    1365             : !> \param cpmat ...
    1366             : !> \param ispin ...
    1367             : !> \param real_only ...
    1368             : !> \param sab_nl ...
    1369             : !> \param cell_to_index ...
    1370             : !> \param xkp ...
    1371             : !> \param wkp ...
    1372             : ! **************************************************************************************************
    1373       27226 :    SUBROUTINE transform_dmat(denmat, rpmat, cpmat, ispin, real_only, sab_nl, cell_to_index, xkp, wkp)
    1374             : 
    1375             :       TYPE(dbcsr_p_type), DIMENSION(:, :)                :: denmat
    1376             :       TYPE(dbcsr_type), POINTER                          :: rpmat, cpmat
    1377             :       INTEGER, INTENT(IN)                                :: ispin
    1378             :       LOGICAL, INTENT(IN)                                :: real_only
    1379             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1380             :          POINTER                                         :: sab_nl
    1381             :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1382             :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xkp
    1383             :       REAL(KIND=dp), INTENT(IN)                          :: wkp
    1384             : 
    1385             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'transform_dmat'
    1386             : 
    1387             :       INTEGER                                            :: handle, iatom, icell, icol, irow, jatom, &
    1388             :                                                             nimg
    1389             :       INTEGER, DIMENSION(3)                              :: cell
    1390             :       LOGICAL                                            :: do_symmetric, found
    1391             :       REAL(KIND=dp)                                      :: arg, coskl, fc, sinkl
    1392       27226 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, dblock, rblock
    1393             :       TYPE(neighbor_list_iterator_p_type), &
    1394       27226 :          DIMENSION(:), POINTER                           :: nl_iterator
    1395             : 
    1396       27226 :       CALL timeset(routineN, handle)
    1397             : 
    1398       27226 :       nimg = SIZE(denmat, 2)
    1399             : 
    1400             :       ! transformation
    1401       27226 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    1402       27226 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
    1403    11833608 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1404    11806382 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom, cell=cell)
    1405             : 
    1406             :          !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
    1407             :          !Therefore, we have: S(R) = sum_k Re(S(k))*cos(k*R) -i^2*Im(S(k))*sin(k*R)
    1408             :          !                         = sum_k Re(S(k))*cos(k*R) + Im(S(k))*sin(k*R)
    1409             :          !fc = +- 1 is due to the usual non-symmetric real-space matrices stored as symmetric ones
    1410             : 
    1411    11806382 :          irow = iatom
    1412    11806382 :          icol = jatom
    1413    11806382 :          fc = 1.0_dp
    1414    11806382 :          IF (do_symmetric .AND. iatom > jatom) THEN
    1415     4982009 :             irow = jatom
    1416     4982009 :             icol = iatom
    1417     4982009 :             fc = -1.0_dp
    1418             :          END IF
    1419             : 
    1420    11806382 :          icell = cell_to_index(cell(1), cell(2), cell(3))
    1421    11806382 :          IF (icell < 1 .OR. icell > nimg) CYCLE
    1422             : 
    1423    11805320 :          arg = REAL(cell(1), dp)*xkp(1) + REAL(cell(2), dp)*xkp(2) + REAL(cell(3), dp)*xkp(3)
    1424    11805320 :          coskl = wkp*COS(twopi*arg)
    1425    11805320 :          sinkl = wkp*fc*SIN(twopi*arg)
    1426             : 
    1427             :          CALL dbcsr_get_block_p(matrix=denmat(ispin, icell)%matrix, row=irow, col=icol, &
    1428    11805320 :                                 block=dblock, found=found)
    1429    11805320 :          IF (.NOT. found) CYCLE
    1430             : 
    1431    11832546 :          IF (real_only) THEN
    1432      176136 :             CALL dbcsr_get_block_p(matrix=rpmat, row=irow, col=icol, block=rblock, found=found)
    1433      176136 :             IF (.NOT. found) CYCLE
    1434    92594280 :             dblock = dblock + coskl*rblock
    1435             :          ELSE
    1436    11629184 :             CALL dbcsr_get_block_p(matrix=rpmat, row=irow, col=icol, block=rblock, found=found)
    1437    11629184 :             IF (.NOT. found) CYCLE
    1438    11629184 :             CALL dbcsr_get_block_p(matrix=cpmat, row=irow, col=icol, block=cblock, found=found)
    1439    11629184 :             IF (.NOT. found) CYCLE
    1440  2340218674 :             dblock = dblock + coskl*rblock
    1441  2340218674 :             dblock = dblock + sinkl*cblock
    1442             :          END IF
    1443             :       END DO
    1444       27226 :       CALL neighbor_list_iterator_release(nl_iterator)
    1445             : 
    1446       27226 :       CALL timestop(handle)
    1447             : 
    1448       27226 :    END SUBROUTINE transform_dmat
    1449             : 
    1450             : ! **************************************************************************************************
    1451             : !> \brief Symmetrization of density matrix - transform to new k-point
    1452             : !> \param smat density matrix at new kpoint
    1453             : !> \param pmat reference density matrix
    1454             : !> \param kmat Kind type rotation matrix
    1455             : !> \param rot Rotation matrix
    1456             : !> \param f0 Permutation of atoms under transformation
    1457             : !> \param atype Atom to kind pointer
    1458             : !> \param symmetric Symmetric matrix
    1459             : !> \param antisymmetric Anti-Symmetric matrix
    1460             : ! **************************************************************************************************
    1461           0 :    SUBROUTINE symtrans(smat, pmat, kmat, rot, f0, atype, symmetric, antisymmetric)
    1462             :       TYPE(dbcsr_type), POINTER                          :: smat, pmat
    1463             :       TYPE(kind_rotmat_type), DIMENSION(:), POINTER      :: kmat
    1464             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: rot
    1465             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: f0, atype
    1466             :       LOGICAL, INTENT(IN), OPTIONAL                      :: symmetric, antisymmetric
    1467             : 
    1468             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'symtrans'
    1469             : 
    1470             :       INTEGER                                            :: handle, iatom, icol, ikind, ip, irow, &
    1471             :                                                             jcol, jkind, jp, jrow, natom, numnodes
    1472             :       LOGICAL                                            :: asym, dorot, found, perm, sym, trans
    1473             :       REAL(KIND=dp)                                      :: dr, fsign
    1474           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: kroti, krotj, pblock, sblock
    1475             :       TYPE(dbcsr_distribution_type)                      :: dist
    1476             :       TYPE(dbcsr_iterator_type)                          :: iter
    1477             : 
    1478           0 :       CALL timeset(routineN, handle)
    1479             : 
    1480             :       ! check symmetry options
    1481           0 :       sym = .FALSE.
    1482           0 :       IF (PRESENT(symmetric)) sym = symmetric
    1483           0 :       asym = .FALSE.
    1484           0 :       IF (PRESENT(antisymmetric)) asym = antisymmetric
    1485             : 
    1486           0 :       CPASSERT(.NOT. (sym .AND. asym))
    1487           0 :       CPASSERT((sym .OR. asym))
    1488             : 
    1489             :       ! do we have permutation of atoms
    1490           0 :       natom = SIZE(f0)
    1491           0 :       perm = .FALSE.
    1492           0 :       DO iatom = 1, natom
    1493           0 :          IF (f0(iatom) == iatom) CYCLE
    1494             :          perm = .TRUE.
    1495           0 :          EXIT
    1496             :       END DO
    1497             : 
    1498             :       ! do we have a real rotation
    1499           0 :       dorot = .FALSE.
    1500           0 :       IF (ABS(SUM(ABS(rot)) - 3.0_dp) > 1.e-12_dp) dorot = .TRUE.
    1501           0 :       dr = ABS(rot(1, 1) - 1.0_dp) + ABS(rot(2, 2) - 1.0_dp) + ABS(rot(3, 3) - 1.0_dp)
    1502           0 :       IF (ABS(dr) > 1.e-12_dp) dorot = .TRUE.
    1503             : 
    1504           0 :       fsign = 1.0_dp
    1505           0 :       IF (asym) fsign = -1.0_dp
    1506             : 
    1507           0 :       IF (dorot .OR. perm) THEN
    1508             :          CALL cp_abort(__LOCATION__, "k-points need FULL_GRID currently. "// &
    1509           0 :                        "Reduced grids not yet working correctly")
    1510           0 :          CALL dbcsr_set(smat, 0.0_dp)
    1511           0 :          IF (perm) THEN
    1512           0 :             CALL dbcsr_get_info(pmat, distribution=dist)
    1513           0 :             CALL dbcsr_distribution_get(dist, numnodes=numnodes)
    1514           0 :             IF (numnodes == 1) THEN
    1515             :                ! the matrices are local to this process
    1516           0 :                CALL dbcsr_iterator_start(iter, pmat)
    1517           0 :                DO WHILE (dbcsr_iterator_blocks_left(iter))
    1518           0 :                   CALL dbcsr_iterator_next_block(iter, irow, icol, pblock)
    1519           0 :                   ip = f0(irow)
    1520           0 :                   jp = f0(icol)
    1521           0 :                   IF (ip <= jp) THEN
    1522           0 :                      jrow = ip
    1523           0 :                      jcol = jp
    1524           0 :                      trans = .FALSE.
    1525             :                   ELSE
    1526           0 :                      jrow = jp
    1527           0 :                      jcol = ip
    1528           0 :                      trans = .TRUE.
    1529             :                   END IF
    1530           0 :                   CALL dbcsr_get_block_p(matrix=smat, row=jrow, col=jcol, BLOCK=sblock, found=found)
    1531           0 :                   CPASSERT(found)
    1532           0 :                   ikind = atype(irow)
    1533           0 :                   jkind = atype(icol)
    1534           0 :                   kroti => kmat(ikind)%rmat
    1535           0 :                   krotj => kmat(jkind)%rmat
    1536             :                   ! rotation
    1537           0 :                   IF (trans) THEN
    1538           0 :                      sblock = fsign*MATMUL(TRANSPOSE(krotj), MATMUL(TRANSPOSE(pblock), kroti))
    1539             :                   ELSE
    1540           0 :                      sblock = fsign*MATMUL(TRANSPOSE(kroti), MATMUL(pblock, krotj))
    1541             :                   END IF
    1542             :                END DO
    1543           0 :                CALL dbcsr_iterator_stop(iter)
    1544             :                !
    1545             :             ELSE
    1546             :                ! distributed matrices, most general code needed
    1547             :                CALL cp_abort(__LOCATION__, "k-points need FULL_GRID currently. "// &
    1548           0 :                              "Reduced grids not yet working correctly")
    1549             :             END IF
    1550             :          ELSE
    1551             :             ! no atom permutations, this is always local
    1552           0 :             CALL dbcsr_copy(smat, pmat)
    1553           0 :             CALL dbcsr_iterator_start(iter, smat)
    1554           0 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
    1555           0 :                CALL dbcsr_iterator_next_block(iter, irow, icol, sblock)
    1556           0 :                ip = f0(irow)
    1557           0 :                jp = f0(icol)
    1558           0 :                IF (ip <= jp) THEN
    1559           0 :                   jrow = ip
    1560           0 :                   jcol = jp
    1561           0 :                   trans = .FALSE.
    1562             :                ELSE
    1563           0 :                   jrow = jp
    1564           0 :                   jcol = ip
    1565           0 :                   trans = .TRUE.
    1566             :                END IF
    1567           0 :                ikind = atype(irow)
    1568           0 :                jkind = atype(icol)
    1569           0 :                kroti => kmat(ikind)%rmat
    1570           0 :                krotj => kmat(jkind)%rmat
    1571             :                ! rotation
    1572           0 :                IF (trans) THEN
    1573           0 :                   sblock = fsign*MATMUL(TRANSPOSE(krotj), MATMUL(TRANSPOSE(sblock), kroti))
    1574             :                ELSE
    1575           0 :                   sblock = fsign*MATMUL(TRANSPOSE(kroti), MATMUL(sblock, krotj))
    1576             :                END IF
    1577             :             END DO
    1578           0 :             CALL dbcsr_iterator_stop(iter)
    1579             :             !
    1580             :          END IF
    1581             :       ELSE
    1582             :          ! this is the identity operation, just copy the matrix
    1583           0 :          CALL dbcsr_copy(smat, pmat)
    1584             :       END IF
    1585             : 
    1586           0 :       CALL timestop(handle)
    1587             : 
    1588           0 :    END SUBROUTINE symtrans
    1589             : 
    1590             : ! **************************************************************************************************
    1591             : !> \brief ...
    1592             : !> \param mat ...
    1593             : ! **************************************************************************************************
    1594           0 :    SUBROUTINE matprint(mat)
    1595             :       TYPE(dbcsr_type), POINTER                          :: mat
    1596             : 
    1597             :       INTEGER                                            :: i, icol, iounit, irow
    1598           0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: mblock
    1599             :       TYPE(dbcsr_iterator_type)                          :: iter
    1600             : 
    1601           0 :       iounit = cp_logger_get_default_io_unit()
    1602           0 :       CALL dbcsr_iterator_start(iter, mat)
    1603           0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    1604           0 :          CALL dbcsr_iterator_next_block(iter, irow, icol, mblock)
    1605             :          !
    1606           0 :          IF (iounit > 0) THEN
    1607           0 :             WRITE (iounit, '(A,2I4)') 'BLOCK  ', irow, icol
    1608           0 :             DO i = 1, SIZE(mblock, 1)
    1609           0 :                WRITE (iounit, '(8F12.6)') mblock(i, :)
    1610             :             END DO
    1611             :          END IF
    1612             :          !
    1613             :       END DO
    1614           0 :       CALL dbcsr_iterator_stop(iter)
    1615             : 
    1616           0 :    END SUBROUTINE matprint
    1617             : ! **************************************************************************************************
    1618             : 
    1619           0 : END MODULE kpoint_methods

Generated by: LCOV version 1.15