LCOV - code coverage report
Current view: top level - src - qs_localizer_torus.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:9ccafda) Lines: 97.7 % 172 168
Test Date: 2026-10-15 00:55:44 Functions: 100.0 % 8 8

            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 Full Born-von-Karman AO operators at a frozen SCF potential.
      10              : !> \author Thomas D. Kuehne, tkuehne@cp2k.org
      11              : ! **************************************************************************************************
      12              : MODULE qs_localizer_torus
      13              :    USE cell_types,                      ONLY: cell_type
      14              :    USE cp_dbcsr_api,                    ONLY: &
      15              :         dbcsr_add, dbcsr_create, dbcsr_desymmetrize, dbcsr_distribution_get, &
      16              :         dbcsr_distribution_new, dbcsr_distribution_release, dbcsr_distribution_type, &
      17              :         dbcsr_finalize, dbcsr_get_info, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      18              :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_p_type, &
      19              :         dbcsr_put_block, dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, &
      20              :         dbcsr_type_no_symmetry, dbcsr_type_symmetric
      21              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      22              :    USE cp_dbcsr_operations,             ONLY: dbcsr_deallocate_matrix_set
      23              :    USE kinds,                           ONLY: dp
      24              :    USE kpoint_methods,                  ONLY: kpoint_init_cell_index,&
      25              :                                               rskp_transform
      26              :    USE kpoint_types,                    ONLY: kpoint_create,&
      27              :                                               kpoint_release,&
      28              :                                               kpoint_type
      29              :    USE mathconstants,                   ONLY: twopi
      30              :    USE message_passing,                 ONLY: mp_para_env_type
      31              :    USE qs_ao_translations,              ONLY: ao_translation_matrices
      32              :    USE qs_environment_types,            ONLY: get_qs_env,&
      33              :                                               qs_env_release,&
      34              :                                               qs_environment_type
      35              :    USE qs_finite_ao,                    ONLY: finite_ao_soc
      36              :    USE qs_gamma2kp,                     ONLY: create_kp_from_gamma
      37              :    USE qs_ks_types,                     ONLY: get_ks_env,&
      38              :                                               qs_ks_env_type
      39              :    USE qs_moments,                      ONLY: build_berry_kpoint_matrix
      40              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      41              : #include "./base/base_uses.f90"
      42              : 
      43              :    IMPLICIT NONE
      44              :    PRIVATE
      45              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_localizer_torus'
      46              :    PUBLIC :: localizer_torus_operators, torus_translation_operators
      47              : CONTAINS
      48              : 
      49              : ! **************************************************************************************************
      50              : !> \brief Lift scalar image operators and ordered Berry integrals to a full real-cell torus.
      51              : !> \param qs_env Converged SCF environment, possibly symmetry reduced
      52              : !> \param grid Gamma-centered property mesh, one in nonperiodic directions
      53              : !> \param directions Oriented periodic directions
      54              : !> \param do_soc Include physical-spin GTH SOC
      55              : !> \param h Newly allocated scalar Hamiltonians on the torus
      56              : !> \param s Newly allocated torus overlap
      57              : !> \param cosines Newly allocated torus cosine matrices, in directions order
      58              : !> \param sines Newly allocated sine matrices, indexed by lattice direction
      59              : !> \param soc Newly allocated torus SOC components when requested
      60              : !> \note No SCF weights or reconstructed occupied MOs enter. Keeping a real-cell AO basis
      61              : !>       also retains the standard physical time-reversal representation for the AII solver.
      62              : ! **************************************************************************************************
      63           16 :    SUBROUTINE localizer_torus_operators(qs_env, grid, directions, do_soc, h, s, cosines, sines, soc)
      64              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      65              :       INTEGER, INTENT(IN)                                :: grid(3), directions(:)
      66              :       LOGICAL, INTENT(IN)                                :: do_soc
      67              :       TYPE(dbcsr_p_type), POINTER                        :: h(:), s(:), cosines(:), sines(:), &
      68              :                                                             soc(:, :)
      69              : 
      70              :       INTEGER                                            :: axis, j, nimages
      71              :       LOGICAL                                            :: do_kpoints
      72              :       TYPE(cell_type), POINTER                           :: cell
      73           16 :       TYPE(dbcsr_p_type), POINTER                        :: cb(:, :), sb(:, :)
      74              :       TYPE(kpoint_type), POINTER                         :: berry
      75              :       TYPE(mp_para_env_type), POINTER                    :: para_env
      76           16 :       TYPE(neighbor_list_set_p_type), POINTER            :: all_pairs(:)
      77              :       TYPE(qs_environment_type), POINTER                 :: qp
      78              : 
      79           16 :       NULLIFY (qp, berry, cb, sb, soc)
      80            0 :       CPASSERT(SIZE(directions) >= 1 .AND. SIZE(directions) <= 3)
      81          108 :       CPASSERT(ALL(directions >= 1) .AND. ALL(directions <= 3))
      82           54 :       DO j = 1, SIZE(directions)
      83          148 :          CPASSERT(COUNT(directions == directions(j)) == 1)
      84              :       END DO
      85           16 :       CALL get_qs_env(qs_env, do_kpoints=do_kpoints)
      86           16 :       IF (do_kpoints) THEN
      87           16 :          qp => qs_env
      88              :       ELSE
      89            0 :          CALL create_kp_from_gamma(qs_env, qp)
      90              :       END IF
      91           16 :       CALL get_qs_env(qp, cell=cell, para_env=para_env, sab_all=all_pairs)
      92           16 :       CALL lift_electronic_operators(qp, grid, do_soc, h, s, soc)
      93          134 :       ALLOCATE (cosines(SIZE(directions)), sines(3))
      94           16 :       CALL kpoint_create(berry)
      95           16 :       CALL kpoint_init_cell_index(berry, all_pairs, para_env, nimages)
      96           64 :       DO axis = 1, 3
      97           48 :          ALLOCATE (sines(axis)%matrix)
      98           48 :          CALL dbcsr_create(sines(axis)%matrix, template=s(1)%matrix, name='TORUS SIN')
      99           64 :          CALL dbcsr_finalize(sines(axis)%matrix)
     100              :       END DO
     101           54 :       DO j = 1, SIZE(directions)
     102           38 :          axis = directions(j)
     103              :          CALL build_berry_kpoint_matrix(qp, cb, sb, twopi*cell%h_inv(axis, :)/REAL(grid(axis), dp), &
     104          152 :                                         ordered=.TRUE., ordered_kpoints=berry)
     105           38 :          ALLOCATE (cosines(j)%matrix)
     106           38 :          CALL dbcsr_create(cosines(j)%matrix, template=s(1)%matrix, name='TORUS COS')
     107           38 :          CALL lift_berry(cb, sb, berry%index_to_cell, grid, axis, cosines(j)%matrix, sines(axis)%matrix)
     108           38 :          CALL dbcsr_deallocate_matrix_set(cb)
     109           54 :          CALL dbcsr_deallocate_matrix_set(sb)
     110              :       END DO
     111           16 :       CALL kpoint_release(berry)
     112           16 :       IF (.NOT. do_kpoints) THEN
     113            0 :          CALL qs_env_release(qp)
     114            0 :          DEALLOCATE (qp)
     115              :       END IF
     116           32 :    END SUBROUTINE localizer_torus_operators
     117              : 
     118              : ! **************************************************************************************************
     119              : !> \brief Full AO torus with translated, periodized Gaussians instead of position coordinates.
     120              : !> \param qs_env Converged SCF environment
     121              : !> \param grid Full Gamma-centered property mesh
     122              : !> \param shifts Cartesian translations in internal bohr
     123              : !> \param do_soc Include post-SCF physical-spin GTH SOC
     124              : !> \param h Newly allocated scalar torus Hamiltonians
     125              : !> \param s Newly allocated torus metric
     126              : !> \param translations Newly allocated nonsymmetric torus translation overlaps
     127              : !> \param soc Newly allocated torus SOC components when requested
     128              : ! **************************************************************************************************
     129            6 :    SUBROUTINE torus_translation_operators(qs_env, grid, shifts, do_soc, h, s, translations, soc)
     130              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     131              :       INTEGER, INTENT(IN)                                :: grid(3)
     132              :       REAL(dp), INTENT(IN)                               :: shifts(:, :)
     133              :       LOGICAL, INTENT(IN)                                :: do_soc
     134              :       TYPE(dbcsr_p_type), POINTER                        :: h(:), s(:), translations(:), soc(:, :)
     135              : 
     136              :       INTEGER                                            :: ir, it, r(3)
     137              :       LOGICAL                                            :: do_kpoints
     138              :       REAL(dp), ALLOCATABLE                              :: displaced(:, :)
     139              :       TYPE(cell_type), POINTER                           :: cell
     140            6 :       TYPE(dbcsr_p_type), POINTER                        :: primitive_s(:, :), residues(:)
     141              :       TYPE(qs_environment_type), POINTER                 :: qp
     142              : 
     143            6 :       CALL get_qs_env(qs_env, do_kpoints=do_kpoints)
     144            6 :       IF (do_kpoints) THEN
     145            4 :          qp => qs_env
     146              :       ELSE
     147            2 :          CALL create_kp_from_gamma(qs_env, qp)
     148              :       END IF
     149            6 :       CALL get_qs_env(qp, cell=cell, matrix_s_kp=primitive_s)
     150            6 :       CALL lift_electronic_operators(qp, grid, do_soc, h, s, soc)
     151           36 :       ALLOCATE (translations(SIZE(shifts, 2)), displaced(3, SIZE(shifts, 2)))
     152           12 :       DO it = 1, SIZE(translations)
     153            6 :          ALLOCATE (translations(it)%matrix)
     154           30 :          CALL create_torus(primitive_s(1, 1)%matrix, PRODUCT(grid), translations(it)%matrix)
     155              :       END DO
     156           38 :       DO ir = 1, PRODUCT(grid)
     157           14 :          r = cell_coordinates(ir, grid)
     158           28 :          DO it = 1, SIZE(translations)
     159          336 :             displaced(:, it) = shifts(:, it) - MATMUL(cell%hmat, REAL(r, dp))
     160              :          END DO
     161           14 :          CALL ao_translation_matrices(qp, displaced, residues, periodic_grid=grid)
     162           28 :          DO it = 1, SIZE(translations)
     163           28 :             CALL lift_blocks(residues(it)%matrix, grid, r, 0, .FALSE., translations(it)%matrix)
     164              :          END DO
     165           20 :          CALL dbcsr_deallocate_matrix_set(residues)
     166              :       END DO
     167            6 :       IF (.NOT. do_kpoints) THEN
     168            2 :          CALL qs_env_release(qp)
     169            2 :          DEALLOCATE (qp)
     170              :       END IF
     171           12 :    END SUBROUTINE torus_translation_operators
     172              : 
     173              : ! **************************************************************************************************
     174              : !> \brief Common Hamiltonian, metric and physical-spin image lifting for the two AO-torus analyses.
     175              : !> \param qp Environment with explicit real-space image matrices
     176              : !> \param grid Property mesh
     177              : !> \param do_soc Include post-SCF GTH SOC
     178              : !> \param h Newly allocated scalar Hamiltonians
     179              : !> \param s Newly allocated overlap
     180              : !> \param soc Newly allocated SOC components, or null without SOC
     181              : ! **************************************************************************************************
     182           22 :    SUBROUTINE lift_electronic_operators(qp, grid, do_soc, h, s, soc)
     183              :       TYPE(qs_environment_type), POINTER                 :: qp
     184              :       INTEGER, INTENT(IN)                                :: grid(3)
     185              :       LOGICAL, INTENT(IN)                                :: do_soc
     186              :       TYPE(dbcsr_p_type), POINTER                        :: h(:), s(:), soc(:, :)
     187              : 
     188              :       INTEGER                                            :: axis, spin
     189           22 :       TYPE(dbcsr_p_type), POINTER                        :: hk(:, :), sk(:, :), vk(:, :)
     190              :       TYPE(kpoint_type), POINTER                         :: kpoints
     191           22 :       TYPE(neighbor_list_set_p_type), POINTER            :: pairs(:)
     192              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     193              : 
     194           22 :       NULLIFY (soc, vk)
     195           22 :       CALL get_qs_env(qp, ks_env=ks_env, matrix_ks_kp=hk, matrix_s_kp=sk, sab_orb=pairs)
     196           22 :       CALL get_ks_env(ks_env, kpoints=kpoints)
     197          110 :       ALLOCATE (h(SIZE(hk, 1)), s(1))
     198           44 :       DO spin = 1, SIZE(hk, 1)
     199           22 :          ALLOCATE (h(spin)%matrix)
     200           44 :          CALL lift_fourier(hk, spin, pairs, kpoints, grid, .FALSE., h(spin)%matrix)
     201              :       END DO
     202           22 :       ALLOCATE (s(1)%matrix)
     203           22 :       CALL lift_fourier(sk, 1, pairs, kpoints, grid, .FALSE., s(1)%matrix)
     204           22 :       IF (do_soc) THEN
     205           14 :          CALL finite_ao_soc(qp, vk)
     206           70 :          ALLOCATE (soc(3, 1))
     207           56 :          DO axis = 1, 3
     208           42 :             ALLOCATE (soc(axis, 1)%matrix)
     209           56 :             CALL lift_fourier(vk, axis, pairs, kpoints, grid, .TRUE., soc(axis, 1)%matrix)
     210              :          END DO
     211           14 :          CALL dbcsr_deallocate_matrix_set(vk)
     212              :       END IF
     213           22 :    END SUBROUTINE lift_electronic_operators
     214              : 
     215              : ! **************************************************************************************************
     216              : !> \brief Repeat the atom-block distribution; cell copies remain on the same MPI owners.
     217              : !> \param source Primitive AO template
     218              : !> \param copies Number of real cells
     219              : !> \param matrix New full-storage torus matrix
     220              : ! **************************************************************************************************
     221           92 :    SUBROUTINE create_torus(source, copies, matrix)
     222              :       TYPE(dbcsr_type), INTENT(IN)                       :: source
     223              :       INTEGER, INTENT(IN)                                :: copies
     224              :       TYPE(dbcsr_type), INTENT(OUT)                      :: matrix
     225              : 
     226              :       INTEGER                                            :: n
     227           92 :       INTEGER, POINTER                                   :: cols(:), ec(:), er(:), es(:), rows(:), &
     228           92 :                                                             sizes(:)
     229              :       TYPE(dbcsr_distribution_type)                      :: distribution, expanded
     230              : 
     231           92 :       CALL dbcsr_get_info(source, distribution=distribution, row_blk_size=sizes)
     232           92 :       CALL dbcsr_distribution_get(distribution, row_dist=rows, col_dist=cols)
     233           92 :       n = SIZE(sizes)*copies
     234          460 :       ALLOCATE (es(n), er(n), ec(n))
     235          184 :       es = RESHAPE(SPREAD(sizes, 2, copies), [n])
     236          184 :       er = RESHAPE(SPREAD(rows, 2, copies), [n])
     237          184 :       ec = RESHAPE(SPREAD(cols, 2, copies), [n])
     238           92 :       CALL dbcsr_distribution_new(expanded, template=distribution, row_dist=er, col_dist=ec)
     239           92 :       CALL dbcsr_create(matrix, 'TORUS AO', expanded, dbcsr_type_no_symmetry, es, es)
     240           92 :       CALL dbcsr_distribution_release(expanded)
     241           92 :       DEALLOCATE (es, er, ec)
     242          184 :    END SUBROUTINE create_torus
     243              : 
     244              : ! **************************************************************************************************
     245              : !> \brief Inverse discrete Fourier transform of the existing CP2K image convention.
     246              : !> \param images Primitive real-space matrices
     247              : !> \param spin Component of images
     248              : !> \param pairs SCF orbital neighbour list
     249              : !> \param kpoints SCF image indexing, not the SCF k-points or weights
     250              : !> \param grid Full Gamma-centered property mesh
     251              : !> \param antisymmetric Whether images are real SOC components (before multiplication by i)
     252              : !> \param matrix New real-cell torus matrix
     253              : !> \note This reference assembly uses O(Nk**2) primitive-block operations, but never
     254              : !>       gathers a dense AO matrix. It intentionally shares rskp_transform conventions.
     255              : ! **************************************************************************************************
     256           86 :    SUBROUTINE lift_fourier(images, spin, pairs, kpoints, grid, antisymmetric, matrix)
     257              :       TYPE(dbcsr_p_type), POINTER                        :: images(:, :)
     258              :       INTEGER, INTENT(IN)                                :: spin
     259              :       TYPE(neighbor_list_set_p_type), POINTER            :: pairs(:)
     260              :       TYPE(kpoint_type), POINTER                         :: kpoints
     261              :       INTEGER, INTENT(IN)                                :: grid(3)
     262              :       LOGICAL, INTENT(IN)                                :: antisymmetric
     263              :       TYPE(dbcsr_type), INTENT(OUT)                      :: matrix
     264              : 
     265              :       INTEGER                                            :: ik, ir, n, r(3)
     266              :       REAL(dp)                                           :: k(3), phase
     267           86 :       TYPE(dbcsr_p_type), POINTER                        :: residues(:)
     268              :       TYPE(dbcsr_type)                                   :: full_im, full_re, im, re
     269              : 
     270          344 :       n = PRODUCT(grid)
     271           86 :       CALL create_torus(images(spin, 1)%matrix, n, matrix)
     272           86 :       CALL dbcsr_create(re, template=images(spin, 1)%matrix, matrix_type=dbcsr_type_symmetric)
     273           86 :       CALL dbcsr_create(im, template=images(spin, 1)%matrix, matrix_type=dbcsr_type_antisymmetric)
     274           86 :       CALL cp_dbcsr_alloc_block_from_nbl(re, pairs)
     275           86 :       CALL cp_dbcsr_alloc_block_from_nbl(im, pairs)
     276           86 :       CALL dbcsr_create(full_re, template=re, matrix_type=dbcsr_type_no_symmetry)
     277           86 :       CALL dbcsr_create(full_im, template=re, matrix_type=dbcsr_type_no_symmetry)
     278          682 :       ALLOCATE (residues(n))
     279          510 :       DO ir = 1, n
     280          424 :          ALLOCATE (residues(ir)%matrix)
     281          424 :          CALL dbcsr_create(residues(ir)%matrix, template=full_re)
     282          510 :          CALL dbcsr_finalize(residues(ir)%matrix)
     283              :       END DO
     284          510 :       DO ik = 1, n
     285         1696 :          k = REAL(cell_coordinates(ik, grid), dp)/REAL(grid, dp)
     286          424 :          CALL dbcsr_set(re, 0.0_dp)
     287          424 :          CALL dbcsr_set(im, 0.0_dp)
     288          424 :          IF (antisymmetric) THEN
     289              :             ! build_core_ppnl already reverses the SOC integral for swapped atom blocks.
     290              :             ! Match the band SOC transform; is_complex would apply that sign a second time.
     291          228 :             CALL rskp_transform(im, re, images, spin, k, kpoints%cell_to_index, pairs)
     292          228 :             CALL dbcsr_desymmetrize(im, full_re)
     293          228 :             CALL dbcsr_desymmetrize(re, full_im)
     294              :          ELSE
     295          196 :             CALL rskp_transform(re, im, images, spin, k, kpoints%cell_to_index, pairs)
     296          196 :             CALL dbcsr_desymmetrize(re, full_re)
     297          196 :             CALL dbcsr_desymmetrize(im, full_im)
     298              :          END IF
     299         3010 :          DO ir = 1, n
     300         2500 :             r = cell_coordinates(ir, grid)
     301        10000 :             phase = twopi*DOT_PRODUCT(k, REAL(r, dp))
     302         2500 :             CALL dbcsr_add(residues(ir)%matrix, full_re, 1.0_dp, COS(phase)/REAL(n, dp))
     303         2924 :             CALL dbcsr_add(residues(ir)%matrix, full_im, 1.0_dp, SIN(phase)/REAL(n, dp))
     304              :          END DO
     305              :       END DO
     306          510 :       DO ir = 1, n
     307          424 :          r = cell_coordinates(ir, grid)
     308          510 :          CALL lift_blocks(residues(ir)%matrix, grid, r, 0, .FALSE., matrix)
     309              :       END DO
     310           86 :       CALL dbcsr_finalize(matrix)
     311           86 :       CALL dbcsr_deallocate_matrix_set(residues)
     312           86 :       CALL dbcsr_release(re)
     313           86 :       CALL dbcsr_release(im)
     314           86 :       CALL dbcsr_release(full_re)
     315           86 :       CALL dbcsr_release(full_im)
     316          172 :    END SUBROUTINE lift_fourier
     317              : 
     318              : ! **************************************************************************************************
     319              : !> \brief Lift ordered Berry integrals with the phase of every translated bra cell.
     320              : !> \param cosmat Primitive ordered cosine integrals
     321              : !> \param sinmat Primitive ordered sine integrals
     322              : !> \param cells Integer image labels
     323              : !> \param grid Torus dimensions
     324              : !> \param axis Direction of the reciprocal torus coordinate
     325              : !> \param cosine Full torus cosine
     326              : !> \param sine Full torus sine
     327              : ! **************************************************************************************************
     328           38 :    SUBROUTINE lift_berry(cosmat, sinmat, cells, grid, axis, cosine, sine)
     329              :       TYPE(dbcsr_p_type), INTENT(INOUT)                  :: cosmat(:, :), sinmat(:, :)
     330              :       INTEGER, INTENT(IN)                                :: cells(:, :), grid(3), axis
     331              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: cosine, sine
     332              : 
     333              :       INTEGER                                            :: ir
     334              : 
     335         2140 :       DO ir = 1, SIZE(cells, 2)
     336         2102 :          CALL lift_blocks(cosmat(1, ir)%matrix, grid, cells(:, ir), axis, .FALSE., cosine)
     337         2102 :          CALL lift_blocks(sinmat(1, ir)%matrix, grid, cells(:, ir), -axis, .TRUE., cosine)
     338         2102 :          CALL lift_blocks(cosmat(1, ir)%matrix, grid, cells(:, ir), axis, .TRUE., sine)
     339         2140 :          CALL lift_blocks(sinmat(1, ir)%matrix, grid, cells(:, ir), axis, .FALSE., sine)
     340              :       END DO
     341           38 :       CALL dbcsr_finalize(cosine)
     342           38 :       CALL dbcsr_finalize(sine)
     343           38 :    END SUBROUTINE lift_berry
     344              : 
     345              : ! **************************************************************************************************
     346              : !> \brief Translate primitive AO blocks onto the torus without changing MPI ownership.
     347              : !> \param source Fully stored primitive matrix for one displacement
     348              : !> \param grid Torus dimensions
     349              : !> \param displacement Ket-cell displacement relative to the bra
     350              : !> \param axis Zero for no phase, signed reciprocal direction otherwise
     351              : !> \param sine Use sine rather than cosine of the translation phase
     352              : !> \param destination Accumulated torus matrix
     353              : ! **************************************************************************************************
     354        17692 :    SUBROUTINE lift_blocks(source, grid, displacement, axis, sine, destination)
     355              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: source
     356              :       INTEGER, INTENT(IN)                                :: grid(3), displacement(3), axis
     357              :       LOGICAL, INTENT(IN)                                :: sine
     358              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: destination
     359              : 
     360              :       INTEGER                                            :: blocks, col, it, iu, row, t(3), u(3)
     361              :       LOGICAL                                            :: transposed
     362              :       REAL(dp)                                           :: factor, phase
     363         8846 :       REAL(dp), POINTER                                  :: block(:, :)
     364              :       TYPE(dbcsr_iterator_type)                          :: iterator
     365              : 
     366         8846 :       CALL dbcsr_get_info(source, nblkrows_total=blocks)
     367         8846 :       CALL dbcsr_iterator_start(iterator, source)
     368        20373 :       DO WHILE (dbcsr_iterator_blocks_left(iterator))
     369        11527 :          CALL dbcsr_iterator_next_block(iterator, row, col, block, transposed=transposed)
     370        11527 :          CPASSERT(.NOT. transposed)
     371       332070 :          IF (ALL(block == 0.0_dp)) CYCLE
     372        89655 :          DO it = 1, PRODUCT(grid)
     373        41741 :             t = cell_coordinates(it, grid)
     374       166964 :             u = MODULO(t + displacement, grid)
     375        41741 :             iu = 1 + u(1) + grid(1)*(u(2) + grid(2)*u(3))
     376        41741 :             factor = 1.0_dp
     377        41741 :             IF (axis /= 0) THEN
     378        39968 :                phase = twopi*REAL(t(ABS(axis)), dp)/REAL(grid(ABS(axis)), dp)
     379        39968 :                IF (sine) THEN
     380        19984 :                   factor = SIN(phase)
     381              :                ELSE
     382        19984 :                   factor = COS(phase)
     383              :                END IF
     384        39968 :                IF (axis < 0) factor = -factor
     385              :             END IF
     386        39968 :             IF (factor == 0.0_dp) CYCLE
     387              :             CALL dbcsr_put_block(destination, row + (it - 1)*blocks, col + (iu - 1)*blocks, &
     388      5361338 :                                  factor*block, summation=.TRUE.)
     389              :          END DO
     390              :       END DO
     391         8846 :       CALL dbcsr_iterator_stop(iterator)
     392         8846 :       CALL dbcsr_finalize(destination)
     393         8846 :    END SUBROUTINE lift_blocks
     394              : 
     395              : ! **************************************************************************************************
     396              : !> \brief Zero-based cell coordinates with the first axis varying fastest.
     397              : !> \param index One-based cell index
     398              : !> \param grid Torus dimensions
     399              : !> \return Integer lattice coordinates
     400              : ! **************************************************************************************************
     401        45103 :    PURE FUNCTION cell_coordinates(index, grid) RESULT(r)
     402              :       INTEGER, INTENT(IN)                                :: index, grid(3)
     403              :       INTEGER                                            :: r(3)
     404              : 
     405        45103 :       r(1) = MODULO(index - 1, grid(1))
     406        45103 :       r(2) = MODULO((index - 1)/grid(1), grid(2))
     407        45103 :       r(3) = (index - 1)/(grid(1)*grid(2))
     408        45103 :    END FUNCTION cell_coordinates
     409              : END MODULE qs_localizer_torus
        

Generated by: LCOV version 2.0-1