LCOV - code coverage report
Current view: top level - src - kpoint_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:1155b05) Lines: 65.8 % 942 620
Test Date: 2026-03-21 06:31:29 Functions: 76.9 % 13 10

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines needed for kpoint calculation
      10              : !> \par History
      11              : !>       2014.07 created [JGH]
      12              : !>       2014.11 unified k-point and gamma-point code [Ole Schuett]
      13              : !> \author JGH
      14              : ! **************************************************************************************************
      15              : MODULE kpoint_methods
      16              :    USE atomic_kind_types,               ONLY: get_atomic_kind
      17              :    USE cell_types,                      ONLY: cell_type,&
      18              :                                               real_to_scaled
      19              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_create,&
      20              :                                               cp_blacs_env_type
      21              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_scale_and_add_fm
      22              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      23              :                                               cp_cfm_release,&
      24              :                                               cp_cfm_to_fm,&
      25              :                                               cp_cfm_type
      26              :    USE cp_control_types,                ONLY: hairy_probes_type
      27              :    USE cp_dbcsr_api,                    ONLY: &
      28              :         dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_desymmetrize, &
      29              :         dbcsr_distribution_get, dbcsr_distribution_type, dbcsr_get_block_p, dbcsr_get_info, &
      30              :         dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
      31              :         dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, dbcsr_set, dbcsr_type, &
      32              :         dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
      33              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      34              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      35              :                                               copy_fm_to_dbcsr
      36              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale
      37              :    USE cp_fm_pool_types,                ONLY: cp_fm_pool_p_type,&
      38              :                                               fm_pool_create_fm,&
      39              :                                               fm_pool_give_back_fm
      40              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_type
      41              :    USE cp_fm_types,                     ONLY: &
      42              :         copy_info_type, cp_fm_cleanup_copy_general, cp_fm_create, cp_fm_finish_copy_general, &
      43              :         cp_fm_get_info, cp_fm_get_submatrix, cp_fm_release, cp_fm_start_copy_general, cp_fm_to_fm, &
      44              :         cp_fm_type
      45              :    USE cp_log_handling,                 ONLY: cp_logger_get_default_io_unit
      46              :    USE cryssym,                         ONLY: crys_sym_gen,&
      47              :                                               csym_type,&
      48              :                                               kpoint_gen,&
      49              :                                               print_crys_symmetry,&
      50              :                                               print_kp_symmetry,&
      51              :                                               release_csym_type
      52              :    USE hairy_probes,                    ONLY: probe_occupancy_kp
      53              :    USE input_constants,                 ONLY: smear_fermi_dirac,&
      54              :                                               smear_gaussian,&
      55              :                                               smear_mp,&
      56              :                                               smear_mv
      57              :    USE kinds,                           ONLY: dp
      58              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      59              :                                               kind_rotmat_type,&
      60              :                                               kpoint_env_create,&
      61              :                                               kpoint_env_p_type,&
      62              :                                               kpoint_env_type,&
      63              :                                               kpoint_sym_create,&
      64              :                                               kpoint_sym_type,&
      65              :                                               kpoint_type
      66              :    USE mathconstants,                   ONLY: gaussi,&
      67              :                                               twopi
      68              :    USE memory_utilities,                ONLY: reallocate
      69              :    USE message_passing,                 ONLY: mp_cart_type,&
      70              :                                               mp_para_env_type
      71              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      72              :    USE particle_types,                  ONLY: particle_type
      73              :    USE qs_matrix_pools,                 ONLY: mpools_create,&
      74              :                                               mpools_get,&
      75              :                                               mpools_rebuild_fm_pools,&
      76              :                                               qs_matrix_pools_type
      77              :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
      78              :                                               get_mo_set,&
      79              :                                               init_mo_set,&
      80              :                                               mo_set_type,&
      81              :                                               set_mo_set
      82              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      83              :                                               get_neighbor_list_set_p,&
      84              :                                               neighbor_list_iterate,&
      85              :                                               neighbor_list_iterator_create,&
      86              :                                               neighbor_list_iterator_p_type,&
      87              :                                               neighbor_list_iterator_release,&
      88              :                                               neighbor_list_set_p_type
      89              :    USE scf_control_types,               ONLY: smear_type
      90              :    USE smearing_utils,                  ONLY: Smearkp,&
      91              :                                               Smearkp2
      92              :    USE util,                            ONLY: get_limit
      93              : #include "./base/base_uses.f90"
      94              : 
      95              :    IMPLICIT NONE
      96              : 
      97              :    PRIVATE
      98              : 
      99              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'kpoint_methods'
     100              : 
     101              :    PUBLIC :: kpoint_initialize, kpoint_env_initialize, kpoint_initialize_mos, kpoint_initialize_mo_set
     102              :    PUBLIC :: kpoint_init_cell_index, kpoint_set_mo_occupation
     103              :    PUBLIC :: kpoint_density_matrices, kpoint_density_transform
     104              :    PUBLIC :: rskp_transform, lowdin_kp_trans
     105              : 
     106              : ! **************************************************************************************************
     107              : 
     108              : CONTAINS
     109              : 
     110              : ! **************************************************************************************************
     111              : !> \brief Generate the kpoints and initialize the kpoint environment
     112              : !> \param kpoint       The kpoint environment
     113              : !> \param particle_set Particle types and coordinates
     114              : !> \param cell         Computational cell information
     115              : ! **************************************************************************************************
     116         7706 :    SUBROUTINE kpoint_initialize(kpoint, particle_set, cell)
     117              : 
     118              :       TYPE(kpoint_type), POINTER                         :: kpoint
     119              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     120              :       TYPE(cell_type), POINTER                           :: cell
     121              : 
     122              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'kpoint_initialize'
     123              : 
     124              :       INTEGER                                            :: handle, i, ic, ik, iounit, ir, ira, is, &
     125              :                                                             j, natom, nkind, nr, ns
     126         7706 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atype
     127              :       LOGICAL                                            :: spez
     128              :       REAL(KIND=dp)                                      :: wsum
     129         7706 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: coord, scoord
     130      6804398 :       TYPE(csym_type)                                    :: crys_sym
     131              :       TYPE(kpoint_sym_type), POINTER                     :: kpsym
     132              : 
     133         7706 :       CALL timeset(routineN, handle)
     134              : 
     135         7706 :       CPASSERT(ASSOCIATED(kpoint))
     136              : 
     137         7722 :       SELECT CASE (kpoint%kp_scheme)
     138              :       CASE ("NONE")
     139              :          ! do nothing
     140              :       CASE ("GAMMA")
     141           16 :          kpoint%nkp = 1
     142           16 :          ALLOCATE (kpoint%xkp(3, 1), kpoint%wkp(1))
     143           64 :          kpoint%xkp(1:3, 1) = 0.0_dp
     144           16 :          kpoint%wkp(1) = 1.0_dp
     145           32 :          ALLOCATE (kpoint%kp_sym(1))
     146           16 :          NULLIFY (kpoint%kp_sym(1)%kpoint_sym)
     147           16 :          CALL kpoint_sym_create(kpoint%kp_sym(1)%kpoint_sym)
     148              :       CASE ("MONKHORST-PACK", "MACDONALD")
     149              : 
     150          176 :          IF (.NOT. kpoint%symmetry) THEN
     151              :             ! we set up a random molecule to avoid any possible symmetry
     152          112 :             natom = 10
     153          112 :             ALLOCATE (coord(3, natom), scoord(3, natom), atype(natom))
     154         1232 :             DO i = 1, natom
     155         1120 :                atype(i) = i
     156         1120 :                coord(1, i) = SIN(i*0.12345_dp)
     157         1120 :                coord(2, i) = COS(i*0.23456_dp)
     158         1120 :                coord(3, i) = SIN(i*0.34567_dp)
     159         1232 :                CALL real_to_scaled(scoord(1:3, i), coord(1:3, i), cell)
     160              :             END DO
     161              :          ELSE
     162           64 :             natom = SIZE(particle_set)
     163          320 :             ALLOCATE (scoord(3, natom), atype(natom))
     164          478 :             DO i = 1, natom
     165          414 :                CALL get_atomic_kind(atomic_kind=particle_set(i)%atomic_kind, kind_number=atype(i))
     166          478 :                CALL real_to_scaled(scoord(1:3, i), particle_set(i)%r(1:3), cell)
     167              :             END DO
     168              :          END IF
     169          176 :          IF (kpoint%verbose) THEN
     170           14 :             iounit = cp_logger_get_default_io_unit()
     171              :          ELSE
     172          162 :             iounit = -1
     173              :          END IF
     174              :          ! kind type list
     175          528 :          ALLOCATE (kpoint%atype(natom))
     176         1710 :          kpoint%atype = atype
     177              : 
     178          176 :          CALL crys_sym_gen(crys_sym, scoord, atype, cell%hmat, delta=kpoint%eps_geo, iounit=iounit)
     179              :          CALL kpoint_gen(crys_sym, kpoint%nkp_grid, symm=kpoint%symmetry, shift=kpoint%kp_shift, &
     180          176 :                          full_grid=kpoint%full_grid)
     181          176 :          kpoint%nkp = crys_sym%nkpoint
     182          880 :          ALLOCATE (kpoint%xkp(3, kpoint%nkp), kpoint%wkp(kpoint%nkp))
     183         1952 :          wsum = SUM(crys_sym%wkpoint)
     184         1952 :          DO ik = 1, kpoint%nkp
     185         7104 :             kpoint%xkp(1:3, ik) = crys_sym%xkpoint(1:3, ik)
     186         1952 :             kpoint%wkp(ik) = crys_sym%wkpoint(ik)/wsum
     187              :          END DO
     188              : 
     189              :          ! print output
     190          176 :          IF (kpoint%symmetry) CALL print_crys_symmetry(crys_sym)
     191          176 :          IF (kpoint%symmetry) CALL print_kp_symmetry(crys_sym)
     192              : 
     193              :          ! transfer symmetry information
     194         2304 :          ALLOCATE (kpoint%kp_sym(kpoint%nkp))
     195         1952 :          DO ik = 1, kpoint%nkp
     196         1776 :             NULLIFY (kpoint%kp_sym(ik)%kpoint_sym)
     197         1776 :             CALL kpoint_sym_create(kpoint%kp_sym(ik)%kpoint_sym)
     198         1776 :             kpsym => kpoint%kp_sym(ik)%kpoint_sym
     199         1952 :             IF (crys_sym%symlib .AND. .NOT. crys_sym%fullgrid .AND. crys_sym%istriz == 1) THEN
     200              :                ! set up the symmetrization information
     201            0 :                kpsym%nwght = NINT(crys_sym%wkpoint(ik))
     202            0 :                ns = kpsym%nwght
     203              :                !
     204            0 :                IF (ns > 1) THEN
     205            0 :                   kpsym%apply_symmetry = .TRUE.
     206            0 :                   natom = SIZE(particle_set)
     207            0 :                   ALLOCATE (kpsym%rot(3, 3, ns))
     208            0 :                   ALLOCATE (kpsym%xkp(3, ns))
     209            0 :                   ALLOCATE (kpsym%rotp(ns))
     210            0 :                   ALLOCATE (kpsym%f0(natom, ns))
     211            0 :                   nr = 0
     212            0 :                   DO is = 1, SIZE(crys_sym%kplink, 2)
     213            0 :                      IF (crys_sym%kplink(2, is) == ik) THEN
     214            0 :                         nr = nr + 1
     215            0 :                         ir = crys_sym%kpop(is)
     216            0 :                         ira = ABS(ir)
     217            0 :                         kpsym%rotp(nr) = ir
     218            0 :                         IF (ir > 0) THEN
     219            0 :                            kpsym%rot(1:3, 1:3, nr) = crys_sym%rt(1:3, 1:3, ira)
     220              :                         ELSE
     221            0 :                            kpsym%rot(1:3, 1:3, nr) = -crys_sym%rt(1:3, 1:3, ira)
     222              :                         END IF
     223            0 :                         kpsym%xkp(1:3, nr) = crys_sym%kpmesh(1:3, is)
     224            0 :                         DO ic = 1, crys_sym%nrtot
     225            0 :                            IF (crys_sym%ibrot(ic) == ira) THEN
     226            0 :                               kpsym%f0(1:natom, nr) = crys_sym%f0(1:natom, ic)
     227              :                               EXIT
     228              :                            END IF
     229              :                         END DO
     230              :                      END IF
     231              :                   END DO
     232              :                   ! Reduce inversion?
     233            0 :                   kpsym%nwred = nr
     234              :                END IF
     235              :             END IF
     236              :          END DO
     237          176 :          IF (kpoint%symmetry) THEN
     238          478 :             nkind = MAXVAL(atype)
     239           64 :             ns = crys_sym%nrtot
     240          264 :             ALLOCATE (kpoint%kind_rotmat(ns, nkind))
     241           64 :             DO i = 1, ns
     242           64 :                DO j = 1, nkind
     243            0 :                   NULLIFY (kpoint%kind_rotmat(i, j)%rmat)
     244              :                END DO
     245              :             END DO
     246          128 :             ALLOCATE (kpoint%ibrot(ns))
     247           64 :             kpoint%ibrot(1:ns) = crys_sym%ibrot(1:ns)
     248              :          END IF
     249              : 
     250          176 :          CALL release_csym_type(crys_sym)
     251          176 :          DEALLOCATE (scoord, atype)
     252              : 
     253              :       CASE ("GENERAL")
     254              :          ! default: no symmetry settings
     255           20 :          ALLOCATE (kpoint%kp_sym(kpoint%nkp))
     256           12 :          DO i = 1, kpoint%nkp
     257            8 :             NULLIFY (kpoint%kp_sym(i)%kpoint_sym)
     258           12 :             CALL kpoint_sym_create(kpoint%kp_sym(i)%kpoint_sym)
     259              :          END DO
     260              :       CASE DEFAULT
     261         7706 :          CPASSERT(.FALSE.)
     262              :       END SELECT
     263              : 
     264              :       ! check for consistency of options
     265         7722 :       SELECT CASE (kpoint%kp_scheme)
     266              :       CASE ("NONE")
     267              :          ! don't use k-point code
     268              :       CASE ("GAMMA")
     269           16 :          CPASSERT(kpoint%nkp == 1)
     270           80 :          CPASSERT(SUM(ABS(kpoint%xkp)) <= 1.e-12_dp)
     271           16 :          CPASSERT(kpoint%wkp(1) == 1.0_dp)
     272           16 :          CPASSERT(.NOT. kpoint%symmetry)
     273              :       CASE ("GENERAL")
     274            4 :          CPASSERT(.NOT. kpoint%symmetry)
     275            4 :          CPASSERT(kpoint%nkp >= 1)
     276              :       CASE ("MONKHORST-PACK", "MACDONALD")
     277         7706 :          CPASSERT(kpoint%nkp >= 1)
     278              :       END SELECT
     279         7706 :       IF (kpoint%use_real_wfn) THEN
     280              :          ! what about inversion symmetry?
     281           24 :          ikloop: DO ik = 1, kpoint%nkp
     282           60 :             DO i = 1, 3
     283           36 :                spez = (kpoint%xkp(i, ik) == 0.0_dp .OR. kpoint%xkp(i, ik) == 0.5_dp)
     284           12 :                IF (.NOT. spez) EXIT ikloop
     285              :             END DO
     286              :          END DO ikloop
     287           12 :          IF (.NOT. spez) THEN
     288              :             ! Warning: real wfn might be wrong for this system
     289              :             CALL cp_warn(__LOCATION__, &
     290              :                          "A calculation using real wavefunctions is requested. "// &
     291            0 :                          "We could not determine if the symmetry of the system allows real wavefunctions. ")
     292              :          END IF
     293              :       END IF
     294              : 
     295         7706 :       CALL timestop(handle)
     296              : 
     297         7706 :    END SUBROUTINE kpoint_initialize
     298              : 
     299              : ! **************************************************************************************************
     300              : !> \brief Initialize the kpoint environment
     301              : !> \param kpoint       Kpoint environment
     302              : !> \param para_env ...
     303              : !> \param blacs_env ...
     304              : !> \param with_aux_fit ...
     305              : ! **************************************************************************************************
     306          252 :    SUBROUTINE kpoint_env_initialize(kpoint, para_env, blacs_env, with_aux_fit)
     307              : 
     308              :       TYPE(kpoint_type), INTENT(INOUT)                   :: kpoint
     309              :       TYPE(mp_para_env_type), INTENT(IN), TARGET         :: para_env
     310              :       TYPE(cp_blacs_env_type), INTENT(IN), TARGET        :: blacs_env
     311              :       LOGICAL, INTENT(IN), OPTIONAL                      :: with_aux_fit
     312              : 
     313              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_env_initialize'
     314              : 
     315              :       INTEGER                                            :: handle, igr, ik, ikk, ngr, niogrp, nkp, &
     316              :                                                             nkp_grp, nkp_loc, npe, unit_nr
     317              :       INTEGER, DIMENSION(2)                              :: dims, pos
     318              :       LOGICAL                                            :: aux_fit
     319          252 :       TYPE(kpoint_env_p_type), DIMENSION(:), POINTER     :: kp_aux_env, kp_env
     320              :       TYPE(kpoint_env_type), POINTER                     :: kp
     321          252 :       TYPE(mp_cart_type)                                 :: comm_cart
     322              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp, para_env_kp
     323              : 
     324          252 :       CALL timeset(routineN, handle)
     325              : 
     326          252 :       IF (PRESENT(with_aux_fit)) THEN
     327          194 :          aux_fit = with_aux_fit
     328              :       ELSE
     329              :          aux_fit = .FALSE.
     330              :       END IF
     331              : 
     332          252 :       kpoint%para_env => para_env
     333          252 :       CALL kpoint%para_env%retain()
     334          252 :       kpoint%blacs_env_all => blacs_env
     335          252 :       CALL kpoint%blacs_env_all%retain()
     336              : 
     337          252 :       CPASSERT(.NOT. ASSOCIATED(kpoint%kp_env))
     338          252 :       IF (aux_fit) THEN
     339           30 :          CPASSERT(.NOT. ASSOCIATED(kpoint%kp_aux_env))
     340              :       END IF
     341              : 
     342          252 :       NULLIFY (kp_env, kp_aux_env)
     343          252 :       nkp = kpoint%nkp
     344          252 :       npe = para_env%num_pe
     345          252 :       IF (npe == 1) THEN
     346              :          ! only one process available -> owns all kpoints
     347            0 :          ALLOCATE (kp_env(nkp))
     348            0 :          DO ik = 1, nkp
     349            0 :             NULLIFY (kp_env(ik)%kpoint_env)
     350            0 :             CALL kpoint_env_create(kp_env(ik)%kpoint_env)
     351            0 :             kp => kp_env(ik)%kpoint_env
     352            0 :             kp%nkpoint = ik
     353            0 :             kp%wkp = kpoint%wkp(ik)
     354            0 :             kp%xkp(1:3) = kpoint%xkp(1:3, ik)
     355            0 :             kp%is_local = .TRUE.
     356              :          END DO
     357            0 :          kpoint%kp_env => kp_env
     358              : 
     359            0 :          IF (aux_fit) THEN
     360            0 :             ALLOCATE (kp_aux_env(nkp))
     361            0 :             DO ik = 1, nkp
     362            0 :                NULLIFY (kp_aux_env(ik)%kpoint_env)
     363            0 :                CALL kpoint_env_create(kp_aux_env(ik)%kpoint_env)
     364            0 :                kp => kp_aux_env(ik)%kpoint_env
     365            0 :                kp%nkpoint = ik
     366            0 :                kp%wkp = kpoint%wkp(ik)
     367            0 :                kp%xkp(1:3) = kpoint%xkp(1:3, ik)
     368            0 :                kp%is_local = .TRUE.
     369              :             END DO
     370              : 
     371            0 :             kpoint%kp_aux_env => kp_aux_env
     372              :          END IF
     373              : 
     374            0 :          ALLOCATE (kpoint%kp_dist(2, 1))
     375            0 :          kpoint%kp_dist(1, 1) = 1
     376            0 :          kpoint%kp_dist(2, 1) = nkp
     377            0 :          kpoint%kp_range(1) = 1
     378            0 :          kpoint%kp_range(2) = nkp
     379              : 
     380              :          ! parallel environments
     381            0 :          kpoint%para_env_kp => para_env
     382            0 :          CALL kpoint%para_env_kp%retain()
     383            0 :          kpoint%para_env_inter_kp => para_env
     384            0 :          CALL kpoint%para_env_inter_kp%retain()
     385            0 :          kpoint%iogrp = .TRUE.
     386            0 :          kpoint%nkp_groups = 1
     387              :       ELSE
     388          252 :          IF (kpoint%parallel_group_size == -1) THEN
     389              :             ! maximum parallelization over kpoints
     390              :             ! making sure that the group size divides the npe and the nkp_grp the nkp
     391              :             ! in the worst case, there will be no parallelism over kpoints.
     392          378 :             DO igr = npe, 1, -1
     393          252 :                IF (MOD(npe, igr) /= 0) CYCLE
     394          252 :                nkp_grp = npe/igr
     395          252 :                IF (MOD(nkp, nkp_grp) /= 0) CYCLE
     396          378 :                ngr = igr
     397              :             END DO
     398          126 :          ELSE IF (kpoint%parallel_group_size == 0) THEN
     399              :             ! no parallelization over kpoints
     400           78 :             ngr = npe
     401           48 :          ELSE IF (kpoint%parallel_group_size > 0) THEN
     402           48 :             ngr = MIN(kpoint%parallel_group_size, npe)
     403              :          ELSE
     404            0 :             CPASSERT(.FALSE.)
     405              :          END IF
     406          252 :          nkp_grp = npe/ngr
     407              :          ! processor dimensions
     408          252 :          dims(1) = ngr
     409          252 :          dims(2) = nkp_grp
     410          252 :          CPASSERT(MOD(nkp, nkp_grp) == 0)
     411          252 :          nkp_loc = nkp/nkp_grp
     412              : 
     413          252 :          IF ((dims(1)*dims(2) /= npe)) THEN
     414            0 :             CPABORT("Number of processors is not divisible by the kpoint group size.")
     415              :          END IF
     416              : 
     417              :          ! Create the subgroups, one for each k-point group and one interconnecting group
     418          252 :          CALL comm_cart%create(comm_old=para_env, ndims=2, dims=dims)
     419          756 :          pos = comm_cart%mepos_cart
     420          252 :          ALLOCATE (para_env_kp)
     421          252 :          CALL para_env_kp%from_split(comm_cart, pos(2))
     422          252 :          ALLOCATE (para_env_inter_kp)
     423          252 :          CALL para_env_inter_kp%from_split(comm_cart, pos(1))
     424          252 :          CALL comm_cart%free()
     425              : 
     426          252 :          niogrp = 0
     427          252 :          IF (para_env%is_source()) niogrp = 1
     428          252 :          CALL para_env_kp%sum(niogrp)
     429          252 :          kpoint%iogrp = (niogrp == 1)
     430              : 
     431              :          ! parallel groups
     432          252 :          kpoint%para_env_kp => para_env_kp
     433          252 :          kpoint%para_env_inter_kp => para_env_inter_kp
     434              : 
     435              :          ! distribution of kpoints
     436          756 :          ALLOCATE (kpoint%kp_dist(2, nkp_grp))
     437          590 :          DO igr = 1, nkp_grp
     438         1266 :             kpoint%kp_dist(1:2, igr) = get_limit(nkp, nkp_grp, igr - 1)
     439              :          END DO
     440              :          ! local kpoints
     441          756 :          kpoint%kp_range(1:2) = kpoint%kp_dist(1:2, para_env_inter_kp%mepos + 1)
     442              : 
     443         2472 :          ALLOCATE (kp_env(nkp_loc))
     444         1968 :          DO ik = 1, nkp_loc
     445         1716 :             NULLIFY (kp_env(ik)%kpoint_env)
     446         1716 :             ikk = kpoint%kp_range(1) + ik - 1
     447         1716 :             CALL kpoint_env_create(kp_env(ik)%kpoint_env)
     448         1716 :             kp => kp_env(ik)%kpoint_env
     449         1716 :             kp%nkpoint = ikk
     450         1716 :             kp%wkp = kpoint%wkp(ikk)
     451         6864 :             kp%xkp(1:3) = kpoint%xkp(1:3, ikk)
     452         1968 :             kp%is_local = (ngr == 1)
     453              :          END DO
     454          252 :          kpoint%kp_env => kp_env
     455              : 
     456          252 :          IF (aux_fit) THEN
     457          274 :             ALLOCATE (kp_aux_env(nkp_loc))
     458          244 :             DO ik = 1, nkp_loc
     459          214 :                NULLIFY (kp_aux_env(ik)%kpoint_env)
     460          214 :                ikk = kpoint%kp_range(1) + ik - 1
     461          214 :                CALL kpoint_env_create(kp_aux_env(ik)%kpoint_env)
     462          214 :                kp => kp_aux_env(ik)%kpoint_env
     463          214 :                kp%nkpoint = ikk
     464          214 :                kp%wkp = kpoint%wkp(ikk)
     465          856 :                kp%xkp(1:3) = kpoint%xkp(1:3, ikk)
     466          244 :                kp%is_local = (ngr == 1)
     467              :             END DO
     468           30 :             kpoint%kp_aux_env => kp_aux_env
     469              :          END IF
     470              : 
     471          252 :          unit_nr = cp_logger_get_default_io_unit()
     472              : 
     473          252 :          IF (unit_nr > 0 .AND. kpoint%verbose) THEN
     474            7 :             WRITE (unit_nr, *)
     475            7 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Number of kpoint groups ", nkp_grp
     476            7 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Size of each kpoint group", ngr
     477            7 :             WRITE (unit_nr, FMT="(T2,A,T71,I10)") "KPOINTS| Number of kpoints per group", nkp_loc
     478              :          END IF
     479          252 :          kpoint%nkp_groups = nkp_grp
     480              : 
     481              :       END IF
     482              : 
     483          252 :       CALL timestop(handle)
     484              : 
     485          504 :    END SUBROUTINE kpoint_env_initialize
     486              : 
     487              : ! **************************************************************************************************
     488              : !> \brief Initialize a set of MOs and density matrix for each kpoint (kpoint group)
     489              : !> \param kpoint  Kpoint environment
     490              : !> \param mos     Reference MOs (global)
     491              : !> \param added_mos ...
     492              : !> \param for_aux_fit ...
     493              : ! **************************************************************************************************
     494          282 :    SUBROUTINE kpoint_initialize_mos(kpoint, mos, added_mos, for_aux_fit)
     495              : 
     496              :       TYPE(kpoint_type), POINTER                         :: kpoint
     497              :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
     498              :       INTEGER, INTENT(IN), OPTIONAL                      :: added_mos
     499              :       LOGICAL, OPTIONAL                                  :: for_aux_fit
     500              : 
     501              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_initialize_mos'
     502              : 
     503              :       INTEGER                                            :: handle, ic, ik, is, nadd, nao, nc, &
     504              :                                                             nelectron, nkp_loc, nmo, nmorig(2), &
     505              :                                                             nspin
     506              :       LOGICAL                                            :: aux_fit
     507              :       REAL(KIND=dp)                                      :: flexible_electron_count, maxocc, n_el_f
     508              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     509          282 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_ao_fm_pools
     510              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     511              :       TYPE(cp_fm_type), POINTER                          :: fmlocal
     512              :       TYPE(kpoint_env_type), POINTER                     :: kp
     513              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
     514              : 
     515          282 :       CALL timeset(routineN, handle)
     516              : 
     517          282 :       IF (PRESENT(for_aux_fit)) THEN
     518           30 :          aux_fit = for_aux_fit
     519              :       ELSE
     520              :          aux_fit = .FALSE.
     521              :       END IF
     522              : 
     523          282 :       CPASSERT(ASSOCIATED(kpoint))
     524              : 
     525              :       IF (.TRUE. .OR. ASSOCIATED(mos(1)%mo_coeff)) THEN
     526          282 :          IF (aux_fit) THEN
     527           30 :             CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
     528              :          END IF
     529              : 
     530          282 :          IF (PRESENT(added_mos)) THEN
     531           58 :             nadd = added_mos
     532              :          ELSE
     533              :             nadd = 0
     534              :          END IF
     535              : 
     536          282 :          IF (kpoint%use_real_wfn) THEN
     537              :             nc = 1
     538              :          ELSE
     539          270 :             nc = 2
     540              :          END IF
     541          282 :          nspin = SIZE(mos, 1)
     542          282 :          nkp_loc = kpoint%kp_range(2) - kpoint%kp_range(1) + 1
     543          282 :          IF (nkp_loc > 0) THEN
     544          282 :             IF (aux_fit) THEN
     545           30 :                CPASSERT(SIZE(kpoint%kp_aux_env) == nkp_loc)
     546              :             ELSE
     547          252 :                CPASSERT(SIZE(kpoint%kp_env) == nkp_loc)
     548              :             END IF
     549              :             ! allocate the mo sets, correct number of kpoints (local), real/complex, spin
     550         2212 :             DO ik = 1, nkp_loc
     551         1930 :                IF (aux_fit) THEN
     552          214 :                   kp => kpoint%kp_aux_env(ik)%kpoint_env
     553              :                ELSE
     554         1716 :                   kp => kpoint%kp_env(ik)%kpoint_env
     555              :                END IF
     556        14288 :                ALLOCATE (kp%mos(nc, nspin))
     557         4406 :                DO is = 1, nspin
     558              :                   CALL get_mo_set(mos(is), nao=nao, nmo=nmo, nelectron=nelectron, &
     559         2194 :                                   n_el_f=n_el_f, maxocc=maxocc, flexible_electron_count=flexible_electron_count)
     560         2194 :                   nmo = MIN(nao, nmo + nadd)
     561         8498 :                   DO ic = 1, nc
     562              :                      CALL allocate_mo_set(kp%mos(ic, is), nao, nmo, nelectron, n_el_f, maxocc, &
     563         6568 :                                           flexible_electron_count)
     564              :                   END DO
     565              :                END DO
     566              :             END DO
     567              : 
     568              :             ! generate the blacs environment for the kpoint group
     569              :             ! we generate a blacs env for each kpoint group in parallel
     570              :             ! we assume here that the group para_env_inter_kp will connect
     571              :             ! equivalent parts of fm matrices, i.e. no reshuffeling of processors
     572          282 :             NULLIFY (blacs_env)
     573          282 :             IF (ASSOCIATED(kpoint%blacs_env)) THEN
     574           30 :                blacs_env => kpoint%blacs_env
     575              :             ELSE
     576          252 :                CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=kpoint%para_env_kp)
     577          252 :                kpoint%blacs_env => blacs_env
     578              :             END IF
     579              : 
     580              :             ! set possible new number of MOs
     581          602 :             DO is = 1, nspin
     582          320 :                CALL get_mo_set(mos(is), nmo=nmorig(is))
     583          320 :                nmo = MIN(nao, nmorig(is) + nadd)
     584          602 :                CALL set_mo_set(mos(is), nmo=nmo)
     585              :             END DO
     586              :             ! matrix pools for the kpoint group, information on MOs is transferred using
     587              :             ! generic mos structure
     588          282 :             NULLIFY (mpools)
     589          282 :             CALL mpools_create(mpools=mpools)
     590              :             CALL mpools_rebuild_fm_pools(mpools=mpools, mos=mos, &
     591          282 :                                          blacs_env=blacs_env, para_env=kpoint%para_env_kp)
     592              : 
     593          282 :             IF (aux_fit) THEN
     594           30 :                kpoint%mpools_aux_fit => mpools
     595              :             ELSE
     596          252 :                kpoint%mpools => mpools
     597              :             END IF
     598              : 
     599              :             ! reset old number of MOs
     600          602 :             DO is = 1, nspin
     601          602 :                CALL set_mo_set(mos(is), nmo=nmorig(is))
     602              :             END DO
     603              : 
     604              :             ! allocate density matrices
     605          282 :             CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
     606          282 :             ALLOCATE (fmlocal)
     607          282 :             CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
     608          282 :             CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
     609         2212 :             DO ik = 1, nkp_loc
     610         1930 :                IF (aux_fit) THEN
     611          214 :                   kp => kpoint%kp_aux_env(ik)%kpoint_env
     612              :                ELSE
     613         1716 :                   kp => kpoint%kp_env(ik)%kpoint_env
     614              :                END IF
     615              :                ! density matrix
     616         1930 :                CALL cp_fm_release(kp%pmat)
     617        14288 :                ALLOCATE (kp%pmat(nc, nspin))
     618         4124 :                DO is = 1, nspin
     619         8498 :                   DO ic = 1, nc
     620         6568 :                      CALL cp_fm_create(kp%pmat(ic, is), matrix_struct)
     621              :                   END DO
     622              :                END DO
     623              :                ! energy weighted density matrix
     624         1930 :                CALL cp_fm_release(kp%wmat)
     625        12358 :                ALLOCATE (kp%wmat(nc, nspin))
     626         4406 :                DO is = 1, nspin
     627         8498 :                   DO ic = 1, nc
     628         6568 :                      CALL cp_fm_create(kp%wmat(ic, is), matrix_struct)
     629              :                   END DO
     630              :                END DO
     631              :             END DO
     632          282 :             CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
     633          282 :             DEALLOCATE (fmlocal)
     634              : 
     635              :          END IF
     636              : 
     637              :       END IF
     638              : 
     639          282 :       CALL timestop(handle)
     640              : 
     641          282 :    END SUBROUTINE kpoint_initialize_mos
     642              : 
     643              : ! **************************************************************************************************
     644              : !> \brief ...
     645              : !> \param kpoint ...
     646              : ! **************************************************************************************************
     647           58 :    SUBROUTINE kpoint_initialize_mo_set(kpoint)
     648              :       TYPE(kpoint_type), POINTER                         :: kpoint
     649              : 
     650              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_initialize_mo_set'
     651              : 
     652              :       INTEGER                                            :: handle, ic, ik, ikk, ispin
     653           58 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_mo_fm_pools
     654              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     655           58 :       TYPE(mo_set_type), DIMENSION(:, :), POINTER        :: moskp
     656              : 
     657           58 :       CALL timeset(routineN, handle)
     658              : 
     659          404 :       DO ik = 1, SIZE(kpoint%kp_env)
     660          346 :          CALL mpools_get(kpoint%mpools, ao_mo_fm_pools=ao_mo_fm_pools)
     661          346 :          moskp => kpoint%kp_env(ik)%kpoint_env%mos
     662          346 :          ikk = kpoint%kp_range(1) + ik - 1
     663          346 :          CPASSERT(ASSOCIATED(moskp))
     664          784 :          DO ispin = 1, SIZE(moskp, 2)
     665         1486 :             DO ic = 1, SIZE(moskp, 1)
     666          760 :                CALL get_mo_set(moskp(ic, ispin), mo_coeff=mo_coeff)
     667         1140 :                IF (.NOT. ASSOCIATED(mo_coeff)) THEN
     668              :                   CALL init_mo_set(moskp(ic, ispin), &
     669          760 :                                    fm_pool=ao_mo_fm_pools(ispin)%pool, name="kpoints")
     670              :                END IF
     671              :             END DO
     672              :          END DO
     673              :       END DO
     674              : 
     675           58 :       CALL timestop(handle)
     676              : 
     677           58 :    END SUBROUTINE kpoint_initialize_mo_set
     678              : 
     679              : ! **************************************************************************************************
     680              : !> \brief Generates the mapping of cell indices and linear RS index
     681              : !>        CELL (0,0,0) is always mapped to index 1
     682              : !> \param kpoint    Kpoint environment
     683              : !> \param sab_nl    Defining neighbour list
     684              : !> \param para_env  Parallel environment
     685              : !> \param nimages   [output]
     686              : ! **************************************************************************************************
     687         1066 :    SUBROUTINE kpoint_init_cell_index(kpoint, sab_nl, para_env, nimages)
     688              : 
     689              :       TYPE(kpoint_type), POINTER                         :: kpoint
     690              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     691              :          POINTER                                         :: sab_nl
     692              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     693              :       INTEGER, INTENT(OUT)                               :: nimages
     694              : 
     695              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_init_cell_index'
     696              : 
     697              :       INTEGER                                            :: handle, i1, i2, i3, ic, icount, it, &
     698              :                                                             ncount
     699              :       INTEGER, DIMENSION(3)                              :: cell, itm
     700         1066 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell, list
     701         1066 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index, cti
     702              :       LOGICAL                                            :: new
     703              :       TYPE(neighbor_list_iterator_p_type), &
     704         1066 :          DIMENSION(:), POINTER                           :: nl_iterator
     705              : 
     706         1066 :       NULLIFY (cell_to_index, index_to_cell)
     707              : 
     708         1066 :       CALL timeset(routineN, handle)
     709              : 
     710         1066 :       CPASSERT(ASSOCIATED(kpoint))
     711              : 
     712         1066 :       ALLOCATE (list(3, 125))
     713       534066 :       list = 0
     714         1066 :       icount = 1
     715              : 
     716         1066 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
     717       682772 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     718       681706 :          CALL get_iterator_info(nl_iterator, cell=cell)
     719              : 
     720       681706 :          new = .TRUE.
     721     41269871 :          DO ic = 1, icount
     722     41178842 :             IF (cell(1) == list(1, ic) .AND. cell(2) == list(2, ic) .AND. &
     723        91029 :                 cell(3) == list(3, ic)) THEN
     724              :                new = .FALSE.
     725              :                EXIT
     726              :             END IF
     727              :          END DO
     728       682772 :          IF (new) THEN
     729        91029 :             icount = icount + 1
     730        91029 :             IF (icount > SIZE(list, 2)) THEN
     731          299 :                CALL reallocate(list, 1, 3, 1, 2*SIZE(list, 2))
     732              :             END IF
     733       364116 :             list(1:3, icount) = cell(1:3)
     734              :          END IF
     735              : 
     736              :       END DO
     737         1066 :       CALL neighbor_list_iterator_release(nl_iterator)
     738              : 
     739        93161 :       itm(1) = MAXVAL(ABS(list(1, 1:icount)))
     740        93161 :       itm(2) = MAXVAL(ABS(list(2, 1:icount)))
     741        93161 :       itm(3) = MAXVAL(ABS(list(3, 1:icount)))
     742         1066 :       CALL para_env%max(itm)
     743         4264 :       it = MAXVAL(itm(1:3))
     744         1066 :       IF (ASSOCIATED(kpoint%cell_to_index)) THEN
     745         1062 :          DEALLOCATE (kpoint%cell_to_index)
     746              :       END IF
     747         5330 :       ALLOCATE (kpoint%cell_to_index(-itm(1):itm(1), -itm(2):itm(2), -itm(3):itm(3)))
     748         1066 :       cell_to_index => kpoint%cell_to_index
     749         1066 :       cti => cell_to_index
     750       221904 :       cti(:, :, :) = 0
     751        93161 :       DO ic = 1, icount
     752        92095 :          i1 = list(1, ic)
     753        92095 :          i2 = list(2, ic)
     754        92095 :          i3 = list(3, ic)
     755        93161 :          cti(i1, i2, i3) = ic
     756              :       END DO
     757       442742 :       CALL para_env%sum(cti)
     758         1066 :       ncount = 0
     759         6412 :       DO i1 = -itm(1), itm(1)
     760        40858 :          DO i2 = -itm(2), itm(2)
     761       225142 :             DO i3 = -itm(3), itm(3)
     762       219796 :                IF (cti(i1, i2, i3) == 0) THEN
     763        83326 :                   cti(i1, i2, i3) = 1000000
     764              :                ELSE
     765       102024 :                   ncount = ncount + 1
     766       102024 :                   cti(i1, i2, i3) = (ABS(i1) + ABS(i2) + ABS(i3))*1000 + ABS(i3)*100 + ABS(i2)*10 + ABS(i1)
     767       102024 :                   cti(i1, i2, i3) = cti(i1, i2, i3) + (i1 + i2 + i3)
     768              :                END IF
     769              :             END DO
     770              :          END DO
     771              :       END DO
     772              : 
     773         1066 :       IF (ASSOCIATED(kpoint%index_to_cell)) THEN
     774         1066 :          DEALLOCATE (kpoint%index_to_cell)
     775              :       END IF
     776         3198 :       ALLOCATE (kpoint%index_to_cell(3, ncount))
     777         1066 :       index_to_cell => kpoint%index_to_cell
     778       103090 :       DO ic = 1, ncount
     779       102024 :          cell = MINLOC(cti)
     780       102024 :          i1 = cell(1) - 1 - itm(1)
     781       102024 :          i2 = cell(2) - 1 - itm(2)
     782       102024 :          i3 = cell(3) - 1 - itm(3)
     783       102024 :          cti(i1, i2, i3) = 1000000
     784       102024 :          index_to_cell(1, ic) = i1
     785       102024 :          index_to_cell(2, ic) = i2
     786       103090 :          index_to_cell(3, ic) = i3
     787              :       END DO
     788       221904 :       cti(:, :, :) = 0
     789       103090 :       DO ic = 1, ncount
     790       102024 :          i1 = index_to_cell(1, ic)
     791       102024 :          i2 = index_to_cell(2, ic)
     792       102024 :          i3 = index_to_cell(3, ic)
     793       103090 :          cti(i1, i2, i3) = ic
     794              :       END DO
     795              : 
     796              :       ! keep pointer to this neighborlist
     797         1066 :       kpoint%sab_nl => sab_nl
     798              : 
     799              :       ! set number of images
     800         1066 :       nimages = SIZE(index_to_cell, 2)
     801              : 
     802         1066 :       DEALLOCATE (list)
     803              : 
     804         1066 :       CALL timestop(handle)
     805              : 
     806         1066 :    END SUBROUTINE kpoint_init_cell_index
     807              : 
     808              : ! **************************************************************************************************
     809              : !> \brief Transformation of real space matrices to a kpoint
     810              : !> \param rmatrix  Real part of kpoint matrix
     811              : !> \param cmatrix  Complex part of kpoint matrix (optional)
     812              : !> \param rsmat    Real space matrices
     813              : !> \param ispin    Spin index
     814              : !> \param xkp      Kpoint coordinates
     815              : !> \param cell_to_index   mapping of cell indices to RS index
     816              : !> \param sab_nl   Defining neighbor list
     817              : !> \param is_complex  Matrix to be transformed is imaginary
     818              : !> \param rs_sign  Matrix to be transformed is csaled by rs_sign
     819              : ! **************************************************************************************************
     820       124016 :    SUBROUTINE rskp_transform(rmatrix, cmatrix, rsmat, ispin, &
     821              :                              xkp, cell_to_index, sab_nl, is_complex, rs_sign)
     822              : 
     823              :       TYPE(dbcsr_type)                                   :: rmatrix
     824              :       TYPE(dbcsr_type), OPTIONAL                         :: cmatrix
     825              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rsmat
     826              :       INTEGER, INTENT(IN)                                :: ispin
     827              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xkp
     828              :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
     829              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     830              :          POINTER                                         :: sab_nl
     831              :       LOGICAL, INTENT(IN), OPTIONAL                      :: is_complex
     832              :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: rs_sign
     833              : 
     834              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'rskp_transform'
     835              : 
     836              :       INTEGER                                            :: handle, iatom, ic, icol, irow, jatom, &
     837              :                                                             nimg
     838              :       INTEGER, DIMENSION(3)                              :: cell
     839              :       LOGICAL                                            :: do_symmetric, found, my_complex, &
     840              :                                                             wfn_real_only
     841              :       REAL(KIND=dp)                                      :: arg, coskl, fsign, fsym, sinkl
     842        62008 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, rblock, rsblock
     843              :       TYPE(neighbor_list_iterator_p_type), &
     844        62008 :          DIMENSION(:), POINTER                           :: nl_iterator
     845              : 
     846        62008 :       CALL timeset(routineN, handle)
     847              : 
     848        62008 :       my_complex = .FALSE.
     849        62008 :       IF (PRESENT(is_complex)) my_complex = is_complex
     850              : 
     851        62008 :       fsign = 1.0_dp
     852        62008 :       IF (PRESENT(rs_sign)) fsign = rs_sign
     853              : 
     854        62008 :       wfn_real_only = .TRUE.
     855        62008 :       IF (PRESENT(cmatrix)) wfn_real_only = .FALSE.
     856              : 
     857        62008 :       nimg = SIZE(rsmat, 2)
     858              : 
     859        62008 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
     860              : 
     861        62008 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
     862     30124011 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
     863     30062003 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom, cell=cell)
     864              : 
     865              :          ! fsym = +- 1 is due to real space matrices being non-symmetric (although in a symmtric type)
     866              :          ! with the link S_mu^0,nu^b = S_nu^0,mu^-b, and the KP matrices beeing Hermitian
     867     30062003 :          fsym = 1.0_dp
     868     30062003 :          irow = iatom
     869     30062003 :          icol = jatom
     870     30062003 :          IF (do_symmetric .AND. (iatom > jatom)) THEN
     871     12662039 :             irow = jatom
     872     12662039 :             icol = iatom
     873     12662039 :             fsym = -1.0_dp
     874              :          END IF
     875              : 
     876     30062003 :          ic = cell_to_index(cell(1), cell(2), cell(3))
     877     30062003 :          IF (ic < 1 .OR. ic > nimg) CYCLE
     878              : 
     879     30061259 :          arg = REAL(cell(1), dp)*xkp(1) + REAL(cell(2), dp)*xkp(2) + REAL(cell(3), dp)*xkp(3)
     880     30061259 :          IF (my_complex) THEN
     881            0 :             coskl = fsign*fsym*COS(twopi*arg)
     882            0 :             sinkl = fsign*SIN(twopi*arg)
     883              :          ELSE
     884     30061259 :             coskl = fsign*COS(twopi*arg)
     885     30061259 :             sinkl = fsign*fsym*SIN(twopi*arg)
     886              :          END IF
     887              : 
     888              :          CALL dbcsr_get_block_p(matrix=rsmat(ispin, ic)%matrix, row=irow, col=icol, &
     889     30061259 :                                 block=rsblock, found=found)
     890     30061259 :          IF (.NOT. found) CYCLE
     891              : 
     892     30123267 :          IF (wfn_real_only) THEN
     893              :             CALL dbcsr_get_block_p(matrix=rmatrix, row=irow, col=icol, &
     894       456120 :                                    block=rblock, found=found)
     895       456120 :             IF (.NOT. found) CYCLE
     896    208940760 :             rblock = rblock + coskl*rsblock
     897              :          ELSE
     898              :             CALL dbcsr_get_block_p(matrix=rmatrix, row=irow, col=icol, &
     899     29605139 :                                    block=rblock, found=found)
     900     29605139 :             IF (.NOT. found) CYCLE
     901              :             CALL dbcsr_get_block_p(matrix=cmatrix, row=irow, col=icol, &
     902     29605139 :                                    block=cblock, found=found)
     903     29605139 :             IF (.NOT. found) CYCLE
     904   5576946081 :             rblock = rblock + coskl*rsblock
     905   5576946081 :             cblock = cblock + sinkl*rsblock
     906              :          END IF
     907              : 
     908              :       END DO
     909        62008 :       CALL neighbor_list_iterator_release(nl_iterator)
     910              : 
     911        62008 :       CALL timestop(handle)
     912              : 
     913        62008 :    END SUBROUTINE rskp_transform
     914              : 
     915              : ! **************************************************************************************************
     916              : !> \brief Given the eigenvalues of all kpoints, calculates the occupation numbers
     917              : !> \param kpoint  Kpoint environment
     918              : !> \param smear   Smearing information
     919              : !> \param probe ...
     920              : ! **************************************************************************************************
     921         5096 :    SUBROUTINE kpoint_set_mo_occupation(kpoint, smear, probe)
     922              : 
     923              :       TYPE(kpoint_type), POINTER                         :: kpoint
     924              :       TYPE(smear_type), POINTER                          :: smear
     925              :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     926              :          POINTER                                         :: probe
     927              : 
     928              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_set_mo_occupation'
     929              : 
     930              :       INTEGER                                            :: handle, ik, ikpgr, ispin, kplocal, nao, &
     931              :                                                             nb, ncol_global, ne_a, ne_b, &
     932              :                                                             nelectron, nkp, nmo, nrow_global, nspin
     933              :       INTEGER, DIMENSION(2)                              :: kp_range
     934              :       REAL(KIND=dp)                                      :: kTS, mu, mus(2), nel
     935         5096 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: smatrix
     936         5096 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: weig, wocc
     937         5096 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :)  :: icoeff, rcoeff
     938         5096 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation, wkp
     939              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     940              :       TYPE(kpoint_env_type), POINTER                     :: kp
     941              :       TYPE(mo_set_type), POINTER                         :: mo_set
     942              :       TYPE(mp_para_env_type), POINTER                    :: para_env_inter_kp
     943              : 
     944         5096 :       CALL timeset(routineN, handle)
     945              : 
     946              :       ! first collect all the eigenvalues
     947         5096 :       CALL get_kpoint_info(kpoint, nkp=nkp)
     948         5096 :       kp => kpoint%kp_env(1)%kpoint_env
     949         5096 :       nspin = SIZE(kp%mos, 2)
     950         5096 :       mo_set => kp%mos(1, 1)
     951         5096 :       CALL get_mo_set(mo_set, nmo=nmo, nao=nao, nelectron=nelectron)
     952         5096 :       ne_a = nelectron
     953         5096 :       IF (nspin == 2) THEN
     954          568 :          CALL get_mo_set(kp%mos(1, 2), nmo=nb, nelectron=ne_b)
     955          568 :          CPASSERT(nmo == nb)
     956              :       END IF
     957        40768 :       ALLOCATE (weig(nmo, nkp, nspin), wocc(nmo, nkp, nspin))
     958       497992 :       weig = 0.0_dp
     959       497992 :       wocc = 0.0_dp
     960         5096 :       IF (PRESENT(probe)) THEN
     961            0 :          ALLOCATE (rcoeff(nao, nmo, nkp, nspin), icoeff(nao, nmo, nkp, nspin))
     962            0 :          rcoeff = 0.0_dp !coeff, real part
     963            0 :          icoeff = 0.0_dp !coeff, imaginary part
     964              :       END IF
     965         5096 :       CALL get_kpoint_info(kpoint, kp_range=kp_range)
     966         5096 :       kplocal = kp_range(2) - kp_range(1) + 1
     967        23246 :       DO ikpgr = 1, kplocal
     968        18150 :          ik = kp_range(1) + ikpgr - 1
     969        18150 :          kp => kpoint%kp_env(ikpgr)%kpoint_env
     970        43496 :          DO ispin = 1, nspin
     971        20250 :             mo_set => kp%mos(1, ispin)
     972        20250 :             CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
     973       364766 :             weig(1:nmo, ik, ispin) = eigenvalues(1:nmo)
     974        38400 :             IF (PRESENT(probe)) THEN
     975            0 :                CALL get_mo_set(mo_set, mo_coeff=mo_coeff)
     976              :                CALL cp_fm_get_info(mo_coeff, &
     977              :                                    nrow_global=nrow_global, &
     978            0 :                                    ncol_global=ncol_global)
     979            0 :                ALLOCATE (smatrix(nrow_global, ncol_global))
     980            0 :                CALL cp_fm_get_submatrix(mo_coeff, smatrix)
     981              : 
     982            0 :                rcoeff(1:nao, 1:nmo, ik, ispin) = smatrix(1:nrow_global, 1:ncol_global)
     983              : 
     984            0 :                DEALLOCATE (smatrix)
     985              : 
     986            0 :                mo_set => kp%mos(2, ispin)
     987              : 
     988            0 :                CALL get_mo_set(mo_set, mo_coeff=mo_coeff)
     989              :                CALL cp_fm_get_info(mo_coeff, &
     990              :                                    nrow_global=nrow_global, &
     991            0 :                                    ncol_global=ncol_global)
     992            0 :                ALLOCATE (smatrix(nrow_global, ncol_global))
     993            0 :                CALL cp_fm_get_submatrix(mo_coeff, smatrix)
     994              : 
     995            0 :                icoeff(1:nao, 1:nmo, ik, ispin) = smatrix(1:nrow_global, 1:ncol_global)
     996              : 
     997            0 :                mo_set => kp%mos(1, ispin)
     998              : 
     999            0 :                DEALLOCATE (smatrix)
    1000              :             END IF
    1001              :          END DO
    1002              :       END DO
    1003         5096 :       CALL get_kpoint_info(kpoint, para_env_inter_kp=para_env_inter_kp)
    1004         5096 :       CALL para_env_inter_kp%sum(weig)
    1005              : 
    1006         5096 :       IF (PRESENT(probe)) THEN
    1007            0 :          CALL para_env_inter_kp%sum(rcoeff)
    1008            0 :          CALL para_env_inter_kp%sum(icoeff)
    1009              :       END IF
    1010              : 
    1011         5096 :       CALL get_kpoint_info(kpoint, wkp=wkp)
    1012              : 
    1013              : !calling of HP module HERE, before smear
    1014         5096 :       IF (PRESENT(probe)) THEN
    1015            0 :          smear%do_smear = .FALSE. !ensures smearing is switched off
    1016              : 
    1017            0 :          IF (nspin == 1) THEN
    1018            0 :             nel = REAL(nelectron, KIND=dp)
    1019              :             CALL probe_occupancy_kp(wocc(:, :, :), mus(1), kTS, weig(:, :, :), rcoeff(:, :, :, :), icoeff(:, :, :, :), 2.0d0, &
    1020            0 :                                     probe, nel, wkp)
    1021              :          ELSE
    1022            0 :             nel = REAL(ne_a, KIND=dp) + REAL(ne_b, KIND=dp)
    1023              :             CALL probe_occupancy_kp(wocc(:, :, :), mu, kTS, weig(:, :, :), rcoeff(:, :, :, :), icoeff(:, :, :, :), 1.0d0, &
    1024            0 :                                     probe, nel, wkp)
    1025            0 :             kTS = kTS/2._dp
    1026            0 :             mus(1:2) = mu
    1027              :          END IF
    1028              : 
    1029            0 :          DO ikpgr = 1, kplocal
    1030            0 :             ik = kp_range(1) + ikpgr - 1
    1031            0 :             kp => kpoint%kp_env(ikpgr)%kpoint_env
    1032            0 :             DO ispin = 1, nspin
    1033            0 :                mo_set => kp%mos(1, ispin)
    1034            0 :                CALL get_mo_set(mo_set, eigenvalues=eigenvalues, occupation_numbers=occupation)
    1035            0 :                eigenvalues(1:nmo) = weig(1:nmo, ik, ispin)
    1036            0 :                occupation(1:nmo) = wocc(1:nmo, ik, ispin)
    1037            0 :                mo_set%kTS = kTS
    1038            0 :                mo_set%mu = mus(ispin)
    1039              : 
    1040            0 :                CALL get_mo_set(mo_set, mo_coeff=mo_coeff)
    1041              :                !get smatrix for kpoint_env ikp
    1042              :                CALL cp_fm_get_info(mo_coeff, &
    1043              :                                    nrow_global=nrow_global, &
    1044            0 :                                    ncol_global=ncol_global)
    1045            0 :                ALLOCATE (smatrix(nrow_global, ncol_global))
    1046            0 :                CALL cp_fm_get_submatrix(mo_coeff, smatrix)
    1047              : 
    1048            0 :                smatrix(1:nrow_global, 1:ncol_global) = rcoeff(1:nao, 1:nmo, ik, ispin)
    1049            0 :                DEALLOCATE (smatrix)
    1050              : 
    1051            0 :                mo_set => kp%mos(2, ispin)
    1052              : 
    1053            0 :                CALL get_mo_set(mo_set, mo_coeff=mo_coeff)
    1054              :                !get smatrix for kpoint_env ikp
    1055              :                CALL cp_fm_get_info(mo_coeff, &
    1056              :                                    nrow_global=nrow_global, &
    1057            0 :                                    ncol_global=ncol_global)
    1058            0 :                ALLOCATE (smatrix(nrow_global, ncol_global))
    1059            0 :                CALL cp_fm_get_submatrix(mo_coeff, smatrix)
    1060              : 
    1061            0 :                smatrix(1:nrow_global, 1:ncol_global) = icoeff(1:nao, 1:nmo, ik, ispin)
    1062            0 :                DEALLOCATE (smatrix)
    1063              : 
    1064            0 :                mo_set => kp%mos(1, ispin)
    1065              : 
    1066              :             END DO
    1067              :          END DO
    1068              : 
    1069            0 :          DEALLOCATE (weig, wocc, rcoeff, icoeff)
    1070              : 
    1071              :       END IF
    1072              : 
    1073              :       IF (PRESENT(probe) .EQV. .FALSE.) THEN
    1074         5096 :          IF (smear%do_smear) THEN
    1075         1516 :             SELECT CASE (smear%method)
    1076              :             CASE (smear_fermi_dirac)
    1077              :                ! finite electronic temperature
    1078          696 :                IF (nspin == 1) THEN
    1079          696 :                   nel = REAL(nelectron, KIND=dp)
    1080              :                   CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1081          696 :                                smear%electronic_temperature, 2.0_dp, smear_fermi_dirac)
    1082            0 :                ELSE IF (smear%fixed_mag_mom > 0.0_dp) THEN
    1083            0 :                   nel = REAL(ne_a, KIND=dp)
    1084              :                   CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1085            0 :                                smear%electronic_temperature, 1.0_dp, smear_fermi_dirac)
    1086            0 :                   nel = REAL(ne_b, KIND=dp)
    1087              :                   CALL Smearkp(wocc(:, :, 2), mus(2), kTS, weig(:, :, 2), nel, wkp, &
    1088            0 :                                smear%electronic_temperature, 1.0_dp, smear_fermi_dirac)
    1089              :                ELSE
    1090            0 :                   nel = REAL(ne_a, KIND=dp) + REAL(ne_b, KIND=dp)
    1091              :                   CALL Smearkp2(wocc(:, :, :), mu, kTS, weig(:, :, :), nel, wkp, &
    1092            0 :                                 smear%electronic_temperature, smear_fermi_dirac)
    1093            0 :                   kTS = kTS/2._dp
    1094            0 :                   mus(1:2) = mu
    1095              :                END IF
    1096              :             CASE (smear_gaussian, smear_mp, smear_mv)
    1097          124 :                IF (nspin == 1) THEN
    1098           96 :                   nel = REAL(nelectron, KIND=dp)
    1099              :                   CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1100           96 :                                smear%smearing_width, 2.0_dp, smear%method)
    1101           28 :                ELSE IF (smear%fixed_mag_mom > 0.0_dp) THEN
    1102            0 :                   nel = REAL(ne_a, KIND=dp)
    1103              :                   CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1104            0 :                                smear%smearing_width, 1.0_dp, smear%method)
    1105            0 :                   nel = REAL(ne_b, KIND=dp)
    1106              :                   CALL Smearkp(wocc(:, :, 2), mus(2), kTS, weig(:, :, 2), nel, wkp, &
    1107            0 :                                smear%smearing_width, 1.0_dp, smear%method)
    1108              :                ELSE
    1109           28 :                   nel = REAL(ne_a, KIND=dp) + REAL(ne_b, KIND=dp)
    1110              :                   CALL Smearkp2(wocc(:, :, :), mu, kTS, weig(:, :, :), nel, wkp, &
    1111           28 :                                 smear%smearing_width, smear%method)
    1112           28 :                   kTS = kTS/2._dp
    1113           84 :                   mus(1:2) = mu
    1114              :                END IF
    1115              :             CASE DEFAULT
    1116          820 :                CPABORT("kpoints: Selected smearing not (yet) supported")
    1117              :             END SELECT
    1118              :          ELSE
    1119              :             ! fixed occupations (2/1)
    1120         4276 :             IF (nspin == 1) THEN
    1121         3736 :                nel = REAL(nelectron, KIND=dp)
    1122              :                CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1123         3736 :                             0.0_dp, 2.0_dp, smear_gaussian)
    1124              :             ELSE
    1125          540 :                nel = REAL(ne_a, KIND=dp)
    1126              :                CALL Smearkp(wocc(:, :, 1), mus(1), kTS, weig(:, :, 1), nel, wkp, &
    1127          540 :                             0.0_dp, 1.0_dp, smear_gaussian)
    1128          540 :                nel = REAL(ne_b, KIND=dp)
    1129              :                CALL Smearkp(wocc(:, :, 2), mus(2), kTS, weig(:, :, 2), nel, wkp, &
    1130          540 :                             0.0_dp, 1.0_dp, smear_gaussian)
    1131              :             END IF
    1132              :          END IF
    1133        23246 :          DO ikpgr = 1, kplocal
    1134        18150 :             ik = kp_range(1) + ikpgr - 1
    1135        18150 :             kp => kpoint%kp_env(ikpgr)%kpoint_env
    1136        43496 :             DO ispin = 1, nspin
    1137        20250 :                mo_set => kp%mos(1, ispin)
    1138        20250 :                CALL get_mo_set(mo_set, eigenvalues=eigenvalues, occupation_numbers=occupation)
    1139       364766 :                eigenvalues(1:nmo) = weig(1:nmo, ik, ispin)
    1140       364766 :                occupation(1:nmo) = wocc(1:nmo, ik, ispin)
    1141        20250 :                mo_set%kTS = kTS
    1142        38400 :                mo_set%mu = mus(ispin)
    1143              :             END DO
    1144              :          END DO
    1145              : 
    1146         5096 :          DEALLOCATE (weig, wocc)
    1147              : 
    1148              :       END IF
    1149              : 
    1150         5096 :       CALL timestop(handle)
    1151              : 
    1152        15288 :    END SUBROUTINE kpoint_set_mo_occupation
    1153              : 
    1154              : ! **************************************************************************************************
    1155              : !> \brief Calculate kpoint density matrices (rho(k), owned by kpoint groups)
    1156              : !> \param kpoint    kpoint environment
    1157              : !> \param energy_weighted  calculate energy weighted density matrix
    1158              : !> \param for_aux_fit ...
    1159              : ! **************************************************************************************************
    1160        16254 :    SUBROUTINE kpoint_density_matrices(kpoint, energy_weighted, for_aux_fit)
    1161              : 
    1162              :       TYPE(kpoint_type), POINTER                         :: kpoint
    1163              :       LOGICAL, OPTIONAL                                  :: energy_weighted, for_aux_fit
    1164              : 
    1165              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_density_matrices'
    1166              : 
    1167              :       INTEGER                                            :: handle, ikpgr, ispin, kplocal, nao, nmo, &
    1168              :                                                             nspin
    1169              :       INTEGER, DIMENSION(2)                              :: kp_range
    1170              :       LOGICAL                                            :: aux_fit, wtype
    1171         5418 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: eigenvalues, occupation
    1172              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1173              :       TYPE(cp_fm_type)                                   :: fwork
    1174              :       TYPE(cp_fm_type), POINTER                          :: cpmat, pmat, rpmat
    1175              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1176              :       TYPE(mo_set_type), POINTER                         :: mo_set
    1177              : 
    1178         5418 :       CALL timeset(routineN, handle)
    1179              : 
    1180         5418 :       IF (PRESENT(energy_weighted)) THEN
    1181          188 :          wtype = energy_weighted
    1182              :       ELSE
    1183              :          ! default is normal density matrix
    1184              :          wtype = .FALSE.
    1185              :       END IF
    1186              : 
    1187         5418 :       IF (PRESENT(for_aux_fit)) THEN
    1188          118 :          aux_fit = for_aux_fit
    1189              :       ELSE
    1190              :          aux_fit = .FALSE.
    1191              :       END IF
    1192              : 
    1193          118 :       IF (aux_fit) THEN
    1194          118 :          CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
    1195              :       END IF
    1196              : 
    1197              :       ! work matrix
    1198         5418 :       IF (aux_fit) THEN
    1199          118 :          mo_set => kpoint%kp_aux_env(1)%kpoint_env%mos(1, 1)
    1200              :       ELSE
    1201         5300 :          mo_set => kpoint%kp_env(1)%kpoint_env%mos(1, 1)
    1202              :       END IF
    1203         5418 :       CALL get_mo_set(mo_set, nao=nao, nmo=nmo)
    1204         5418 :       CALL cp_fm_get_info(mo_set%mo_coeff, matrix_struct=matrix_struct)
    1205         5418 :       CALL cp_fm_create(fwork, matrix_struct)
    1206              : 
    1207         5418 :       CALL get_kpoint_info(kpoint, kp_range=kp_range)
    1208         5418 :       kplocal = kp_range(2) - kp_range(1) + 1
    1209        26424 :       DO ikpgr = 1, kplocal
    1210        21006 :          IF (aux_fit) THEN
    1211         1864 :             kp => kpoint%kp_aux_env(ikpgr)%kpoint_env
    1212              :          ELSE
    1213        19142 :             kp => kpoint%kp_env(ikpgr)%kpoint_env
    1214              :          END IF
    1215        21006 :          nspin = SIZE(kp%mos, 2)
    1216        49782 :          DO ispin = 1, nspin
    1217        23358 :             mo_set => kp%mos(1, ispin)
    1218        23358 :             IF (wtype) THEN
    1219         1016 :                CALL get_mo_set(mo_set, eigenvalues=eigenvalues)
    1220              :             END IF
    1221        44364 :             IF (kpoint%use_real_wfn) THEN
    1222          104 :                IF (wtype) THEN
    1223           10 :                   pmat => kp%wmat(1, ispin)
    1224              :                ELSE
    1225           94 :                   pmat => kp%pmat(1, ispin)
    1226              :                END IF
    1227          104 :                CALL get_mo_set(mo_set, occupation_numbers=occupation)
    1228          104 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1229          104 :                CALL cp_fm_column_scale(fwork, occupation)
    1230          104 :                IF (wtype) THEN
    1231           10 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1232              :                END IF
    1233          104 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, pmat)
    1234              :             ELSE
    1235        23254 :                IF (wtype) THEN
    1236         1006 :                   rpmat => kp%wmat(1, ispin)
    1237         1006 :                   cpmat => kp%wmat(2, ispin)
    1238              :                ELSE
    1239        22248 :                   rpmat => kp%pmat(1, ispin)
    1240        22248 :                   cpmat => kp%pmat(2, ispin)
    1241              :                END IF
    1242        23254 :                CALL get_mo_set(mo_set, occupation_numbers=occupation)
    1243        23254 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1244        23254 :                CALL cp_fm_column_scale(fwork, occupation)
    1245        23254 :                IF (wtype) THEN
    1246         1006 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1247              :                END IF
    1248              :                ! Re(c)*Re(c)
    1249        23254 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, rpmat)
    1250        23254 :                mo_set => kp%mos(2, ispin)
    1251              :                ! Im(c)*Re(c)
    1252        23254 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 0.0_dp, cpmat)
    1253              :                ! Re(c)*Im(c)
    1254        23254 :                CALL parallel_gemm("N", "T", nao, nao, nmo, -1.0_dp, fwork, mo_set%mo_coeff, 1.0_dp, cpmat)
    1255        23254 :                CALL cp_fm_to_fm(mo_set%mo_coeff, fwork)
    1256        23254 :                CALL cp_fm_column_scale(fwork, occupation)
    1257        23254 :                IF (wtype) THEN
    1258         1006 :                   CALL cp_fm_column_scale(fwork, eigenvalues)
    1259              :                END IF
    1260              :                ! Im(c)*Im(c)
    1261        23254 :                CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, mo_set%mo_coeff, fwork, 1.0_dp, rpmat)
    1262              :             END IF
    1263              :          END DO
    1264              :       END DO
    1265              : 
    1266         5418 :       CALL cp_fm_release(fwork)
    1267              : 
    1268         5418 :       CALL timestop(handle)
    1269              : 
    1270         5418 :    END SUBROUTINE kpoint_density_matrices
    1271              : 
    1272              : ! **************************************************************************************************
    1273              : !> \brief Kpoint transformation of density matrix for Lowdin population analysis
    1274              : !>        Transforms matrices to kpoint, distributes kpoint groups, performs S^1/2 P S^1/2
    1275              : !> \param matrix_p     Density matrices (RS indices, global)
    1276              : !> \param kpoints      Kpoint environment
    1277              : !> \param ispin        spin component
    1278              : !> \param fmwork       full matrices distributed over all groups
    1279              : !> \par History
    1280              : !>      02.2026 created [JGH]
    1281              : ! **************************************************************************************************
    1282            0 :    SUBROUTINE lowdin_kp_trans(matrix_p, kpoints, ispin, fmwork)
    1283              : 
    1284              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p
    1285              :       TYPE(kpoint_type), POINTER                         :: kpoints
    1286              :       INTEGER, INTENT(IN)                                :: ispin
    1287              :       TYPE(cp_fm_type), DIMENSION(:)                     :: fmwork
    1288              : 
    1289              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'lowdin_kp_trans'
    1290              :       COMPLEX(KIND=dp), PARAMETER                        :: cone = (1.0_dp, 0.0_dp), &
    1291              :                                                             czero = (0.0_dp, 0.0_dp)
    1292              : 
    1293              :       INTEGER                                            :: handle, igroup, ik, ikp, indx, kplocal, &
    1294              :                                                             nao, nkp, nkp_groups
    1295              :       INTEGER, DIMENSION(2)                              :: kp_range
    1296            0 :       INTEGER, DIMENSION(:, :), POINTER                  :: kp_dist
    1297            0 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1298              :       LOGICAL                                            :: my_kpgrp, use_real_wfn
    1299            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1300            0 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:, :) :: info
    1301              :       TYPE(cp_cfm_type)                                  :: csmat, cwork
    1302            0 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_ao_fm_pools
    1303              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
    1304              :       TYPE(cp_fm_type)                                   :: fmdummy, fmlocal, rsmat
    1305              :       TYPE(dbcsr_type), POINTER                          :: cmatrix, rmatrix, tmpmat
    1306              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1307              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1308              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1309            0 :          POINTER                                         :: sab_nl
    1310              :       TYPE(qs_matrix_pools_type), POINTER                :: mpools
    1311              : 
    1312            0 :       CALL timeset(routineN, handle)
    1313              : 
    1314            0 :       NULLIFY (sab_nl)
    1315              :       CALL get_kpoint_info(kpoints, nkp=nkp, xkp=xkp, use_real_wfn=use_real_wfn, kp_range=kp_range, &
    1316              :                            nkp_groups=nkp_groups, kp_dist=kp_dist, sab_nl=sab_nl, &
    1317            0 :                            cell_to_index=cell_to_index)
    1318            0 :       CPASSERT(ASSOCIATED(sab_nl))
    1319            0 :       kplocal = kp_range(2) - kp_range(1) + 1
    1320              : 
    1321              :       ! allocate some work matrices
    1322            0 :       ALLOCATE (rmatrix, cmatrix, tmpmat)
    1323              :       CALL dbcsr_create(rmatrix, template=matrix_p(1, 1)%matrix, &
    1324            0 :                         matrix_type=dbcsr_type_symmetric)
    1325              :       CALL dbcsr_create(cmatrix, template=matrix_p(1, 1)%matrix, &
    1326            0 :                         matrix_type=dbcsr_type_antisymmetric)
    1327              :       CALL dbcsr_create(tmpmat, template=matrix_p(1, 1)%matrix, &
    1328            0 :                         matrix_type=dbcsr_type_no_symmetry)
    1329            0 :       CALL cp_dbcsr_alloc_block_from_nbl(rmatrix, sab_nl)
    1330            0 :       CALL cp_dbcsr_alloc_block_from_nbl(cmatrix, sab_nl)
    1331              : 
    1332              :       ! fm pools to be used within a kpoint group
    1333            0 :       CALL get_kpoint_info(kpoints, mpools=mpools)
    1334            0 :       CALL mpools_get(mpools, ao_ao_fm_pools=ao_ao_fm_pools)
    1335              : 
    1336            0 :       CALL fm_pool_create_fm(ao_ao_fm_pools(1)%pool, fmlocal)
    1337            0 :       CALL cp_fm_get_info(fmlocal, matrix_struct=matrix_struct)
    1338              : 
    1339            0 :       IF (use_real_wfn) THEN
    1340            0 :          CALL cp_fm_create(rsmat, matrix_struct)
    1341              :       ELSE
    1342            0 :          CALL cp_cfm_create(csmat, matrix_struct)
    1343            0 :          CALL cp_cfm_create(cwork, matrix_struct)
    1344              :       END IF
    1345              : 
    1346            0 :       CALL cp_fm_get_info(fmwork(1), nrow_global=nao)
    1347              : 
    1348            0 :       para_env => kpoints%blacs_env_all%para_env
    1349            0 :       ALLOCATE (info(kplocal*nkp_groups, 2))
    1350              : 
    1351              :       ! Setup and start all the communication
    1352            0 :       indx = 0
    1353            0 :       DO ikp = 1, kplocal
    1354            0 :          DO igroup = 1, nkp_groups
    1355              :             ! number of current kpoint
    1356            0 :             ik = kp_dist(1, igroup) + ikp - 1
    1357            0 :             my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    1358            0 :             indx = indx + 1
    1359            0 :             IF (use_real_wfn) THEN
    1360            0 :                CALL dbcsr_set(rmatrix, 0.0_dp)
    1361              :                CALL rskp_transform(rmatrix=rmatrix, rsmat=matrix_p, ispin=ispin, &
    1362            0 :                                    xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
    1363            0 :                CALL dbcsr_desymmetrize(rmatrix, tmpmat)
    1364            0 :                CALL copy_dbcsr_to_fm(tmpmat, fmwork(1))
    1365              :             ELSE
    1366            0 :                CALL dbcsr_set(rmatrix, 0.0_dp)
    1367            0 :                CALL dbcsr_set(cmatrix, 0.0_dp)
    1368              :                CALL rskp_transform(rmatrix=rmatrix, cmatrix=cmatrix, rsmat=matrix_p, ispin=ispin, &
    1369            0 :                                    xkp=xkp(1:3, ik), cell_to_index=cell_to_index, sab_nl=sab_nl)
    1370            0 :                CALL dbcsr_desymmetrize(rmatrix, tmpmat)
    1371            0 :                CALL copy_dbcsr_to_fm(tmpmat, fmwork(1))
    1372            0 :                CALL dbcsr_desymmetrize(cmatrix, tmpmat)
    1373            0 :                CALL copy_dbcsr_to_fm(tmpmat, fmwork(2))
    1374              :             END IF
    1375              :             ! transfer to kpoint group
    1376              :             ! redistribution of matrices, new blacs environment
    1377              :             ! fmwork -> fmlocal -> rsmat/csmat
    1378            0 :             IF (use_real_wfn) THEN
    1379            0 :                IF (my_kpgrp) THEN
    1380            0 :                   CALL cp_fm_start_copy_general(fmwork(1), rsmat, para_env, info(indx, 1))
    1381              :                ELSE
    1382            0 :                   CALL cp_fm_start_copy_general(fmwork(1), fmdummy, para_env, info(indx, 1))
    1383              :                END IF
    1384              :             ELSE
    1385            0 :                IF (my_kpgrp) THEN
    1386            0 :                   CALL cp_fm_start_copy_general(fmwork(1), fmlocal, para_env, info(indx, 1))
    1387            0 :                   CALL cp_fm_start_copy_general(fmwork(2), fmlocal, para_env, info(indx, 2))
    1388              :                ELSE
    1389            0 :                   CALL cp_fm_start_copy_general(fmwork(1), fmdummy, para_env, info(indx, 1))
    1390            0 :                   CALL cp_fm_start_copy_general(fmwork(2), fmdummy, para_env, info(indx, 2))
    1391              :                END IF
    1392              :             END IF
    1393              :          END DO
    1394              :       END DO
    1395              : 
    1396              :       ! Finish communication then tranform in each group
    1397              :       indx = 0
    1398            0 :       DO ikp = 1, kplocal
    1399            0 :          DO igroup = 1, nkp_groups
    1400              :             ! number of current kpoint
    1401            0 :             ik = kp_dist(1, igroup) + ikp - 1
    1402            0 :             my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    1403            0 :             indx = indx + 1
    1404            0 :             IF (my_kpgrp) THEN
    1405            0 :                IF (use_real_wfn) THEN
    1406            0 :                   CALL cp_fm_finish_copy_general(rsmat, info(indx, 1))
    1407              :                ELSE
    1408            0 :                   CALL cp_fm_finish_copy_general(fmlocal, info(indx, 1))
    1409            0 :                   CALL cp_cfm_scale_and_add_fm(czero, csmat, cone, fmlocal)
    1410            0 :                   CALL cp_fm_finish_copy_general(fmlocal, info(indx, 2))
    1411            0 :                   CALL cp_cfm_scale_and_add_fm(cone, csmat, gaussi, fmlocal)
    1412              :                END IF
    1413              :             END IF
    1414              :          END DO
    1415              : 
    1416              :          ! Each kpoint group has now information on a kpoint to be transformed
    1417            0 :          kp => kpoints%kp_env(ikp)%kpoint_env
    1418            0 :          IF (use_real_wfn) THEN
    1419              :             CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, rsmat, kp%shalf, &
    1420            0 :                                0.0_dp, fmlocal)
    1421              :             CALL parallel_gemm("N", "N", nao, nao, nao, 1.0_dp, kp%shalf, fmlocal, &
    1422            0 :                                0.0_dp, kp%pmat(1, ispin))
    1423              :          ELSE
    1424              :             CALL parallel_gemm("N", "N", nao, nao, nao, cone, csmat, kp%cshalf, &
    1425            0 :                                czero, cwork)
    1426              :             CALL parallel_gemm("N", "N", nao, nao, nao, cone, kp%cshalf, cwork, &
    1427            0 :                                czero, csmat)
    1428            0 :             CALL cp_cfm_to_fm(csmat, kp%pmat(1, ispin), kp%pmat(2, ispin))
    1429              :          END IF
    1430              :       END DO
    1431              : 
    1432              :       ! Clean up communication
    1433              :       indx = 0
    1434            0 :       DO ikp = 1, kplocal
    1435            0 :          DO igroup = 1, nkp_groups
    1436              :             ! number of current kpoint
    1437            0 :             ik = kp_dist(1, igroup) + ikp - 1
    1438            0 :             my_kpgrp = (ik >= kpoints%kp_range(1) .AND. ik <= kpoints%kp_range(2))
    1439            0 :             indx = indx + 1
    1440            0 :             IF (use_real_wfn) THEN
    1441            0 :                CALL cp_fm_cleanup_copy_general(info(indx, 1))
    1442              :             ELSE
    1443            0 :                CALL cp_fm_cleanup_copy_general(info(indx, 1))
    1444            0 :                CALL cp_fm_cleanup_copy_general(info(indx, 2))
    1445              :             END IF
    1446              :          END DO
    1447              :       END DO
    1448              : 
    1449              :       ! All done
    1450            0 :       DEALLOCATE (info)
    1451              : 
    1452            0 :       CALL dbcsr_deallocate_matrix(rmatrix)
    1453            0 :       CALL dbcsr_deallocate_matrix(cmatrix)
    1454            0 :       CALL dbcsr_deallocate_matrix(tmpmat)
    1455              : 
    1456            0 :       IF (use_real_wfn) THEN
    1457            0 :          CALL cp_fm_release(rsmat)
    1458              :       ELSE
    1459            0 :          CALL cp_cfm_release(csmat)
    1460            0 :          CALL cp_cfm_release(cwork)
    1461              :       END IF
    1462            0 :       CALL fm_pool_give_back_fm(ao_ao_fm_pools(1)%pool, fmlocal)
    1463              : 
    1464            0 :       CALL timestop(handle)
    1465              : 
    1466            0 :    END SUBROUTINE lowdin_kp_trans
    1467              : 
    1468              : ! **************************************************************************************************
    1469              : !> \brief generate real space density matrices in DBCSR format
    1470              : !> \param kpoint  Kpoint environment
    1471              : !> \param denmat  Real space (DBCSR) density matrices
    1472              : !> \param wtype   True = energy weighted density matrix
    1473              : !>                False = normal density matrix
    1474              : !> \param tempmat DBCSR matrix to be used as template
    1475              : !> \param sab_nl ...
    1476              : !> \param fmwork  FM work matrices (kpoint group)
    1477              : !> \param for_aux_fit ...
    1478              : !> \param pmat_ext ...
    1479              : ! **************************************************************************************************
    1480         5648 :    SUBROUTINE kpoint_density_transform(kpoint, denmat, wtype, tempmat, sab_nl, fmwork, for_aux_fit, pmat_ext)
    1481              : 
    1482              :       TYPE(kpoint_type), POINTER                         :: kpoint
    1483              :       TYPE(dbcsr_p_type), DIMENSION(:, :)                :: denmat
    1484              :       LOGICAL, INTENT(IN)                                :: wtype
    1485              :       TYPE(dbcsr_type), POINTER                          :: tempmat
    1486              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1487              :          POINTER                                         :: sab_nl
    1488              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fmwork
    1489              :       LOGICAL, OPTIONAL                                  :: for_aux_fit
    1490              :       TYPE(cp_fm_type), DIMENSION(:, :, :), INTENT(IN), &
    1491              :          OPTIONAL                                        :: pmat_ext
    1492              : 
    1493              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'kpoint_density_transform'
    1494              : 
    1495              :       INTEGER                                            :: handle, ic, ik, ikk, indx, ir, ira, is, &
    1496              :                                                             ispin, jr, nc, nimg, nkp, nspin
    1497         5648 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1498              :       LOGICAL                                            :: aux_fit, do_ext, do_symmetric, my_kpgrp, &
    1499              :                                                             real_only
    1500              :       REAL(KIND=dp)                                      :: wkpx
    1501         5648 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: wkp
    1502         5648 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: xkp
    1503         5648 :       TYPE(copy_info_type), ALLOCATABLE, DIMENSION(:)    :: info
    1504              :       TYPE(cp_fm_type)                                   :: fmdummy
    1505              :       TYPE(dbcsr_type), POINTER                          :: cpmat, rpmat, scpmat, srpmat
    1506         5648 :       TYPE(kind_rotmat_type), DIMENSION(:), POINTER      :: kind_rot
    1507              :       TYPE(kpoint_env_type), POINTER                     :: kp
    1508              :       TYPE(kpoint_sym_type), POINTER                     :: kpsym
    1509              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1510              : 
    1511         5648 :       CALL timeset(routineN, handle)
    1512              : 
    1513         5648 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    1514              : 
    1515         5648 :       IF (PRESENT(for_aux_fit)) THEN
    1516          348 :          aux_fit = for_aux_fit
    1517              :       ELSE
    1518              :          aux_fit = .FALSE.
    1519              :       END IF
    1520              : 
    1521         5648 :       do_ext = .FALSE.
    1522         5648 :       IF (PRESENT(pmat_ext)) do_ext = .TRUE.
    1523              : 
    1524         5648 :       IF (aux_fit) THEN
    1525          200 :          CPASSERT(ASSOCIATED(kpoint%kp_aux_env))
    1526              :       END IF
    1527              : 
    1528              :       ! work storage
    1529         5648 :       ALLOCATE (rpmat)
    1530              :       CALL dbcsr_create(rpmat, template=tempmat, &
    1531         5700 :                         matrix_type=MERGE(dbcsr_type_symmetric, dbcsr_type_no_symmetry, do_symmetric))
    1532         5648 :       CALL cp_dbcsr_alloc_block_from_nbl(rpmat, sab_nl)
    1533         5648 :       CALL dbcsr_set(rpmat, 0.0_dp)
    1534         5648 :       ALLOCATE (cpmat)
    1535              :       CALL dbcsr_create(cpmat, template=tempmat, &
    1536         5700 :                         matrix_type=MERGE(dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, do_symmetric))
    1537         5648 :       CALL cp_dbcsr_alloc_block_from_nbl(cpmat, sab_nl)
    1538         5648 :       CALL dbcsr_set(cpmat, 0.0_dp)
    1539         5648 :       IF (.NOT. kpoint%full_grid) THEN
    1540         4066 :          ALLOCATE (srpmat)
    1541         4066 :          CALL dbcsr_create(srpmat, template=rpmat)
    1542         4066 :          CALL cp_dbcsr_alloc_block_from_nbl(srpmat, sab_nl)
    1543         4066 :          CALL dbcsr_set(srpmat, 0.0_dp)
    1544         4066 :          ALLOCATE (scpmat)
    1545         4066 :          CALL dbcsr_create(scpmat, template=cpmat)
    1546         4066 :          CALL cp_dbcsr_alloc_block_from_nbl(scpmat, sab_nl)
    1547         4066 :          CALL dbcsr_set(scpmat, 0.0_dp)
    1548              :       END IF
    1549              : 
    1550              :       CALL get_kpoint_info(kpoint, nkp=nkp, xkp=xkp, wkp=wkp, &
    1551         5648 :                            cell_to_index=cell_to_index)
    1552              :       ! initialize real space density matrices
    1553         5648 :       IF (aux_fit) THEN
    1554          200 :          kp => kpoint%kp_aux_env(1)%kpoint_env
    1555              :       ELSE
    1556         5448 :          kp => kpoint%kp_env(1)%kpoint_env
    1557              :       END IF
    1558         5648 :       nspin = SIZE(kp%mos, 2)
    1559         5648 :       nc = SIZE(kp%mos, 1)
    1560         5648 :       nimg = SIZE(denmat, 2)
    1561         5648 :       real_only = (nc == 1)
    1562              : 
    1563         5648 :       para_env => kpoint%blacs_env_all%para_env
    1564       133180 :       ALLOCATE (info(nspin*nkp*nc))
    1565              : 
    1566              :       ! Start all the communication
    1567         5648 :       indx = 0
    1568        11946 :       DO ispin = 1, nspin
    1569       624362 :          DO ic = 1, nimg
    1570       624362 :             CALL dbcsr_set(denmat(ispin, ic)%matrix, 0.0_dp)
    1571              :          END DO
    1572              :          !
    1573        47524 :          DO ik = 1, nkp
    1574        35578 :             my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
    1575              :             IF (my_kpgrp) THEN
    1576        26302 :                ikk = ik - kpoint%kp_range(1) + 1
    1577        26302 :                IF (aux_fit) THEN
    1578         2682 :                   kp => kpoint%kp_aux_env(ikk)%kpoint_env
    1579              :                ELSE
    1580        23620 :                   kp => kpoint%kp_env(ikk)%kpoint_env
    1581              :                END IF
    1582              :             ELSE
    1583              :                NULLIFY (kp)
    1584              :             END IF
    1585              :             ! collect this density matrix on all processors
    1586        35578 :             CPASSERT(SIZE(fmwork) >= nc)
    1587              : 
    1588        41876 :             IF (my_kpgrp) THEN
    1589        78802 :                DO ic = 1, nc
    1590        52500 :                   indx = indx + 1
    1591        78802 :                   IF (do_ext) THEN
    1592         5364 :                      CALL cp_fm_start_copy_general(pmat_ext(ikk, ic, ispin), fmwork(ic), para_env, info(indx))
    1593              :                   ELSE
    1594        47136 :                      IF (wtype) THEN
    1595         2022 :                         CALL cp_fm_start_copy_general(kp%wmat(ic, ispin), fmwork(ic), para_env, info(indx))
    1596              :                      ELSE
    1597        45114 :                         CALL cp_fm_start_copy_general(kp%pmat(ic, ispin), fmwork(ic), para_env, info(indx))
    1598              :                      END IF
    1599              :                   END IF
    1600              :                END DO
    1601              :             ELSE
    1602        27828 :                DO ic = 1, nc
    1603        18552 :                   indx = indx + 1
    1604        27828 :                   CALL cp_fm_start_copy_general(fmdummy, fmwork(ic), para_env, info(indx))
    1605              :                END DO
    1606              :             END IF
    1607              :          END DO
    1608              :       END DO
    1609              : 
    1610              :       ! Finish communication and transform the received matrices
    1611         5648 :       indx = 0
    1612        11946 :       DO ispin = 1, nspin
    1613        47524 :          DO ik = 1, nkp
    1614       106630 :             DO ic = 1, nc
    1615        71052 :                indx = indx + 1
    1616       106630 :                CALL cp_fm_finish_copy_general(fmwork(ic), info(indx))
    1617              :             END DO
    1618              : 
    1619              :             ! reduce to dbcsr storage
    1620        35578 :             IF (real_only) THEN
    1621          104 :                CALL copy_fm_to_dbcsr(fmwork(1), rpmat, keep_sparsity=.TRUE.)
    1622              :             ELSE
    1623        35474 :                CALL copy_fm_to_dbcsr(fmwork(1), rpmat, keep_sparsity=.TRUE.)
    1624        35474 :                CALL copy_fm_to_dbcsr(fmwork(2), cpmat, keep_sparsity=.TRUE.)
    1625              :             END IF
    1626              : 
    1627              :             ! symmetrization
    1628        35578 :             kpsym => kpoint%kp_sym(ik)%kpoint_sym
    1629        35578 :             CPASSERT(ASSOCIATED(kpsym))
    1630              : 
    1631        41876 :             IF (kpsym%apply_symmetry) THEN
    1632            0 :                wkpx = wkp(ik)/REAL(kpsym%nwght, KIND=dp)
    1633            0 :                DO is = 1, kpsym%nwght
    1634            0 :                   ir = ABS(kpsym%rotp(is))
    1635            0 :                   ira = 0
    1636            0 :                   DO jr = 1, SIZE(kpoint%ibrot)
    1637            0 :                      IF (ir == kpoint%ibrot(jr)) ira = jr
    1638              :                   END DO
    1639            0 :                   CPASSERT(ira > 0)
    1640            0 :                   kind_rot => kpoint%kind_rotmat(ira, :)
    1641            0 :                   IF (real_only) THEN
    1642              :                      CALL symtrans(srpmat, rpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
    1643            0 :                                    kpsym%f0(:, is), kpoint%atype, symmetric=.TRUE.)
    1644              :                   ELSE
    1645              :                      CALL symtrans(srpmat, rpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
    1646            0 :                                    kpsym%f0(:, is), kpoint%atype, symmetric=.TRUE.)
    1647              :                      CALL symtrans(scpmat, cpmat, kind_rot, kpsym%rot(1:3, 1:3, is), &
    1648            0 :                                    kpsym%f0(:, is), kpoint%atype, antisymmetric=.TRUE.)
    1649              :                   END IF
    1650              :                   CALL transform_dmat(denmat, srpmat, scpmat, ispin, real_only, sab_nl, &
    1651            0 :                                       cell_to_index, kpsym%xkp(1:3, is), wkpx)
    1652              :                END DO
    1653              :             ELSE
    1654              :                ! transformation
    1655              :                CALL transform_dmat(denmat, rpmat, cpmat, ispin, real_only, sab_nl, &
    1656        35578 :                                    cell_to_index, xkp(1:3, ik), wkp(ik))
    1657              :             END IF
    1658              :          END DO
    1659              :       END DO
    1660              : 
    1661              :       ! Clean up communication
    1662         5648 :       indx = 0
    1663        11946 :       DO ispin = 1, nspin
    1664        47524 :          DO ik = 1, nkp
    1665        35578 :             my_kpgrp = (ik >= kpoint%kp_range(1) .AND. ik <= kpoint%kp_range(2))
    1666         6298 :             IF (my_kpgrp) THEN
    1667        26302 :                ikk = ik - kpoint%kp_range(1) + 1
    1668              :                IF (aux_fit) THEN
    1669        26302 :                   kp => kpoint%kp_aux_env(ikk)%kpoint_env
    1670              :                ELSE
    1671        26302 :                   kp => kpoint%kp_env(ikk)%kpoint_env
    1672              :                END IF
    1673              : 
    1674        78802 :                DO ic = 1, nc
    1675        52500 :                   indx = indx + 1
    1676        78802 :                   CALL cp_fm_cleanup_copy_general(info(indx))
    1677              :                END DO
    1678              :             ELSE
    1679              :                ! calls with dummy arguments, so not included
    1680              :                ! therefore just increment counter by trip count
    1681         9276 :                indx = indx + nc
    1682              :             END IF
    1683              :          END DO
    1684              :       END DO
    1685              : 
    1686              :       ! All done
    1687        76700 :       DEALLOCATE (info)
    1688              : 
    1689         5648 :       CALL dbcsr_deallocate_matrix(rpmat)
    1690         5648 :       CALL dbcsr_deallocate_matrix(cpmat)
    1691         5648 :       IF (.NOT. kpoint%full_grid) THEN
    1692         4066 :          CALL dbcsr_deallocate_matrix(srpmat)
    1693         4066 :          CALL dbcsr_deallocate_matrix(scpmat)
    1694              :       END IF
    1695              : 
    1696         5648 :       CALL timestop(handle)
    1697              : 
    1698         5648 :    END SUBROUTINE kpoint_density_transform
    1699              : 
    1700              : ! **************************************************************************************************
    1701              : !> \brief real space density matrices in DBCSR format
    1702              : !> \param denmat  Real space (DBCSR) density matrix
    1703              : !> \param rpmat ...
    1704              : !> \param cpmat ...
    1705              : !> \param ispin ...
    1706              : !> \param real_only ...
    1707              : !> \param sab_nl ...
    1708              : !> \param cell_to_index ...
    1709              : !> \param xkp ...
    1710              : !> \param wkp ...
    1711              : ! **************************************************************************************************
    1712        35578 :    SUBROUTINE transform_dmat(denmat, rpmat, cpmat, ispin, real_only, sab_nl, cell_to_index, xkp, wkp)
    1713              : 
    1714              :       TYPE(dbcsr_p_type), DIMENSION(:, :)                :: denmat
    1715              :       TYPE(dbcsr_type), POINTER                          :: rpmat, cpmat
    1716              :       INTEGER, INTENT(IN)                                :: ispin
    1717              :       LOGICAL, INTENT(IN)                                :: real_only
    1718              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    1719              :          POINTER                                         :: sab_nl
    1720              :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
    1721              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xkp
    1722              :       REAL(KIND=dp), INTENT(IN)                          :: wkp
    1723              : 
    1724              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'transform_dmat'
    1725              : 
    1726              :       INTEGER                                            :: handle, iatom, icell, icol, irow, jatom, &
    1727              :                                                             nimg
    1728              :       INTEGER, DIMENSION(3)                              :: cell
    1729              :       LOGICAL                                            :: do_symmetric, found
    1730              :       REAL(KIND=dp)                                      :: arg, coskl, fc, sinkl
    1731        35578 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: cblock, dblock, rblock
    1732              :       TYPE(neighbor_list_iterator_p_type), &
    1733        35578 :          DIMENSION(:), POINTER                           :: nl_iterator
    1734              : 
    1735        35578 :       CALL timeset(routineN, handle)
    1736              : 
    1737        35578 :       nimg = SIZE(denmat, 2)
    1738              : 
    1739              :       ! transformation
    1740        35578 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_nl, symmetric=do_symmetric)
    1741        35578 :       CALL neighbor_list_iterator_create(nl_iterator, sab_nl)
    1742     16074071 :       DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
    1743     16038493 :          CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom, cell=cell)
    1744              : 
    1745              :          !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
    1746              :          !Therefore, we have: S(R) = sum_k Re(S(k))*cos(k*R) -i^2*Im(S(k))*sin(k*R)
    1747              :          !                         = sum_k Re(S(k))*cos(k*R) + Im(S(k))*sin(k*R)
    1748              :          !fc = +- 1 is due to the usual non-symmetric real-space matrices stored as symmetric ones
    1749              : 
    1750     16038493 :          irow = iatom
    1751     16038493 :          icol = jatom
    1752     16038493 :          fc = 1.0_dp
    1753     16038493 :          IF (do_symmetric .AND. iatom > jatom) THEN
    1754      6739460 :             irow = jatom
    1755      6739460 :             icol = iatom
    1756      6739460 :             fc = -1.0_dp
    1757              :          END IF
    1758              : 
    1759     16038493 :          icell = cell_to_index(cell(1), cell(2), cell(3))
    1760     16038493 :          IF (icell < 1 .OR. icell > nimg) CYCLE
    1761              : 
    1762     16037215 :          arg = REAL(cell(1), dp)*xkp(1) + REAL(cell(2), dp)*xkp(2) + REAL(cell(3), dp)*xkp(3)
    1763     16037215 :          coskl = wkp*COS(twopi*arg)
    1764     16037215 :          sinkl = wkp*fc*SIN(twopi*arg)
    1765              : 
    1766              :          CALL dbcsr_get_block_p(matrix=denmat(ispin, icell)%matrix, row=irow, col=icol, &
    1767     16037215 :                                 block=dblock, found=found)
    1768     16037215 :          IF (.NOT. found) CYCLE
    1769              : 
    1770     16072793 :          IF (real_only) THEN
    1771       252264 :             CALL dbcsr_get_block_p(matrix=rpmat, row=irow, col=icol, block=rblock, found=found)
    1772       252264 :             IF (.NOT. found) CYCLE
    1773    120381000 :             dblock = dblock + coskl*rblock
    1774              :          ELSE
    1775     15784951 :             CALL dbcsr_get_block_p(matrix=rpmat, row=irow, col=icol, block=rblock, found=found)
    1776     15784951 :             IF (.NOT. found) CYCLE
    1777     15784951 :             CALL dbcsr_get_block_p(matrix=cpmat, row=irow, col=icol, block=cblock, found=found)
    1778     15784951 :             IF (.NOT. found) CYCLE
    1779   2977247053 :             dblock = dblock + coskl*rblock
    1780   2977247053 :             dblock = dblock + sinkl*cblock
    1781              :          END IF
    1782              :       END DO
    1783        35578 :       CALL neighbor_list_iterator_release(nl_iterator)
    1784              : 
    1785        35578 :       CALL timestop(handle)
    1786              : 
    1787        35578 :    END SUBROUTINE transform_dmat
    1788              : 
    1789              : ! **************************************************************************************************
    1790              : !> \brief Symmetrization of density matrix - transform to new k-point
    1791              : !> \param smat density matrix at new kpoint
    1792              : !> \param pmat reference density matrix
    1793              : !> \param kmat Kind type rotation matrix
    1794              : !> \param rot Rotation matrix
    1795              : !> \param f0 Permutation of atoms under transformation
    1796              : !> \param atype Atom to kind pointer
    1797              : !> \param symmetric Symmetric matrix
    1798              : !> \param antisymmetric Anti-Symmetric matrix
    1799              : ! **************************************************************************************************
    1800            0 :    SUBROUTINE symtrans(smat, pmat, kmat, rot, f0, atype, symmetric, antisymmetric)
    1801              :       TYPE(dbcsr_type), POINTER                          :: smat, pmat
    1802              :       TYPE(kind_rotmat_type), DIMENSION(:), POINTER      :: kmat
    1803              :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: rot
    1804              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: f0, atype
    1805              :       LOGICAL, INTENT(IN), OPTIONAL                      :: symmetric, antisymmetric
    1806              : 
    1807              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'symtrans'
    1808              : 
    1809              :       INTEGER                                            :: handle, iatom, icol, ikind, ip, irow, &
    1810              :                                                             jcol, jkind, jp, jrow, natom, numnodes
    1811              :       LOGICAL                                            :: asym, dorot, found, perm, sym, trans
    1812              :       REAL(KIND=dp)                                      :: dr, fsign
    1813            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: kroti, krotj, pblock, sblock
    1814              :       TYPE(dbcsr_distribution_type)                      :: dist
    1815              :       TYPE(dbcsr_iterator_type)                          :: iter
    1816              : 
    1817            0 :       CALL timeset(routineN, handle)
    1818              : 
    1819              :       ! check symmetry options
    1820            0 :       sym = .FALSE.
    1821            0 :       IF (PRESENT(symmetric)) sym = symmetric
    1822            0 :       asym = .FALSE.
    1823            0 :       IF (PRESENT(antisymmetric)) asym = antisymmetric
    1824              : 
    1825            0 :       CPASSERT(.NOT. (sym .AND. asym))
    1826            0 :       CPASSERT((sym .OR. asym))
    1827              : 
    1828              :       ! do we have permutation of atoms
    1829            0 :       natom = SIZE(f0)
    1830            0 :       perm = .FALSE.
    1831            0 :       DO iatom = 1, natom
    1832            0 :          IF (f0(iatom) == iatom) CYCLE
    1833              :          perm = .TRUE.
    1834            0 :          EXIT
    1835              :       END DO
    1836              : 
    1837              :       ! do we have a real rotation
    1838            0 :       dorot = .FALSE.
    1839            0 :       IF (ABS(SUM(ABS(rot)) - 3.0_dp) > 1.e-12_dp) dorot = .TRUE.
    1840            0 :       dr = ABS(rot(1, 1) - 1.0_dp) + ABS(rot(2, 2) - 1.0_dp) + ABS(rot(3, 3) - 1.0_dp)
    1841            0 :       IF (ABS(dr) > 1.e-12_dp) dorot = .TRUE.
    1842              : 
    1843            0 :       fsign = 1.0_dp
    1844            0 :       IF (asym) fsign = -1.0_dp
    1845              : 
    1846            0 :       IF (dorot .OR. perm) THEN
    1847              :          CALL cp_abort(__LOCATION__, "k-points need FULL_GRID currently. "// &
    1848            0 :                        "Reduced grids not yet working correctly")
    1849            0 :          CALL dbcsr_set(smat, 0.0_dp)
    1850            0 :          IF (perm) THEN
    1851            0 :             CALL dbcsr_get_info(pmat, distribution=dist)
    1852            0 :             CALL dbcsr_distribution_get(dist, numnodes=numnodes)
    1853            0 :             IF (numnodes == 1) THEN
    1854              :                ! the matrices are local to this process
    1855            0 :                CALL dbcsr_iterator_start(iter, pmat)
    1856            0 :                DO WHILE (dbcsr_iterator_blocks_left(iter))
    1857            0 :                   CALL dbcsr_iterator_next_block(iter, irow, icol, pblock)
    1858            0 :                   ip = f0(irow)
    1859            0 :                   jp = f0(icol)
    1860            0 :                   IF (ip <= jp) THEN
    1861            0 :                      jrow = ip
    1862            0 :                      jcol = jp
    1863            0 :                      trans = .FALSE.
    1864              :                   ELSE
    1865            0 :                      jrow = jp
    1866            0 :                      jcol = ip
    1867            0 :                      trans = .TRUE.
    1868              :                   END IF
    1869            0 :                   CALL dbcsr_get_block_p(matrix=smat, row=jrow, col=jcol, BLOCK=sblock, found=found)
    1870            0 :                   CPASSERT(found)
    1871            0 :                   ikind = atype(irow)
    1872            0 :                   jkind = atype(icol)
    1873            0 :                   kroti => kmat(ikind)%rmat
    1874            0 :                   krotj => kmat(jkind)%rmat
    1875              :                   ! rotation
    1876            0 :                   IF (trans) THEN
    1877            0 :                      sblock = fsign*MATMUL(TRANSPOSE(krotj), MATMUL(TRANSPOSE(pblock), kroti))
    1878              :                   ELSE
    1879            0 :                      sblock = fsign*MATMUL(TRANSPOSE(kroti), MATMUL(pblock, krotj))
    1880              :                   END IF
    1881              :                END DO
    1882            0 :                CALL dbcsr_iterator_stop(iter)
    1883              :                !
    1884              :             ELSE
    1885              :                ! distributed matrices, most general code needed
    1886              :                CALL cp_abort(__LOCATION__, "k-points need FULL_GRID currently. "// &
    1887            0 :                              "Reduced grids not yet working correctly")
    1888              :             END IF
    1889              :          ELSE
    1890              :             ! no atom permutations, this is always local
    1891            0 :             CALL dbcsr_copy(smat, pmat)
    1892            0 :             CALL dbcsr_iterator_start(iter, smat)
    1893            0 :             DO WHILE (dbcsr_iterator_blocks_left(iter))
    1894            0 :                CALL dbcsr_iterator_next_block(iter, irow, icol, sblock)
    1895            0 :                ip = f0(irow)
    1896            0 :                jp = f0(icol)
    1897            0 :                IF (ip <= jp) THEN
    1898            0 :                   jrow = ip
    1899            0 :                   jcol = jp
    1900            0 :                   trans = .FALSE.
    1901              :                ELSE
    1902            0 :                   jrow = jp
    1903            0 :                   jcol = ip
    1904            0 :                   trans = .TRUE.
    1905              :                END IF
    1906            0 :                ikind = atype(irow)
    1907            0 :                jkind = atype(icol)
    1908            0 :                kroti => kmat(ikind)%rmat
    1909            0 :                krotj => kmat(jkind)%rmat
    1910              :                ! rotation
    1911            0 :                IF (trans) THEN
    1912            0 :                   sblock = fsign*MATMUL(TRANSPOSE(krotj), MATMUL(TRANSPOSE(sblock), kroti))
    1913              :                ELSE
    1914            0 :                   sblock = fsign*MATMUL(TRANSPOSE(kroti), MATMUL(sblock, krotj))
    1915              :                END IF
    1916              :             END DO
    1917            0 :             CALL dbcsr_iterator_stop(iter)
    1918              :             !
    1919              :          END IF
    1920              :       ELSE
    1921              :          ! this is the identity operation, just copy the matrix
    1922            0 :          CALL dbcsr_copy(smat, pmat)
    1923              :       END IF
    1924              : 
    1925            0 :       CALL timestop(handle)
    1926              : 
    1927            0 :    END SUBROUTINE symtrans
    1928              : 
    1929              : ! **************************************************************************************************
    1930              : !> \brief ...
    1931              : !> \param mat ...
    1932              : ! **************************************************************************************************
    1933            0 :    SUBROUTINE matprint(mat)
    1934              :       TYPE(dbcsr_type), POINTER                          :: mat
    1935              : 
    1936              :       INTEGER                                            :: i, icol, iounit, irow
    1937            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: mblock
    1938              :       TYPE(dbcsr_iterator_type)                          :: iter
    1939              : 
    1940            0 :       iounit = cp_logger_get_default_io_unit()
    1941            0 :       CALL dbcsr_iterator_start(iter, mat)
    1942            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    1943            0 :          CALL dbcsr_iterator_next_block(iter, irow, icol, mblock)
    1944              :          !
    1945            0 :          IF (iounit > 0) THEN
    1946            0 :             WRITE (iounit, '(A,2I4)') 'BLOCK  ', irow, icol
    1947            0 :             DO i = 1, SIZE(mblock, 1)
    1948            0 :                WRITE (iounit, '(8F12.6)') mblock(i, :)
    1949              :             END DO
    1950              :          END IF
    1951              :          !
    1952              :       END DO
    1953            0 :       CALL dbcsr_iterator_stop(iter)
    1954              : 
    1955            0 :    END SUBROUTINE matprint
    1956              : ! **************************************************************************************************
    1957              : 
    1958            0 : END MODULE kpoint_methods
        

Generated by: LCOV version 2.0-1