LCOV - code coverage report
Current view: top level - src - xray_diffraction.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:ccc2433) Lines: 436 439 99.3 %
Date: 2024-04-25 07:09:54 Functions: 3 3 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \par Literature
      10             : !>      M. Krack, A. Gambirasio, and M. Parrinello,
      11             : !>      "Ab-initio x-ray scattering of liquid water",
      12             : !>      J. Chem. Phys. 117, 9409 (2002)
      13             : !> \author Matthias Krack
      14             : !> \date   30.11.2005
      15             : ! **************************************************************************************************
      16             : MODULE xray_diffraction
      17             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      18             :                                               get_atomic_kind
      19             :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      20             :                                               gto_basis_set_type
      21             :    USE bibliography,                    ONLY: Krack2002,&
      22             :                                               cite_reference
      23             :    USE cell_types,                      ONLY: cell_type,&
      24             :                                               pbc
      25             :    USE cp_control_types,                ONLY: dft_control_type
      26             :    USE kinds,                           ONLY: dp,&
      27             :                                               int_8
      28             :    USE mathconstants,                   ONLY: pi,&
      29             :                                               twopi
      30             :    USE memory_utilities,                ONLY: reallocate
      31             :    USE message_passing,                 ONLY: mp_para_env_type
      32             :    USE orbital_pointers,                ONLY: indco,&
      33             :                                               nco,&
      34             :                                               ncoset,&
      35             :                                               nso,&
      36             :                                               nsoset
      37             :    USE orbital_transformation_matrices, ONLY: orbtramat
      38             :    USE particle_types,                  ONLY: particle_type
      39             :    USE paw_basis_types,                 ONLY: get_paw_basis_info
      40             :    USE physcon,                         ONLY: angstrom
      41             :    USE pw_env_types,                    ONLY: pw_env_get,&
      42             :                                               pw_env_type
      43             :    USE pw_grids,                        ONLY: get_pw_grid_info
      44             :    USE pw_methods,                      ONLY: pw_axpy,&
      45             :                                               pw_integrate_function,&
      46             :                                               pw_scale,&
      47             :                                               pw_transfer,&
      48             :                                               pw_zero
      49             :    USE pw_pool_types,                   ONLY: pw_pool_type
      50             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      51             :                                               pw_r3d_rs_type
      52             :    USE qs_environment_types,            ONLY: get_qs_env,&
      53             :                                               qs_environment_type
      54             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      55             :                                               qs_kind_type
      56             :    USE qs_rho_atom_types,               ONLY: get_rho_atom,&
      57             :                                               rho_atom_coeff,&
      58             :                                               rho_atom_type
      59             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      60             :                                               qs_rho_type
      61             :    USE util,                            ONLY: sort
      62             : #include "./base/base_uses.f90"
      63             : 
      64             :    IMPLICIT NONE
      65             : 
      66             :    PRIVATE
      67             : 
      68             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xray_diffraction'
      69             : 
      70             :    PUBLIC :: calculate_rhotot_elec_gspace, &
      71             :              xray_diffraction_spectrum
      72             : 
      73             : CONTAINS
      74             : 
      75             : ! **************************************************************************************************
      76             : !> \brief Calculate the coherent X-ray diffraction spectrum using the total
      77             : !>        electronic density in reciprocal space (g-space).
      78             : !> \param qs_env ...
      79             : !> \param unit_number ...
      80             : !> \param q_max ...
      81             : !> \date   30.11.2005
      82             : !> \author Matthias Krack
      83             : ! **************************************************************************************************
      84         120 :    SUBROUTINE xray_diffraction_spectrum(qs_env, unit_number, q_max)
      85             : 
      86             :       TYPE(qs_environment_type), POINTER                 :: qs_env
      87             :       INTEGER, INTENT(IN)                                :: unit_number
      88             :       REAL(KIND=dp), INTENT(IN)                          :: q_max
      89             : 
      90             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'xray_diffraction_spectrum'
      91             :       INTEGER, PARAMETER                                 :: nblock = 100
      92             : 
      93             :       INTEGER                                            :: handle, i, ig, ig_shell, ipe, ishell, &
      94             :                                                             jg, ng, npe, nshell, nshell_gather
      95             :       INTEGER(KIND=int_8)                                :: ngpts
      96             :       INTEGER, DIMENSION(3)                              :: npts
      97          30 :       INTEGER, DIMENSION(:), POINTER                     :: aux_index, ng_shell, ng_shell_gather, &
      98          30 :                                                             nshell_pe, offset_pe
      99             :       REAL(KIND=dp)                                      :: cutoff, f, f2, q, rho_hard, rho_soft, &
     100             :                                                             rho_total
     101             :       REAL(KIND=dp), DIMENSION(3)                        :: dg, dr
     102          30 :       REAL(KIND=dp), DIMENSION(:), POINTER :: f2sum, f2sum_gather, f4sum, f4sum_gather, fmax, &
     103          30 :          fmax_gather, fmin, fmin_gather, fsum, fsum_gather, gsq, q_shell, q_shell_gather
     104          30 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     105             :       TYPE(dft_control_type), POINTER                    :: dft_control
     106             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     107          30 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     108             :       TYPE(pw_c1d_gs_type)                               :: rhotot_elec_gspace
     109             :       TYPE(pw_env_type), POINTER                         :: pw_env
     110             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     111             :       TYPE(qs_rho_type), POINTER                         :: rho
     112          30 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho_atom_set
     113             : 
     114           0 :       CPASSERT(ASSOCIATED(qs_env))
     115             : 
     116          30 :       CALL timeset(routineN, handle)
     117             : 
     118          30 :       NULLIFY (atomic_kind_set)
     119          30 :       NULLIFY (aux_index)
     120          30 :       NULLIFY (auxbas_pw_pool)
     121          30 :       NULLIFY (dft_control)
     122          30 :       NULLIFY (f2sum)
     123          30 :       NULLIFY (f2sum_gather)
     124          30 :       NULLIFY (f4sum)
     125          30 :       NULLIFY (f4sum_gather)
     126          30 :       NULLIFY (fmax)
     127          30 :       NULLIFY (fmax_gather)
     128          30 :       NULLIFY (fmin)
     129          30 :       NULLIFY (fmin_gather)
     130          30 :       NULLIFY (fsum)
     131          30 :       NULLIFY (fsum_gather)
     132          30 :       NULLIFY (gsq)
     133          30 :       NULLIFY (ng_shell)
     134          30 :       NULLIFY (ng_shell_gather)
     135          30 :       NULLIFY (nshell_pe)
     136          30 :       NULLIFY (offset_pe)
     137          30 :       NULLIFY (para_env)
     138          30 :       NULLIFY (particle_set)
     139          30 :       NULLIFY (pw_env)
     140          30 :       NULLIFY (q_shell)
     141          30 :       NULLIFY (q_shell_gather)
     142          30 :       NULLIFY (rho)
     143          30 :       NULLIFY (rho_atom_set)
     144             : 
     145          30 :       CALL cite_reference(Krack2002)
     146             : 
     147             :       CALL get_qs_env(qs_env=qs_env, &
     148             :                       atomic_kind_set=atomic_kind_set, &
     149             :                       dft_control=dft_control, &
     150             :                       para_env=para_env, &
     151             :                       particle_set=particle_set, &
     152             :                       pw_env=pw_env, &
     153             :                       rho=rho, &
     154          30 :                       rho_atom_set=rho_atom_set)
     155             : 
     156             :       CALL pw_env_get(pw_env=pw_env, &
     157          30 :                       auxbas_pw_pool=auxbas_pw_pool)
     158             : 
     159          30 :       npe = para_env%num_pe
     160             : 
     161             :       ! Plane waves grid to assemble the total electronic density
     162             : 
     163          30 :       CALL auxbas_pw_pool%create_pw(pw=rhotot_elec_gspace)
     164          30 :       CALL pw_zero(rhotot_elec_gspace)
     165             : 
     166             :       CALL get_pw_grid_info(pw_grid=rhotot_elec_gspace%pw_grid, &
     167             :                             dr=dr, &
     168             :                             npts=npts, &
     169             :                             cutoff=cutoff, &
     170             :                             ngpts=ngpts, &
     171          30 :                             gsquare=gsq)
     172             : 
     173         120 :       dg(:) = twopi/(npts(:)*dr(:))
     174             : 
     175             :       ! Build the total electronic density in reciprocal space
     176             : 
     177             :       CALL calculate_rhotot_elec_gspace(qs_env=qs_env, &
     178             :                                         auxbas_pw_pool=auxbas_pw_pool, &
     179             :                                         rhotot_elec_gspace=rhotot_elec_gspace, &
     180             :                                         q_max=q_max, &
     181             :                                         rho_hard=rho_hard, &
     182          30 :                                         rho_soft=rho_soft)
     183             : 
     184          30 :       rho_total = rho_hard + rho_soft
     185             : 
     186             :       ! Calculate the coherent X-ray spectrum
     187             : 
     188             :       ! Now we have to gather the data from all processes, since each
     189             :       ! process has only worked his sub-grid
     190             : 
     191             :       ! Scan the g-vector shells
     192             : 
     193          30 :       CALL reallocate(q_shell, 1, nblock)
     194          30 :       CALL reallocate(ng_shell, 1, nblock)
     195             : 
     196          30 :       ng = SIZE(gsq)
     197             : 
     198          30 :       jg = 1
     199          30 :       nshell = 1
     200          30 :       q_shell(1) = SQRT(gsq(1))
     201          30 :       ng_shell(1) = 1
     202             : 
     203      232603 :       DO ig = 2, ng
     204      232603 :          CPASSERT(gsq(ig) >= gsq(jg))
     205      232603 :          IF (ABS(gsq(ig) - gsq(jg)) > 1.0E-12_dp) THEN
     206        5359 :             nshell = nshell + 1
     207        5359 :             IF (nshell > SIZE(q_shell)) THEN
     208          44 :                CALL reallocate(q_shell, 1, SIZE(q_shell) + nblock)
     209          44 :                CALL reallocate(ng_shell, 1, SIZE(ng_shell) + nblock)
     210             :             END IF
     211        5359 :             q = SQRT(gsq(ig))
     212        5359 :             IF (q > q_max) THEN
     213          30 :                nshell = nshell - 1
     214          30 :                EXIT
     215             :             END IF
     216        5329 :             q_shell(nshell) = q
     217        5329 :             ng_shell(nshell) = 1
     218        5329 :             jg = ig
     219             :          ELSE
     220      227244 :             ng_shell(nshell) = ng_shell(nshell) + 1
     221             :          END IF
     222             :       END DO
     223             : 
     224          30 :       CALL reallocate(q_shell, 1, nshell)
     225          30 :       CALL reallocate(ng_shell, 1, nshell)
     226          30 :       CALL reallocate(fmin, 1, nshell)
     227          30 :       CALL reallocate(fmax, 1, nshell)
     228          30 :       CALL reallocate(fsum, 1, nshell)
     229          30 :       CALL reallocate(f2sum, 1, nshell)
     230          30 :       CALL reallocate(f4sum, 1, nshell)
     231             : 
     232          30 :       ig = 0
     233        5389 :       DO ishell = 1, nshell
     234        5359 :          fmin(ishell) = HUGE(0.0_dp)
     235        5359 :          fmax(ishell) = 0.0_dp
     236        5359 :          fsum(ishell) = 0.0_dp
     237        5359 :          f2sum(ishell) = 0.0_dp
     238        5359 :          f4sum(ishell) = 0.0_dp
     239      237962 :          DO ig_shell = 1, ng_shell(ishell)
     240      232603 :             f = ABS(rhotot_elec_gspace%array(ig + ig_shell))
     241      232603 :             fmin(ishell) = MIN(fmin(ishell), f)
     242      232603 :             fmax(ishell) = MAX(fmax(ishell), f)
     243      232603 :             fsum(ishell) = fsum(ishell) + f
     244      232603 :             f2 = f*f
     245      232603 :             f2sum(ishell) = f2sum(ishell) + f2
     246      237962 :             f4sum(ishell) = f4sum(ishell) + f2*f2
     247             :          END DO
     248        5389 :          ig = ig + ng_shell(ishell)
     249             :       END DO
     250             : 
     251          30 :       CALL reallocate(nshell_pe, 0, npe - 1)
     252          30 :       CALL reallocate(offset_pe, 0, npe - 1)
     253             : 
     254             :       ! Root (source) process gathers the number of shell of each process
     255             : 
     256          90 :       CALL para_env%gather(nshell, nshell_pe)
     257             : 
     258             :       ! Only the root process which has to print the full spectrum has to
     259             :       ! allocate here the receive buffers with their real sizes
     260             : 
     261          30 :       IF (unit_number > 0) THEN
     262          45 :          nshell_gather = SUM(nshell_pe)
     263          15 :          offset_pe(0) = 0
     264          30 :          DO ipe = 1, npe - 1
     265          30 :             offset_pe(ipe) = offset_pe(ipe - 1) + nshell_pe(ipe - 1)
     266             :          END DO
     267             :       ELSE
     268          15 :          nshell_gather = 1 ! dummy value for the non-root processes
     269             :       END IF
     270             : 
     271          30 :       CALL reallocate(q_shell_gather, 1, nshell_gather)
     272          30 :       CALL reallocate(ng_shell_gather, 1, nshell_gather)
     273          30 :       CALL reallocate(fmin_gather, 1, nshell_gather)
     274          30 :       CALL reallocate(fmax_gather, 1, nshell_gather)
     275          30 :       CALL reallocate(fsum_gather, 1, nshell_gather)
     276          30 :       CALL reallocate(f2sum_gather, 1, nshell_gather)
     277          30 :       CALL reallocate(f4sum_gather, 1, nshell_gather)
     278             : 
     279       10883 :       CALL para_env%gatherv(q_shell, q_shell_gather, nshell_pe, offset_pe)
     280       10883 :       CALL para_env%gatherv(ng_shell, ng_shell_gather, nshell_pe, offset_pe)
     281       10883 :       CALL para_env%gatherv(fmax, fmax_gather, nshell_pe, offset_pe)
     282       10883 :       CALL para_env%gatherv(fmin, fmin_gather, nshell_pe, offset_pe)
     283       10883 :       CALL para_env%gatherv(fsum, fsum_gather, nshell_pe, offset_pe)
     284       10883 :       CALL para_env%gatherv(f2sum, f2sum_gather, nshell_pe, offset_pe)
     285       10883 :       CALL para_env%gatherv(f4sum, f4sum_gather, nshell_pe, offset_pe)
     286             : 
     287          30 :       IF (ASSOCIATED(offset_pe)) THEN
     288          30 :          DEALLOCATE (offset_pe)
     289             :       END IF
     290             : 
     291          30 :       IF (ASSOCIATED(nshell_pe)) THEN
     292          30 :          DEALLOCATE (nshell_pe)
     293             :       END IF
     294             : 
     295             :       ! Print X-ray diffraction spectrum (I/O node only)
     296             : 
     297          30 :       IF (unit_number > 0) THEN
     298             : 
     299          15 :          CALL reallocate(aux_index, 1, nshell_gather)
     300             : 
     301             :          ! Sort the gathered shells
     302             : 
     303          15 :          CALL sort(q_shell_gather, nshell_gather, aux_index)
     304             : 
     305             :          ! Allocate final arrays of sufficient size, i.e. nshell_gather
     306             :          ! is always greater or equal the final nshell value
     307             : 
     308          15 :          CALL reallocate(q_shell, 1, nshell_gather)
     309          15 :          CALL reallocate(ng_shell, 1, nshell_gather)
     310          15 :          CALL reallocate(fmin, 1, nshell_gather)
     311          15 :          CALL reallocate(fmax, 1, nshell_gather)
     312          15 :          CALL reallocate(fsum, 1, nshell_gather)
     313          15 :          CALL reallocate(f2sum, 1, nshell_gather)
     314          15 :          CALL reallocate(f4sum, 1, nshell_gather)
     315             : 
     316          15 :          jg = 1
     317          15 :          nshell = 1
     318          15 :          q_shell(1) = q_shell_gather(1)
     319          15 :          i = aux_index(1)
     320          15 :          ng_shell(1) = ng_shell_gather(i)
     321          15 :          fmin(1) = fmin_gather(i)
     322          15 :          fmax(1) = fmax_gather(i)
     323          15 :          fsum(1) = fsum_gather(i)
     324          15 :          f2sum(1) = f2sum_gather(i)
     325          15 :          f4sum(1) = f4sum_gather(i)
     326             : 
     327        5359 :          DO ig = 2, nshell_gather
     328        5344 :             i = aux_index(ig)
     329        5359 :             IF (ABS(q_shell_gather(ig) - q_shell_gather(jg)) > 1.0E-12_dp) THEN
     330        2796 :                nshell = nshell + 1
     331        2796 :                q_shell(nshell) = q_shell_gather(ig)
     332        2796 :                ng_shell(nshell) = ng_shell_gather(i)
     333        2796 :                fmin(nshell) = fmin_gather(i)
     334        2796 :                fmax(nshell) = fmax_gather(i)
     335        2796 :                fsum(nshell) = fsum_gather(i)
     336        2796 :                f2sum(nshell) = f2sum_gather(i)
     337        2796 :                f4sum(nshell) = f4sum_gather(i)
     338        2796 :                jg = ig
     339             :             ELSE
     340        2548 :                ng_shell(nshell) = ng_shell(nshell) + ng_shell_gather(i)
     341        2548 :                fmin(nshell) = MIN(fmin(nshell), fmin_gather(i))
     342        2548 :                fmax(nshell) = MAX(fmax(nshell), fmax_gather(i))
     343        2548 :                fsum(nshell) = fsum(nshell) + fsum_gather(i)
     344        2548 :                f2sum(nshell) = f2sum(nshell) + f2sum_gather(i)
     345        2548 :                f4sum(nshell) = f4sum(nshell) + f4sum_gather(i)
     346             :             END IF
     347             :          END DO
     348             : 
     349             :          ! The auxiliary index array is no longer needed now
     350             : 
     351          15 :          IF (ASSOCIATED(aux_index)) THEN
     352          15 :             DEALLOCATE (aux_index)
     353             :          END IF
     354             : 
     355             :          ! Allocate the final arrays for printing with their real size
     356             : 
     357          15 :          CALL reallocate(q_shell, 1, nshell)
     358          15 :          CALL reallocate(ng_shell, 1, nshell)
     359          15 :          CALL reallocate(fmin, 1, nshell)
     360          15 :          CALL reallocate(fmax, 1, nshell)
     361          15 :          CALL reallocate(fsum, 1, nshell)
     362          15 :          CALL reallocate(f2sum, 1, nshell)
     363          15 :          CALL reallocate(f4sum, 1, nshell)
     364             : 
     365             :          ! Write the X-ray diffraction spectrum to the specified file
     366             : 
     367             :          WRITE (UNIT=unit_number, FMT="(A)") &
     368          15 :             "#", &
     369          15 :             "# Coherent X-ray diffraction spectrum", &
     370          30 :             "#"
     371             :          WRITE (UNIT=unit_number, FMT="(A,1X,F20.10)") &
     372          15 :             "# Soft electronic charge (G-space) :", rho_soft, &
     373          15 :             "# Hard electronic charge (G-space) :", rho_hard, &
     374          15 :             "# Total electronic charge (G-space):", rho_total, &
     375          15 :             "# Density cutoff [Rydberg]         :", 2.0_dp*cutoff, &
     376          15 :             "# q(min) [1/Angstrom]              :", q_shell(2)/angstrom, &
     377          15 :             "# q(max) [1/Angstrom]              :", q_shell(nshell)/angstrom, &
     378          30 :             "# q(max) [1/Angstrom] (requested)  :", q_max/angstrom
     379             :          WRITE (UNIT=unit_number, FMT="(A,2X,I8)") &
     380          15 :             "# Number of g-vectors (grid points):", ngpts, &
     381          30 :             "# Number of g-vector shells        :", nshell
     382             :          WRITE (UNIT=unit_number, FMT="(A,3(1X,I6))") &
     383          15 :             "# Grid size (a,b,c)                :", npts(1:3)
     384             :          WRITE (UNIT=unit_number, FMT="(A,3F7.3)") &
     385          60 :             "# dg [1/Angstrom]                  :", dg(1:3)/angstrom, &
     386          75 :             "# dr [Angstrom]                    :", dr(1:3)*angstrom
     387             :          WRITE (UNIT=unit_number, FMT="(A)") &
     388          15 :             "#", &
     389             :             "# shell  points         q [1/A]      <|F(q)|^2>     Min(|F(q)|)"// &
     390          30 :             "     Max(|F(q)|)      <|F(q)|>^2      <|F(q)|^4>"
     391             : 
     392        2826 :          DO ishell = 1, nshell
     393             :             WRITE (UNIT=unit_number, FMT="(T2,I6,2X,I6,5(1X,F15.6),1X,ES15.6)") &
     394        2811 :                ishell, &
     395        2811 :                ng_shell(ishell), &
     396        2811 :                q_shell(ishell)/angstrom, &
     397        2811 :                f2sum(ishell)/REAL(ng_shell(ishell), KIND=dp), &
     398        2811 :                fmin(ishell), &
     399        2811 :                fmax(ishell), &
     400        2811 :                (fsum(ishell)/REAL(ng_shell(ishell), KIND=dp))**2, &
     401        5637 :                f4sum(ishell)/REAL(ng_shell(ishell), KIND=dp)
     402             :          END DO
     403             : 
     404             :       END IF
     405             : 
     406             :       ! Release work storage
     407             : 
     408          30 :       IF (ASSOCIATED(fmin)) THEN
     409          30 :          DEALLOCATE (fmin)
     410             :       END IF
     411             : 
     412          30 :       IF (ASSOCIATED(fmax)) THEN
     413          30 :          DEALLOCATE (fmax)
     414             :       END IF
     415             : 
     416          30 :       IF (ASSOCIATED(fsum)) THEN
     417          30 :          DEALLOCATE (fsum)
     418             :       END IF
     419             : 
     420          30 :       IF (ASSOCIATED(f2sum)) THEN
     421          30 :          DEALLOCATE (f2sum)
     422             :       END IF
     423             : 
     424          30 :       IF (ASSOCIATED(f4sum)) THEN
     425          30 :          DEALLOCATE (f4sum)
     426             :       END IF
     427             : 
     428          30 :       IF (ASSOCIATED(ng_shell)) THEN
     429          30 :          DEALLOCATE (ng_shell)
     430             :       END IF
     431             : 
     432          30 :       IF (ASSOCIATED(q_shell)) THEN
     433          30 :          DEALLOCATE (q_shell)
     434             :       END IF
     435             : 
     436          30 :       IF (ASSOCIATED(fmin_gather)) THEN
     437          30 :          DEALLOCATE (fmin_gather)
     438             :       END IF
     439             : 
     440          30 :       IF (ASSOCIATED(fmax_gather)) THEN
     441          30 :          DEALLOCATE (fmax_gather)
     442             :       END IF
     443             : 
     444          30 :       IF (ASSOCIATED(fsum_gather)) THEN
     445          30 :          DEALLOCATE (fsum_gather)
     446             :       END IF
     447             : 
     448          30 :       IF (ASSOCIATED(f2sum_gather)) THEN
     449          30 :          DEALLOCATE (f2sum_gather)
     450             :       END IF
     451             : 
     452          30 :       IF (ASSOCIATED(f4sum_gather)) THEN
     453          30 :          DEALLOCATE (f4sum_gather)
     454             :       END IF
     455             : 
     456          30 :       IF (ASSOCIATED(ng_shell_gather)) THEN
     457          30 :          DEALLOCATE (ng_shell_gather)
     458             :       END IF
     459             : 
     460          30 :       IF (ASSOCIATED(q_shell_gather)) THEN
     461          30 :          DEALLOCATE (q_shell_gather)
     462             :       END IF
     463             : 
     464          30 :       CALL auxbas_pw_pool%give_back_pw(rhotot_elec_gspace)
     465             : 
     466          30 :       CALL timestop(handle)
     467             : 
     468          30 :    END SUBROUTINE xray_diffraction_spectrum
     469             : 
     470             : ! **************************************************************************************************
     471             : !> \brief  The total electronic density in reciprocal space (g-space) is
     472             : !>         calculated.
     473             : !> \param qs_env ...
     474             : !> \param auxbas_pw_pool ...
     475             : !> \param rhotot_elec_gspace ...
     476             : !> \param q_max ...
     477             : !> \param rho_hard ...
     478             : !> \param rho_soft ...
     479             : !> \param fsign ...
     480             : !> \date   14.03.2008 (splitted from the routine xray_diffraction_spectrum)
     481             : !> \author Matthias Krack
     482             : !> \note   This code assumes that the g-vectors are ordered (in gsq and %cc)
     483             : ! **************************************************************************************************
     484         108 :    SUBROUTINE calculate_rhotot_elec_gspace(qs_env, auxbas_pw_pool, &
     485             :                                            rhotot_elec_gspace, q_max, rho_hard, &
     486             :                                            rho_soft, fsign)
     487             : 
     488             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     489             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     490             :       TYPE(pw_c1d_gs_type), INTENT(INOUT)                :: rhotot_elec_gspace
     491             :       REAL(KIND=dp), INTENT(IN)                          :: q_max
     492             :       REAL(KIND=dp), INTENT(OUT)                         :: rho_hard, rho_soft
     493             :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: fsign
     494             : 
     495             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_rhotot_elec_gspace'
     496             : 
     497             :       INTEGER :: atom, handle, iatom, ico, ico1_pgf, ico1_set, ikind, ipgf, iset, iso, iso1_pgf, &
     498             :          iso1_set, ison, ispin, jco, jco1_pgf, jco1_set, jpgf, jset, jso, jso1_pgf, jso1_set, &
     499             :          json, la, lb, maxco, maxso, na, natom, nb, ncoa, ncob, ncotot, nkind, nsatbas, nset, &
     500             :          nsoa, nsob, nsotot, nspin
     501          36 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list, lmax, lmin, npgf, o2nindex
     502             :       LOGICAL                                            :: orthorhombic, paw_atom
     503             :       REAL(KIND=dp)                                      :: alpha, eps_rho_gspace, rho_total, scale, &
     504             :                                                             volume
     505             :       REAL(KIND=dp), DIMENSION(3)                        :: ra
     506          36 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: delta_cpc, pab, work, zet
     507          36 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     508             :       TYPE(cell_type), POINTER                           :: cell
     509             :       TYPE(dft_control_type), POINTER                    :: dft_control
     510             :       TYPE(gto_basis_set_type), POINTER                  :: basis_1c_set
     511          36 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     512             :       TYPE(pw_c1d_gs_type)                               :: rho_elec_gspace
     513          36 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
     514          36 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     515             :       TYPE(qs_rho_type), POINTER                         :: rho
     516          36 :       TYPE(rho_atom_coeff), DIMENSION(:), POINTER        :: cpc_h, cpc_s
     517          36 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho_atom_set
     518             :       TYPE(rho_atom_type), POINTER                       :: rho_atom
     519             : 
     520           0 :       CPASSERT(ASSOCIATED(qs_env))
     521          36 :       CPASSERT(ASSOCIATED(auxbas_pw_pool))
     522             : 
     523          36 :       CALL timeset(routineN, handle)
     524             : 
     525          36 :       NULLIFY (atom_list)
     526          36 :       NULLIFY (atomic_kind_set)
     527          36 :       NULLIFY (qs_kind_set)
     528          36 :       NULLIFY (cell)
     529          36 :       NULLIFY (cpc_h)
     530          36 :       NULLIFY (cpc_s)
     531          36 :       NULLIFY (delta_cpc)
     532          36 :       NULLIFY (dft_control)
     533          36 :       NULLIFY (lmax)
     534          36 :       NULLIFY (lmin)
     535          36 :       NULLIFY (npgf)
     536          36 :       NULLIFY (basis_1c_set)
     537          36 :       NULLIFY (pab)
     538          36 :       NULLIFY (particle_set)
     539          36 :       NULLIFY (rho, rho_r)
     540          36 :       NULLIFY (rho_atom)
     541          36 :       NULLIFY (rho_atom_set)
     542          36 :       NULLIFY (work)
     543          36 :       NULLIFY (zet)
     544             : 
     545             :       CALL get_qs_env(qs_env=qs_env, &
     546             :                       atomic_kind_set=atomic_kind_set, &
     547             :                       qs_kind_set=qs_kind_set, &
     548             :                       cell=cell, &
     549             :                       dft_control=dft_control, &
     550             :                       particle_set=particle_set, &
     551             :                       rho=rho, &
     552          36 :                       rho_atom_set=rho_atom_set)
     553             : 
     554          36 :       CALL qs_rho_get(rho, rho_r=rho_r)
     555          36 :       eps_rho_gspace = dft_control%qs_control%eps_rho_gspace
     556          36 :       nkind = SIZE(atomic_kind_set)
     557          36 :       nspin = dft_control%nspins
     558             : 
     559             :       ! Load the soft contribution of the electronic density
     560             : 
     561          36 :       CALL auxbas_pw_pool%create_pw(pw=rho_elec_gspace)
     562             : 
     563          36 :       CALL pw_zero(rhotot_elec_gspace)
     564             : 
     565          76 :       DO ispin = 1, nspin
     566          40 :          CALL pw_zero(rho_elec_gspace)
     567          40 :          CALL pw_transfer(rho_r(ispin), rho_elec_gspace)
     568          40 :          IF (PRESENT(fsign) .AND. (ispin == 2)) THEN
     569           2 :             alpha = fsign
     570             :          ELSE
     571          38 :             alpha = 1.0_dp
     572             :          END IF
     573          76 :          CALL pw_axpy(rho_elec_gspace, rhotot_elec_gspace, alpha=alpha)
     574             :       END DO
     575             : 
     576             :       ! Release the auxiliary PW grid for the calculation of the soft
     577             :       ! contribution
     578             : 
     579          36 :       CALL auxbas_pw_pool%give_back_pw(rho_elec_gspace)
     580             : 
     581          36 :       rho_soft = pw_integrate_function(rhotot_elec_gspace, isign=-1)
     582             : 
     583             :       CALL get_pw_grid_info(pw_grid=rhotot_elec_gspace%pw_grid, &
     584             :                             vol=volume, &
     585          36 :                             orthorhombic=orthorhombic)
     586          36 :       IF (.NOT. orthorhombic) THEN
     587             :          CALL cp_abort(__LOCATION__, &
     588           0 :                        "The calculation of XRD spectra for non-orthorhombic cells is not implemented")
     589             :       END IF
     590             : 
     591          36 :       CALL pw_scale(rhotot_elec_gspace, volume)
     592             : 
     593             :       ! Add the hard contribution of the electronic density
     594             : 
     595             :       ! Each process has to loop over all PAW atoms, since the g-space grid
     596             :       ! is already distributed over all processes
     597             : 
     598         104 :       DO ikind = 1, nkind
     599             : 
     600             :          CALL get_atomic_kind(atomic_kind_set(ikind), &
     601             :                               atom_list=atom_list, &
     602          68 :                               natom=natom)
     603             : 
     604             :          CALL get_qs_kind(qs_kind_set(ikind), &
     605             :                           basis_set=basis_1c_set, &
     606             :                           basis_type="GAPW_1C", &
     607          68 :                           paw_atom=paw_atom)
     608             : 
     609          68 :          IF (.NOT. paw_atom) CYCLE ! no PAW atom: nothing to do
     610             : 
     611          16 :          CALL get_paw_basis_info(basis_1c_set, o2nindex=o2nindex, nsatbas=nsatbas)
     612             : 
     613             :          CALL get_gto_basis_set(gto_basis_set=basis_1c_set, &
     614             :                                 lmax=lmax, &
     615             :                                 lmin=lmin, &
     616             :                                 maxco=maxco, &
     617             :                                 maxso=maxso, &
     618             :                                 npgf=npgf, &
     619             :                                 nset=nset, &
     620          16 :                                 zet=zet)
     621             : 
     622          16 :          ncotot = maxco*nset
     623          16 :          nsotot = maxso*nset
     624          16 :          CALL reallocate(delta_cpc, 1, nsatbas, 1, nsatbas)
     625          16 :          CALL reallocate(pab, 1, ncotot, 1, ncotot)
     626          16 :          CALL reallocate(work, 1, maxso, 1, maxco)
     627             : 
     628          40 :          DO iatom = 1, natom
     629             : 
     630          24 :             atom = atom_list(iatom)
     631          24 :             rho_atom => rho_atom_set(atom)
     632             : 
     633             :             CALL get_rho_atom(rho_atom=rho_atom, &
     634             :                               cpc_h=cpc_h, &
     635          24 :                               cpc_s=cpc_s)
     636             : 
     637          24 :             ra(:) = pbc(particle_set(iatom)%r, cell)
     638             : 
     639       12280 :             delta_cpc = 0.0_dp
     640             : 
     641          60 :             DO ispin = 1, nspin
     642          36 :                IF (PRESENT(fsign) .AND. (ispin == 2)) THEN
     643           6 :                   alpha = fsign
     644             :                ELSE
     645          30 :                   alpha = 1.0_dp
     646             :                END IF
     647       21388 :                delta_cpc = delta_cpc + alpha*(cpc_h(ispin)%r_coef - cpc_s(ispin)%r_coef)
     648             :             END DO
     649             : 
     650          24 :             scale = 1.0_dp
     651             : 
     652         120 :             DO iset = 1, nset
     653          80 :                ico1_set = (iset - 1)*maxco + 1
     654          80 :                iso1_set = (iset - 1)*maxso + 1
     655          80 :                ncoa = ncoset(lmax(iset))
     656          80 :                nsoa = nsoset(lmax(iset))
     657         392 :                DO jset = 1, nset
     658         288 :                   jco1_set = (jset - 1)*maxco + 1
     659         288 :                   jso1_set = (jset - 1)*maxso + 1
     660         288 :                   ncob = ncoset(lmax(jset))
     661         288 :                   nsob = nsoset(lmax(jset))
     662        1136 :                   DO ipgf = 1, npgf(iset)
     663         768 :                      ico1_pgf = ico1_set + (ipgf - 1)*ncoa
     664         768 :                      iso1_pgf = iso1_set + (ipgf - 1)*nsoa
     665        3120 :                      DO jpgf = 1, npgf(jset)
     666        2064 :                         jco1_pgf = jco1_set + (jpgf - 1)*ncob
     667        2064 :                         jso1_pgf = jso1_set + (jpgf - 1)*nsob
     668        2064 :                         ico = ico1_pgf + ncoset(lmin(iset) - 1)
     669        2064 :                         iso = iso1_pgf + nsoset(lmin(iset) - 1)
     670             : 
     671             :                         ! Transformation spherical to Cartesian
     672             : 
     673        4832 :                         DO la = lmin(iset), lmax(iset)
     674        2768 :                            jco = jco1_pgf + ncoset(lmin(jset) - 1)
     675        2768 :                            jso = jso1_pgf + nsoset(lmin(jset) - 1)
     676        6496 :                            DO lb = lmin(jset), lmax(jset)
     677        3728 :                               ison = o2nindex(iso)
     678        3728 :                               json = o2nindex(jso)
     679             :                               CALL dgemm("N", "N", nso(la), nco(lb), nso(lb), 1.0_dp, &
     680             :                                          delta_cpc(ison:ison + nso(la) - 1, json), SIZE(delta_cpc, 1), &
     681             :                                          orbtramat(lb)%slm, nso(lb), 0.0_dp, work, &
     682        3728 :                                          maxso)
     683             :                               CALL dgemm("T", "N", nco(la), nco(lb), nso(la), 1.0_dp, &
     684             :                                          orbtramat(la)%slm, nso(la), work, maxso, &
     685        3728 :                                          0.0_dp, pab(ico:ico + nco(la) - 1, jco), SIZE(pab, 1))
     686        3728 :                               jco = jco + nco(lb)
     687        6496 :                               jso = jso + nso(lb)
     688             :                            END DO ! next lb
     689        2768 :                            ico = ico + nco(la)
     690        4832 :                            iso = iso + nso(la)
     691             :                         END DO ! next la
     692             : 
     693             :                         ! Collocate current product of primitive Cartesian functions
     694             : 
     695        2064 :                         na = ico1_pgf - 1
     696        2064 :                         nb = jco1_pgf - 1
     697             : 
     698             :                         CALL collocate_pgf_product_gspace( &
     699             :                            la_max=lmax(iset), &
     700             :                            zeta=zet(ipgf, iset), &
     701             :                            la_min=lmin(iset), &
     702             :                            lb_max=lmax(jset), &
     703             :                            zetb=zet(jpgf, jset), &
     704             :                            lb_min=lmin(jset), &
     705             :                            ra=ra, &
     706             :                            rab=(/0.0_dp, 0.0_dp, 0.0_dp/), &
     707             :                            rab2=0.0_dp, &
     708             :                            scale=scale, &
     709             :                            pab=pab, &
     710             :                            na=na, &
     711             :                            nb=nb, &
     712             :                            eps_rho_gspace=eps_rho_gspace, &
     713             :                            gsq_max=q_max*q_max, &
     714        2832 :                            pw=rhotot_elec_gspace)
     715             : 
     716             :                      END DO ! next primitive Gaussian function "jpgf"
     717             :                   END DO ! next primitive Gaussian function "ipgf"
     718             :                END DO ! next shell set "jset"
     719             :             END DO ! next shell set "iset"
     720             :          END DO ! next atom "iatom" of atomic kind "ikind"
     721         136 :          DEALLOCATE (o2nindex)
     722             :       END DO ! next atomic kind "ikind"
     723             : 
     724          36 :       rho_total = pw_integrate_function(rhotot_elec_gspace, isign=-1)/volume
     725             : 
     726          36 :       rho_hard = rho_total - rho_soft
     727             : 
     728             :       ! Release work storage
     729             : 
     730          36 :       IF (ASSOCIATED(delta_cpc)) THEN
     731           8 :          DEALLOCATE (delta_cpc)
     732             :       END IF
     733             : 
     734          36 :       IF (ASSOCIATED(work)) THEN
     735           8 :          DEALLOCATE (work)
     736             :       END IF
     737             : 
     738          36 :       IF (ASSOCIATED(pab)) THEN
     739           8 :          DEALLOCATE (pab)
     740             :       END IF
     741             : 
     742          36 :       CALL timestop(handle)
     743             : 
     744          36 :    END SUBROUTINE calculate_rhotot_elec_gspace
     745             : 
     746             : ! **************************************************************************************************
     747             : !> \brief low level collocation of primitive gaussian functions in g-space
     748             : !> \param la_max ...
     749             : !> \param zeta ...
     750             : !> \param la_min ...
     751             : !> \param lb_max ...
     752             : !> \param zetb ...
     753             : !> \param lb_min ...
     754             : !> \param ra ...
     755             : !> \param rab ...
     756             : !> \param rab2 ...
     757             : !> \param scale ...
     758             : !> \param pab ...
     759             : !> \param na ...
     760             : !> \param nb ...
     761             : !> \param eps_rho_gspace ...
     762             : !> \param gsq_max ...
     763             : !> \param pw ...
     764             : ! **************************************************************************************************
     765        2064 :    SUBROUTINE collocate_pgf_product_gspace(la_max, zeta, la_min, &
     766             :                                            lb_max, zetb, lb_min, &
     767             :                                            ra, rab, rab2, scale, pab, na, nb, &
     768             :                                            eps_rho_gspace, gsq_max, pw)
     769             : 
     770             :       ! NOTE: this routine is much slower than the real-space version of collocate_pgf_product
     771             : 
     772             :       INTEGER, INTENT(IN)                                :: la_max
     773             :       REAL(dp), INTENT(IN)                               :: zeta
     774             :       INTEGER, INTENT(IN)                                :: la_min, lb_max
     775             :       REAL(dp), INTENT(IN)                               :: zetb
     776             :       INTEGER, INTENT(IN)                                :: lb_min
     777             :       REAL(dp), DIMENSION(3), INTENT(IN)                 :: ra, rab
     778             :       REAL(dp), INTENT(IN)                               :: rab2, scale
     779             :       REAL(dp), DIMENSION(:, :), POINTER                 :: pab
     780             :       INTEGER, INTENT(IN)                                :: na, nb
     781             :       REAL(dp), INTENT(IN)                               :: eps_rho_gspace, gsq_max
     782             :       TYPE(pw_c1d_gs_type), INTENT(IN)                   :: pw
     783             : 
     784             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'collocate_pgf_product_gspace'
     785             : 
     786             :       COMPLEX(dp), DIMENSION(3)                          :: phasefactor
     787        2064 :       COMPLEX(dp), DIMENSION(:), POINTER                 :: rag, rbg
     788        2064 :       COMPLEX(dp), DIMENSION(:, :, :, :), POINTER        :: cubeaxis
     789             :       INTEGER                                            :: ax, ay, az, bx, by, bz, handle, i, ico, &
     790             :                                                             ig, ig2, jco, jg, kg, la, lb, &
     791             :                                                             lb_cube_min, lb_grid, ub_cube_max, &
     792             :                                                             ub_grid
     793             :       INTEGER, DIMENSION(3)                              :: lb_cube, ub_cube
     794             :       REAL(dp)                                           :: f, fa, fb, pij, prefactor, rzetp, &
     795             :                                                             twozetp, zetp
     796             :       REAL(dp), DIMENSION(3)                             :: dg, expfactor, fap, fbp, rap, rbp, rp
     797        2064 :       REAL(dp), DIMENSION(:), POINTER                    :: g
     798             : 
     799        2064 :       CALL timeset(routineN, handle)
     800             : 
     801        8256 :       dg(:) = twopi/(pw%pw_grid%npts(:)*pw%pw_grid%dr(:))
     802             : 
     803        2064 :       zetp = zeta + zetb
     804        2064 :       rzetp = 1.0_dp/zetp
     805        2064 :       f = zetb*rzetp
     806        8256 :       rap(:) = f*rab(:)
     807        8256 :       rbp(:) = rap(:) - rab(:)
     808        8256 :       rp(:) = ra(:) + rap(:)
     809        2064 :       twozetp = 2.0_dp*zetp
     810        8256 :       fap(:) = twozetp*rap(:)
     811        8256 :       fbp(:) = twozetp*rbp(:)
     812             : 
     813        2064 :       prefactor = scale*SQRT((pi*rzetp)**3)*EXP(-zeta*f*rab2)
     814        8256 :       phasefactor(:) = EXP(CMPLX(0.0_dp, -rp(:)*dg(:), KIND=dp))
     815        8256 :       expfactor(:) = EXP(-0.25*rzetp*dg(:)*dg(:))
     816             : 
     817        8256 :       lb_cube(:) = pw%pw_grid%bounds(1, :)
     818        8256 :       ub_cube(:) = pw%pw_grid%bounds(2, :)
     819             : 
     820        8256 :       lb_cube_min = MINVAL(lb_cube(:))
     821        8256 :       ub_cube_max = MAXVAL(ub_cube(:))
     822             : 
     823        2064 :       NULLIFY (cubeaxis, g, rag, rbg)
     824             : 
     825        2064 :       CALL reallocate(cubeaxis, lb_cube_min, ub_cube_max, 1, 3, 0, la_max, 0, lb_max)
     826        2064 :       CALL reallocate(g, lb_cube_min, ub_cube_max)
     827        2064 :       CALL reallocate(rag, lb_cube_min, ub_cube_max)
     828        2064 :       CALL reallocate(rbg, lb_cube_min, ub_cube_max)
     829             : 
     830        2064 :       lb_grid = LBOUND(pw%array, 1)
     831        2064 :       ub_grid = UBOUND(pw%array, 1)
     832             : 
     833        8256 :       DO i = 1, 3
     834             : 
     835      340560 :          DO ig = lb_cube(i), ub_cube(i)
     836      334368 :             ig2 = ig*ig
     837      340560 :             cubeaxis(ig, i, 0, 0) = expfactor(i)**ig2*phasefactor(i)**ig
     838             :          END DO
     839             : 
     840        8256 :          IF (la_max > 0) THEN
     841      145200 :             DO ig = lb_cube(i), ub_cube(i)
     842      142560 :                g(ig) = REAL(ig, dp)*dg(i)
     843      142560 :                rag(ig) = CMPLX(fap(i), -g(ig), KIND=dp)
     844      145200 :                cubeaxis(ig, i, 1, 0) = rag(ig)*cubeaxis(ig, i, 0, 0)
     845             :             END DO
     846        3168 :             DO la = 2, la_max
     847         528 :                fa = REAL(la - 1, dp)*twozetp
     848       31680 :                DO ig = lb_cube(i), ub_cube(i)
     849             :                   cubeaxis(ig, i, la, 0) = rag(ig)*cubeaxis(ig, i, la - 1, 0) + &
     850       29040 :                                            fa*cubeaxis(ig, i, la - 2, 0)
     851             :                END DO
     852             :             END DO
     853        2640 :             IF (lb_max > 0) THEN
     854       66000 :                fa = twozetp
     855       66000 :                DO ig = lb_cube(i), ub_cube(i)
     856       64800 :                   rbg(ig) = CMPLX(fbp(i), -g(ig), KIND=dp)
     857       64800 :                   cubeaxis(ig, i, 0, 1) = rbg(ig)*cubeaxis(ig, i, 0, 0)
     858             :                   cubeaxis(ig, i, 1, 1) = rbg(ig)*cubeaxis(ig, i, 1, 0) + &
     859       66000 :                                           fa*cubeaxis(ig, i, 0, 0)
     860             :                END DO
     861        1440 :                DO lb = 2, lb_max
     862         240 :                   fb = REAL(lb - 1, dp)*twozetp
     863       14400 :                   DO ig = lb_cube(i), ub_cube(i)
     864             :                      cubeaxis(ig, i, 0, lb) = rbg(ig)*cubeaxis(ig, i, 0, lb - 1) + &
     865       12960 :                                               fb*cubeaxis(ig, i, 0, lb - 2)
     866             :                      cubeaxis(ig, i, 1, lb) = rbg(ig)*cubeaxis(ig, i, 1, lb - 1) + &
     867             :                                               fb*cubeaxis(ig, i, 1, lb - 2) + &
     868       13200 :                                               fa*cubeaxis(ig, i, 0, lb - 1)
     869             :                   END DO
     870             :                END DO
     871        1440 :                DO la = 2, la_max
     872         240 :                   fa = REAL(la, dp)*twozetp
     873       13200 :                   DO ig = lb_cube(i), ub_cube(i)
     874             :                      cubeaxis(ig, i, la, 1) = rbg(ig)*cubeaxis(ig, i, la, 0) + &
     875       13200 :                                               fa*cubeaxis(ig, i, la - 1, 0)
     876             :                   END DO
     877        1488 :                   DO lb = 2, lb_max
     878          48 :                      fb = REAL(lb - 1, dp)*twozetp
     879        2880 :                      DO ig = lb_cube(i), ub_cube(i)
     880             :                         cubeaxis(ig, i, la, lb) = rbg(ig)*cubeaxis(ig, i, la, lb - 1) + &
     881             :                                                   fb*cubeaxis(ig, i, la, lb - 2) + &
     882        2640 :                                                   fa*cubeaxis(ig, i, la - 1, lb - 1)
     883             :                      END DO
     884             :                   END DO
     885             :                END DO
     886             :             END IF
     887             :          ELSE
     888        3552 :             IF (lb_max > 0) THEN
     889       79200 :                DO ig = lb_cube(i), ub_cube(i)
     890       77760 :                   g(ig) = REAL(ig, dp)*dg(i)
     891       77760 :                   rbg(ig) = CMPLX(fbp(i), -g(ig), KIND=dp)
     892       79200 :                   cubeaxis(ig, i, 0, 1) = rbg(ig)*cubeaxis(ig, i, 0, 0)
     893             :                END DO
     894        1728 :                DO lb = 2, lb_max
     895         288 :                   fb = REAL(lb - 1, dp)*twozetp
     896       17280 :                   DO ig = lb_cube(i), ub_cube(i)
     897             :                      cubeaxis(ig, i, 0, lb) = rbg(ig)*cubeaxis(ig, i, 0, lb - 1) + &
     898       15840 :                                               fb*cubeaxis(ig, i, 0, lb - 2)
     899             :                   END DO
     900             :                END DO
     901             :             END IF
     902             :          END IF
     903             : 
     904             :       END DO
     905             : 
     906        5184 :       DO la = 0, la_max
     907        9936 :          DO lb = 0, lb_max
     908        4752 :             IF (la + lb == 0) CYCLE
     909        2688 :             fa = (1.0_dp/twozetp)**(la + lb)
     910       13872 :             DO i = 1, 3
     911      448272 :                DO ig = lb_cube(i), ub_cube(i)
     912      443520 :                   cubeaxis(ig, i, la, lb) = fa*cubeaxis(ig, i, la, lb)
     913             :                END DO
     914             :             END DO
     915             :          END DO
     916             :       END DO
     917             : 
     918             :       ! Add the current primitive Gaussian function product to grid
     919             : 
     920        7120 :       DO ico = ncoset(la_min - 1) + 1, ncoset(la_max)
     921             : 
     922        5056 :          ax = indco(1, ico)
     923        5056 :          ay = indco(2, ico)
     924        5056 :          az = indco(3, ico)
     925             : 
     926       19792 :          DO jco = ncoset(lb_min - 1) + 1, ncoset(lb_max)
     927             : 
     928       12672 :             pij = prefactor*pab(na + ico, nb + jco)
     929             : 
     930       12672 :             IF (ABS(pij) < eps_rho_gspace) CYCLE
     931             : 
     932        4916 :             bx = indco(1, jco)
     933        4916 :             by = indco(2, jco)
     934        4916 :             bz = indco(3, jco)
     935             : 
     936   387056484 :             DO i = lb_grid, ub_grid
     937   387046512 :                IF (pw%pw_grid%gsq(i) > gsq_max) CYCLE
     938   346285458 :                ig = pw%pw_grid%g_hat(1, i)
     939   346285458 :                jg = pw%pw_grid%g_hat(2, i)
     940   346285458 :                kg = pw%pw_grid%g_hat(3, i)
     941             :                pw%array(i) = pw%array(i) + pij*cubeaxis(ig, 1, ax, bx)* &
     942             :                              cubeaxis(jg, 2, ay, by)* &
     943   387059184 :                              cubeaxis(kg, 3, az, bz)
     944             :             END DO
     945             : 
     946             :          END DO
     947             : 
     948             :       END DO
     949             : 
     950        2064 :       DEALLOCATE (cubeaxis)
     951        2064 :       DEALLOCATE (g)
     952        2064 :       DEALLOCATE (rag)
     953        2064 :       DEALLOCATE (rbg)
     954             : 
     955        2064 :       CALL timestop(handle)
     956             : 
     957        2064 :    END SUBROUTINE collocate_pgf_product_gspace
     958             : 
     959             : END MODULE xray_diffraction

Generated by: LCOV version 1.15