LCOV - code coverage report
Current view: top level - src - kpoint_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:cccd2f3) Lines: 78.8 % 1015 800
Test Date: 2026-05-06 07:07:47 Functions: 86.7 % 15 13

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

Generated by: LCOV version 2.0-1