LCOV - code coverage report
Current view: top level - src - kpoint_k_r_trafo_simple.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 89.5 % 162 145
Test Date: 2026-11-04 00:58:17 Functions: 90.9 % 11 10

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Implements simple k-space/R-space transformations and Gamma-point MIC reconstruction.
      10              : !> \note This code is less performant/more memory consuming than the methods in kpoint_methods.F
      11              : !>       Use only when transformations are not the computational bottleneck.
      12              : !> \par History
      13              : !>       11.2025 created [Stepan Marek]
      14              : !> \author Stepan Marek
      15              : ! **************************************************************************************************
      16              : MODULE kpoint_k_r_trafo_simple
      17              :    USE cell_types,                      ONLY: cell_type,&
      18              :                                               minimum_image_weights
      19              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      20              :                                               cp_cfm_type
      21              :    USE cp_dbcsr_api,                    ONLY: dbcsr_get_info,&
      22              :                                               dbcsr_get_readonly_block_p,&
      23              :                                               dbcsr_p_type,&
      24              :                                               dbcsr_type,&
      25              :                                               dbcsr_type_antisymmetric,&
      26              :                                               dbcsr_type_no_symmetry
      27              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_equivalent
      28              :    USE cp_fm_types,                     ONLY: cp_fm_get_info,&
      29              :                                               cp_fm_type
      30              :    USE kinds,                           ONLY: dp
      31              :    USE kpoint_types,                    ONLY: kpoint_type
      32              :    USE mathconstants,                   ONLY: twopi,&
      33              :                                               z_zero
      34              :    USE message_passing,                 ONLY: mp_comm_type
      35              :    USE particle_types,                  ONLY: particle_type
      36              :    USE qs_neighbor_list_types,          ONLY: get_iterator_info,&
      37              :                                               neighbor_list_iterate,&
      38              :                                               neighbor_list_iterator_create,&
      39              :                                               neighbor_list_iterator_p_type,&
      40              :                                               neighbor_list_iterator_release,&
      41              :                                               neighbor_list_set_p_type
      42              : #include "./base/base_uses.f90"
      43              : 
      44              :    IMPLICIT NONE
      45              : 
      46              :    PRIVATE
      47              : 
      48              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'kpoint_k_r_trafo_simple'
      49              : 
      50              :    PUBLIC :: replicate_rs_matrices, &
      51              :              rs_to_kp, &
      52              :              fm_gamma_to_kp, &
      53              :              fm_rs_to_kp, &
      54              :              add_kp_to_all_rs, &
      55              :              fm_add_kp_to_all_rs, &
      56              :              add_kp_to_rs
      57              : 
      58              : CONTAINS
      59              : ! **************************************************************************************************
      60              : !> \brief Convert dbcsr matrices representing operators in real-space image cells to arrays
      61              : !> \param rs_dbcsr_in Array of dbcsr matrices
      62              : !> \param kpoint_in The kpoint environment of the source matrix (providing neighbor list and cell_to_index)
      63              : !> \param rs_array_out Multidimensional array - matrices are duplicated on each MPI rank
      64              : !>                     dim  1 : spin, dim 2 : rows, dim 3 : cols, dim 4 : image index
      65              : !> \param cell_to_index_out Cell to index array for the destination array
      66              : !> \date 11.2025
      67              : !> \author Stepan Marek
      68              : ! **************************************************************************************************
      69          158 :    SUBROUTINE replicate_rs_matrices(rs_dbcsr_in, kpoint_in, rs_array_out, cell_to_index_out)
      70              :       ! dimension 1 : spin, dimension 2 : image cell index
      71              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rs_dbcsr_in
      72              :       TYPE(kpoint_type), POINTER                         :: kpoint_in
      73              :       REAL(kind=dp), DIMENSION(:, :, :, :)               :: rs_array_out
      74              :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index_out
      75              : 
      76              :       CHARACTER(len=*), PARAMETER :: routineN = 'replicate_rs_matrices'
      77              : 
      78              :       CHARACTER                                          :: matrix_sym
      79              :       INTEGER                                            :: handle, iatom, ispin, jatom, n_spin, &
      80              :                                                             src_index
      81              :       INTEGER, DIMENSION(3)                              :: cell
      82              :       TYPE(mp_comm_type)                                 :: group
      83              :       TYPE(neighbor_list_iterator_p_type), &
      84          158 :          DIMENSION(:), POINTER                           :: iterator
      85              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
      86          158 :          POINTER                                         :: sab_kp_src
      87              : 
      88          158 :       CALL timeset(routineN, handle)
      89              : 
      90          158 :       IF (SIZE(rs_dbcsr_in, 2) < 1) THEN
      91            0 :          CALL cp_abort(__LOCATION__, "No source image cells provided!")
      92              :       END IF
      93              :       ! Start by constructing the cell_to_index_src
      94          158 :       sab_kp_src => kpoint_in%sab_nl
      95              :       ! NOTE : The first index in matrix_s_kp is not spin index, but number of derivatives.
      96              :       !        But, for matrix_ks_kp, this is indeed the spin index.
      97          158 :       n_spin = SIZE(rs_dbcsr_in, 1)
      98          158 :       CALL dbcsr_get_info(rs_dbcsr_in(1, 1)%matrix, group=group, matrix_type=matrix_sym)
      99          434 :       DO ispin = 1, n_spin
     100          276 :          CALL neighbor_list_iterator_create(iterator, sab_kp_src)
     101        17189 :          DO WHILE (neighbor_list_iterate(iterator) == 0)
     102        16913 :             CALL get_iterator_info(iterator, cell=cell, iatom=iatom, jatom=jatom)
     103        16913 :             src_index = kpoint_in%cell_to_index(cell(1), cell(2), cell(3))
     104        16913 :             IF (src_index == 0) THEN
     105            0 :                CALL cp_abort(__LOCATION__, "Image not found in the source array.")
     106              :             END IF
     107              :             ! NOTE : Expect only specific symmetry storage relevant for kpoint calculations
     108        17189 :             IF (matrix_sym == dbcsr_type_no_symmetry) THEN
     109              :                CALL write_block_no_sym(iatom, jatom, cell, rs_dbcsr_in(ispin, src_index)%matrix, &
     110        10161 :                                        rs_array_out(ispin, :, :, :), cell_to_index_out)
     111              :             ELSE
     112              :                CALL write_block_symmetric(iatom, jatom, cell, rs_dbcsr_in(ispin, src_index)%matrix, &
     113              :                                           rs_array_out(ispin, :, :, :), cell_to_index_out, &
     114        12102 :                                           MERGE(-1.0_dp, 1.0_dp, matrix_sym == dbcsr_type_antisymmetric))
     115              :             END IF
     116              :          END DO
     117          434 :          CALL neighbor_list_iterator_release(iterator)
     118              :       END DO
     119     25605570 :       CALL group%sum(rs_array_out(:, :, :, :))
     120          158 :       CALL timestop(handle)
     121          158 :    END SUBROUTINE replicate_rs_matrices
     122              : ! **************************************************************************************************
     123              : !> \brief Expand a triangular image block and its symmetric or antisymmetric mirror.
     124              : !> \param iatom first atom index
     125              : !> \param jatom second atom index
     126              : !> \param cell Current cell (of second atom)
     127              : !> \param matrix_in Input DBCSR matrix in canonical atom order
     128              : !> \param array_out Multidimensional array - dim 1 : rows, dim 2 : cols, dim 3 : rs_index
     129              : !> \param cell_to_index_out Mapping of cell coords to rs_indices
     130              : !> \param transpose_sign -1 for antisymmetric SOC image matrices, +1 otherwise
     131              : !> \date 11.2025
     132              : !> \author Stepan Marek
     133              : ! **************************************************************************************************
     134         6752 :    SUBROUTINE write_block_symmetric(iatom, jatom, cell, matrix_in, array_out, cell_to_index_out, transpose_sign)
     135              :       INTEGER, INTENT(IN)                                :: iatom, jatom
     136              :       INTEGER, DIMENSION(3), INTENT(IN)                  :: cell
     137              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix_in
     138              :       REAL(kind=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: array_out
     139              :       INTEGER, DIMENSION(:, :, :), INTENT(IN), POINTER   :: cell_to_index_out
     140              :       REAL(dp), INTENT(IN)                               :: transpose_sign
     141              : 
     142              :       INTEGER                                            :: col_offset, col_size, dest_index, &
     143              :                                                             dest_index_t, i, i_g, j, j_g, &
     144              :                                                             row_offset, row_size
     145         6752 :       INTEGER, DIMENSION(:), POINTER                     :: col_offsets, row_offsets
     146              :       LOGICAL                                            :: found
     147         6752 :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: block
     148              : 
     149         6752 :       CALL dbcsr_get_info(matrix_in, row_blk_offset=row_offsets, col_blk_offset=col_offsets)
     150         6752 :       IF (iatom > jatom) THEN
     151              :          CALL dbcsr_get_readonly_block_p(matrix_in, row=jatom, col=iatom, block=block, &
     152         2333 :                                          row_size=row_size, col_size=col_size, found=found)
     153         2335 :          IF (.NOT. found) RETURN
     154              :          ! Block found, prepare for write
     155         2331 :          dest_index = cell_to_index_out(-cell(1), -cell(2), -cell(3))
     156         2331 :          IF (dest_index == 0) CPABORT("Mirror image index not present.")
     157         2331 :          dest_index_t = cell_to_index_out(cell(1), cell(2), cell(3))
     158         2331 :          IF (dest_index_t == 0) CPABORT("Image index not present.")
     159         2331 :          row_offset = row_offsets(jatom)
     160         2331 :          col_offset = col_offsets(iatom)
     161              :       ELSE
     162              :          CALL dbcsr_get_readonly_block_p(matrix_in, row=iatom, col=jatom, block=block, &
     163         4419 :                                          row_size=row_size, col_size=col_size, found=found)
     164         4419 :          IF (.NOT. found) RETURN
     165              :          ! Block found, prepare for write
     166         4417 :          dest_index = cell_to_index_out(cell(1), cell(2), cell(3))
     167         4417 :          IF (dest_index == 0) CPABORT("Image index not present.")
     168         4417 :          dest_index_t = cell_to_index_out(-cell(1), -cell(2), -cell(3))
     169         4417 :          IF (dest_index_t == 0) CPABORT("Mirror image index not present.")
     170         4417 :          row_offset = row_offsets(iatom)
     171         4417 :          col_offset = col_offsets(jatom)
     172              :       END IF
     173              :       ! The stored block is already in canonical atom order. Only the mirror changes sign.
     174              :       !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,j,i_g,j_g) &
     175              :       !$OMP SHARED(row_size, col_size, row_offset, col_offset, array_out, &
     176         6748 :       !$OMP dest_index, dest_index_t, block, iatom, jatom, transpose_sign)
     177              :       DO i = 1, row_size
     178              :          i_g = i + row_offset - 1
     179              :          DO j = 1, col_size
     180              :             j_g = j + col_offset - 1
     181              :             array_out(i_g, j_g, dest_index) = block(i, j)
     182              :             IF (iatom /= jatom) array_out(j_g, i_g, dest_index_t) = transpose_sign*block(i, j)
     183              :          END DO
     184              :       END DO
     185              :       !$OMP END PARALLEL DO
     186         6752 :    END SUBROUTINE write_block_symmetric
     187              : ! **************************************************************************************************
     188              : !> \brief Write a single block from the dbcsr matrix to correct place, assuming no symmetry dbcsr
     189              : !> \param iatom first atom index
     190              : !> \param jatom second atom index
     191              : !> \param cell Current cell (of second atom)
     192              : !> \param matrix_in DBCSR matrix input, symmetric assumed (A_(mu nu)^(R) = A_(nu mu)^(-R))
     193              : !> \param array_out Multidimensional array - dim 1 : rows, dim 2 : cols, dim 3 : rs_index
     194              : !> \param cell_to_index_out Mapping of cell coords to rs_indices
     195              : !> \date 11.2025
     196              : !> \author Stepan Marek
     197              : ! **************************************************************************************************
     198        10161 :    SUBROUTINE write_block_no_sym(iatom, jatom, cell, matrix_in, array_out, cell_to_index_out)
     199              :       INTEGER, INTENT(IN)                                :: iatom, jatom
     200              :       INTEGER, DIMENSION(3), INTENT(IN)                  :: cell
     201              :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix_in
     202              :       REAL(kind=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: array_out
     203              :       INTEGER, DIMENSION(:, :, :), INTENT(IN), POINTER   :: cell_to_index_out
     204              : 
     205              :       INTEGER                                            :: col_offset, col_size, dest_index, i, &
     206              :                                                             i_g, j, j_g, row_offset, row_size
     207        10161 :       INTEGER, DIMENSION(:), POINTER                     :: col_offsets, row_offsets
     208              :       LOGICAL                                            :: found
     209        10161 :       REAL(kind=dp), DIMENSION(:, :), POINTER            :: block
     210              : 
     211        10161 :       dest_index = cell_to_index_out(cell(1), cell(2), cell(3))
     212            0 :       IF (dest_index == 0) CPABORT("Image index not present.")
     213        10161 :       CALL dbcsr_get_info(matrix_in, row_blk_offset=row_offsets, col_blk_offset=col_offsets)
     214        10161 :       row_offset = row_offsets(iatom)
     215        10161 :       col_offset = col_offsets(jatom)
     216              :       CALL dbcsr_get_readonly_block_p(matrix_in, row=iatom, col=jatom, block=block, found=found, &
     217        10161 :                                       row_size=row_size, col_size=col_size)
     218              :       !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i, j, i_g, j_g) &
     219        10161 :       !$OMP SHARED(row_size, col_size, row_offset, col_offset, dest_index, block, array_out)
     220              :       DO i = 1, row_size
     221              :          i_g = i + row_offset - 1
     222              :          DO j = 1, col_size
     223              :             j_g = j + col_offset - 1
     224              :             array_out(i_g, j_g, dest_index) = block(i, j)
     225              :          END DO
     226              :       END DO
     227              :       !$OMP END PARALLEL DO
     228        10161 :    END SUBROUTINE write_block_no_sym
     229              : ! **************************************************************************************************
     230              : !> \brief Integrate RS matrices (stored as Fortran array) into a kpoint matrix at given kp
     231              : !> \param rs_real Multidimensional array of real parts of the matrix, dim 1 : rows, dim 2 : cols, dim 3 : image index
     232              : !> \param ks_complex Target complex k-space matrix
     233              : !> \param index_to_cell Gets the image cell coordinates from the rs_dbcsr index
     234              : !> \param xkp Single kpoint where the transformation is evalued at
     235              : !> \param deriv_direction Derivative direction - indicates along which cartesian direction to take the derivative
     236              : !> \param hmat Cell size matrix, required for the derivative
     237              : !> \date 11.2025
     238              : !> \author Stepan Marek
     239              : ! **************************************************************************************************
     240        46402 :    SUBROUTINE rs_to_kp(rs_real, ks_complex, index_to_cell, xkp, deriv_direction, hmat)
     241              :       REAL(kind=dp), DIMENSION(:, :, :), INTENT(IN)      :: rs_real
     242              :       COMPLEX(kind=dp), DIMENSION(:, :), INTENT(OUT)     :: ks_complex
     243              :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
     244              :       REAL(kind=dp), DIMENSION(3), INTENT(IN)            :: xkp
     245              :       INTEGER, INTENT(IN), OPTIONAL                      :: deriv_direction
     246              :       REAL(kind=dp), DIMENSION(3, 3), INTENT(IN), &
     247              :          OPTIONAL                                        :: hmat
     248              : 
     249              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'rs_to_kp'
     250              : 
     251              :       INTEGER                                            :: handle, i, n_images
     252              : 
     253        46402 :       CALL timeset(routineN, handle)
     254              :       ! Get matrix constants
     255        46402 :       n_images = SIZE(rs_real, 3)
     256              :       ! Get the required derivatives for the deriv direction
     257        46402 :       IF (PRESENT(deriv_direction)) THEN
     258          603 :          IF (.NOT. PRESENT(hmat) .AND. deriv_direction /= 0) THEN
     259            0 :             CALL cp_abort(__LOCATION__, "Derivative requested but h matrix not provided!")
     260              :          END IF
     261              :       END IF
     262              :       ! Now, iterate over realspace and build the sum
     263      2390480 :       ks_complex(:, :) = CMPLX(0.0, 0.0, kind=dp)
     264       503426 :       DO i = 1, n_images
     265       503426 :          CALL add_rs_to_kp(ks_complex, rs_real(:, :, i), xkp, i, index_to_cell, deriv_direction, hmat)
     266              :       END DO
     267        46402 :       CALL timestop(handle)
     268        46402 :    END SUBROUTINE rs_to_kp
     269              : 
     270              : ! **************************************************************************************************
     271              : !> \brief Reconstruct a complex k-point matrix from a real Gamma matrix using one MIC phase.
     272              : !>        Among images within 1.0E-6 of the minimum distance, select the last candidate
     273              : !>        in index_to_cell order whose lattice coordinates lie between -1 and 1.
     274              : !> \param cfm_kp Complex output, with the same distributed layout as fm_gamma.
     275              : !> \param fm_gamma Real Gamma matrix.
     276              : !> \param cell Simulation cell.
     277              : !> \param particle_set Atom positions defining the minimum images.
     278              : !> \param atom_from_bf Atom index of each row/column basis function.
     279              : !> \param index_to_cell Candidate lattice translations, indexed (direction, image).
     280              : !> \param xkp Target k-point in reciprocal-cell coordinates.
     281              : ! **************************************************************************************************
     282         9524 :    SUBROUTINE fm_gamma_to_kp(cfm_kp, fm_gamma, cell, particle_set, atom_from_bf, index_to_cell, xkp)
     283              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: cfm_kp
     284              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_gamma
     285              :       TYPE(cell_type), INTENT(IN), POINTER               :: cell
     286              :       TYPE(particle_type), DIMENSION(:), INTENT(IN)      :: particle_set
     287              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: atom_from_bf
     288              :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: index_to_cell
     289              :       REAL(KIND=dp), DIMENSION(3), INTENT(IN)            :: xkp
     290              : 
     291              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'fm_gamma_to_kp'
     292              : 
     293              :       COMPLEX(KIND=dp)                                   :: phase
     294         9524 :       COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:)        :: phases, row_phases
     295              :       INTEGER                                            :: handle, i_atom, i_atom_old, i_cell, &
     296              :                                                             i_mic_cell, i_row, j_atom, j_atom_old, &
     297              :                                                             j_col, ncol_local, nrow_local, &
     298              :                                                             num_cells
     299         9524 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     300              :       LOGICAL                                            :: same_layout
     301              :       REAL(KIND=dp)                                      :: arg
     302         9524 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: weights
     303              : 
     304         9524 :       CALL timeset(routineN, handle)
     305              : 
     306         9524 :       CPASSERT(ASSOCIATED(fm_gamma%matrix_struct))
     307         9524 :       CPASSERT(fm_gamma%matrix_struct%nrow_global == fm_gamma%matrix_struct%ncol_global)
     308         9524 :       CPASSERT(SIZE(atom_from_bf) == fm_gamma%matrix_struct%nrow_global)
     309       322004 :       CPASSERT(ALL(atom_from_bf >= 1) .AND. ALL(atom_from_bf <= SIZE(particle_set)))
     310         9524 :       CPASSERT(SIZE(index_to_cell, 1) == 3 .AND. SIZE(index_to_cell, 2) > 0)
     311         9524 :       IF (.NOT. ASSOCIATED(cfm_kp%local_data)) CALL cp_cfm_create(cfm_kp, fm_gamma%matrix_struct)
     312         9524 :       same_layout = cp_fm_struct_equivalent(cfm_kp%matrix_struct, fm_gamma%matrix_struct)
     313        95240 :       same_layout = same_layout .AND. ALL(cfm_kp%matrix_struct%descriptor == fm_gamma%matrix_struct%descriptor)
     314         9524 :       CPASSERT(same_layout)
     315              :       CALL cp_fm_get_info(fm_gamma, nrow_local=nrow_local, ncol_local=ncol_local, &
     316         9524 :                           row_indices=row_indices, col_indices=col_indices)
     317              : 
     318         9524 :       num_cells = SIZE(index_to_cell, 2)
     319        66668 :       ALLOCATE (weights(num_cells), phases(num_cells), row_phases(nrow_local))
     320        75616 :       DO i_cell = 1, num_cells
     321       264368 :          arg = DOT_PRODUCT(REAL(index_to_cell(:, i_cell), KIND=dp), xkp)
     322        75616 :          phases(i_cell) = CMPLX(COS(twopi*arg), SIN(twopi*arg), KIND=dp)
     323              :       END DO
     324              : 
     325         9524 :       j_atom_old = 0
     326         9524 :       phase = CMPLX(1.0_dp, 0.0_dp, dp)
     327       165764 :       DO j_col = 1, ncol_local
     328       156240 :          j_atom = atom_from_bf(col_indices(j_col))
     329       156240 :          IF (j_atom /= j_atom_old) THEN
     330              :             ! Reuse the atom-pair phases for all local columns on the same atom.
     331              :             i_atom_old = 0
     332       211031 :             DO i_row = 1, nrow_local
     333       188777 :                i_atom = atom_from_bf(row_indices(i_row))
     334       188777 :                IF (i_atom /= i_atom_old) THEN
     335              :                   CALL minimum_image_weights(particle_set(i_atom)%r, particle_set(j_atom)%r, &
     336        41786 :                                              cell, index_to_cell, weights)
     337              :                   ! The weights identify the nearest images; use only the last eligible phase.
     338              :                   i_mic_cell = FINDLOC(weights > 0.0_dp .AND. &
     339      1498036 :                                        ALL(ABS(index_to_cell) <= 1, DIM=1), .TRUE., DIM=1, BACK=.TRUE.)
     340        41786 :                   CPASSERT(i_mic_cell > 0)
     341        41786 :                   phase = phases(i_mic_cell)
     342              :                END IF
     343       188777 :                row_phases(i_row) = phase
     344       211031 :                i_atom_old = i_atom
     345              :             END DO
     346              :             j_atom_old = j_atom
     347              :          END IF
     348      2370514 :          cfm_kp%local_data(1:nrow_local, j_col) = row_phases*fm_gamma%local_data(1:nrow_local, j_col)
     349              :       END DO
     350              : 
     351         9524 :       CALL timestop(handle)
     352              : 
     353        28572 :    END SUBROUTINE fm_gamma_to_kp
     354              : 
     355              : ! **************************************************************************************************
     356              : !> \brief Transforms array of fm RS matrices into cfm k-space matrix, at given kpoint index
     357              : !> \param cfm_kp The resulting complex fm matrix, containing the k-space matrix elements
     358              : !> \param fm_rs The real space matrix array
     359              : !> \param kpoints Structure containing information about number, positions, weights etc. of kpoints
     360              : !> \param ikp Index of the target kpoint at which the transformation is evaluated
     361              : !> \par History
     362              : !>    05.2024 Created [Jan Wilhelm]
     363              : !>    11.2025 Moved to general file [Stepan Marek]
     364              : ! **************************************************************************************************
     365         4886 :    SUBROUTINE fm_rs_to_kp(cfm_kp, fm_rs, kpoints, ikp)
     366              :       TYPE(cp_cfm_type)                                  :: cfm_kp
     367              :       TYPE(cp_fm_type), DIMENSION(:)                     :: fm_rs
     368              :       TYPE(kpoint_type), POINTER                         :: kpoints
     369              :       INTEGER                                            :: ikp
     370              : 
     371              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'fm_rs_to_kp'
     372              : 
     373              :       INTEGER                                            :: handle, img, nimages, nimages_fm_rs
     374              : 
     375         4886 :       CALL timeset(routineN, handle)
     376              : 
     377         4886 :       nimages = SIZE(kpoints%index_to_cell, 2)
     378         4886 :       nimages_fm_rs = SIZE(fm_rs)
     379              : 
     380         4886 :       IF (nimages /= nimages_fm_rs) CALL cp_abort(__LOCATION__, "Index to cell and provided fm "// &
     381            0 :                                                   "array are inconsistent.")
     382              : 
     383       428743 :       cfm_kp%local_data(:, :) = z_zero
     384        48860 :       DO img = 1, nimages
     385              : 
     386              :          CALL add_rs_to_kp(cfm_kp%local_data, fm_rs(img)%local_data, kpoints%xkp(1:3, ikp), &
     387        48860 :                            img, kpoints%index_to_cell)
     388              : 
     389              :       END DO
     390              : 
     391         4886 :       CALL timestop(handle)
     392         4886 :    END SUBROUTINE fm_rs_to_kp
     393              : ! **************************************************************************************************
     394              : !> \brief Adds a single RS array with correct phase factor to the target k-space argument
     395              : !> \param ks_array_out The array representing (part) of the complex k-space matrix
     396              : !> \param rs_array_in The RS input array
     397              : !> \param xkp The kpoint coordinates, in units of unit cell
     398              : !> \param imindex The RS index, used for index to cell determination
     399              : !> \param index_to_cell Getting cell coordinates from the imindex
     400              : !> \param deriv_direction The cartesian direction of the derivative
     401              : !> \param hmat The unit cell dimensions
     402              : !> \par History
     403              : !>    05.2024 Created [Jan Wilhelm]
     404              : !>    11.2025 Added k-derivative option [Shridhar Shanbhag]
     405              : !>    11.2025 Moved to general file [Stepan Marek]
     406              : !> \note Always produces non-symmetric matrix, given a non-symmetric RS array
     407              : ! **************************************************************************************************
     408       500998 :    SUBROUTINE add_rs_to_kp(ks_array_out, rs_array_in, xkp, imindex, index_to_cell, deriv_direction, hmat)
     409              :       COMPLEX(kind=dp), DIMENSION(:, :), INTENT(INOUT)   :: ks_array_out
     410              :       REAL(kind=dp), DIMENSION(:, :), INTENT(IN)         :: rs_array_in
     411              :       REAL(kind=dp), DIMENSION(3), INTENT(IN)            :: xkp
     412              :       INTEGER, INTENT(IN)                                :: imindex
     413              :       INTEGER, DIMENSION(:, :), INTENT(IN)               :: index_to_cell
     414              :       INTEGER, INTENT(IN), OPTIONAL                      :: deriv_direction
     415              :       REAL(kind=dp), DIMENSION(3, 3), INTENT(IN), &
     416              :          OPTIONAL                                        :: hmat
     417              : 
     418              :       COMPLEX(kind=dp)                                   :: deriv_factor, phase_factor
     419              :       INTEGER                                            :: i, j
     420              :       REAL(kind=dp), DIMENSION(3)                        :: cell_vector
     421              : 
     422       500998 :       IF (PRESENT(deriv_direction) .AND. (.NOT. PRESENT(hmat))) THEN
     423            0 :          CALL cp_abort(__LOCATION__, "Deriv. direction given but no hmat provided")
     424              :       END IF
     425              : 
     426       500998 :       deriv_factor = CMPLX(1.0, 0.0, kind=dp)
     427       500998 :       IF (PRESENT(deriv_direction)) THEN
     428       485840 :          cell_vector = MATMUL(hmat, index_to_cell(1:3, imindex))
     429              :          ! Multiply by i R(direction)
     430        30365 :          deriv_factor = CMPLX(0.0, cell_vector(deriv_direction), kind=dp)
     431              :       END IF
     432              : 
     433              :       phase_factor = CMPLX(COS(twopi*SUM(xkp(:)*index_to_cell(:, imindex))), &
     434      3506986 :                            SIN(twopi*SUM(xkp(:)*index_to_cell(:, imindex))), kind=dp)
     435              : 
     436      4240464 :       DO i = 1, SIZE(ks_array_out, 1)
     437     52623646 :          DO j = 1, SIZE(ks_array_out, 2)
     438              :             ks_array_out(i, j) = ks_array_out(i, j) + &
     439     52122648 :                                  deriv_factor*phase_factor*rs_array_in(i, j)
     440              :          END DO
     441              :       END DO
     442       500998 :    END SUBROUTINE add_rs_to_kp
     443              : ! **************************************************************************************************
     444              : !> \brief Adds given kpoint matrix to all rs matrices
     445              : !> \param array_kp Input k-space matrix array
     446              : !> \param array_rs Output rs arrays
     447              : !> \param kpoints Structure containing information about number, positions, weights etc. of kpoints
     448              : !> \param ikp Index of the target kpoint at which the transformation is evaluated
     449              : !> \param index_to_cell_ext External supplied index_to_cell
     450              : !> \par History
     451              : !>    05.2024 Created [Jan Wilhelm]
     452              : !>    11.2025 Moved to general file [Stepan Marek]
     453              : !> \note Part of transform in parallelism over k-points (hence why not for a single rs cell)
     454              : ! **************************************************************************************************
     455        34240 :    SUBROUTINE add_kp_to_all_rs(array_kp, array_rs, kpoints, ikp, index_to_cell_ext)
     456              :       COMPLEX(kind=dp), DIMENSION(:, :)                  :: array_kp
     457              :       REAL(kind=dp), DIMENSION(:, :, :)                  :: array_rs
     458              :       TYPE(kpoint_type), POINTER                         :: kpoints
     459              :       INTEGER                                            :: ikp
     460              :       INTEGER, DIMENSION(:, :), OPTIONAL, POINTER        :: index_to_cell_ext
     461              : 
     462              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'add_kp_to_all_rs'
     463              : 
     464              :       INTEGER                                            :: handle, img
     465              :       INTEGER, DIMENSION(3)                              :: cell
     466        34240 :       INTEGER, DIMENSION(:, :), POINTER                  :: index_to_cell
     467              : 
     468        34240 :       index_to_cell => kpoints%index_to_cell
     469        33280 :       IF (PRESENT(index_to_cell_ext)) index_to_cell => index_to_cell_ext
     470              : 
     471        34240 :       CALL timeset(routineN, handle)
     472              : 
     473        34240 :       IF (SIZE(array_rs, 3) /= SIZE(index_to_cell, 2)) CALL cp_abort(__LOCATION__, &
     474            0 :                                                                   "The provided RS array and cell_to_index array are inconsistent.")
     475              : 
     476       342400 :       DO img = 1, SIZE(array_rs, 3)
     477      1232640 :          cell(:) = index_to_cell(:, img)
     478       342400 :          CALL add_kp_to_rs(array_kp, array_rs(:, :, img), cell, kpoints, ikp)
     479              :       END DO
     480              : 
     481        34240 :       CALL timestop(handle)
     482        34240 :    END SUBROUTINE add_kp_to_all_rs
     483              : ! **************************************************************************************************
     484              : !> \brief Adds given kpoint matrix to a single rs matrix
     485              : !> \param cfm_kp The input complex fm matrix, containing the k-space matrix elements
     486              : !> \param fm_rs The real space matrix array
     487              : !> \param kpoints Structure containing information about number, positions, weights etc. of kpoints
     488              : !> \param ikp Index of the target kpoint at which the transformation is evaluated
     489              : !> \par History
     490              : !>    05.2024 Created [Jan Wilhelm]
     491              : !>    11.2025 Moved to general file [Stepan Marek]
     492              : !> \note Part of transform in parallelism over k-points (hence why not for a single rs cell)
     493              : ! **************************************************************************************************
     494         6912 :    SUBROUTINE fm_add_kp_to_all_rs(cfm_kp, fm_rs, kpoints, ikp)
     495              :       TYPE(cp_cfm_type)                                  :: cfm_kp
     496              :       TYPE(cp_fm_type), DIMENSION(:)                     :: fm_rs
     497              :       TYPE(kpoint_type), POINTER                         :: kpoints
     498              :       INTEGER                                            :: ikp
     499              : 
     500              :       CHARACTER(len=*), PARAMETER :: routineN = 'fm_add_kp_to_all_rs'
     501              : 
     502              :       INTEGER                                            :: handle, img
     503              :       INTEGER, DIMENSION(3)                              :: cell
     504              : 
     505         6912 :       CALL timeset(routineN, handle)
     506              : 
     507         6912 :       IF (SIZE(fm_rs, 1) /= SIZE(kpoints%index_to_cell, 2)) CALL cp_abort(__LOCATION__, &
     508            0 :                                                                   "The provided RS array and cell_to_index array are inconsistent.")
     509              : 
     510        69120 :       DO img = 1, SIZE(fm_rs, 1)
     511       248832 :          cell(:) = kpoints%index_to_cell(:, img)
     512        69120 :          CALL add_kp_to_rs(cfm_kp%local_data, fm_rs(img)%local_data, cell, kpoints, ikp)
     513              :       END DO
     514         6912 :       CALL timestop(handle)
     515         6912 :    END SUBROUTINE fm_add_kp_to_all_rs
     516              : ! **************************************************************************************************
     517              : !> \brief Adds given kpoint matrix to a single rs matrix
     518              : !> \param array_kp The resulting complex fm matrix, containing the k-space matrix elements
     519              : !> \param array_rs The real space matrix array
     520              : !> \param cell The image cell of the target RS matrix
     521              : !> \param kpoints Structure containing information about number, positions, weights etc. of kpoints
     522              : !> \param ikp Index of the target kpoint at which the transformation is evaluated
     523              : !> \par History
     524              : !>    05.2024 Created [Jan Wilhelm]
     525              : !>    11.2025 Moved to general file [Stepan Marek]
     526              : !> \note Part of transform in parallelism over k-points (hence why not for a single rs cell)
     527              : ! **************************************************************************************************
     528       370368 :    SUBROUTINE add_kp_to_rs(array_kp, array_rs, cell, kpoints, ikp)
     529              :       COMPLEX(kind=dp), DIMENSION(:, :)                  :: array_kp
     530              :       REAL(kind=dp), DIMENSION(:, :)                     :: array_rs
     531              :       INTEGER, DIMENSION(3)                              :: cell
     532              :       TYPE(kpoint_type), POINTER                         :: kpoints
     533              :       INTEGER                                            :: ikp
     534              : 
     535              :       REAL(kind=dp)                                      :: phase
     536              : 
     537              :       ! Determine the phase
     538      1481472 :       phase = twopi*SUM(kpoints%xkp(:, ikp)*cell(:))
     539              :       ! The array is real - it is assumed that imaginary parts cancel each other, so they are not handled
     540              :       ! Then e^(-i phi) S(k) = Re(S(k)) cos(phi) - i sin (phi) i Im(S(k)) =
     541              :       ! = Re(S(k)) cos(phi) + Im(S(k)) sin(phi)
     542              :       array_rs(:, :) = array_rs(:, :) + (REAL(array_kp(:, :))*COS(phase) + &
     543     18832176 :                                          AIMAG(array_kp(:, :))*SIN(phase))*kpoints%wkp(ikp)
     544       370368 :    END SUBROUTINE add_kp_to_rs
     545              : ! **************************************************************************************************
     546              : !> \brief Calculates the inverse transform, assuming all kpoints are present on the given rank
     547              : !> \param array_kp The input complex fm matrix, containing the k-space matrix elements
     548              : !> \param array_rs The output real space matrix array
     549              : !> \param cell The image cell of the target RS matrix
     550              : !> \param kpoints Structure containing information about number, positions, weights etc. of kpoints
     551              : !> \par History
     552              : !>    05.2024 Created [Jan Wilhelm]
     553              : !>    11.2025 Moved to general file [Stepan Marek]
     554              : !> \note Part of transform in parallelism over k-points
     555              : ! **************************************************************************************************
     556            0 :    SUBROUTINE kp_to_rs(array_kp, array_rs, cell, kpoints)
     557              :       COMPLEX(kind=dp), DIMENSION(:, :, :)               :: array_kp
     558              :       REAL(kind=dp), DIMENSION(:, :)                     :: array_rs
     559              :       INTEGER, DIMENSION(3)                              :: cell
     560              :       TYPE(kpoint_type), POINTER                         :: kpoints
     561              : 
     562              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'kp_to_rs'
     563              : 
     564              :       INTEGER                                            :: handle, ikp
     565              : 
     566            0 :       IF (kpoints%nkp /= SIZE(array_kp, 3)) CALL cp_abort(__LOCATION__, &
     567            0 :                                                           "Provided kpoints and array_kp are inconsistent.")
     568              : 
     569            0 :       CALL timeset(routineN, handle)
     570              : 
     571            0 :       array_rs(:, :) = 0.0_dp
     572            0 :       DO ikp = 1, kpoints%nkp
     573            0 :          CALL add_kp_to_rs(array_kp(:, :, ikp), array_rs, cell, kpoints, ikp)
     574              :       END DO
     575              : 
     576            0 :       CALL timestop(handle)
     577            0 :    END SUBROUTINE kp_to_rs
     578              : END MODULE kpoint_k_r_trafo_simple
        

Generated by: LCOV version 2.0-1