LCOV - code coverage report
Current view: top level - src/pw - pw_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 70.8 % 503 356
Test Date: 2025-12-04 06:27:48 Functions: 20.6 % 199 41

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \note
      10              : !>      If parallel mode is distributed certain combination of
      11              : !>      "in_use" and "in_space" can not be used.
      12              : !>      For performance reasons it would be better to have the loops
      13              : !>      over g-vectors in the gather/scatter routines in new subprograms
      14              : !>      with the actual arrays (also the addressing) in the parameter list
      15              : !> \par History
      16              : !>      JGH (29-Dec-2000) : Changes for parallel use
      17              : !>      JGH (13-Mar-2001) : added timing calls
      18              : !>      JGH (26-Feb-2003) : OpenMP enabled
      19              : !>      JGH (17-Nov-2007) : Removed mass arrays
      20              : !>      JGH (01-Dec-2007) : Removed and renamed routines
      21              : !>      JGH (04-Jul-2019) : added pw_multiply routine
      22              : !>      03.2008 [tlaino] : Splitting pw_types into pw_types and pw_methods
      23              : !> \author apsi
      24              : ! **************************************************************************************************
      25              : MODULE pw_methods
      26              :    #:include "pw_types.fypp"
      27              :    USE cp_log_handling, ONLY: cp_logger_get_default_io_unit, &
      28              :                               cp_to_string
      29              :    USE fft_tools, ONLY: BWFFT, &
      30              :                         FWFFT, &
      31              :                         fft3d
      32              :    USE kahan_sum, ONLY: accurate_dot_product, &
      33              :                         accurate_sum
      34              :    USE kinds, ONLY: dp
      35              :    USE machine, ONLY: m_memory
      36              :    USE mathconstants, ONLY: gaussi, &
      37              :                             z_zero
      38              :    USE pw_copy_all, ONLY: pw_copy_match
      39              :    USE pw_fpga, ONLY: pw_fpga_c1dr3d_3d_dp, &
      40              :                       pw_fpga_c1dr3d_3d_sp, &
      41              :                       pw_fpga_init_bitstream, &
      42              :                       pw_fpga_r3dc1d_3d_dp, &
      43              :                       pw_fpga_r3dc1d_3d_sp
      44              :    USE pw_gpu, ONLY: pw_gpu_c1dr3d_3d, &
      45              :                      pw_gpu_c1dr3d_3d_ps, &
      46              :                      pw_gpu_r3dc1d_3d, &
      47              :                      pw_gpu_r3dc1d_3d_ps
      48              :    USE pw_grid_types, ONLY: HALFSPACE, &
      49              :                             PW_MODE_DISTRIBUTED, &
      50              :                             PW_MODE_LOCAL, &
      51              :                             pw_grid_type
      52              :    #:for space in pw_spaces
      53              :       #:for kind in pw_kinds
      54              :          USE pw_types, ONLY: pw_${kind}$_${space}$_type
      55              :       #:endfor
      56              :    #:endfor
      57              : #include "../base/base_uses.f90"
      58              : 
      59              :    IMPLICIT NONE
      60              : 
      61              :    PRIVATE
      62              : 
      63              :    PUBLIC :: pw_zero, pw_structure_factor, pw_smoothing
      64              :    PUBLIC :: pw_copy, pw_axpy, pw_transfer, pw_scale
      65              :    PUBLIC :: pw_gauss_damp, pw_compl_gauss_damp, pw_derive, pw_laplace, pw_dr2, pw_write, pw_multiply
      66              :    PUBLIC :: pw_log_deriv_gauss, pw_log_deriv_compl_gauss, pw_log_deriv_mix_cl, pw_log_deriv_trunc
      67              :    PUBLIC :: pw_gauss_damp_mix, pw_multiply_with
      68              :    PUBLIC :: pw_integral_ab, pw_integral_a2b
      69              :    PUBLIC :: pw_dr2_gg, pw_integrate_function
      70              :    PUBLIC :: pw_set, pw_truncated
      71              :    PUBLIC :: pw_scatter, pw_gather
      72              :    PUBLIC :: pw_copy_to_array, pw_copy_from_array
      73              : 
      74              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pw_methods'
      75              :    LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE.
      76              :    INTEGER, PARAMETER, PUBLIC  ::  do_accurate_sum = 0, &
      77              :                                   do_standard_sum = 1
      78              : 
      79              :    INTERFACE pw_zero
      80              :       #:for space in pw_spaces
      81              :          #:for kind in pw_kinds
      82              :             MODULE PROCEDURE pw_zero_${kind}$_${space}$
      83              :          #:endfor
      84              :       #:endfor
      85              :    END INTERFACE
      86              : 
      87              :    INTERFACE pw_scale
      88              :       #:for space in pw_spaces
      89              :          #:for kind in pw_kinds
      90              :             MODULE PROCEDURE pw_scale_${kind}$_${space}$
      91              :          #:endfor
      92              :       #:endfor
      93              :    END INTERFACE
      94              : 
      95              :    INTERFACE pw_write
      96              :       #:for space in pw_spaces
      97              :          #:for kind in pw_kinds
      98              :             MODULE PROCEDURE pw_write_${kind}$_${space}$
      99              :          #:endfor
     100              :       #:endfor
     101              :    END INTERFACE
     102              : 
     103              :    INTERFACE pw_integrate_function
     104              :       #:for space in pw_spaces
     105              :          #:for kind in pw_kinds
     106              :             MODULE PROCEDURE pw_integrate_function_${kind}$_${space}$
     107              :          #:endfor
     108              :       #:endfor
     109              :    END INTERFACE
     110              : 
     111              :    INTERFACE pw_set
     112              :       #:for space in pw_spaces
     113              :          #:for kind in pw_kinds
     114              :             MODULE PROCEDURE pw_set_value_${kind}$_${space}$
     115              :             MODULE PROCEDURE pw_zero_${kind}$_${space}$
     116              :          #:endfor
     117              :       #:endfor
     118              :    END INTERFACE
     119              : 
     120              :    INTERFACE pw_copy
     121              :       #:for space in pw_spaces
     122              :          #:for kind, kind2 in pw_kinds2_sameD
     123              :             MODULE PROCEDURE pw_copy_${kind}$_${kind2}$_${space}$
     124              :          #:endfor
     125              :       #:endfor
     126              :    END INTERFACE
     127              : 
     128              :    INTERFACE pw_axpy
     129              :       #:for space in pw_spaces
     130              :          #:for kind, kind2 in pw_kinds2_sameD
     131              :             MODULE PROCEDURE pw_axpy_${kind}$_${kind2}$_${space}$
     132              :          #:endfor
     133              :       #:endfor
     134              :    END INTERFACE
     135              : 
     136              :    INTERFACE pw_multiply
     137              :       #:for space in pw_spaces
     138              :          #:for kind, kind2 in pw_kinds2_sameD
     139              :             MODULE PROCEDURE pw_multiply_${kind}$_${kind2}$_${space}$
     140              :          #:endfor
     141              :       #:endfor
     142              :    END INTERFACE
     143              : 
     144              :    INTERFACE pw_multiply_with
     145              :       #:for space in pw_spaces
     146              :          #:for kind, kind2 in pw_kinds2_sameD
     147              :             MODULE PROCEDURE pw_multiply_with_${kind}$_${kind2}$_${space}$
     148              :          #:endfor
     149              :       #:endfor
     150              :    END INTERFACE
     151              : 
     152              :    INTERFACE pw_integral_ab
     153              :       #:for space in pw_spaces
     154              :          #:for kind, kind2 in pw_kinds2_sameD
     155              :             MODULE PROCEDURE pw_integral_ab_${kind}$_${kind2}$_${space}$
     156              :          #:endfor
     157              :       #:endfor
     158              :    END INTERFACE
     159              : 
     160              :    INTERFACE pw_integral_a2b
     161              :       #:for kind, kind2 in pw_kinds2_sameD
     162              :          #:if kind[1]=="1"
     163              :             MODULE PROCEDURE pw_integral_a2b_${kind}$_${kind2}$
     164              :          #:endif
     165              :       #:endfor
     166              :    END INTERFACE
     167              : 
     168              :    INTERFACE pw_gather
     169              :       #:for kind in pw_kinds
     170              :          #:if kind[1]=="1"
     171              :             MODULE PROCEDURE pw_gather_p_${kind}$
     172              :          #:endif
     173              :       #:endfor
     174              :       #:for kind, kind2 in pw_kinds2
     175              :          #:if kind[1]=="1" and kind2[1]=="3"
     176              :             MODULE PROCEDURE pw_gather_s_${kind}$_${kind2}$
     177              :          #:endif
     178              :       #:endfor
     179              :    END INTERFACE
     180              : 
     181              :    INTERFACE pw_scatter
     182              :       #:for kind in pw_kinds
     183              :          #:if kind[1]=="1"
     184              :             MODULE PROCEDURE pw_scatter_p_${kind}$
     185              :          #:endif
     186              :       #:endfor
     187              :       #:for kind, kind2 in pw_kinds2
     188              :          #:if kind[1]=="1" and kind2[1]=="3"
     189              :             MODULE PROCEDURE pw_scatter_s_${kind}$_${kind2}$
     190              :          #:endif
     191              :       #:endfor
     192              :    END INTERFACE
     193              : 
     194              :    INTERFACE pw_copy_to_array
     195              :       #:for space in pw_spaces
     196              :          #:for kind, kind2 in pw_kinds2_sameD
     197              :             MODULE PROCEDURE pw_copy_to_array_${kind}$_${kind2}$_${space}$
     198              :          #:endfor
     199              :       #:endfor
     200              :    END INTERFACE
     201              : 
     202              :    INTERFACE pw_copy_from_array
     203              :       #:for space in pw_spaces
     204              :          #:for kind, kind2 in pw_kinds2_sameD
     205              :             MODULE PROCEDURE pw_copy_from_array_${kind}$_${kind2}$_${space}$
     206              :          #:endfor
     207              :       #:endfor
     208              :    END INTERFACE
     209              : 
     210              :    INTERFACE pw_transfer
     211              :       #:for kind, kind2 in pw_kinds2
     212              :          #:if kind[1]=="1" and kind2[1]=="3"
     213              :             MODULE PROCEDURE pw_gather_s_${kind}$_${kind2}$_2
     214              :             MODULE PROCEDURE pw_scatter_s_${kind}$_${kind2}$_2
     215              :          #:endif
     216              :          #:for space in pw_spaces
     217              :             #:if kind[1]==kind2[1]
     218              :                MODULE PROCEDURE pw_copy_${kind}$_${kind2}$_${space}$
     219              :             #:endif
     220              :          #:endfor
     221              :          #:if kind2[0]=="c" and kind[1]=="3"
     222              :             MODULE PROCEDURE fft_wrap_pw1pw2_${kind}$_${kind2}$_rs_gs
     223              :          #:endif
     224              :          #:if kind[0]=="c" and kind2[1]=="3"
     225              :             MODULE PROCEDURE fft_wrap_pw1pw2_${kind}$_${kind2}$_gs_rs
     226              :          #:endif
     227              :       #:endfor
     228              :    END INTERFACE
     229              : 
     230              : CONTAINS
     231              :    #:for kind, type in pw_list
     232              :       #:for space in pw_spaces
     233              : ! **************************************************************************************************
     234              : !> \brief Set values of a pw type to zero
     235              : !> \param pw ...
     236              : !> \par History
     237              : !>      none
     238              : !> \author apsi
     239              : ! **************************************************************************************************
     240      1167187 :          SUBROUTINE pw_zero_${kind}$_${space}$ (pw)
     241              : 
     242              :             TYPE(pw_${kind}$_${space}$_type), INTENT(INOUT)                       :: pw
     243              : 
     244              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_zero'
     245              : 
     246              :             INTEGER                                            :: handle
     247              : 
     248      1167187 :             CALL timeset(routineN, handle)
     249              : 
     250              : #if !defined(__INTEL_LLVM_COMPILER) || (20250000 <= __INTEL_LLVM_COMPILER)
     251      1167187 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw)
     252              :             pw%array = ${type2type("0.0_dp", "r3d", kind)}$
     253              : !$OMP END PARALLEL WORKSHARE
     254              : #else
     255              :             pw%array = ${type2type("0.0_dp", "r3d", kind)}$
     256              : #endif
     257              : 
     258      1167187 :             CALL timestop(handle)
     259              : 
     260      1167187 :          END SUBROUTINE pw_zero_${kind}$_${space}$
     261              : 
     262              : ! **************************************************************************************************
     263              : !> \brief multiplies pw coeffs with a number
     264              : !> \param pw ...
     265              : !> \param a ...
     266              : !> \par History
     267              : !>      11.2004 created [Joost VandeVondele]
     268              : ! **************************************************************************************************
     269       479467 :          SUBROUTINE pw_scale_${kind}$_${space}$ (pw, a)
     270              : 
     271              :             TYPE(pw_${kind}$_${space}$_type), INTENT(INOUT)                       :: pw
     272              :             REAL(KIND=dp), INTENT(IN)                          :: a
     273              : 
     274              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_scale'
     275              : 
     276              :             INTEGER                                            :: handle
     277              : 
     278       479467 :             CALL timeset(routineN, handle)
     279              : 
     280       479467 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(A, pw)
     281              :             pw%array = a*pw%array
     282              : !$OMP END PARALLEL WORKSHARE
     283              : 
     284       479467 :             CALL timestop(handle)
     285              : 
     286       479467 :          END SUBROUTINE pw_scale_${kind}$_${space}$
     287              : 
     288              : ! **************************************************************************************************
     289              : !> \brief writes a small description of the actual grid
     290              : !>      (change to output the data as cube file, maybe with an
     291              : !>      optional long_description arg?)
     292              : !> \param pw the pw data to output
     293              : !> \param unit_nr the unit to output to
     294              : !> \par History
     295              : !>      08.2002 created [fawzi]
     296              : !> \author Fawzi Mohamed
     297              : ! **************************************************************************************************
     298            0 :          SUBROUTINE pw_write_${kind}$_${space}$ (pw, unit_nr)
     299              : 
     300              :             TYPE(pw_${kind}$_${space}$_type), INTENT(in)                          :: pw
     301              :             INTEGER, INTENT(in)                                :: unit_nr
     302              : 
     303              :             INTEGER                                            :: iostatus
     304              : 
     305            0 :             WRITE (unit=unit_nr, fmt="('<pw>:{ ')", iostat=iostatus)
     306              : 
     307            0 :             WRITE (unit=unit_nr, fmt="(a)", iostat=iostatus) " in_use=${kind}$"
     308            0 :             IF (ASSOCIATED(pw%array)) THEN
     309              :                #:if kind[1]=='1'
     310              :                   WRITE (unit=unit_nr, fmt="(' array=<${kind[0]}$(',i8,':',i8,')>')") &
     311            0 :                      LBOUND(pw%array, 1), UBOUND(pw%array, 1)
     312              :                #:else
     313              :                   WRITE (unit=unit_nr, fmt="(' array=<${kind[0]}$(',i8,':',i8,',',i8,':',i8,',',i8,':',i8,')>')") &
     314            0 :                      LBOUND(pw%array, 1), UBOUND(pw%array, 1), LBOUND(pw%array, 2), UBOUND(pw%array, 2), &
     315            0 :                      LBOUND(pw%array, 3), UBOUND(pw%array, 3)
     316              :                #:endif
     317              :             ELSE
     318            0 :                WRITE (unit=unit_nr, fmt="(' array=*null*')")
     319              :             END IF
     320              : 
     321            0 :          END SUBROUTINE pw_write_${kind}$_${space}$
     322              : 
     323              : ! **************************************************************************************************
     324              : !> \brief ...
     325              : !> \param fun ...
     326              : !> \param isign ...
     327              : !> \param oprt ...
     328              : !> \return ...
     329              : ! **************************************************************************************************
     330       456760 :          FUNCTION pw_integrate_function_${kind}$_${space}$ (fun, isign, oprt) RESULT(total_fun)
     331              : 
     332              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: fun
     333              :             INTEGER, INTENT(IN), OPTIONAL                      :: isign
     334              :             CHARACTER(len=*), INTENT(IN), OPTIONAL             :: oprt
     335              :             REAL(KIND=dp)                                      :: total_fun
     336              : 
     337              :             INTEGER                                            :: iop
     338              : 
     339       456760 :             iop = 0
     340              : 
     341       456760 :             IF (PRESENT(oprt)) THEN
     342              :                SELECT CASE (oprt)
     343              :                CASE ("ABS", "abs")
     344            0 :                   iop = 1
     345              :                CASE DEFAULT
     346         2056 :                   CPABORT("Unknown operator")
     347              :                END SELECT
     348              :             END IF
     349              : 
     350       110463 :             total_fun = 0.0_dp
     351              : 
     352              :             #:if space == "rs"
     353              :                ! do reduction using maximum accuracy
     354              :                IF (iop == 1) THEN
     355    106814718 :                   total_fun = fun%pw_grid%dvol*accurate_sum(ABS(fun%array))
     356              :                ELSE
     357       344241 :                   total_fun = fun%pw_grid%dvol*accurate_sum(${type2type("fun%array", kind, "r1d")}$)
     358              :                END IF
     359              :             #:elif space == "gs"
     360              :                IF (iop == 1) &
     361            0 :                   CPABORT("Operator ABS not implemented")
     362              :                #:if kind[1:]=="1d"
     363       110463 :                   IF (fun%pw_grid%have_g0) total_fun = fun%pw_grid%vol*${type2type("fun%array(1)", kind, "r1d")}$
     364              :                #:else
     365            0 :                   CPABORT("Reciprocal space integration for 3D grids not implemented!")
     366              :                #:endif
     367              :             #:else
     368              :                CPABORT("No space defined")
     369              :             #:endif
     370              : 
     371       456760 :             IF (fun%pw_grid%para%mode /= PW_MODE_LOCAL) THEN
     372       451192 :                CALL fun%pw_grid%para%group%sum(total_fun)
     373              :             END IF
     374              : 
     375       456760 :             IF (PRESENT(isign)) THEN
     376       334117 :                total_fun = total_fun*SIGN(1._dp, REAL(isign, dp))
     377              :             END IF
     378              : 
     379       456760 :          END FUNCTION pw_integrate_function_${kind}$_${space}$
     380              : 
     381              : ! **************************************************************************************************
     382              : !> \brief ...
     383              : !> \param pw ...
     384              : !> \param value ...
     385              : ! **************************************************************************************************
     386          118 :          SUBROUTINE pw_set_value_${kind}$_${space}$ (pw, value)
     387              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw
     388              :             REAL(KIND=dp), INTENT(IN)                          :: value
     389              : 
     390              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_set_value'
     391              : 
     392              :             INTEGER                                            :: handle
     393              : 
     394          118 :             CALL timeset(routineN, handle)
     395              : 
     396          118 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw,value)
     397              :             pw%array = ${type2type("value", "r3d", kind)}$
     398              : !$OMP END PARALLEL WORKSHARE
     399              : 
     400          118 :             CALL timestop(handle)
     401              : 
     402          118 :          END SUBROUTINE pw_set_value_${kind}$_${space}$
     403              :       #:endfor
     404              : 
     405              :       #:if kind[1]=="1"
     406              : ! **************************************************************************************************
     407              : !> \brief ...
     408              : !> \param pw ...
     409              : !> \param c ...
     410              : !> \param scale ...
     411              : ! **************************************************************************************************
     412      1399888 :          SUBROUTINE pw_gather_p_${kind}$ (pw, c, scale)
     413              : 
     414              :             TYPE(pw_${kind}$_gs_type), INTENT(INOUT)                       :: pw
     415              :             COMPLEX(KIND=dp), DIMENSION(:, :), CONTIGUOUS, INTENT(IN)      :: c
     416              :             REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
     417              : 
     418              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_gather_p'
     419              : 
     420              :             INTEGER                                            :: gpt, handle, l, m, mn, n
     421              : 
     422      1399888 :             CALL timeset(routineN, handle)
     423              : 
     424      1399888 :             IF (pw%pw_grid%para%mode /= PW_MODE_DISTRIBUTED) THEN
     425            0 :                CPABORT("This grid type is not distributed")
     426              :             END IF
     427              : 
     428              :             ASSOCIATE (mapl => pw%pw_grid%mapl%pos, mapm => pw%pw_grid%mapm%pos, mapn => pw%pw_grid%mapn%pos, &
     429              :                        ngpts => SIZE(pw%pw_grid%gsq), ghat => pw%pw_grid%g_hat, yzq => pw%pw_grid%para%yzq)
     430              : 
     431      1399888 :                IF (PRESENT(scale)) THEN
     432              : !$OMP PARALLEL DO DEFAULT(NONE) &
     433              : !$OMP             PRIVATE(l, m, mn, n) &
     434            0 : !$OMP             SHARED(c, pw, scale)
     435              :                   DO gpt = 1, ngpts
     436              :                      l = mapl(ghat(1, gpt)) + 1
     437              :                      m = mapm(ghat(2, gpt)) + 1
     438              :                      n = mapn(ghat(3, gpt)) + 1
     439              :                      mn = yzq(m, n)
     440              :                      pw%array(gpt) = scale*${type2type("c(l, mn)", "c3d", kind)}$
     441              :                   END DO
     442              : !$OMP END PARALLEL DO
     443              :                ELSE
     444              : !$OMP PARALLEL DO DEFAULT(NONE) &
     445              : !$OMP             PRIVATE(l, m, mn, n) &
     446      1399888 : !$OMP             SHARED(c, pw)
     447              :                   DO gpt = 1, ngpts
     448              :                      l = mapl(ghat(1, gpt)) + 1
     449              :                      m = mapm(ghat(2, gpt)) + 1
     450              :                      n = mapn(ghat(3, gpt)) + 1
     451              :                      mn = yzq(m, n)
     452              :                      pw%array(gpt) = ${type2type("c(l, mn)", "c3d", kind)}$
     453              :                   END DO
     454              : !$OMP END PARALLEL DO
     455              :                END IF
     456              : 
     457              :             END ASSOCIATE
     458              : 
     459      1399888 :             CALL timestop(handle)
     460              : 
     461      1399888 :          END SUBROUTINE pw_gather_p_${kind}$
     462              : 
     463              : ! **************************************************************************************************
     464              : !> \brief ...
     465              : !> \param pw ...
     466              : !> \param c ...
     467              : !> \param scale ...
     468              : ! **************************************************************************************************
     469      1419454 :          SUBROUTINE pw_scatter_p_${kind}$ (pw, c, scale)
     470              :             TYPE(pw_${kind}$_gs_type), INTENT(IN)                          :: pw
     471              :             COMPLEX(KIND=dp), DIMENSION(:, :), CONTIGUOUS, INTENT(INOUT)   :: c
     472              :             REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
     473              : 
     474              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_scatter_p'
     475              : 
     476              :             INTEGER                                            :: gpt, handle, l, m, mn, n
     477              : 
     478      1419454 :             CALL timeset(routineN, handle)
     479              : 
     480      1419454 :             IF (pw%pw_grid%para%mode /= PW_MODE_DISTRIBUTED) THEN
     481            0 :                CPABORT("This grid type is not distributed")
     482              :             END IF
     483              : 
     484              :             ASSOCIATE (mapl => pw%pw_grid%mapl%pos, mapm => pw%pw_grid%mapm%pos, mapn => pw%pw_grid%mapn%pos, &
     485              :                        ghat => pw%pw_grid%g_hat, yzq => pw%pw_grid%para%yzq, ngpts => SIZE(pw%pw_grid%gsq))
     486              : 
     487  45267951884 :                IF (.NOT. PRESENT(scale)) c = z_zero
     488              : 
     489      1419454 :                IF (PRESENT(scale)) THEN
     490              : !$OMP PARALLEL DO DEFAULT(NONE) &
     491              : !$OMP             PRIVATE(l, m, mn, n) &
     492            0 : !$OMP             SHARED(c, pw, scale)
     493              :                   DO gpt = 1, ngpts
     494              :                      l = mapl(ghat(1, gpt)) + 1
     495              :                      m = mapm(ghat(2, gpt)) + 1
     496              :                      n = mapn(ghat(3, gpt)) + 1
     497              :                      mn = yzq(m, n)
     498              :                      c(l, mn) = ${type2type("scale*pw%array(gpt)", kind, "c3d")}$
     499              :                   END DO
     500              : !$OMP END PARALLEL DO
     501              :                ELSE
     502              : !$OMP PARALLEL DO DEFAULT(NONE) &
     503              : !$OMP             PRIVATE(l, m, mn, n) &
     504      1419454 : !$OMP             SHARED(c, pw)
     505              :                   DO gpt = 1, ngpts
     506              :                      l = mapl(ghat(1, gpt)) + 1
     507              :                      m = mapm(ghat(2, gpt)) + 1
     508              :                      n = mapn(ghat(3, gpt)) + 1
     509              :                      mn = yzq(m, n)
     510              :                      c(l, mn) = ${type2type("pw%array(gpt)", kind, "c3d")}$
     511              :                   END DO
     512              : !$OMP END PARALLEL DO
     513              :                END IF
     514              : 
     515              :             END ASSOCIATE
     516              : 
     517      1419454 :             IF (pw%pw_grid%grid_span == HALFSPACE) THEN
     518              : 
     519              :                ASSOCIATE (mapm => pw%pw_grid%mapm%neg, mapn => pw%pw_grid%mapn%neg, mapl => pw%pw_grid%mapl%neg, &
     520              :                           ghat => pw%pw_grid%g_hat, ngpts => SIZE(pw%pw_grid%gsq), yzq => pw%pw_grid%para%yzq)
     521              : 
     522       125616 :                   IF (PRESENT(scale)) THEN
     523              : !$OMP PARALLEL DO DEFAULT(NONE) &
     524              : !$OMP             PRIVATE(l, m, mn, n) &
     525            0 : !$OMP             SHARED(c, pw, scale)
     526              :                      DO gpt = 1, ngpts
     527              :                         l = mapl(ghat(1, gpt)) + 1
     528              :                         m = mapm(ghat(2, gpt)) + 1
     529              :                         n = mapn(ghat(3, gpt)) + 1
     530              :                         mn = yzq(m, n)
     531              :                         c(l, mn) = scale*#{if kind[0]=="c"}#CONJG#{endif}#(${type2type("pw%array(gpt)", kind, "c3d")}$)
     532              :                      END DO
     533              : !$OMP END PARALLEL DO
     534              :                   ELSE
     535              : !$OMP PARALLEL DO DEFAULT(NONE) &
     536              : !$OMP             PRIVATE(l, m, mn, n) &
     537       125616 : !$OMP             SHARED(c, pw)
     538              :                      DO gpt = 1, ngpts
     539              :                         l = mapl(ghat(1, gpt)) + 1
     540              :                         m = mapm(ghat(2, gpt)) + 1
     541              :                         n = mapn(ghat(3, gpt)) + 1
     542              :                         mn = yzq(m, n)
     543              :                         c(l, mn) = #{if kind[0]=="c"}#CONJG#{endif}#(${type2type("pw%array(gpt)", kind, "c3d")}$)
     544              :                      END DO
     545              : !$OMP END PARALLEL DO
     546              :                   END IF
     547              :                END ASSOCIATE
     548              :             END IF
     549              : 
     550      1419454 :             CALL timestop(handle)
     551              : 
     552      1419454 :          END SUBROUTINE pw_scatter_p_${kind}$
     553              :       #:endif
     554              :    #:endfor
     555              : 
     556              :    #:for kind, type, kind2, type2 in pw_list2_sameD
     557              :       #:for space in pw_spaces
     558              : ! **************************************************************************************************
     559              : !> \brief copy a pw type variable
     560              : !> \param pw1 ...
     561              : !> \param pw2 ...
     562              : !> \par History
     563              : !>      JGH (7-Mar-2001) : check for pw_grid %id_nr, allow copy if
     564              : !>        in_use == COMPLEXDATA1D and in_space == RECIPROCALSPACE
     565              : !>      JGH (21-Feb-2003) : Code for generalized reference grids
     566              : !> \author apsi
     567              : !> \note
     568              : !>      Currently only copying of respective types allowed,
     569              : !>      in order to avoid errors
     570              : ! **************************************************************************************************
     571      3209728 :          SUBROUTINE pw_copy_${kind}$_${kind2}$_${space}$ (pw1, pw2)
     572              : 
     573              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw1
     574              :             TYPE(pw_${kind2}$_${space}$_type), INTENT(INOUT)                       :: pw2
     575              : 
     576              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_copy'
     577              : 
     578              :             INTEGER                                            :: handle
     579              :             #:if kind[1:]=='1d'
     580              :                INTEGER :: i, j, ng, ng1, ng2, ns
     581              :             #:endif
     582              : 
     583      3209728 :             CALL timeset(routineN, handle)
     584              : 
     585      3209728 :             IF (pw1%pw_grid%spherical .neqv. pw2%pw_grid%spherical) &
     586            0 :                CPABORT("Both grids must be either spherical or non-spherical!")
     587              :             #:if space != "gs"
     588       645406 :                IF (pw1%pw_grid%spherical) &
     589            0 :                   CPABORT("Spherical grids only exist in reciprocal space!")
     590              :             #:endif
     591              : 
     592              :             #:if kind[1]=='1'
     593      2564322 :                IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
     594       689789 :                   IF (pw1%pw_grid%spherical .AND. pw2%pw_grid%spherical) THEN
     595            0 :                      IF (pw_compatible(pw1%pw_grid, pw2%pw_grid)) THEN
     596            0 :                         ng1 = SIZE(pw1%array)
     597            0 :                         ng2 = SIZE(pw2%array)
     598            0 :                         ng = MIN(ng1, ng2)
     599            0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(ng, pw1, pw2)
     600              :                         pw2%array(1:ng) = ${type2type("pw1%array(1:ng)", kind, kind2)}$
     601              : !$OMP END PARALLEL WORKSHARE
     602            0 :                         IF (ng2 > ng) THEN
     603            0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(ng, ng2, pw2)
     604              :                            pw2%array(ng + 1:ng2) = ${type2type("0.0_dp", "r3d", kind2)}$
     605              : !$OMP END PARALLEL WORKSHARE
     606              :                         END IF
     607              :                      ELSE
     608            0 :                         CPABORT("Copies between spherical grids require compatible grids!")
     609              :                      END IF
     610              :                   ELSE
     611       689789 :                      ng1 = SIZE(pw1%array)
     612       689789 :                      ng2 = SIZE(pw2%array)
     613       689789 :                      ns = 2*MAX(ng1, ng2)
     614              : 
     615       689789 :                      IF ((pw1%pw_grid%id_nr == pw2%pw_grid%reference)) THEN
     616       689421 :                         IF (ng1 >= ng2) THEN
     617              : !$OMP PARALLEL DO DEFAULT(NONE) &
     618              : !$OMP             PRIVATE(i,j) &
     619       689421 : !$OMP             SHARED(ng2, pw1, pw2)
     620              :                            DO i = 1, ng2
     621              :                               j = pw2%pw_grid%gidx(i)
     622              :                               pw2%array(i) = ${type2type("pw1%array(j)", kind, kind2)}$
     623              :                            END DO
     624              : !$OMP END PARALLEL DO
     625              :                         ELSE
     626            0 :                            CALL pw_zero(pw2)
     627              : !$OMP PARALLEL DO DEFAULT(NONE) &
     628              : !$OMP             PRIVATE(i,j) &
     629            0 : !$OMP             SHARED(ng1, pw1, pw2)
     630              :                            DO i = 1, ng1
     631              :                               j = pw2%pw_grid%gidx(i)
     632              :                               pw2%array(j) = ${type2type("pw1%array(i)", kind, kind2)}$
     633              :                            END DO
     634              : !$OMP END PARALLEL DO
     635              :                         END IF
     636          368 :                      ELSE IF ((pw2%pw_grid%id_nr == pw1%pw_grid%reference)) THEN
     637          366 :                         IF (ng1 >= ng2) THEN
     638            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng2, pw1, pw2)
     639              :                            DO i = 1, ng2
     640              :                               j = pw1%pw_grid%gidx(i)
     641              :                               pw2%array(i) = ${type2type("pw1%array(j)", kind, kind2)}$
     642              :                            END DO
     643              : !$OMP END PARALLEL DO
     644              :                         ELSE
     645          366 :                            CALL pw_zero(pw2)
     646          366 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng1, pw1, pw2)
     647              :                            DO i = 1, ng1
     648              :                               j = pw1%pw_grid%gidx(i)
     649              :                               pw2%array(j) = ${type2type("pw1%array(i)", kind, kind2)}$
     650              :                            END DO
     651              : !$OMP END PARALLEL DO
     652              :                         END IF
     653              :                      ELSE
     654              :                         #:if kind=='c1d' and kind2=='c1d' and space=="gs"
     655            2 :                            CALL pw_copy_match(pw1, pw2)
     656              :                         #:else
     657            0 :                            CPABORT("Copy not implemented!")
     658              :                         #:endif
     659              :                      END IF
     660              : 
     661              :                   END IF
     662              : 
     663              :                ELSE
     664      1874533 : !$OMP PARALLEL WORKSHARE PRIVATE(i) DEFAULT(NONE) SHARED(pw1, pw2)
     665              :                   pw2%array = ${type2type("pw1%array", kind, kind2)}$
     666              : !$OMP END PARALLEL WORKSHARE
     667              :                END IF
     668              :             #:else
     669      2581624 :                IF (ANY(SHAPE(pw2%array) /= SHAPE(pw1%array))) &
     670            0 :                   CPABORT("3D grids must be compatible!")
     671       645406 :                IF (pw1%pw_grid%spherical) &
     672            0 :                   CPABORT("3D grids must not be spherical!")
     673       645406 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1,pw2)
     674              :                pw2%array(:, :, :) = ${type2type("pw1%array(:, :, :)", kind, kind2)}$
     675              : !$OMP END PARALLEL WORKSHARE
     676              :             #:endif
     677              : 
     678      3209728 :             CALL timestop(handle)
     679              : 
     680      3209728 :          END SUBROUTINE pw_copy_${kind}$_${kind2}$_${space}$
     681              : 
     682              : ! **************************************************************************************************
     683              : !> \brief ...
     684              : !> \param pw ...
     685              : !> \param array ...
     686              : ! **************************************************************************************************
     687      1698950 :          SUBROUTINE pw_copy_to_array_${kind}$_${kind2}$_${space}$ (pw, array)
     688              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw
     689              :             ${type2}$, INTENT(INOUT)   :: array
     690              : 
     691              :             CHARACTER(len=*), PARAMETER :: routineN = 'pw_copy_to_array'
     692              : 
     693              :             INTEGER                                            :: handle
     694              : 
     695      1698950 :             CALL timeset(routineN, handle)
     696              : 
     697              :             #:if kind[1]=="1"
     698            0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw, array)
     699              :                array(:) = ${type2type("pw%array(:)", kind, kind2)}$
     700              : !$OMP END PARALLEL WORKSHARE
     701              :             #:else
     702      1698950 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw, array)
     703              :                array(:, :, :) = ${type2type("pw%array(:, :, :)", kind, kind2)}$
     704              : !$OMP END PARALLEL WORKSHARE
     705              :             #:endif
     706              : 
     707      1698950 :             CALL timestop(handle)
     708      1698950 :          END SUBROUTINE pw_copy_to_array_${kind}$_${kind2}$_${space}$
     709              : 
     710              : ! **************************************************************************************************
     711              : !> \brief ...
     712              : !> \param pw ...
     713              : !> \param array ...
     714              : ! **************************************************************************************************
     715      1734825 :          SUBROUTINE pw_copy_from_array_${kind}$_${kind2}$_${space}$ (pw, array)
     716              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw
     717              :             ${type2}$, INTENT(IN)      :: array
     718              : 
     719              :             CHARACTER(len=*), PARAMETER :: routineN = 'pw_copy_from_array'
     720              : 
     721              :             INTEGER                                            :: handle
     722              : 
     723      1734825 :             CALL timeset(routineN, handle)
     724              : 
     725      1734825 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw, array)
     726              :             pw%array = ${type2type("array", kind2, kind)}$
     727              : !$OMP END PARALLEL WORKSHARE
     728              : 
     729      1734825 :             CALL timestop(handle)
     730      1734825 :          END SUBROUTINE pw_copy_from_array_${kind}$_${kind2}$_${space}$
     731              : 
     732              : ! **************************************************************************************************
     733              : !> \brief pw2 = alpha*pw1 + beta*pw2
     734              : !>      alpha defaults to 1, beta defaults to 1
     735              : !> \param pw1 ...
     736              : !> \param pw2 ...
     737              : !> \param alpha ...
     738              : !> \param beta ...
     739              : !> \param allow_noncompatible_grids ...
     740              : !> \par History
     741              : !>      JGH (21-Feb-2003) : added reference grid functionality
     742              : !>      JGH (01-Dec-2007) : rename and remove complex alpha
     743              : !> \author apsi
     744              : !> \note
     745              : !>      Currently only summing up of respective types allowed,
     746              : !>      in order to avoid errors
     747              : ! **************************************************************************************************
     748      1974870 :          SUBROUTINE pw_axpy_${kind}$_${kind2}$_${space}$ (pw1, pw2, alpha, beta, allow_noncompatible_grids)
     749              : 
     750              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw1
     751              :             TYPE(pw_${kind2}$_${space}$_type), INTENT(INOUT)                       :: pw2
     752              :             REAL(KIND=dp), INTENT(in), OPTIONAL                :: alpha, beta
     753              :             LOGICAL, INTENT(IN), OPTIONAL                      :: allow_noncompatible_grids
     754              : 
     755              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_axpy'
     756              : 
     757              :             INTEGER                                            :: handle
     758              :             LOGICAL                                            :: my_allow_noncompatible_grids
     759              :             REAL(KIND=dp)                                      :: my_alpha, my_beta
     760              :             #:if kind[1]=='1'
     761              :                INTEGER                                            :: i, j, ng, ng1, ng2
     762              :             #:endif
     763              : 
     764      1974870 :             CALL timeset(routineN, handle)
     765              : 
     766      1974870 :             my_alpha = 1.0_dp
     767      1974870 :             IF (PRESENT(alpha)) my_alpha = alpha
     768              : 
     769      1974870 :             my_beta = 1.0_dp
     770      1974870 :             IF (PRESENT(beta)) my_beta = beta
     771              : 
     772      1974870 :             my_allow_noncompatible_grids = .FALSE.
     773      1974870 :             IF (PRESENT(allow_noncompatible_grids)) my_allow_noncompatible_grids = allow_noncompatible_grids
     774              : 
     775      1974870 :             IF (my_beta /= 1.0_dp) THEN
     776       102082 :                IF (my_beta == 0.0_dp) THEN
     777         1678 :                   CALL pw_zero(pw2)
     778              :                ELSE
     779       100404 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw2,my_beta)
     780              :                   pw2%array = pw2%array*my_beta
     781              : !$OMP END PARALLEL WORKSHARE
     782              :                END IF
     783              :             END IF
     784              : 
     785              :             #:if kind[1]=='1'
     786      1458891 :                IF (ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
     787              : 
     788       686442 :                   IF (my_alpha == 1.0_dp) THEN
     789       667930 : !$OMP PARALLEL WORKSHARE PRIVATE(i) DEFAULT(NONE) SHARED(pw1, pw2)
     790              :                      pw2%array = pw2%array + ${type2type("pw1%array", kind, kind2)}$
     791              : !$OMP END PARALLEL WORKSHARE
     792        18512 :                   ELSE IF (my_alpha /= 0.0_dp) THEN
     793        18512 : !$OMP PARALLEL WORKSHARE PRIVATE(i) DEFAULT(NONE) SHARED(pw2,pw1,my_alpha)
     794              :                      pw2%array = pw2%array + my_alpha*${type2type("pw1%array", kind, kind2)}$
     795              : !$OMP END PARALLEL WORKSHARE
     796              :                   END IF
     797              : 
     798       772449 :                ELSE IF (pw_compatible(pw1%pw_grid, pw2%pw_grid) .OR. my_allow_noncompatible_grids) THEN
     799              : 
     800       772449 :                   ng1 = SIZE(pw1%array)
     801       772449 :                   ng2 = SIZE(pw2%array)
     802       772449 :                   ng = MIN(ng1, ng2)
     803              : 
     804       772449 :                   IF (pw1%pw_grid%spherical) THEN
     805            0 :                      IF (my_alpha == 1.0_dp) THEN
     806            0 : !$OMP PARALLEL DO PRIVATE(i) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     807              :                         DO i = 1, ng
     808              :                            pw2%array(i) = pw2%array(i) + ${type2type("pw1%array(i)", kind, kind2)}$
     809              :                         END DO
     810              : !$OMP END PARALLEL DO
     811            0 :                      ELSE IF (my_alpha /= 0.0_dp) THEN
     812            0 : !$OMP PARALLEL DO PRIVATE(i) DEFAULT(NONE) SHARED(pw2,pw1,my_alpha,ng)
     813              :                         DO i = 1, ng
     814              :                            pw2%array(i) = pw2%array(i) + my_alpha*${type2type("pw1%array(i)", kind, kind2)}$
     815              :                         END DO
     816              : !$OMP END PARALLEL DO
     817              :                      END IF
     818       772449 :                   ELSE IF ((pw1%pw_grid%id_nr == pw2%pw_grid%reference)) THEN
     819         1204 :                      IF (ng1 >= ng2) THEN
     820         1204 :                         IF (my_alpha == 1.0_dp) THEN
     821         1204 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     822              :                            DO i = 1, ng
     823              :                               j = pw2%pw_grid%gidx(i)
     824              :                               pw2%array(i) = pw2%array(i) + ${type2type("pw1%array(j)", kind, kind2)}$
     825              :                            END DO
     826              : !$OMP END PARALLEL DO
     827            0 :                         ELSE IF (my_alpha /= 0.0_dp) THEN
     828            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(my_alpha, ng, pw1, pw2)
     829              :                            DO i = 1, ng
     830              :                               j = pw2%pw_grid%gidx(i)
     831              :                               pw2%array(i) = pw2%array(i) + my_alpha*${type2type("pw1%array(j)", kind, kind2)}$
     832              :                            END DO
     833              : !$OMP END PARALLEL DO
     834              :                         END IF
     835              :                      ELSE
     836            0 :                         IF (my_alpha == 1.0_dp) THEN
     837            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     838              :                            DO i = 1, ng
     839              :                               j = pw2%pw_grid%gidx(i)
     840              :                               pw2%array(j) = pw2%array(j) + ${type2type("pw1%array(i)", kind, kind2)}$
     841              :                            END DO
     842              : !$OMP END PARALLEL DO
     843            0 :                         ELSE IF (my_alpha /= 0.0_dp) THEN
     844            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(my_alpha, ng, pw1, pw2)
     845              :                            DO i = 1, ng
     846              :                               j = pw2%pw_grid%gidx(i)
     847              :                               pw2%array(j) = pw2%array(j) + my_alpha*${type2type("pw1%array(i)", kind, kind2)}$
     848              :                            END DO
     849              : !$OMP END PARALLEL DO
     850              :                         END IF
     851              :                      END IF
     852       771245 :                   ELSE IF ((pw2%pw_grid%id_nr == pw1%pw_grid%reference)) THEN
     853       771245 :                      IF (ng1 >= ng2) THEN
     854            0 :                         IF (my_alpha == 1.0_dp) THEN
     855            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     856              :                            DO i = 1, ng
     857              :                               j = pw1%pw_grid%gidx(i)
     858              :                               pw2%array(i) = pw2%array(i) + ${type2type("pw1%array(j)", kind, kind2)}$
     859              :                            END DO
     860              : !$OMP END PARALLEL DO
     861            0 :                         ELSE IF (my_alpha /= 0.0_dp) THEN
     862            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(my_alpha, ng, pw1, pw2)
     863              :                            DO i = 1, ng
     864              :                               j = pw1%pw_grid%gidx(i)
     865              :                               pw2%array(i) = pw2%array(i) + my_alpha*${type2type("pw1%array(j)", kind, kind2)}$
     866              :                            END DO
     867              : !$OMP END PARALLEL DO
     868              :                         END IF
     869              :                      ELSE
     870       771245 :                         IF (my_alpha == 1.0_dp) THEN
     871       771245 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     872              :                            DO i = 1, ng
     873              :                               j = pw1%pw_grid%gidx(i)
     874              :                               pw2%array(j) = pw2%array(j) + ${type2type("pw1%array(i)", kind, kind2)}$
     875              :                            END DO
     876              : !$OMP END PARALLEL DO
     877            0 :                         ELSE IF (my_alpha /= 0.0_dp) THEN
     878            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(my_alpha, ng, pw1, pw2)
     879              :                            DO i = 1, ng
     880              :                               j = pw1%pw_grid%gidx(i)
     881              :                               pw2%array(j) = pw2%array(j) + my_alpha*${type2type("pw1%array(i)", kind, kind2)}$
     882              :                            END DO
     883              : !$OMP END PARALLEL DO
     884              :                         END IF
     885              :                      END IF
     886              :                   ELSE
     887            0 :                      CPABORT("Grids not compatible")
     888              :                   END IF
     889              :                   #:else
     890       515979 :                   IF (ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
     891       515449 :                      IF (my_alpha == 1.0_dp) THEN
     892       306585 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1, pw2)
     893              :                         pw2%array = pw2%array + ${type2type("pw1%array", kind, kind2)}$
     894              : !$OMP END PARALLEL WORKSHARE
     895       208864 :                      ELSE IF (my_alpha /= 0.0_dp) THEN
     896       207420 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1, pw2, my_alpha)
     897              :                         pw2%array = pw2%array + my_alpha*${type2type("pw1%array", kind, kind2)}$
     898              : !$OMP END PARALLEL WORKSHARE
     899              :                      END IF
     900              : 
     901          530 :                   ELSE IF (pw_compatible(pw1%pw_grid, pw2%pw_grid) .OR. my_allow_noncompatible_grids) THEN
     902              : 
     903         2120 :                      IF (ANY(SHAPE(pw1%array) /= SHAPE(pw2%array))) &
     904            0 :                         CPABORT("Noncommensurate grids not implemented for 3D grids!")
     905              : 
     906          530 :                      IF (my_alpha == 1.0_dp) THEN
     907          444 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1,pw2)
     908              :                         pw2%array = pw2%array + ${type2type("pw1%array", kind, kind2)}$
     909              : !$OMP END PARALLEL WORKSHARE
     910              :                      ELSE
     911           86 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1,pw2,my_alpha)
     912              :                         pw2%array = pw2%array + my_alpha*${type2type("pw1%array", kind, kind2)}$
     913              : !$OMP END PARALLEL WORKSHARE
     914              :                      END IF
     915              :                      #:endif
     916              : 
     917              :                   ELSE
     918              : 
     919            0 :                      CPABORT("Grids not compatible")
     920              : 
     921              :                   END IF
     922              : 
     923      1974870 :                   CALL timestop(handle)
     924              : 
     925      1974870 :                   END SUBROUTINE pw_axpy_${kind}$_${kind2}$_${space}$
     926              : 
     927              : ! **************************************************************************************************
     928              : !> \brief pw_out = pw_out + alpha * pw1 * pw2
     929              : !>      alpha defaults to 1
     930              : !> \param pw_out ...
     931              : !> \param pw1 ...
     932              : !> \param pw2 ...
     933              : !> \param alpha ...
     934              : !> \author JGH
     935              : ! **************************************************************************************************
     936         3273 :                   SUBROUTINE pw_multiply_${kind}$_${kind2}$_${space}$ (pw_out, pw1, pw2, alpha)
     937              : 
     938              :                      TYPE(pw_${kind}$_${space}$_type), INTENT(INOUT)                       :: pw_out
     939              :                      TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw1
     940              :                      TYPE(pw_${kind2}$_${space}$_type), INTENT(IN) :: pw2
     941              :                      REAL(KIND=dp), INTENT(IN), OPTIONAL                :: alpha
     942              : 
     943              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_multiply'
     944              : 
     945              :                      INTEGER                                            :: handle
     946              :                      REAL(KIND=dp)                                      :: my_alpha
     947              : 
     948         3273 :                      CALL timeset(routineN, handle)
     949              : 
     950         3273 :                      my_alpha = 1.0_dp
     951         3273 :                      IF (PRESENT(alpha)) my_alpha = alpha
     952              : 
     953         6546 :                      IF (.NOT. ASSOCIATED(pw_out%pw_grid, pw1%pw_grid) .OR. .NOT. ASSOCIATED(pw_out%pw_grid, pw2%pw_grid)) &
     954            0 :                         CPABORT("pw_multiply not implemented for non-identical grids!")
     955              : 
     956              : #if !defined(__INTEL_LLVM_COMPILER) || (20250000 <= __INTEL_LLVM_COMPILER)
     957         3273 :                      IF (my_alpha == 1.0_dp) THEN
     958         3209 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw_out, pw1, pw2)
     959              :                         pw_out%array = pw_out%array + pw1%array*${type2type("pw2%array", kind2, kind)}$
     960              : !$OMP END PARALLEL WORKSHARE
     961              :                      ELSE
     962           64 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(my_alpha, pw_out, pw1, pw2)
     963              :                         pw_out%array = pw_out%array + my_alpha*pw1%array*${type2type("pw2%array", kind2, kind)}$
     964              : !$OMP END PARALLEL WORKSHARE
     965              :                      END IF
     966              : #else
     967              :                      IF (my_alpha == 1.0_dp) THEN
     968              :                         pw_out%array = pw_out%array + pw1%array*${type2type("pw2%array", kind2, kind)}$
     969              :                      ELSE
     970              :                         pw_out%array = pw_out%array + my_alpha*pw1%array*${type2type("pw2%array", kind2, kind)}$
     971              :                      END IF
     972              : #endif
     973              : 
     974         3273 :                      CALL timestop(handle)
     975              : 
     976         3273 :                   END SUBROUTINE pw_multiply_${kind}$_${kind2}$_${space}$
     977              : 
     978              : ! **************************************************************************************************
     979              : !> \brief ...
     980              : !> \param pw1 ...
     981              : !> \param pw2 ...
     982              : ! **************************************************************************************************
     983       439288 :                   SUBROUTINE pw_multiply_with_${kind}$_${kind2}$_${space}$ (pw1, pw2)
     984              :                      TYPE(pw_${kind}$_${space}$_type), INTENT(INOUT)                       :: pw1
     985              :                      TYPE(pw_${kind2}$_${space}$_type), INTENT(IN)                          :: pw2
     986              : 
     987              :                      CHARACTER(LEN=*), PARAMETER                        :: routineN = 'pw_multiply_with'
     988              : 
     989              :                      INTEGER                                            :: handle
     990              : 
     991       439288 :                      CALL timeset(routineN, handle)
     992              : 
     993       439288 :                      IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) &
     994            0 :                         CPABORT("Incompatible grids!")
     995              : 
     996       439288 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1,pw2)
     997              :                      pw1%array = pw1%array*${type2type("pw2%array", kind2, kind)}$
     998              : !$OMP END PARALLEL WORKSHARE
     999              : 
    1000       439288 :                      CALL timestop(handle)
    1001              : 
    1002       439288 :                   END SUBROUTINE pw_multiply_with_${kind}$_${kind2}$_${space}$
    1003              : 
    1004              : ! **************************************************************************************************
    1005              : !> \brief Calculate integral over unit cell for functions in plane wave basis
    1006              : !>      only returns the real part of it ......
    1007              : !> \param pw1 ...
    1008              : !> \param pw2 ...
    1009              : !> \param sumtype ...
    1010              : !> \param just_sum ...
    1011              : !> \param local_only ...
    1012              : !> \return ...
    1013              : !> \par History
    1014              : !>      JGH (14-Mar-2001) : Parallel sum and some tests, HALFSPACE case
    1015              : !> \author apsi
    1016              : ! **************************************************************************************************
    1017       714791 :                FUNCTION pw_integral_ab_${kind}$_${kind2}$_${space}$ (pw1, pw2, sumtype, just_sum, local_only) RESULT(integral_value)
    1018              : 
    1019              :                      TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw1
    1020              :                      TYPE(pw_${kind2}$_${space}$_type), INTENT(IN)                          :: pw2
    1021              :                      INTEGER, INTENT(IN), OPTIONAL                      :: sumtype
    1022              :                      LOGICAL, INTENT(IN), OPTIONAL                      :: just_sum, local_only
    1023              :                      REAL(KIND=dp)                                      :: integral_value
    1024              : 
    1025              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_integral_ab_${kind}$_${kind2}$_${space}$'
    1026              : 
    1027              :                      INTEGER                                            :: handle, loc_sumtype
    1028              :                      LOGICAL                                            :: my_just_sum, my_local_only
    1029              : 
    1030       714791 :                      CALL timeset(routineN, handle)
    1031              : 
    1032       714791 :                      loc_sumtype = do_accurate_sum
    1033       714791 :                      IF (PRESENT(sumtype)) loc_sumtype = sumtype
    1034              : 
    1035       714791 :                      my_local_only = .FALSE.
    1036       714791 :                      IF (PRESENT(local_only)) my_local_only = local_only
    1037              : 
    1038       714791 :                      IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
    1039            0 :                         CPABORT("Grids incompatible")
    1040              :                      END IF
    1041              : 
    1042       714791 :                      my_just_sum = .FALSE.
    1043       714791 :                      IF (PRESENT(just_sum)) my_just_sum = just_sum
    1044              : 
    1045              :                      ! do standard sum
    1046       714791 :                      IF (loc_sumtype == do_standard_sum) THEN
    1047              : 
    1048              :                         ! Do standard sum
    1049              : 
    1050              :                         #:if kind=="r1d" and kind2=="r1d"
    1051            0 :                            integral_value = DOT_PRODUCT(pw1%array, pw2%array)
    1052              :                         #:elif kind=="r3d" and kind2=="r3d"
    1053   1060157396 :                            integral_value = SUM(pw1%array*pw2%array)
    1054              :                         #:elif kind[0]=="r"
    1055            0 :                            integral_value = SUM(pw1%array*REAL(pw2%array, KIND=dp)) !? complex bit
    1056              :                         #:elif kind2[0]=="r"
    1057            0 :                            integral_value = SUM(REAL(pw1%array, KIND=dp)*pw2%array) !? complex bit
    1058              :                         #:else
    1059              :                            integral_value = SUM(REAL(CONJG(pw1%array) &
    1060            0 :                                                      *pw2%array, KIND=dp)) !? complex bit
    1061              :                         #:endif
    1062              : 
    1063              :                      ELSE
    1064              : 
    1065              :                         ! Do accurate sum
    1066              :                         #:if kind[0]=="r" and kind2[0]=="r"
    1067        54232 :                            integral_value = accurate_dot_product(pw1%array, pw2%array)
    1068              :                         #:elif kind[0]=="r"
    1069            0 :                            integral_value = accurate_sum(pw1%array*REAL(pw2%array, KIND=dp)) !? complex bit
    1070              :                         #:elif kind2[0]=="r"
    1071            0 :                            integral_value = accurate_sum(REAL(pw1%array, KIND=dp)*pw2%array) !? complex bit
    1072              :                         #:else
    1073   9616388147 :                            integral_value = accurate_sum(REAL(CONJG(pw1%array)*pw2%array, KIND=dp))
    1074              :                         #:endif
    1075              : 
    1076              :                      END IF
    1077              : 
    1078       714791 :                      IF (.NOT. my_just_sum) THEN
    1079              :                         #:if space == "rs"
    1080       305700 :                            integral_value = integral_value*pw1%pw_grid%dvol
    1081              :                         #:elif space == "gs"
    1082       408981 :                            integral_value = integral_value*pw1%pw_grid%vol
    1083              :                         #:else
    1084              :                            #:stop "Unknown space: "+space
    1085              :                         #:endif
    1086              :                      END IF
    1087              : 
    1088              :                      #:if kind[1]=="1"
    1089       408981 :                         IF (pw1%pw_grid%grid_span == HALFSPACE) THEN
    1090       240914 :                            integral_value = 2.0_dp*integral_value
    1091       240914 :                            IF (pw1%pw_grid%have_g0) integral_value = integral_value - &
    1092              :                            #:if kind[0]=="c"
    1093       130866 :                                                                      REAL(CONJG(pw1%array(1))*pw2%array(1), KIND=dp)
    1094              :                               #:elif kind2[0]=="r"
    1095            0 :                               pw1%array(1)*pw2%array(1)
    1096              :                               #:else
    1097            0 :                               pw1%array(1)*REAL(pw2%array(1), KIND=dp)
    1098              :                               #:endif
    1099              :                            END IF
    1100              :                         #:endif
    1101              : 
    1102       714791 :                         IF (.NOT. my_local_only .AND. pw1%pw_grid%para%mode == PW_MODE_DISTRIBUTED) &
    1103       396076 :                            CALL pw1%pw_grid%para%group%sum(integral_value)
    1104              : 
    1105       714791 :                         CALL timestop(handle)
    1106              : 
    1107       714791 :                      END FUNCTION pw_integral_ab_${kind}$_${kind2}$_${space}$
    1108              :                      #:endfor
    1109              : 
    1110              :                      #:if kind[1]=="1"
    1111              : ! **************************************************************************************************
    1112              : !> \brief ...
    1113              : !> \param pw1 ...
    1114              : !> \param pw2 ...
    1115              : !> \return ...
    1116              : ! **************************************************************************************************
    1117        84348 :                         FUNCTION pw_integral_a2b_${kind}$_${kind2}$ (pw1, pw2) RESULT(integral_value)
    1118              : 
    1119              :                            TYPE(pw_${kind}$_gs_type), INTENT(IN)                          :: pw1
    1120              :                            TYPE(pw_${kind2}$_gs_type), INTENT(IN) :: pw2
    1121              :                            REAL(KIND=dp)                                      :: integral_value
    1122              : 
    1123              :                            CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_integral_a2b'
    1124              : 
    1125              :                            INTEGER                                            :: handle
    1126              : 
    1127        84348 :                            CALL timeset(routineN, handle)
    1128              : 
    1129        84348 :                            IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
    1130            0 :                               CPABORT("Grids incompatible")
    1131              :                            END IF
    1132              : 
    1133              :                            #:if kind[0]=="c"
    1134              :                               #:if kind2[0]=="c"
    1135    243958524 :                                  integral_value = accurate_sum(REAL(CONJG(pw1%array)*pw2%array, KIND=dp)*pw1%pw_grid%gsq)
    1136              :                               #:else
    1137            0 :                                  integral_value = accurate_sum(REAL(CONJG(pw1%array), KIND=dp)*pw2%array*pw1%pw_grid%gsq)
    1138              :                               #:endif
    1139              :                            #:elif kind2[0]=="c"
    1140            0 :                               integral_value = accurate_sum(pw1%array*REAL(pw2%array, KIND=dp)*pw1%pw_grid%gsq)
    1141              :                            #:else
    1142            0 :                               integral_value = accurate_sum(pw1%array*pw2%array*pw1%pw_grid%gsq)
    1143              :                            #:endif
    1144        84348 :                            IF (pw1%pw_grid%grid_span == HALFSPACE) THEN
    1145        84348 :                               integral_value = 2.0_dp*integral_value
    1146              :                            END IF
    1147              : 
    1148        84348 :                            integral_value = integral_value*pw1%pw_grid%vol
    1149              : 
    1150        84348 :                            IF (pw1%pw_grid%para%mode == PW_MODE_DISTRIBUTED) &
    1151        79620 :                               CALL pw1%pw_grid%para%group%sum(integral_value)
    1152        84348 :                            CALL timestop(handle)
    1153              : 
    1154        84348 :                         END FUNCTION pw_integral_a2b_${kind}$_${kind2}$
    1155              :                      #:endif
    1156              :                   #:endfor
    1157              : 
    1158              :                   #:for kind, type, kind2, type2 in pw_list2
    1159              :                      #:for space in pw_spaces
    1160              :                         #:for space2 in pw_spaces
    1161              : 
    1162              :                            #:if space != space2 and ((space=="rs" and kind[1]=="3" and kind2[0]=="c") or (space=="gs" and kind2[1]=="3" and kind[0]=="c"))
    1163              : ! **************************************************************************************************
    1164              : !> \brief Generic function for 3d FFT of a coefficient_type or pw_r3d_rs_type
    1165              : !> \param pw1 ...
    1166              : !> \param pw2 ...
    1167              : !> \param debug ...
    1168              : !> \par History
    1169              : !>      JGH (30-12-2000): New setup of functions and adaptation to parallelism
    1170              : !>      JGH (04-01-2001): Moved routine from pws to this module, only covers
    1171              : !>                        pw_types, no more coefficient types
    1172              : !> \author apsi
    1173              : !> \note
    1174              : !>       fft_wrap_pw1pw2
    1175              : ! **************************************************************************************************
    1176      3434847 :                               SUBROUTINE fft_wrap_pw1pw2_${kind}$_${kind2}$_${space}$_${space2}$ (pw1, pw2, debug)
    1177              : 
    1178              :                                  TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                  :: pw1
    1179              :                                  TYPE(pw_${kind2}$_${space2}$_type), INTENT(INOUT)               :: pw2
    1180              :                                  LOGICAL, INTENT(IN), OPTIONAL                      :: debug
    1181              : 
    1182              :                                  CHARACTER(len=*), PARAMETER                        :: routineN = 'fft_wrap_pw1pw2'
    1183              : 
    1184      3434847 :                                  COMPLEX(KIND=dp), DIMENSION(:, :), CONTIGUOUS, POINTER         :: grays
    1185      3434847 :                                  COMPLEX(KIND=dp), DIMENSION(:, :, :), CONTIGUOUS, POINTER      :: c_in, c_out
    1186              :                                  INTEGER                                            ::  handle, handle2, my_pos, nrays, &
    1187              :                                                                                        out_unit
    1188              :                                  #:if (space=="rs" and kind=="r3d" and kind2=="c1d") or (space=="gs" and kind=="c1d" and kind2=="r3d")
    1189              :                                     INTEGER, DIMENSION(3)                              :: nloc
    1190              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1191              :                                     LOGICAL                                            :: use_pw_gpu
    1192              : #endif
    1193              :                                  #:endif
    1194      3434847 :                                  INTEGER, DIMENSION(:), POINTER                     :: n
    1195              :                                  LOGICAL                                            :: test
    1196              : 
    1197      3434847 :                                  CALL timeset(routineN, handle2)
    1198      3434847 :                                  out_unit = cp_logger_get_default_io_unit()
    1199              :                                  CALL timeset(routineN//"_"//TRIM(ADJUSTL(cp_to_string( &
    1200      3434847 :                                                                           CEILING(pw1%pw_grid%cutoff/10)*10))), handle)
    1201              : 
    1202      3434847 :                                  NULLIFY (c_in)
    1203      3434847 :                                  NULLIFY (c_out)
    1204              : 
    1205      3434847 :                                  IF (PRESENT(debug)) THEN
    1206         1072 :                                     test = debug
    1207              :                                  ELSE
    1208      3433775 :                                     test = .FALSE.
    1209              :                                  END IF
    1210              : 
    1211              :                                  !..check if grids are compatible
    1212      3434847 :                                  IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
    1213            0 :                                     IF (pw1%pw_grid%dvol /= pw2%pw_grid%dvol) THEN
    1214            0 :                                        CPABORT("PW grids not compatible")
    1215              :                                     END IF
    1216            0 :                                     IF (pw1%pw_grid%para%group /= pw2%pw_grid%para%group) THEN
    1217            0 :                                        CPABORT("PW grids have not compatible MPI groups")
    1218              :                                     END IF
    1219              :                                  END IF
    1220              : 
    1221      3434847 :                                  n => pw1%pw_grid%npts
    1222              : 
    1223      3434847 :                                  IF (pw1%pw_grid%para%mode == PW_MODE_LOCAL) THEN
    1224              : 
    1225              :                                     !
    1226              :                                     !..replicated data, use local FFT
    1227              :                                     !
    1228              : 
    1229       615505 :                                     IF (test .AND. out_unit > 0) THEN
    1230            0 :                                        WRITE (out_unit, '(A)') " FFT Protocol "
    1231              :                                        #:if space=="rs"
    1232            0 :                                           WRITE (out_unit, '(A,T76,A)') "  Transform direction ", "FWFFT"
    1233            0 :                                           WRITE (out_unit, '(A,T72,A)') "  in space ", "REALSPACE"
    1234            0 :                                           WRITE (out_unit, '(A,T72,A)') "  out space ", "REALSPACE"
    1235              :                                        #:else
    1236            0 :                                           WRITE (out_unit, '(A,T76,A)') "  Transform direction ", "BWFFT"
    1237            0 :                                           WRITE (out_unit, '(A,T66,A)') "  in space ", "RECIPROCALSPACE"
    1238            0 :                                           WRITE (out_unit, '(A,T66,A)') "  out space ", "RECIPROCALSPACE"
    1239              :                                        #:endif
    1240              :                                     END IF
    1241              : 
    1242              :                                     #:if space=="rs"
    1243              :                                        #:if kind==kind2=="c3d"
    1244            0 :                                           c_in => pw1%array
    1245            0 :                                           c_out => pw2%array
    1246            0 :                                           CALL fft3d(FWFFT, n, c_in, c_out, debug=test)
    1247              :                                        #:elif kind=="r3d" and kind2=="c3d"
    1248            0 :                                           pw2%array = CMPLX(pw1%array, 0.0_dp, KIND=dp)
    1249            0 :                                           c_out => pw2%array
    1250            0 :                                           CALL fft3d(FWFFT, n, c_out, debug=test)
    1251              :                                        #:elif kind=="c3d" and kind2=="c1d"
    1252            0 :                                           c_in => pw1%array
    1253            0 :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1254              :                                           ! transform
    1255            0 :                                           CALL fft3d(FWFFT, n, c_in, c_out, debug=test)
    1256              :                                           ! gather results
    1257            0 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  PW_GATHER : 3d -> 1d "
    1258            0 :                                           CALL pw_gather_s_${kind2}$_c3d(pw2, c_out)
    1259            0 :                                           DEALLOCATE (c_out)
    1260              :                                        #:elif kind=="r3d" and kind2=="c1d"
    1261              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1262              :                                           CALL pw_gpu_r3dc1d_3d(pw1, pw2)
    1263              : #elif defined (__PW_FPGA)
    1264              :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1265              :                                           ! check if bitstream for the fft size is present
    1266              :                                           ! if not, perform fft3d in CPU
    1267              :                                           IF (pw_fpga_init_bitstream(n) == 1) THEN
    1268              :                                              CALL pw_copy_to_array(pw1, c_out)
    1269              : #if (__PW_FPGA_SP && __PW_FPGA)
    1270              :                                              CALL pw_fpga_r3dc1d_3d_sp(n, c_out)
    1271              : #else
    1272              :                                              CALL pw_fpga_r3dc1d_3d_dp(n, c_out)
    1273              : #endif
    1274              :                                              CALL zdscal(n(1)*n(2)*n(3), 1.0_dp/pw1%pw_grid%ngpts, c_out, 1)
    1275              :                                              CALL pw_gather_s_${kind2}$_c3d(pw2, c_out)
    1276              :                                           ELSE
    1277              :                                              CALL pw_copy_to_array(pw1, c_out)
    1278              :                                              CALL fft3d(FWFFT, n, c_out, debug=test)
    1279              :                                              CALL pw_gather_s_${kind2}$_c3d(pw2, c_out)
    1280              :                                           END IF
    1281              :                                           DEALLOCATE (c_out)
    1282              : #else
    1283      1497990 :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1284   2821586992 :                                           c_out = 0.0_dp
    1285       299598 :                                           CALL pw_copy_to_array(pw1, c_out)
    1286       299598 :                                           CALL fft3d(FWFFT, n, c_out, debug=test)
    1287       299598 :                                           CALL pw_gather_s_${kind2}$_c3d(pw2, c_out)
    1288       299598 :                                           DEALLOCATE (c_out)
    1289              : #endif
    1290              :                                        #:endif
    1291              :                                     #:else
    1292              :                                        #:if kind=="c3d" and kind2=="c3d"
    1293            0 :                                           c_in => pw1%array
    1294            0 :                                           c_out => pw2%array
    1295            0 :                                           CALL fft3d(BWFFT, n, c_in, c_out, debug=test)
    1296              :                                        #:elif kind=="c3d" and kind2=="r3d"
    1297            0 :                                           c_in => pw1%array
    1298            0 :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1299            0 :                                           CALL fft3d(BWFFT, n, c_in, c_out, debug=test)
    1300              :                                           ! use real part only
    1301            0 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  REAL part "
    1302            0 :                                           pw2%array = REAL(c_out, KIND=dp)
    1303            0 :                                           DEALLOCATE (c_out)
    1304              :                                        #:elif kind=="c1d" and kind2=="c3d"
    1305            0 :                                           c_out => pw2%array
    1306            0 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  PW_SCATTER : 3d -> 1d "
    1307            0 :                                           CALL pw_scatter_s_${kind}$_c3d(pw1, c_out)
    1308            0 :                                           CALL fft3d(BWFFT, n, c_out, debug=test)
    1309              :                                        #:elif kind=="c1d" and kind2=="r3d"
    1310              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1311              :                                           CALL pw_gpu_c1dr3d_3d(pw1, pw2)
    1312              : #elif defined (__PW_FPGA)
    1313              :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1314              :                                           ! check if bitstream for the fft size is present
    1315              :                                           ! if not, perform fft3d in CPU
    1316              :                                           IF (pw_fpga_init_bitstream(n) == 1) THEN
    1317              :                                              CALL pw_scatter_s_${kind}$_c3d(pw1, c_out)
    1318              :                                              ! transform using FPGA
    1319              : #if (__PW_FPGA_SP && __PW_FPGA)
    1320              :                                              CALL pw_fpga_c1dr3d_3d_sp(n, c_out)
    1321              : #else
    1322              :                                              CALL pw_fpga_c1dr3d_3d_dp(n, c_out)
    1323              : #endif
    1324              :                                              CALL zdscal(n(1)*n(2)*n(3), 1.0_dp, c_out, 1)
    1325              :                                              ! use real part only
    1326              :                                              CALL pw_copy_from_array(pw2, c_out)
    1327              :                                           ELSE
    1328              :                                              IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  PW_SCATTER : 3d -> 1d "
    1329              :                                              CALL pw_scatter_s_${kind}$_c3d(pw1, c_out)
    1330              :                                              ! transform
    1331              :                                              CALL fft3d(BWFFT, n, c_out, debug=test)
    1332              :                                              ! use real part only
    1333              :                                              IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  REAL part "
    1334              :                                              CALL pw_copy_from_array(pw2, c_out)
    1335              :                                           END IF
    1336              :                                           DEALLOCATE (c_out)
    1337              : #else
    1338      1579535 :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1339       315907 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  PW_SCATTER : 3d -> 1d "
    1340       315907 :                                           CALL pw_scatter_s_${kind}$_c3d(pw1, c_out)
    1341              :                                           ! transform
    1342       315907 :                                           CALL fft3d(BWFFT, n, c_out, debug=test)
    1343              :                                           ! use real part only
    1344       315907 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  REAL part "
    1345       315907 :                                           CALL pw_copy_from_array(pw2, c_out)
    1346       315907 :                                           DEALLOCATE (c_out)
    1347              : #endif
    1348              :                                        #:endif
    1349              :                                     #:endif
    1350              : 
    1351       615505 :                                     IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') " End of FFT Protocol "
    1352              : 
    1353              :                                  ELSE
    1354              : 
    1355              :                                     !
    1356              :                                     !..parallel FFT
    1357              :                                     !
    1358              : 
    1359      2819342 :                                     IF (test .AND. out_unit > 0) THEN
    1360            8 :                                        WRITE (out_unit, '(A)') " FFT Protocol "
    1361              :                                        #:if space=="rs"
    1362            4 :                                           WRITE (out_unit, '(A,T76,A)') "  Transform direction ", "FWFFT"
    1363            4 :                                           WRITE (out_unit, '(A,T72,A)') "  in space ", "REALSPACE"
    1364            4 :                                           WRITE (out_unit, '(A,T72,A)') "  out space ", "REALSPACE"
    1365              :                                        #:else
    1366            4 :                                           WRITE (out_unit, '(A,T76,A)') "  Transform direction ", "BWFFT"
    1367            4 :                                           WRITE (out_unit, '(A,T66,A)') "  in space ", "RECIPROCALSPACE"
    1368            4 :                                           WRITE (out_unit, '(A,T66,A)') "  out space ", "RECIPROCALSPACE"
    1369              :                                        #:endif
    1370              :                                     END IF
    1371              : 
    1372      2819342 :                                     my_pos = pw1%pw_grid%para%group%mepos
    1373      2819342 :                                     nrays = pw1%pw_grid%para%nyzray(my_pos)
    1374      2819342 :                                     grays => pw1%pw_grid%grays
    1375              : 
    1376              :                                     #:if space=="rs"
    1377              :                                        #:if kind=="c3d" and kind2=="c1d"
    1378              :                                           !..prepare input
    1379          536 :                                           c_in => pw1%array
    1380      1918288 :                                           grays = z_zero
    1381              :                                           !..transform
    1382          536 :                                           IF (pw1%pw_grid%para%ray_distribution) THEN
    1383              :                                              CALL fft3d(FWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1384              :                                                         pw1%pw_grid%para%yzp, pw1%pw_grid%para%nyzray, &
    1385          432 :                                                         pw1%pw_grid%para%bo, debug=test)
    1386              :                                           ELSE
    1387              :                                              CALL fft3d(FWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1388          104 :                                                         pw1%pw_grid%para%bo, debug=test)
    1389              :                                           END IF
    1390              :                                           !..prepare output
    1391          536 :                                           IF (test .AND. out_unit > 0) &
    1392            4 :                                              WRITE (out_unit, '(A)') "  PW_GATHER : 2d -> 1d "
    1393          536 :                                           CALL pw_gather_p_${kind2}$ (pw2, grays)
    1394              :                                        #:elif kind=="r3d" and kind2=="c1d"
    1395              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1396              :                                           ! (no ray dist. is not efficient in CUDA)
    1397              :                                           use_pw_gpu = pw1%pw_grid%para%ray_distribution
    1398              :                                           IF (use_pw_gpu) THEN
    1399              :                                              CALL pw_gpu_r3dc1d_3d_ps(pw1, pw2)
    1400              :                                           ELSE
    1401              : #endif
    1402              : !..   prepare input
    1403      5597408 :                                              nloc = pw1%pw_grid%npts_local
    1404      6996760 :                                              ALLOCATE (c_in(nloc(1), nloc(2), nloc(3)))
    1405      1399352 :                                              CALL pw_copy_to_array(pw1, c_in)
    1406  40906488664 :                                              grays = z_zero
    1407              :                                              !..transform
    1408      1399352 :                                              IF (pw1%pw_grid%para%ray_distribution) THEN
    1409              :                                                 CALL fft3d(FWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1410              :                                                            pw1%pw_grid%para%yzp, pw1%pw_grid%para%nyzray, &
    1411      1399352 :                                                            pw1%pw_grid%para%bo, debug=test)
    1412              :                                              ELSE
    1413              :                                                 CALL fft3d(FWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1414            0 :                                                            pw1%pw_grid%para%bo, debug=test)
    1415              :                                              END IF
    1416              :                                              !..prepare output
    1417      1399352 :                                              IF (test .AND. out_unit > 0) &
    1418            0 :                                                 WRITE (out_unit, '(A)') "  PW_GATHER : 2d -> 1d "
    1419      1399352 :                                              CALL pw_gather_p_${kind2}$ (pw2, grays)
    1420      1399352 :                                              DEALLOCATE (c_in)
    1421              : 
    1422              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1423              :                                           END IF
    1424              : #endif
    1425              :                                        #:endif
    1426              :                                     #:else
    1427              :                                        #:if kind=="c1d" and kind2=="c3d"
    1428              :                                           !..prepare input
    1429          536 :                                           IF (test .AND. out_unit > 0) &
    1430            4 :                                              WRITE (out_unit, '(A)') "  PW_SCATTER : 2d -> 1d "
    1431      1918288 :                                           grays = z_zero
    1432          536 :                                           CALL pw_scatter_p_${kind}$ (pw1, grays)
    1433          536 :                                           c_in => pw2%array
    1434              :                                           !..transform
    1435          536 :                                           IF (pw1%pw_grid%para%ray_distribution) THEN
    1436              :                                              CALL fft3d(BWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1437              :                                                         pw1%pw_grid%para%yzp, pw1%pw_grid%para%nyzray, &
    1438          432 :                                                         pw1%pw_grid%para%bo, debug=test)
    1439              :                                           ELSE
    1440              :                                              CALL fft3d(BWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1441          104 :                                                         pw1%pw_grid%para%bo, debug=test)
    1442              :                                           END IF
    1443              :                                           !..prepare output (nothing to do)
    1444              :                                        #:elif kind=="c1d" and kind2=="r3d"
    1445              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1446              :                                           ! (no ray dist. is not efficient in CUDA)
    1447              :                                           use_pw_gpu = pw1%pw_grid%para%ray_distribution
    1448              :                                           IF (use_pw_gpu) THEN
    1449              :                                              CALL pw_gpu_c1dr3d_3d_ps(pw1, pw2)
    1450              :                                           ELSE
    1451              : #endif
    1452              : !..   prepare input
    1453      1418918 :                                              IF (test .AND. out_unit > 0) &
    1454            0 :                                                 WRITE (out_unit, '(A)') "  PW_SCATTER : 2d -> 1d "
    1455  45266033596 :                                              grays = z_zero
    1456      1418918 :                                              CALL pw_scatter_p_${kind}$ (pw1, grays)
    1457      5675672 :                                              nloc = pw2%pw_grid%npts_local
    1458      7094590 :                                              ALLOCATE (c_in(nloc(1), nloc(2), nloc(3)))
    1459              :                                              !..transform
    1460      1418918 :                                              IF (pw1%pw_grid%para%ray_distribution) THEN
    1461              :                                                 CALL fft3d(BWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1462              :                                                            pw1%pw_grid%para%yzp, pw1%pw_grid%para%nyzray, &
    1463      1418918 :                                                            pw1%pw_grid%para%bo, debug=test)
    1464              :                                              ELSE
    1465              :                                                 CALL fft3d(BWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1466            0 :                                                            pw1%pw_grid%para%bo, debug=test)
    1467              :                                              END IF
    1468              :                                              !..prepare output
    1469      1418918 :                                              IF (test .AND. out_unit > 0) &
    1470            0 :                                                 WRITE (out_unit, '(A)') "  Real part "
    1471      1418918 :                                              CALL pw_copy_from_array(pw2, c_in)
    1472      1418918 :                                              DEALLOCATE (c_in)
    1473              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1474              :                                           END IF
    1475              : #endif
    1476              :                                        #:endif
    1477              :                                     #:endif
    1478              :                                  END IF
    1479              : 
    1480      3434847 :                                  IF (test .AND. out_unit > 0) THEN
    1481            8 :                                     WRITE (out_unit, '(A)') " End of FFT Protocol "
    1482              :                                  END IF
    1483              : 
    1484      3434847 :                                  CALL timestop(handle)
    1485      3434847 :                                  CALL timestop(handle2)
    1486              : 
    1487      3434847 :                               END SUBROUTINE fft_wrap_pw1pw2_${kind}$_${kind2}$_${space}$_${space2}$
    1488              :                            #:endif
    1489              :                         #:endfor
    1490              :                      #:endfor
    1491              : 
    1492              :                      #:if kind[1]=='1' and kind2[1]=='3'
    1493              : 
    1494              : ! **************************************************************************************************
    1495              : !> \brief Gathers the pw vector from a 3d data field
    1496              : !> \param pw ...
    1497              : !> \param c ...
    1498              : !> \param scale ...
    1499              : !> \par History
    1500              : !>      none
    1501              : !> \author JGH
    1502              : ! **************************************************************************************************
    1503            0 :                         SUBROUTINE pw_gather_s_${kind}$_${kind2}$_2(pw1, pw2, scale)
    1504              : 
    1505              :                            TYPE(pw_${kind2}$_gs_type), INTENT(IN)                       :: pw1
    1506              :                            TYPE(pw_${kind}$_gs_type), INTENT(INOUT)   :: pw2
    1507              :                            REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
    1508              : 
    1509            0 :                            CALL pw_gather_s_${kind}$_${kind2}$ (pw2, pw1%array, scale)
    1510              : 
    1511            0 :                         END SUBROUTINE pw_gather_s_${kind}$_${kind2}$_2
    1512              : 
    1513              : ! **************************************************************************************************
    1514              : !> \brief Gathers the pw vector from a 3d data field
    1515              : !> \param pw ...
    1516              : !> \param c ...
    1517              : !> \param scale ...
    1518              : !> \par History
    1519              : !>      none
    1520              : !> \author JGH
    1521              : ! **************************************************************************************************
    1522       299598 :                         SUBROUTINE pw_gather_s_${kind}$_${kind2}$ (pw, c, scale)
    1523              : 
    1524              :                            TYPE(pw_${kind}$_gs_type), INTENT(INOUT)                       :: pw
    1525              :                            ${type2}$, CONTIGUOUS, INTENT(IN)   :: c
    1526              :                            REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
    1527              : 
    1528              :                            CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_gather_s'
    1529              : 
    1530              :                            INTEGER                                            :: gpt, handle, l, m, n
    1531              : 
    1532       299598 :                            CALL timeset(routineN, handle)
    1533              : 
    1534              :                            ASSOCIATE (mapl => pw%pw_grid%mapl%pos, mapm => pw%pw_grid%mapm%pos, mapn => pw%pw_grid%mapn%pos, &
    1535              :                                       ngpts => SIZE(pw%pw_grid%gsq), ghat => pw%pw_grid%g_hat)
    1536              : 
    1537       299598 :                               IF (PRESENT(scale)) THEN
    1538            0 : !$OMP PARALLEL DO PRIVATE(gpt, l, m, n) DEFAULT(NONE) SHARED(c, pw, scale)
    1539              :                                  DO gpt = 1, ngpts
    1540              :                                     l = mapl(ghat(1, gpt)) + 1
    1541              :                                     m = mapm(ghat(2, gpt)) + 1
    1542              :                                     n = mapn(ghat(3, gpt)) + 1
    1543              :                                     pw%array(gpt) = scale*${type2type("c(l, m, n)", kind2, kind)}$
    1544              :                                  END DO
    1545              : !$OMP END PARALLEL DO
    1546              :                               ELSE
    1547       299598 : !$OMP PARALLEL DO PRIVATE(gpt, l, m, n) DEFAULT(NONE) SHARED(c, pw)
    1548              :                                  DO gpt = 1, ngpts
    1549              :                                     l = mapl(ghat(1, gpt)) + 1
    1550              :                                     m = mapm(ghat(2, gpt)) + 1
    1551              :                                     n = mapn(ghat(3, gpt)) + 1
    1552              :                                     pw%array(gpt) = ${type2type("c(l, m, n)", kind2, kind)}$
    1553              :                                  END DO
    1554              : !$OMP END PARALLEL DO
    1555              :                               END IF
    1556              : 
    1557              :                            END ASSOCIATE
    1558              : 
    1559       299598 :                            CALL timestop(handle)
    1560              : 
    1561       299598 :                         END SUBROUTINE pw_gather_s_${kind}$_${kind2}$
    1562              : 
    1563              : ! **************************************************************************************************
    1564              : !> \brief Scatters a pw vector to a 3d data field
    1565              : !> \param pw ...
    1566              : !> \param c ...
    1567              : !> \param scale ...
    1568              : !> \par History
    1569              : !>      none
    1570              : !> \author JGH
    1571              : ! **************************************************************************************************
    1572            0 :                         SUBROUTINE pw_scatter_s_${kind}$_${kind2}$_2(pw1, pw2, scale)
    1573              : 
    1574              :                            TYPE(pw_${kind}$_gs_type), INTENT(IN)                 :: pw1
    1575              :                            TYPE(pw_${kind2}$_gs_type), INTENT(INOUT)               :: pw2
    1576              :                            REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
    1577              : 
    1578            0 :                            CALL pw_scatter_s_${kind}$_${kind2}$ (pw1, pw2%array, scale)
    1579              : 
    1580            0 :                         END SUBROUTINE pw_scatter_s_${kind}$_${kind2}$_2
    1581              : 
    1582              : ! **************************************************************************************************
    1583              : !> \brief Scatters a pw vector to a 3d data field
    1584              : !> \param pw ...
    1585              : !> \param c ...
    1586              : !> \param scale ...
    1587              : !> \par History
    1588              : !>      none
    1589              : !> \author JGH
    1590              : ! **************************************************************************************************
    1591       315907 :                         SUBROUTINE pw_scatter_s_${kind}$_${kind2}$ (pw, c, scale)
    1592              : 
    1593              :                            TYPE(pw_${kind}$_gs_type), INTENT(IN)                 :: pw
    1594              :                            ${type2}$, CONTIGUOUS, INTENT(INOUT)               :: c
    1595              :                            REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
    1596              : 
    1597              :                            CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_scatter_s'
    1598              : 
    1599              :                            INTEGER                                            :: gpt, handle, l, m, n
    1600              : 
    1601       315907 :                            CALL timeset(routineN, handle)
    1602              : 
    1603              :                            ASSOCIATE (mapl => pw%pw_grid%mapl%pos, mapm => pw%pw_grid%mapm%pos, mapn => pw%pw_grid%mapn%pos, &
    1604              :                                       ghat => pw%pw_grid%g_hat, ngpts => SIZE(pw%pw_grid%gsq))
    1605              : 
    1606              :                               ! should only zero the unused bits (but the zero is needed)
    1607   2726346966 :                               IF (.NOT. PRESENT(scale)) c = 0.0_dp
    1608              : 
    1609       315907 :                               IF (PRESENT(scale)) THEN
    1610            0 : !$OMP PARALLEL DO PRIVATE(gpt, l, m, n) DEFAULT(NONE) SHARED(c, pw, scale)
    1611              :                                  DO gpt = 1, ngpts
    1612              :                                     l = mapl(ghat(1, gpt)) + 1
    1613              :                                     m = mapm(ghat(2, gpt)) + 1
    1614              :                                     n = mapn(ghat(3, gpt)) + 1
    1615              :                                     c(l, m, n) = scale*${type2type("pw%array(gpt)", kind, kind2)}$
    1616              :                                  END DO
    1617              : !$OMP END PARALLEL DO
    1618              :                               ELSE
    1619       315907 : !$OMP PARALLEL DO PRIVATE(gpt, l, m, n) DEFAULT(NONE) SHARED(c, pw)
    1620              :                                  DO gpt = 1, ngpts
    1621              :                                     l = mapl(ghat(1, gpt)) + 1
    1622              :                                     m = mapm(ghat(2, gpt)) + 1
    1623              :                                     n = mapn(ghat(3, gpt)) + 1
    1624              :                                     c(l, m, n) = ${type2type("pw%array(gpt)", kind, kind2)}$
    1625              :                                  END DO
    1626              : !$OMP END PARALLEL DO
    1627              :                               END IF
    1628              : 
    1629              :                            END ASSOCIATE
    1630              : 
    1631       315907 :                            IF (pw%pw_grid%grid_span == HALFSPACE) THEN
    1632              : 
    1633              :                               ASSOCIATE (mapl => pw%pw_grid%mapl%neg, mapm => pw%pw_grid%mapm%neg, mapn => pw%pw_grid%mapn%neg, &
    1634              :                                          ghat => pw%pw_grid%g_hat, ngpts => SIZE(pw%pw_grid%gsq))
    1635              : 
    1636         8922 :                                  IF (PRESENT(scale)) THEN
    1637            0 : !$OMP PARALLEL DO PRIVATE(gpt, l, m, n) DEFAULT(NONE) SHARED(c, pw, scale)
    1638              :                                     DO gpt = 1, ngpts
    1639              :                                        l = mapl(ghat(1, gpt)) + 1
    1640              :                                        m = mapm(ghat(2, gpt)) + 1
    1641              :                                        n = mapn(ghat(3, gpt)) + 1
    1642              :                                        c(l, m, n) = scale*#{if kind[0]=="c" and kind2[0]=="c"}#CONJG#{endif}#(${type2type("pw%array(gpt)", kind, kind2)}$)
    1643              :                                     END DO
    1644              : !$OMP END PARALLEL DO
    1645              :                                  ELSE
    1646         8922 : !$OMP PARALLEL DO PRIVATE(gpt, l, m, n) DEFAULT(NONE) SHARED(c, pw)
    1647              :                                     DO gpt = 1, ngpts
    1648              :                                        l = mapl(ghat(1, gpt)) + 1
    1649              :                                        m = mapm(ghat(2, gpt)) + 1
    1650              :                                        n = mapn(ghat(3, gpt)) + 1
    1651              :                                        c(l, m, n) = #{if kind[0]=="c" and kind2[0]=="c"}#CONJG#{endif}#(${type2type("pw%array(gpt)", kind, kind2)}$)
    1652              :                                     END DO
    1653              : !$OMP END PARALLEL DO
    1654              :                                  END IF
    1655              : 
    1656              :                               END ASSOCIATE
    1657              : 
    1658              :                            END IF
    1659              : 
    1660       315907 :                            CALL timestop(handle)
    1661              : 
    1662       315907 :                         END SUBROUTINE pw_scatter_s_${kind}$_${kind2}$
    1663              :                      #:endif
    1664              :                   #:endfor
    1665              : 
    1666              : ! **************************************************************************************************
    1667              : !> \brief Multiply all data points with a Gaussian damping factor
    1668              : !>        Needed for longrange Coulomb potential
    1669              : !>        V(\vec r)=erf(omega*r)/r
    1670              : !>        V(\vec g)=\frac{4*\pi}{g**2}*exp(-g**2/omega**2)
    1671              : !> \param pw ...
    1672              : !> \param omega ...
    1673              : !> \par History
    1674              : !>      Frederick Stein (12-04-2019) created
    1675              : !> \author Frederick Stein (12-Apr-2019)
    1676              : !> \note
    1677              : !>      Performs a Gaussian damping
    1678              : ! **************************************************************************************************
    1679         3841 :                   SUBROUTINE pw_gauss_damp(pw, omega)
    1680              : 
    1681              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1682              :                      REAL(KIND=dp), INTENT(IN)                          :: omega
    1683              : 
    1684              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_gauss_damp'
    1685              : 
    1686              :                      INTEGER                                            :: handle, i
    1687              :                      REAL(KIND=dp)                                      :: omega_2, tmp
    1688              : 
    1689         3841 :                      CALL timeset(routineN, handle)
    1690         3841 :                      CPASSERT(omega >= 0)
    1691              : 
    1692         3841 :                      omega_2 = omega*omega
    1693         3841 :                      omega_2 = 0.25_dp/omega_2
    1694              : 
    1695         3841 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp) SHARED(pw,omega_2)
    1696              :                      DO i = 1, SIZE(pw%array)
    1697              :                         tmp = EXP(-pw%pw_grid%gsq(i)*omega_2)
    1698              :                         pw%array(i) = pw%array(i)*tmp
    1699              :                      END DO
    1700              : !$OMP END PARALLEL DO
    1701              : 
    1702         3841 :                      CALL timestop(handle)
    1703              : 
    1704         3841 :                   END SUBROUTINE pw_gauss_damp
    1705              : 
    1706              : ! **************************************************************************************************
    1707              : !> \brief Multiply all data points with the logarithmic derivative of a Gaussian
    1708              : !> \param pw ...
    1709              : !> \param omega ...
    1710              : !> \note
    1711              : !>      Performs a Gaussian damping
    1712              : ! **************************************************************************************************
    1713         1329 :                   SUBROUTINE pw_log_deriv_gauss(pw, omega)
    1714              : 
    1715              :                      TYPE(pw_c1d_gs_type), INTENT(IN)                          :: pw
    1716              :                      REAL(KIND=dp), INTENT(IN)                          :: omega
    1717              : 
    1718              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_log_deriv_gauss'
    1719              : 
    1720              :                      INTEGER                                            :: handle, i
    1721              :                      REAL(KIND=dp)                                      :: omega_2, tmp
    1722              : 
    1723         1329 :                      CALL timeset(routineN, handle)
    1724         1329 :                      CPASSERT(omega >= 0)
    1725              : 
    1726         1329 :                      omega_2 = omega*omega
    1727         1329 :                      omega_2 = 0.25_dp/omega_2
    1728              : 
    1729         1329 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp) SHARED(pw,omega_2)
    1730              :                      DO i = 1, SIZE(pw%array)
    1731              :                         tmp = 1.0_dp + omega_2*pw%pw_grid%gsq(i)
    1732              :                         pw%array(i) = pw%array(i)*tmp
    1733              :                      END DO
    1734              : !$OMP END PARALLEL DO
    1735              : 
    1736         1329 :                      CALL timestop(handle)
    1737         1329 :                   END SUBROUTINE pw_log_deriv_gauss
    1738              : 
    1739              : ! **************************************************************************************************
    1740              : !> \brief Multiply all data points with a Gaussian damping factor
    1741              : !>        Needed for longrange Coulomb potential
    1742              : !>        V(\vec r)=erf(omega*r)/r
    1743              : !>        V(\vec g)=\frac{4*\pi}{g**2}*exp(-g**2/omega**2)
    1744              : !> \param pw ...
    1745              : !> \param omega ...
    1746              : !> \par History
    1747              : !>      Frederick Stein (12-04-2019) created
    1748              : !> \author Frederick Stein (12-Apr-2019)
    1749              : !> \note
    1750              : !>      Performs a Gaussian damping
    1751              : ! **************************************************************************************************
    1752            0 :                   SUBROUTINE pw_compl_gauss_damp(pw, omega)
    1753              : 
    1754              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1755              :                      REAL(KIND=dp), INTENT(IN)                          :: omega
    1756              : 
    1757              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_compl_gauss_damp'
    1758              : 
    1759              :                      INTEGER                                            :: cnt, handle, i
    1760              :                      REAL(KIND=dp)                                      :: omega_2, tmp, tmp2
    1761              : 
    1762            0 :                      CALL timeset(routineN, handle)
    1763              : 
    1764            0 :                      omega_2 = omega*omega
    1765            0 :                      omega_2 = 0.25_dp/omega_2
    1766              : 
    1767            0 :                      cnt = SIZE(pw%array)
    1768              : 
    1769            0 : !$OMP PARALLEL DO PRIVATE(i, tmp, tmp2) DEFAULT(NONE) SHARED(cnt, pw,omega_2)
    1770              :                      DO i = 1, cnt
    1771              :                         tmp = -omega_2*pw%pw_grid%gsq(i)
    1772              :                         IF (ABS(tmp) > 1.0E-5_dp) THEN
    1773              :                            tmp2 = 1.0_dp - EXP(tmp)
    1774              :                         ELSE
    1775              :                            tmp2 = tmp + 0.5_dp*tmp*(tmp + (1.0_dp/3.0_dp)*tmp**2)
    1776              :                         END IF
    1777              :                         pw%array(i) = pw%array(i)*tmp2
    1778              :                      END DO
    1779              : !$OMP END PARALLEL DO
    1780              : 
    1781            0 :                      CALL timestop(handle)
    1782              : 
    1783            0 :                   END SUBROUTINE pw_compl_gauss_damp
    1784              : 
    1785              : ! **************************************************************************************************
    1786              : !> \brief Multiply all data points with the logarithmic derivative of the complementary Gaussian damping factor
    1787              : !> \param pw ...
    1788              : !> \param omega ...
    1789              : !> \note
    1790              : ! **************************************************************************************************
    1791            0 :                   SUBROUTINE pw_log_deriv_compl_gauss(pw, omega)
    1792              : 
    1793              :                      TYPE(pw_c1d_gs_type), INTENT(IN)                          :: pw
    1794              :                      REAL(KIND=dp), INTENT(IN)                          :: omega
    1795              : 
    1796              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_log_deriv_compl_gauss'
    1797              : 
    1798              :                      INTEGER                                            :: handle, i
    1799              :                      REAL(KIND=dp)                                      :: omega_2, tmp, tmp2
    1800              : 
    1801            0 :                      CALL timeset(routineN, handle)
    1802              : 
    1803            0 :                      omega_2 = omega*omega
    1804            0 :                      omega_2 = 0.25_dp/omega_2
    1805              : 
    1806              : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp,tmp2) &
    1807            0 : !$OMP             SHARED(pw,omega_2)
    1808              :                      DO i = 1, SIZE(pw%array)
    1809              :                         tmp = omega_2*pw%pw_grid%gsq(i)
    1810              :                         ! For too small arguments, use the Taylor polynomial to prevent division by zero
    1811              :                         IF (ABS(tmp) >= 0.003_dp) THEN
    1812              :                            tmp2 = 1.0_dp - tmp*EXP(-tmp)/(1.0_dp - EXP(-tmp))
    1813              :                         ELSE
    1814              :                            tmp2 = 0.5_dp*tmp - tmp**2/12.0_dp
    1815              :                         END IF
    1816              :                         pw%array(i) = pw%array(i)*tmp2
    1817              :                      END DO
    1818              : !$OMP END PARALLEL DO
    1819              : 
    1820            0 :                      CALL timestop(handle)
    1821              : 
    1822            0 :                   END SUBROUTINE pw_log_deriv_compl_gauss
    1823              : 
    1824              : ! **************************************************************************************************
    1825              : !> \brief Multiply all data points with a Gaussian damping factor and mixes it with the original function
    1826              : !>        Needed for mixed longrange/Coulomb potential
    1827              : !>        V(\vec r)=(a+b*erf(omega*r))/r
    1828              : !>        V(\vec g)=\frac{4*\pi}{g**2}*(a+b*exp(-g**2/omega**2))
    1829              : !> \param pw ...
    1830              : !> \param omega ...
    1831              : !> \param scale_coul ...
    1832              : !> \param scale_long ...
    1833              : !> \par History
    1834              : !>      Frederick Stein (16-Dec-2021) created
    1835              : !> \author Frederick Stein (16-Dec-2021)
    1836              : !> \note
    1837              : !>      Performs a Gaussian damping
    1838              : ! **************************************************************************************************
    1839          332 :                   SUBROUTINE pw_gauss_damp_mix(pw, omega, scale_coul, scale_long)
    1840              : 
    1841              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1842              :                      REAL(KIND=dp), INTENT(IN)                          :: omega, scale_coul, scale_long
    1843              : 
    1844              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_gauss_damp_mix'
    1845              : 
    1846              :                      INTEGER                                            :: handle, i
    1847              :                      REAL(KIND=dp)                                      :: omega_2, tmp
    1848              : 
    1849          332 :                      CALL timeset(routineN, handle)
    1850              : 
    1851          332 :                      omega_2 = omega*omega
    1852          332 :                      omega_2 = 0.25_dp/omega_2
    1853              : 
    1854          332 : !$OMP PARALLEL DO DEFAULT(NONE) SHARED(pw, omega_2, scale_coul, scale_long) PRIVATE(i,tmp)
    1855              :                      DO i = 1, SIZE(pw%array)
    1856              :                         tmp = scale_coul + scale_long*EXP(-pw%pw_grid%gsq(i)*omega_2)
    1857              :                         pw%array(i) = pw%array(i)*tmp
    1858              :                      END DO
    1859              : !$OMP END PARALLEL DO
    1860              : 
    1861          332 :                      CALL timestop(handle)
    1862              : 
    1863          332 :                   END SUBROUTINE pw_gauss_damp_mix
    1864              : 
    1865              : ! **************************************************************************************************
    1866              : !> \brief Multiply all data points with the logarithmic derivative of the mixed longrange/Coulomb potential
    1867              : !>        Needed for mixed longrange/Coulomb potential
    1868              : !> \param pw ...
    1869              : !> \param omega ...
    1870              : !> \param scale_coul ...
    1871              : !> \param scale_long ...
    1872              : !> \note
    1873              : ! **************************************************************************************************
    1874          249 :                   SUBROUTINE pw_log_deriv_mix_cl(pw, omega, scale_coul, scale_long)
    1875              : 
    1876              :                      TYPE(pw_c1d_gs_type), INTENT(IN)                          :: pw
    1877              :                      REAL(KIND=dp), INTENT(IN)                          :: omega, scale_coul, scale_long
    1878              : 
    1879              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_log_deriv_mix_cl'
    1880              : 
    1881              :                      INTEGER                                            :: handle, i
    1882              :                      REAL(KIND=dp)                                      :: omega_2, tmp, tmp2
    1883              : 
    1884          249 :                      CALL timeset(routineN, handle)
    1885              : 
    1886          249 :                      omega_2 = omega*omega
    1887          249 :                      omega_2 = 0.25_dp/omega_2
    1888              : 
    1889              : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp,tmp2) &
    1890          249 : !$OMP             SHARED(pw,omega_2,scale_long,scale_coul)
    1891              :                      DO i = 1, SIZE(pw%array)
    1892              :                         tmp = omega_2*pw%pw_grid%gsq(i)
    1893              :                         tmp2 = 1.0_dp + scale_long*tmp*EXP(-tmp)/(scale_coul + scale_long*EXP(-tmp))
    1894              :                         pw%array(i) = pw%array(i)*tmp2
    1895              :                      END DO
    1896              : !$OMP END PARALLEL DO
    1897              : 
    1898          249 :                      CALL timestop(handle)
    1899              : 
    1900          249 :                   END SUBROUTINE pw_log_deriv_mix_cl
    1901              : 
    1902              : ! **************************************************************************************************
    1903              : !> \brief Multiply all data points with a complementary cosine
    1904              : !>        Needed for truncated Coulomb potential
    1905              : !>        V(\vec r)=1/r if r<rc, 0 else
    1906              : !>        V(\vec g)=\frac{4*\pi}{g**2}*(1-cos(g*rc))
    1907              : !> \param pw ...
    1908              : !> \param rcutoff ...
    1909              : !> \par History
    1910              : !>      Frederick Stein (07-06-2021) created
    1911              : !> \author Frederick Stein (07-Jun-2021)
    1912              : !> \note
    1913              : !>      Multiplies by complementary cosine
    1914              : ! **************************************************************************************************
    1915            0 :                   SUBROUTINE pw_truncated(pw, rcutoff)
    1916              : 
    1917              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1918              :                      REAL(KIND=dp), INTENT(IN)                          :: rcutoff
    1919              : 
    1920              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_truncated'
    1921              : 
    1922              :                      INTEGER                                            :: handle, i
    1923              :                      REAL(KIND=dp)                                      :: tmp, tmp2
    1924              : 
    1925            0 :                      CALL timeset(routineN, handle)
    1926            0 :                      CPASSERT(rcutoff >= 0)
    1927              : 
    1928            0 : !$OMP PARALLEL DO PRIVATE(i,tmp,tmp2) DEFAULT(NONE) SHARED(pw, rcutoff)
    1929              :                      DO i = 1, SIZE(pw%array)
    1930              :                         tmp = SQRT(pw%pw_grid%gsq(i))*rcutoff
    1931              :                         IF (tmp >= 0.005_dp) THEN
    1932              :                            tmp2 = 1.0_dp - COS(tmp)
    1933              :                         ELSE
    1934              :                            tmp2 = tmp**2/2.0_dp*(1.0 - tmp**2/12.0_dp)
    1935              :                         END IF
    1936              :                         pw%array(i) = pw%array(i)*tmp2
    1937              :                      END DO
    1938              : !$OMP END PARALLEL DO
    1939              : 
    1940            0 :                      CALL timestop(handle)
    1941              : 
    1942            0 :                   END SUBROUTINE pw_truncated
    1943              : 
    1944              : ! **************************************************************************************************
    1945              : !> \brief Multiply all data points with the logarithmic derivative of the complementary cosine
    1946              : !>        This function is needed for virials using truncated Coulomb potentials
    1947              : !> \param pw ...
    1948              : !> \param rcutoff ...
    1949              : !> \note
    1950              : ! **************************************************************************************************
    1951            0 :                   SUBROUTINE pw_log_deriv_trunc(pw, rcutoff)
    1952              : 
    1953              :                      TYPE(pw_c1d_gs_type), INTENT(IN)                          :: pw
    1954              :                      REAL(KIND=dp), INTENT(IN)                          :: rcutoff
    1955              : 
    1956              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_log_deriv_trunc'
    1957              : 
    1958              :                      INTEGER                                            :: handle, i
    1959              :                      REAL(KIND=dp)                                      :: rchalf, tmp, tmp2
    1960              : 
    1961            0 :                      CALL timeset(routineN, handle)
    1962            0 :                      CPASSERT(rcutoff >= 0)
    1963              : 
    1964            0 :                      rchalf = 0.5_dp*rcutoff
    1965              : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp,tmp2) &
    1966            0 : !$OMP             SHARED(pw,rchalf)
    1967              :                      DO i = 1, SIZE(pw%array)
    1968              :                         tmp = rchalf*SQRT(pw%pw_grid%gsq(i))
    1969              :                         ! For too small arguments, use the Taylor polynomial to prevent division by zero
    1970              :                         IF (ABS(tmp) >= 0.0001_dp) THEN
    1971              :                            tmp2 = 1.0_dp - tmp/TAN(tmp)
    1972              :                         ELSE
    1973              :                            tmp2 = tmp**2*(1.0_dp + tmp**2/15.0_dp)/3.0_dp
    1974              :                         END IF
    1975              :                         pw%array(i) = pw%array(i)*tmp2
    1976              :                      END DO
    1977              : !$OMP END PARALLEL DO
    1978              : 
    1979            0 :                      CALL timestop(handle)
    1980              : 
    1981            0 :                   END SUBROUTINE pw_log_deriv_trunc
    1982              : 
    1983              : ! **************************************************************************************************
    1984              : !> \brief Calculate the derivative of a plane wave vector
    1985              : !> \param pw ...
    1986              : !> \param n ...
    1987              : !> \par History
    1988              : !>      JGH (06-10-2002) allow only for inplace derivatives
    1989              : !> \author JGH (25-Feb-2001)
    1990              : !> \note
    1991              : !>      Calculate the derivative dx^n(1) dy^n(2) dz^n(3) PW
    1992              : ! **************************************************************************************************
    1993      1346883 :                   SUBROUTINE pw_derive(pw, n)
    1994              : 
    1995              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1996              :                      INTEGER, DIMENSION(3), INTENT(IN)                  :: n
    1997              : 
    1998              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_derive'
    1999              : 
    2000              :                      COMPLEX(KIND=dp)                                   :: im
    2001              :                      INTEGER                                            :: handle, m, idx, idir
    2002              : 
    2003      1346883 :                      CALL timeset(routineN, handle)
    2004              : 
    2005      5387532 :                      IF (ANY(n < 0)) &
    2006            0 :                         CPABORT("Nonnegative exponents are not supported!")
    2007              : 
    2008      5387532 :                      m = SUM(n)
    2009      1346883 :                      im = gaussi**m
    2010              : 
    2011      5387532 :                      DO idir = 1, 3
    2012      5387532 :                         IF (n(idir) == 1) THEN
    2013      1346883 : !$OMP PARALLEL DO DEFAULT(NONE) SHARED(pw,idir) PRIVATE(idx)
    2014              :                            DO idx = 1, SIZE(pw%array)
    2015              :                               pw%array(idx) = pw%array(idx)*pw%pw_grid%g(idir, idx)
    2016              :                            END DO
    2017              : !$OMP END PARALLEL DO
    2018      2693766 :                         ELSE IF (n(idir) > 1) THEN
    2019          450 : !$OMP PARALLEL DO DEFAULT(NONE) SHARED(n, pw,idir) PRIVATE(idx)
    2020              :                            DO idx = 1, SIZE(pw%array)
    2021              :                               pw%array(idx) = pw%array(idx)*pw%pw_grid%g(idir, idx)**n(idir)
    2022              :                            END DO
    2023              : !$OMP END PARALLEL DO
    2024              :                         END IF
    2025              :                      END DO
    2026              : 
    2027              :                      ! im can take the values 1, -1, i, -i
    2028              :                      ! skip this if im == 1
    2029      1346883 :                      IF (ABS(REAL(im, KIND=dp) - 1.0_dp) > 1.0E-10_dp) THEN
    2030      1346883 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(im, pw)
    2031              :                         pw%array(:) = im*pw%array(:)
    2032              : !$OMP END PARALLEL WORKSHARE
    2033              :                      END IF
    2034              : 
    2035      1346883 :                      CALL timestop(handle)
    2036              : 
    2037      1346883 :                   END SUBROUTINE pw_derive
    2038              : 
    2039              : ! **************************************************************************************************
    2040              : !> \brief Calculate the Laplacian of a plane wave vector
    2041              : !> \param pw ...
    2042              : !> \par History
    2043              : !>      Frederick Stein (01-02-2022) created
    2044              : !> \author JGH (25-Feb-2001)
    2045              : !> \note
    2046              : !>      Calculate the derivative DELTA PW
    2047              : ! **************************************************************************************************
    2048         2982 :                   SUBROUTINE pw_laplace(pw)
    2049              : 
    2050              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    2051              : 
    2052              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_laplace'
    2053              : 
    2054              :                      INTEGER                                            :: handle
    2055              : 
    2056         2982 :                      CALL timeset(routineN, handle)
    2057              : 
    2058         2982 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw)
    2059              :                      pw%array(:) = -pw%array(:)*pw%pw_grid%gsq(:)
    2060              : !$OMP END PARALLEL WORKSHARE
    2061              : 
    2062         2982 :                      CALL timestop(handle)
    2063              : 
    2064         2982 :                   END SUBROUTINE pw_laplace
    2065              : 
    2066              : ! **************************************************************************************************
    2067              : !> \brief Calculate the tensorial 2nd derivative of a plane wave vector
    2068              : !> \param pw ...
    2069              : !> \param pwdr2 ...
    2070              : !> \param i ...
    2071              : !> \param j ...
    2072              : !> \par History
    2073              : !>      none
    2074              : !> \author JGH (05-May-2006)
    2075              : !> \note
    2076              : ! **************************************************************************************************
    2077          198 :                   SUBROUTINE pw_dr2(pw, pwdr2, i, j)
    2078              : 
    2079              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw, pwdr2
    2080              :                      INTEGER, INTENT(IN)                                :: i, j
    2081              : 
    2082              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_dr2'
    2083              : 
    2084              :                      INTEGER                                            :: cnt, handle, ig
    2085              :                      REAL(KIND=dp)                                      :: gg, o3
    2086              : 
    2087          198 :                      CALL timeset(routineN, handle)
    2088              : 
    2089          198 :                      o3 = 1.0_dp/3.0_dp
    2090              : 
    2091          198 :                      cnt = SIZE(pw%array)
    2092              : 
    2093          198 :                      IF (i == j) THEN
    2094          108 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(ig,gg) SHARED(cnt, i, o3, pw, pwdr2)
    2095              :                         DO ig = 1, cnt
    2096              :                            gg = pw%pw_grid%g(i, ig)**2 - o3*pw%pw_grid%gsq(ig)
    2097              :                            pwdr2%array(ig) = gg*pw%array(ig)
    2098              :                         END DO
    2099              : !$OMP END PARALLEL DO
    2100              :                      ELSE
    2101           90 : !$OMP PARALLEL DO PRIVATE (ig) DEFAULT(NONE) SHARED(cnt, i, j, pw, pwdr2)
    2102              :                         DO ig = 1, cnt
    2103              :                            pwdr2%array(ig) = pw%array(ig)*(pw%pw_grid%g(i, ig)*pw%pw_grid%g(j, ig))
    2104              :                         END DO
    2105              : !$OMP END PARALLEL DO
    2106              :                      END IF
    2107              : 
    2108          198 :                      CALL timestop(handle)
    2109              : 
    2110          198 :                   END SUBROUTINE pw_dr2
    2111              : 
    2112              : ! **************************************************************************************************
    2113              : !> \brief Calculate the tensorial 2nd derivative of a plane wave vector
    2114              : !>      and divides by |G|^2. pwdr2_gg(G=0) is put to zero.
    2115              : !> \param pw ...
    2116              : !> \param pwdr2_gg ...
    2117              : !> \param i ...
    2118              : !> \param j ...
    2119              : !> \par History
    2120              : !>      none
    2121              : !> \author RD (20-Nov-2006)
    2122              : !> \note
    2123              : !>      Adapted from pw_dr2
    2124              : ! **************************************************************************************************
    2125           12 :                   SUBROUTINE pw_dr2_gg(pw, pwdr2_gg, i, j)
    2126              : 
    2127              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw, pwdr2_gg
    2128              :                      INTEGER, INTENT(IN)                                :: i, j
    2129              : 
    2130              :                      INTEGER                                            :: cnt, handle, ig
    2131              :                      REAL(KIND=dp)                                      :: gg, o3
    2132              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_dr2_gg'
    2133              : 
    2134           12 :                      CALL timeset(routineN, handle)
    2135              : 
    2136           12 :                      o3 = 1.0_dp/3.0_dp
    2137              : 
    2138           12 :                      cnt = SIZE(pw%array)
    2139              : 
    2140           12 :                      IF (i == j) THEN
    2141            6 : !$OMP PARALLEL DO PRIVATE (ig) DEFAULT(NONE) PRIVATE(gg) SHARED(cnt, i, o3, pw, pwdr2_gg)
    2142              :                         DO ig = pw%pw_grid%first_gne0, cnt
    2143              :                            gg = pw%pw_grid%g(i, ig)**2 - o3*pw%pw_grid%gsq(ig)
    2144              :                            pwdr2_gg%array(ig) = gg/pw%pw_grid%gsq(ig)*pw%array(ig)
    2145              :                         END DO
    2146              : !$OMP END PARALLEL DO
    2147              :                      ELSE
    2148            6 : !$OMP PARALLEL DO PRIVATE (ig) DEFAULT(NONE) SHARED(cnt, i, j, pw, pwdr2_gg)
    2149              :                         DO ig = pw%pw_grid%first_gne0, cnt
    2150              :                            pwdr2_gg%array(ig) = pw%array(ig)*((pw%pw_grid%g(i, ig)*pw%pw_grid%g(j, ig)) &
    2151              :                                                               /pw%pw_grid%gsq(ig))
    2152              :                         END DO
    2153              : !$OMP END PARALLEL DO
    2154              :                      END IF
    2155              : 
    2156           12 :                      IF (pw%pw_grid%have_g0) pwdr2_gg%array(1) = 0.0_dp
    2157              : 
    2158           12 :                      CALL timestop(handle)
    2159              : 
    2160           12 :                   END SUBROUTINE pw_dr2_gg
    2161              : 
    2162              : ! **************************************************************************************************
    2163              : !> \brief Multiplies a G-space function with a smoothing factor of the form
    2164              : !>      f(|G|) = exp((ecut - G^2)/sigma)/(1+exp((ecut - G^2)/sigma))
    2165              : !> \param pw ...
    2166              : !> \param ecut ...
    2167              : !> \param sigma ...
    2168              : !> \par History
    2169              : !>      none
    2170              : !> \author JGH (09-June-2006)
    2171              : !> \note
    2172              : ! **************************************************************************************************
    2173           30 :                   SUBROUTINE pw_smoothing(pw, ecut, sigma)
    2174              : 
    2175              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    2176              :                      REAL(KIND=dp), INTENT(IN)                          :: ecut, sigma
    2177              : 
    2178              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_smoothing'
    2179              : 
    2180              :                      INTEGER                                            :: cnt, handle, ig
    2181              :                      REAL(KIND=dp)                                      :: arg, f
    2182              : 
    2183           30 :                      CALL timeset(routineN, handle)
    2184              : 
    2185           30 :                      cnt = SIZE(pw%array)
    2186              : 
    2187           30 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(ig, arg, f) SHARED(cnt, ecut, pw, sigma)
    2188              :                      DO ig = 1, cnt
    2189              :                         arg = (ecut - pw%pw_grid%gsq(ig))/sigma
    2190              :                         f = EXP(arg)/(1 + EXP(arg))
    2191              :                         pw%array(ig) = f*pw%array(ig)
    2192              :                      END DO
    2193              : !$OMP END PARALLEL DO
    2194              : 
    2195           30 :                      CALL timestop(handle)
    2196              : 
    2197           30 :                   END SUBROUTINE pw_smoothing
    2198              : 
    2199              : ! **************************************************************************************************
    2200              : !> \brief ...
    2201              : !> \param grida ...
    2202              : !> \param gridb ...
    2203              : !> \return ...
    2204              : ! **************************************************************************************************
    2205       772979 :                   ELEMENTAL FUNCTION pw_compatible(grida, gridb) RESULT(compat)
    2206              : 
    2207              :                      TYPE(pw_grid_type), INTENT(IN)                     :: grida, gridb
    2208              :                      LOGICAL                                            :: compat
    2209              : 
    2210       772979 :                      compat = .FALSE.
    2211              : 
    2212       772979 :                      IF (grida%id_nr == gridb%id_nr) THEN
    2213              :                         compat = .TRUE.
    2214       772979 :                      ELSE IF (grida%reference == gridb%id_nr) THEN
    2215              :                         compat = .TRUE.
    2216         1734 :                      ELSE IF (gridb%reference == grida%id_nr) THEN
    2217         1204 :                         compat = .TRUE.
    2218              :                      END IF
    2219              : 
    2220       772979 :                   END FUNCTION pw_compatible
    2221              : 
    2222              : ! **************************************************************************************************
    2223              : !> \brief Calculate the structure factor for point r
    2224              : !> \param sf ...
    2225              : !> \param r ...
    2226              : !> \par History
    2227              : !>      none
    2228              : !> \author JGH (05-May-2006)
    2229              : !> \note
    2230              : ! **************************************************************************************************
    2231           76 :                   SUBROUTINE pw_structure_factor(sf, r)
    2232              : 
    2233              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: sf
    2234              :                      REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: r
    2235              : 
    2236              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_structure_factor'
    2237              : 
    2238              :                      INTEGER                                            :: cnt, handle, ig
    2239              :                      REAL(KIND=dp)                                      :: arg
    2240              : 
    2241           76 :                      CALL timeset(routineN, handle)
    2242              : 
    2243           76 :                      cnt = SIZE(sf%array)
    2244              : 
    2245           76 : !$OMP PARALLEL DO PRIVATE (ig, arg) DEFAULT(NONE) SHARED(cnt, r, sf)
    2246              :                      DO ig = 1, cnt
    2247              :                         arg = DOT_PRODUCT(sf%pw_grid%g(:, ig), r)
    2248              :                         sf%array(ig) = CMPLX(COS(arg), -SIN(arg), KIND=dp)
    2249              :                      END DO
    2250              : !$OMP END PARALLEL DO
    2251              : 
    2252           76 :                      CALL timestop(handle)
    2253              : 
    2254           76 :                   END SUBROUTINE pw_structure_factor
    2255              : 
    2256              :                   END MODULE pw_methods
        

Generated by: LCOV version 2.0-1