LCOV - code coverage report
Current view: top level - src/pw - pw_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:e08e82d) Lines: 73.0 % 511 373
Test Date: 2026-10-16 00:55:08 Functions: 22.6 % 199 45

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \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      1400243 :          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      1400243 :             CALL timeset(routineN, handle)
     249              : 
     250              : #if !defined(__INTEL_LLVM_COMPILER) || (20250000 <= __INTEL_LLVM_COMPILER)
     251      1400243 : !$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      1400243 :             CALL timestop(handle)
     259              : 
     260      1400243 :          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       611192 :          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       611192 :             CALL timeset(routineN, handle)
     279              : 
     280       611192 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(A, pw)
     281              :             pw%array = a*pw%array
     282              : !$OMP END PARALLEL WORKSHARE
     283              : 
     284       611192 :             CALL timestop(handle)
     285              : 
     286       611192 :          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       602969 :          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       602969 :             iop = 0
     340              : 
     341       602969 :             IF (PRESENT(oprt)) THEN
     342              :                SELECT CASE (oprt)
     343              :                CASE ("ABS", "abs")
     344            0 :                   iop = 1
     345              :                CASE DEFAULT
     346         2762 :                   CPABORT("Unknown operator")
     347              :                END SELECT
     348              :             END IF
     349              : 
     350       142199 :             total_fun = 0.0_dp
     351              : 
     352              :             #:if space == "rs"
     353              :                ! do reduction using maximum accuracy
     354              :                IF (iop == 1) THEN
     355    145746101 :                   total_fun = fun%pw_grid%dvol*accurate_sum(ABS(fun%array))
     356              :                ELSE
     357       458008 :                   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       142199 :                   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       602969 :             IF (fun%pw_grid%para%mode /= PW_MODE_LOCAL) THEN
     372       597177 :                CALL fun%pw_grid%para%group%sum(total_fun)
     373              :             END IF
     374              : 
     375       602969 :             IF (PRESENT(isign)) THEN
     376       444906 :                total_fun = total_fun*SIGN(1._dp, REAL(isign, dp))
     377              :             END IF
     378              : 
     379       602969 :          END FUNCTION pw_integrate_function_${kind}$_${space}$
     380              : 
     381              : ! **************************************************************************************************
     382              : !> \brief ...
     383              : !> \param pw ...
     384              : !> \param value ...
     385              : ! **************************************************************************************************
     386          144 :          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          144 :             CALL timeset(routineN, handle)
     395              : 
     396          144 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw,value)
     397              :             pw%array = ${type2type("value", "r3d", kind)}$
     398              : !$OMP END PARALLEL WORKSHARE
     399              : 
     400          144 :             CALL timestop(handle)
     401              : 
     402          144 :          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      1830465 :          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), TARGET :: c
     416              :             REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
     417              : 
     418              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_gather_p'
     419              : 
     420              :             INTEGER                                            :: gpt, handle
     421      1830465 :             COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:), POINTER :: c_1d
     422              : 
     423      1830465 :             CALL timeset(routineN, handle)
     424              : 
     425      1830465 :             IF (pw%pw_grid%para%mode /= PW_MODE_DISTRIBUTED) THEN
     426            0 :                CPABORT("This grid type is not distributed")
     427              :             END IF
     428              : 
     429              :             ! Rank-1 pointer remap of contiguous c for flat g_hatmap indexing
     430      5491395 :             c_1d(1:SIZE(c)) => c
     431              :             ASSOCIATE (ngpts => SIZE(pw%pw_grid%gsq), g_hatmap => pw%pw_grid%g_hatmap)
     432              : 
     433      1830465 :                IF (PRESENT(scale)) THEN
     434              : !$OMP PARALLEL DO DEFAULT(NONE) &
     435              : !$OMP             PRIVATE(gpt) &
     436            0 : !$OMP             SHARED(c_1d, pw, scale)
     437              :                   DO gpt = 1, ngpts
     438              :                      pw%array(gpt) = scale*${type2type("c_1d(g_hatmap(gpt, 1) + 1)", "c3d", kind)}$
     439              :                   END DO
     440              : !$OMP END PARALLEL DO
     441              :                ELSE
     442              : !$OMP PARALLEL DO DEFAULT(NONE) &
     443              : !$OMP             PRIVATE(gpt) &
     444      1830465 : !$OMP             SHARED(c_1d, pw)
     445              :                   DO gpt = 1, ngpts
     446              :                      pw%array(gpt) = ${type2type("c_1d(g_hatmap(gpt, 1) + 1)", "c3d", kind)}$
     447              :                   END DO
     448              : !$OMP END PARALLEL DO
     449              :                END IF
     450              : 
     451              :             END ASSOCIATE
     452              : 
     453      1830465 :             CALL timestop(handle)
     454              : 
     455      1830465 :          END SUBROUTINE pw_gather_p_${kind}$
     456              : 
     457              : ! **************************************************************************************************
     458              : !> \brief ...
     459              : !> \param pw ...
     460              : !> \param c ...
     461              : !> \param scale ...
     462              : ! **************************************************************************************************
     463      1828652 :          SUBROUTINE pw_scatter_p_${kind}$ (pw, c, scale)
     464              :             TYPE(pw_${kind}$_gs_type), INTENT(IN)                          :: pw
     465              :             COMPLEX(KIND=dp), DIMENSION(:, :), CONTIGUOUS, INTENT(INOUT), TARGET :: c
     466              :             REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
     467              : 
     468              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_scatter_p'
     469              : 
     470              :             INTEGER                                            :: gpt, handle
     471      1828652 :             COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:), POINTER :: c_1d
     472              : 
     473      1828652 :             CALL timeset(routineN, handle)
     474              : 
     475      1828652 :             IF (pw%pw_grid%para%mode /= PW_MODE_DISTRIBUTED) THEN
     476            0 :                CPABORT("This grid type is not distributed")
     477              :             END IF
     478              : 
     479              :             ! Rank-1 pointer remap of contiguous c for flat g_hatmap indexing
     480      5485956 :             c_1d(1:SIZE(c)) => c
     481              :             ASSOCIATE (g_hatmap => pw%pw_grid%g_hatmap, ngpts => SIZE(pw%pw_grid%gsq))
     482              : 
     483  59782709340 :                IF (.NOT. PRESENT(scale)) c = z_zero
     484              : 
     485              :                IF (PRESENT(scale)) THEN
     486              : !$OMP PARALLEL DO DEFAULT(NONE) &
     487              : !$OMP             PRIVATE(gpt) &
     488            0 : !$OMP             SHARED(c_1d, pw, scale)
     489              :                   DO gpt = 1, ngpts
     490              :                      c_1d(g_hatmap(gpt, 1) + 1) = ${type2type("scale*pw%array(gpt)", kind, "c3d")}$
     491              :                   END DO
     492              : !$OMP END PARALLEL DO
     493              :                ELSE
     494              : !$OMP PARALLEL DO DEFAULT(NONE) &
     495              : !$OMP             PRIVATE(gpt) &
     496      1828652 : !$OMP             SHARED(c_1d, pw)
     497              :                   DO gpt = 1, ngpts
     498              :                      c_1d(g_hatmap(gpt, 1) + 1) = ${type2type("pw%array(gpt)", kind, "c3d")}$
     499              :                   END DO
     500              : !$OMP END PARALLEL DO
     501              :                END IF
     502              : 
     503      3657304 :                IF (pw%pw_grid%grid_span == HALFSPACE) THEN
     504              : 
     505       138958 :                   IF (PRESENT(scale)) THEN
     506              : !$OMP PARALLEL DO DEFAULT(NONE) &
     507              : !$OMP             PRIVATE(gpt) &
     508            0 : !$OMP             SHARED(c_1d, pw, scale)
     509              :                      DO gpt = 1, ngpts
     510              :                         c_1d(g_hatmap(gpt, 2) + 1) = scale*#{if kind[0]=="c"}#CONJG#{endif}#(${type2type("pw%array(gpt)", kind, "c3d")}$)
     511              :                      END DO
     512              : !$OMP END PARALLEL DO
     513              :                   ELSE
     514              : !$OMP PARALLEL DO DEFAULT(NONE) &
     515              : !$OMP             PRIVATE(gpt) &
     516       138958 : !$OMP             SHARED(c_1d, pw)
     517              :                      DO gpt = 1, ngpts
     518              :                         c_1d(g_hatmap(gpt, 2) + 1) = #{if kind[0]=="c"}#CONJG#{endif}#(${type2type("pw%array(gpt)", kind, "c3d")}$)
     519              :                      END DO
     520              : !$OMP END PARALLEL DO
     521              :                   END IF
     522              :                END IF
     523              : 
     524              :             END ASSOCIATE
     525              : 
     526      1828652 :             CALL timestop(handle)
     527              : 
     528      1828652 :          END SUBROUTINE pw_scatter_p_${kind}$
     529              :       #:endif
     530              :    #:endfor
     531              : 
     532              :    #:for kind, type, kind2, type2 in pw_list2_sameD
     533              :       #:for space in pw_spaces
     534              : ! **************************************************************************************************
     535              : !> \brief copy a pw type variable
     536              : !> \param pw1 ...
     537              : !> \param pw2 ...
     538              : !> \par History
     539              : !>      JGH (7-Mar-2001) : check for pw_grid %id_nr, allow copy if
     540              : !>        in_use == COMPLEXDATA1D and in_space == RECIPROCALSPACE
     541              : !>      JGH (21-Feb-2003) : Code for generalized reference grids
     542              : !> \author apsi
     543              : !> \note
     544              : !>      Currently only copying of respective types allowed,
     545              : !>      in order to avoid errors
     546              : ! **************************************************************************************************
     547      3949449 :          SUBROUTINE pw_copy_${kind}$_${kind2}$_${space}$ (pw1, pw2)
     548              : 
     549              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw1
     550              :             TYPE(pw_${kind2}$_${space}$_type), INTENT(INOUT)                       :: pw2
     551              : 
     552              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_copy'
     553              : 
     554              :             INTEGER                                            :: handle
     555              :             #:if kind[1:]=='1d'
     556              :                INTEGER :: i, j, ng, ng1, ng2, ns
     557              :             #:endif
     558              : 
     559      3949449 :             CALL timeset(routineN, handle)
     560              : 
     561      3949449 :             IF (pw1%pw_grid%spherical .neqv. pw2%pw_grid%spherical) &
     562            0 :                CPABORT("Both grids must be either spherical or non-spherical!")
     563              :             #:if space != "gs"
     564       824358 :                IF (pw1%pw_grid%spherical) &
     565            0 :                   CPABORT("Spherical grids only exist in reciprocal space!")
     566              :             #:endif
     567              : 
     568              :             #:if kind[1]=='1'
     569      3125091 :                IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
     570       847553 :                   IF (pw1%pw_grid%spherical .AND. pw2%pw_grid%spherical) THEN
     571            0 :                      IF (pw_compatible(pw1%pw_grid, pw2%pw_grid)) THEN
     572            0 :                         ng1 = SIZE(pw1%array)
     573            0 :                         ng2 = SIZE(pw2%array)
     574            0 :                         ng = MIN(ng1, ng2)
     575            0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(ng, pw1, pw2)
     576              :                         pw2%array(1:ng) = ${type2type("pw1%array(1:ng)", kind, kind2)}$
     577              : !$OMP END PARALLEL WORKSHARE
     578            0 :                         IF (ng2 > ng) THEN
     579            0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(ng, ng2, pw2)
     580              :                            pw2%array(ng + 1:ng2) = ${type2type("0.0_dp", "r3d", kind2)}$
     581              : !$OMP END PARALLEL WORKSHARE
     582              :                         END IF
     583              :                      ELSE
     584            0 :                         CPABORT("Copies between spherical grids require compatible grids!")
     585              :                      END IF
     586              :                   ELSE
     587       847553 :                      ng1 = SIZE(pw1%array)
     588       847553 :                      ng2 = SIZE(pw2%array)
     589       847553 :                      ns = 2*MAX(ng1, ng2)
     590              : 
     591       847553 :                      IF ((pw1%pw_grid%id_nr == pw2%pw_grid%reference)) THEN
     592       843533 :                         IF (ng1 >= ng2) THEN
     593              : !$OMP PARALLEL DO DEFAULT(NONE) &
     594              : !$OMP             PRIVATE(i,j) &
     595       843513 : !$OMP             SHARED(ng2, pw1, pw2)
     596              :                            DO i = 1, ng2
     597              :                               j = pw2%pw_grid%gidx(i)
     598              :                               pw2%array(i) = ${type2type("pw1%array(j)", kind, kind2)}$
     599              :                            END DO
     600              : !$OMP END PARALLEL DO
     601              :                         ELSE
     602           20 :                            CALL pw_zero(pw2)
     603              : !$OMP PARALLEL DO DEFAULT(NONE) &
     604              : !$OMP             PRIVATE(i,j) &
     605           20 : !$OMP             SHARED(ng1, pw1, pw2)
     606              :                            DO i = 1, ng1
     607              :                               j = pw2%pw_grid%gidx(i)
     608              :                               pw2%array(j) = ${type2type("pw1%array(i)", kind, kind2)}$
     609              :                            END DO
     610              : !$OMP END PARALLEL DO
     611              :                         END IF
     612         4020 :                      ELSE IF ((pw2%pw_grid%id_nr == pw1%pw_grid%reference)) THEN
     613         4000 :                         IF (ng1 >= ng2) THEN
     614          380 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng2, pw1, pw2)
     615              :                            DO i = 1, ng2
     616              :                               j = pw1%pw_grid%gidx(i)
     617              :                               pw2%array(i) = ${type2type("pw1%array(j)", kind, kind2)}$
     618              :                            END DO
     619              : !$OMP END PARALLEL DO
     620              :                         ELSE
     621         3620 :                            CALL pw_zero(pw2)
     622         3620 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng1, pw1, pw2)
     623              :                            DO i = 1, ng1
     624              :                               j = pw1%pw_grid%gidx(i)
     625              :                               pw2%array(j) = ${type2type("pw1%array(i)", kind, kind2)}$
     626              :                            END DO
     627              : !$OMP END PARALLEL DO
     628              :                         END IF
     629              :                      ELSE
     630              :                         #:if kind=='c1d' and kind2=='c1d' and space=="gs"
     631           20 :                            CALL pw_copy_match(pw1, pw2)
     632              :                         #:else
     633            0 :                            CPABORT("Copy not implemented!")
     634              :                         #:endif
     635              :                      END IF
     636              : 
     637              :                   END IF
     638              : 
     639              :                ELSE
     640      2277538 : !$OMP PARALLEL WORKSHARE PRIVATE(i) DEFAULT(NONE) SHARED(pw1, pw2)
     641              :                   pw2%array = ${type2type("pw1%array", kind, kind2)}$
     642              : !$OMP END PARALLEL WORKSHARE
     643              :                END IF
     644              :             #:else
     645      3297432 :                IF (ANY(SHAPE(pw2%array) /= SHAPE(pw1%array))) &
     646            0 :                   CPABORT("3D grids must be compatible!")
     647       824358 :                IF (pw1%pw_grid%spherical) &
     648            0 :                   CPABORT("3D grids must not be spherical!")
     649       824358 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1,pw2)
     650              :                pw2%array(:, :, :) = ${type2type("pw1%array(:, :, :)", kind, kind2)}$
     651              : !$OMP END PARALLEL WORKSHARE
     652              :             #:endif
     653              : 
     654      3949449 :             CALL timestop(handle)
     655              : 
     656      3949449 :          END SUBROUTINE pw_copy_${kind}$_${kind2}$_${space}$
     657              : 
     658              : ! **************************************************************************************************
     659              : !> \brief ...
     660              : !> \param pw ...
     661              : !> \param array ...
     662              : ! **************************************************************************************************
     663      2130736 :          SUBROUTINE pw_copy_to_array_${kind}$_${kind2}$_${space}$ (pw, array)
     664              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw
     665              :             ${type2}$, INTENT(INOUT)   :: array
     666              : 
     667              :             CHARACTER(len=*), PARAMETER :: routineN = 'pw_copy_to_array'
     668              : 
     669              :             INTEGER                                            :: handle
     670              : 
     671      2130736 :             CALL timeset(routineN, handle)
     672              : 
     673              :             #:if kind[1]=="1"
     674            0 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw, array)
     675              :                array(:) = ${type2type("pw%array(:)", kind, kind2)}$
     676              : !$OMP END PARALLEL WORKSHARE
     677              :             #:else
     678      2130736 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw, array)
     679              :                array(:, :, :) = ${type2type("pw%array(:, :, :)", kind, kind2)}$
     680              : !$OMP END PARALLEL WORKSHARE
     681              :             #:endif
     682              : 
     683      2130736 :             CALL timestop(handle)
     684      2130736 :          END SUBROUTINE pw_copy_to_array_${kind}$_${kind2}$_${space}$
     685              : 
     686              : ! **************************************************************************************************
     687              : !> \brief ...
     688              : !> \param pw ...
     689              : !> \param array ...
     690              : ! **************************************************************************************************
     691      2145733 :          SUBROUTINE pw_copy_from_array_${kind}$_${kind2}$_${space}$ (pw, array)
     692              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw
     693              :             ${type2}$, INTENT(IN)      :: array
     694              : 
     695              :             CHARACTER(len=*), PARAMETER :: routineN = 'pw_copy_from_array'
     696              : 
     697              :             INTEGER                                            :: handle
     698              : 
     699      2145733 :             CALL timeset(routineN, handle)
     700              : 
     701      2145733 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw, array)
     702              :             pw%array = ${type2type("array", kind2, kind)}$
     703              : !$OMP END PARALLEL WORKSHARE
     704              : 
     705      2145733 :             CALL timestop(handle)
     706      2145733 :          END SUBROUTINE pw_copy_from_array_${kind}$_${kind2}$_${space}$
     707              : 
     708              : ! **************************************************************************************************
     709              : !> \brief pw2 = alpha*pw1 + beta*pw2
     710              : !>      alpha defaults to 1, beta defaults to 1
     711              : !> \param pw1 ...
     712              : !> \param pw2 ...
     713              : !> \param alpha ...
     714              : !> \param beta ...
     715              : !> \param allow_noncompatible_grids ...
     716              : !> \par History
     717              : !>      JGH (21-Feb-2003) : added reference grid functionality
     718              : !>      JGH (01-Dec-2007) : rename and remove complex alpha
     719              : !> \author apsi
     720              : !> \note
     721              : !>      Currently only summing up of respective types allowed,
     722              : !>      in order to avoid errors
     723              : ! **************************************************************************************************
     724      2452220 :          SUBROUTINE pw_axpy_${kind}$_${kind2}$_${space}$ (pw1, pw2, alpha, beta, allow_noncompatible_grids)
     725              : 
     726              :             TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw1
     727              :             TYPE(pw_${kind2}$_${space}$_type), INTENT(INOUT)                       :: pw2
     728              :             REAL(KIND=dp), INTENT(in), OPTIONAL                :: alpha, beta
     729              :             LOGICAL, INTENT(IN), OPTIONAL                      :: allow_noncompatible_grids
     730              : 
     731              :             CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_axpy'
     732              : 
     733              :             INTEGER                                            :: handle
     734              :             LOGICAL                                            :: my_allow_noncompatible_grids
     735              :             REAL(KIND=dp)                                      :: my_alpha, my_beta
     736              :             #:if kind[1]=='1'
     737              :                INTEGER                                            :: i, j, ng, ng1, ng2
     738              :             #:endif
     739              : 
     740      2452220 :             CALL timeset(routineN, handle)
     741              : 
     742      2452220 :             my_alpha = 1.0_dp
     743      2452220 :             IF (PRESENT(alpha)) my_alpha = alpha
     744              : 
     745      2452220 :             my_beta = 1.0_dp
     746      2452220 :             IF (PRESENT(beta)) my_beta = beta
     747              : 
     748      2452220 :             my_allow_noncompatible_grids = .FALSE.
     749      2452220 :             IF (PRESENT(allow_noncompatible_grids)) my_allow_noncompatible_grids = allow_noncompatible_grids
     750              : 
     751      2452220 :             IF (my_beta /= 1.0_dp) THEN
     752       134980 :                IF (my_beta == 0.0_dp) THEN
     753         2164 :                   CALL pw_zero(pw2)
     754              :                ELSE
     755       132816 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw2,my_beta)
     756              :                   pw2%array = pw2%array*my_beta
     757              : !$OMP END PARALLEL WORKSHARE
     758              :                END IF
     759              :             END IF
     760              : 
     761              :             #:if kind[1]=='1'
     762      1823205 :                IF (ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
     763              : 
     764       885503 :                   IF (my_alpha == 1.0_dp) THEN
     765       862643 : !$OMP PARALLEL WORKSHARE PRIVATE(i) DEFAULT(NONE) SHARED(pw1, pw2)
     766              :                      pw2%array = pw2%array + ${type2type("pw1%array", kind, kind2)}$
     767              : !$OMP END PARALLEL WORKSHARE
     768        22860 :                   ELSE IF (my_alpha /= 0.0_dp) THEN
     769        22860 : !$OMP PARALLEL WORKSHARE PRIVATE(i) DEFAULT(NONE) SHARED(pw2,pw1,my_alpha)
     770              :                      pw2%array = pw2%array + my_alpha*${type2type("pw1%array", kind, kind2)}$
     771              : !$OMP END PARALLEL WORKSHARE
     772              :                   END IF
     773              : 
     774       937702 :                ELSE IF (pw_compatible(pw1%pw_grid, pw2%pw_grid) .OR. my_allow_noncompatible_grids) THEN
     775              : 
     776       937702 :                   ng1 = SIZE(pw1%array)
     777       937702 :                   ng2 = SIZE(pw2%array)
     778       937702 :                   ng = MIN(ng1, ng2)
     779              : 
     780       937702 :                   IF (pw1%pw_grid%spherical) THEN
     781            0 :                      IF (my_alpha == 1.0_dp) THEN
     782            0 : !$OMP PARALLEL DO PRIVATE(i) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     783              :                         DO i = 1, ng
     784              :                            pw2%array(i) = pw2%array(i) + ${type2type("pw1%array(i)", kind, kind2)}$
     785              :                         END DO
     786              : !$OMP END PARALLEL DO
     787            0 :                      ELSE IF (my_alpha /= 0.0_dp) THEN
     788            0 : !$OMP PARALLEL DO PRIVATE(i) DEFAULT(NONE) SHARED(pw2,pw1,my_alpha,ng)
     789              :                         DO i = 1, ng
     790              :                            pw2%array(i) = pw2%array(i) + my_alpha*${type2type("pw1%array(i)", kind, kind2)}$
     791              :                         END DO
     792              : !$OMP END PARALLEL DO
     793              :                      END IF
     794       937702 :                   ELSE IF ((pw1%pw_grid%id_nr == pw2%pw_grid%reference)) THEN
     795         1554 :                      IF (ng1 >= ng2) THEN
     796         1554 :                         IF (my_alpha == 1.0_dp) THEN
     797         1554 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     798              :                            DO i = 1, ng
     799              :                               j = pw2%pw_grid%gidx(i)
     800              :                               pw2%array(i) = pw2%array(i) + ${type2type("pw1%array(j)", kind, kind2)}$
     801              :                            END DO
     802              : !$OMP END PARALLEL DO
     803            0 :                         ELSE IF (my_alpha /= 0.0_dp) THEN
     804            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(my_alpha, ng, pw1, pw2)
     805              :                            DO i = 1, ng
     806              :                               j = pw2%pw_grid%gidx(i)
     807              :                               pw2%array(i) = pw2%array(i) + my_alpha*${type2type("pw1%array(j)", kind, kind2)}$
     808              :                            END DO
     809              : !$OMP END PARALLEL DO
     810              :                         END IF
     811              :                      ELSE
     812            0 :                         IF (my_alpha == 1.0_dp) THEN
     813            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     814              :                            DO i = 1, ng
     815              :                               j = pw2%pw_grid%gidx(i)
     816              :                               pw2%array(j) = pw2%array(j) + ${type2type("pw1%array(i)", kind, kind2)}$
     817              :                            END DO
     818              : !$OMP END PARALLEL DO
     819            0 :                         ELSE IF (my_alpha /= 0.0_dp) THEN
     820            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(my_alpha, ng, pw1, pw2)
     821              :                            DO i = 1, ng
     822              :                               j = pw2%pw_grid%gidx(i)
     823              :                               pw2%array(j) = pw2%array(j) + my_alpha*${type2type("pw1%array(i)", kind, kind2)}$
     824              :                            END DO
     825              : !$OMP END PARALLEL DO
     826              :                         END IF
     827              :                      END IF
     828       936148 :                   ELSE IF ((pw2%pw_grid%id_nr == pw1%pw_grid%reference)) THEN
     829       936148 :                      IF (ng1 >= ng2) THEN
     830            0 :                         IF (my_alpha == 1.0_dp) THEN
     831            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     832              :                            DO i = 1, ng
     833              :                               j = pw1%pw_grid%gidx(i)
     834              :                               pw2%array(i) = pw2%array(i) + ${type2type("pw1%array(j)", kind, kind2)}$
     835              :                            END DO
     836              : !$OMP END PARALLEL DO
     837            0 :                         ELSE IF (my_alpha /= 0.0_dp) THEN
     838            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(my_alpha, ng, pw1, pw2)
     839              :                            DO i = 1, ng
     840              :                               j = pw1%pw_grid%gidx(i)
     841              :                               pw2%array(i) = pw2%array(i) + my_alpha*${type2type("pw1%array(j)", kind, kind2)}$
     842              :                            END DO
     843              : !$OMP END PARALLEL DO
     844              :                         END IF
     845              :                      ELSE
     846       936148 :                         IF (my_alpha == 1.0_dp) THEN
     847       936148 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(ng, pw1, pw2)
     848              :                            DO i = 1, ng
     849              :                               j = pw1%pw_grid%gidx(i)
     850              :                               pw2%array(j) = pw2%array(j) + ${type2type("pw1%array(i)", kind, kind2)}$
     851              :                            END DO
     852              : !$OMP END PARALLEL DO
     853            0 :                         ELSE IF (my_alpha /= 0.0_dp) THEN
     854            0 : !$OMP PARALLEL DO PRIVATE(i,j) DEFAULT(NONE) SHARED(my_alpha, ng, pw1, pw2)
     855              :                            DO i = 1, ng
     856              :                               j = pw1%pw_grid%gidx(i)
     857              :                               pw2%array(j) = pw2%array(j) + my_alpha*${type2type("pw1%array(i)", kind, kind2)}$
     858              :                            END DO
     859              : !$OMP END PARALLEL DO
     860              :                         END IF
     861              :                      END IF
     862              :                   ELSE
     863            0 :                      CPABORT("Grids not compatible")
     864              :                   END IF
     865              :                   #:else
     866       629015 :                   IF (ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
     867       628485 :                      IF (my_alpha == 1.0_dp) THEN
     868       399289 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1, pw2)
     869              :                         pw2%array = pw2%array + ${type2type("pw1%array", kind, kind2)}$
     870              : !$OMP END PARALLEL WORKSHARE
     871       229196 :                      ELSE IF (my_alpha /= 0.0_dp) THEN
     872       227676 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1, pw2, my_alpha)
     873              :                         pw2%array = pw2%array + my_alpha*${type2type("pw1%array", kind, kind2)}$
     874              : !$OMP END PARALLEL WORKSHARE
     875              :                      END IF
     876              : 
     877          530 :                   ELSE IF (pw_compatible(pw1%pw_grid, pw2%pw_grid) .OR. my_allow_noncompatible_grids) THEN
     878              : 
     879         2120 :                      IF (ANY(SHAPE(pw1%array) /= SHAPE(pw2%array))) &
     880            0 :                         CPABORT("Noncommensurate grids not implemented for 3D grids!")
     881              : 
     882          530 :                      IF (my_alpha == 1.0_dp) THEN
     883          444 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1,pw2)
     884              :                         pw2%array = pw2%array + ${type2type("pw1%array", kind, kind2)}$
     885              : !$OMP END PARALLEL WORKSHARE
     886              :                      ELSE
     887           86 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1,pw2,my_alpha)
     888              :                         pw2%array = pw2%array + my_alpha*${type2type("pw1%array", kind, kind2)}$
     889              : !$OMP END PARALLEL WORKSHARE
     890              :                      END IF
     891              :                      #:endif
     892              : 
     893              :                   ELSE
     894              : 
     895            0 :                      CPABORT("Grids not compatible")
     896              : 
     897              :                   END IF
     898              : 
     899      2452220 :                   CALL timestop(handle)
     900              : 
     901      2452220 :                   END SUBROUTINE pw_axpy_${kind}$_${kind2}$_${space}$
     902              : 
     903              : ! **************************************************************************************************
     904              : !> \brief pw_out = pw_out + alpha * pw1 * pw2
     905              : !>      alpha defaults to 1
     906              : !> \param pw_out ...
     907              : !> \param pw1 ...
     908              : !> \param pw2 ...
     909              : !> \param alpha ...
     910              : !> \author JGH
     911              : ! **************************************************************************************************
     912         4943 :                   SUBROUTINE pw_multiply_${kind}$_${kind2}$_${space}$ (pw_out, pw1, pw2, alpha)
     913              : 
     914              :                      TYPE(pw_${kind}$_${space}$_type), INTENT(INOUT)                       :: pw_out
     915              :                      TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw1
     916              :                      TYPE(pw_${kind2}$_${space}$_type), INTENT(IN) :: pw2
     917              :                      REAL(KIND=dp), INTENT(IN), OPTIONAL                :: alpha
     918              : 
     919              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_multiply'
     920              : 
     921              :                      INTEGER                                            :: handle
     922              :                      REAL(KIND=dp)                                      :: my_alpha
     923              : 
     924         4943 :                      CALL timeset(routineN, handle)
     925              : 
     926         4943 :                      my_alpha = 1.0_dp
     927         4943 :                      IF (PRESENT(alpha)) my_alpha = alpha
     928              : 
     929         9886 :                      IF (.NOT. ASSOCIATED(pw_out%pw_grid, pw1%pw_grid) .OR. .NOT. ASSOCIATED(pw_out%pw_grid, pw2%pw_grid)) &
     930            0 :                         CPABORT("pw_multiply not implemented for non-identical grids!")
     931              : 
     932              : #if !defined(__INTEL_LLVM_COMPILER) || (20250000 <= __INTEL_LLVM_COMPILER)
     933         4943 :                      IF (my_alpha == 1.0_dp) THEN
     934         4875 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw_out, pw1, pw2)
     935              :                         pw_out%array = pw_out%array + pw1%array*${type2type("pw2%array", kind2, kind)}$
     936              : !$OMP END PARALLEL WORKSHARE
     937              :                      ELSE
     938           68 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(my_alpha, pw_out, pw1, pw2)
     939              :                         pw_out%array = pw_out%array + my_alpha*pw1%array*${type2type("pw2%array", kind2, kind)}$
     940              : !$OMP END PARALLEL WORKSHARE
     941              :                      END IF
     942              : #else
     943              :                      IF (my_alpha == 1.0_dp) THEN
     944              :                         pw_out%array = pw_out%array + pw1%array*${type2type("pw2%array", kind2, kind)}$
     945              :                      ELSE
     946              :                         pw_out%array = pw_out%array + my_alpha*pw1%array*${type2type("pw2%array", kind2, kind)}$
     947              :                      END IF
     948              : #endif
     949              : 
     950         4943 :                      CALL timestop(handle)
     951              : 
     952         4943 :                   END SUBROUTINE pw_multiply_${kind}$_${kind2}$_${space}$
     953              : 
     954              : ! **************************************************************************************************
     955              : !> \brief ...
     956              : !> \param pw1 ...
     957              : !> \param pw2 ...
     958              : ! **************************************************************************************************
     959       527231 :                   SUBROUTINE pw_multiply_with_${kind}$_${kind2}$_${space}$ (pw1, pw2)
     960              :                      TYPE(pw_${kind}$_${space}$_type), INTENT(INOUT)                       :: pw1
     961              :                      TYPE(pw_${kind2}$_${space}$_type), INTENT(IN)                          :: pw2
     962              : 
     963              :                      CHARACTER(LEN=*), PARAMETER                        :: routineN = 'pw_multiply_with'
     964              : 
     965              :                      INTEGER                                            :: handle
     966              : 
     967       527231 :                      CALL timeset(routineN, handle)
     968              : 
     969       527231 :                      IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) &
     970            0 :                         CPABORT("Incompatible grids!")
     971              : 
     972       527231 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw1,pw2)
     973              :                      pw1%array = pw1%array*${type2type("pw2%array", kind2, kind)}$
     974              : !$OMP END PARALLEL WORKSHARE
     975              : 
     976       527231 :                      CALL timestop(handle)
     977              : 
     978       527231 :                   END SUBROUTINE pw_multiply_with_${kind}$_${kind2}$_${space}$
     979              : 
     980              : ! **************************************************************************************************
     981              : !> \brief Calculate integral over unit cell for functions in plane wave basis
     982              : !>      only returns the real part of it ......
     983              : !> \param pw1 ...
     984              : !> \param pw2 ...
     985              : !> \param sumtype ...
     986              : !> \param just_sum ...
     987              : !> \param local_only ...
     988              : !> \return ...
     989              : !> \par History
     990              : !>      JGH (14-Mar-2001) : Parallel sum and some tests, HALFSPACE case
     991              : !> \author apsi
     992              : ! **************************************************************************************************
     993       772670 :                FUNCTION pw_integral_ab_${kind}$_${kind2}$_${space}$ (pw1, pw2, sumtype, just_sum, local_only) RESULT(integral_value)
     994              : 
     995              :                      TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                          :: pw1
     996              :                      TYPE(pw_${kind2}$_${space}$_type), INTENT(IN)                          :: pw2
     997              :                      INTEGER, INTENT(IN), OPTIONAL                      :: sumtype
     998              :                      LOGICAL, INTENT(IN), OPTIONAL                      :: just_sum, local_only
     999              :                      REAL(KIND=dp)                                      :: integral_value
    1000              : 
    1001              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_integral_ab_${kind}$_${kind2}$_${space}$'
    1002              : 
    1003              :                      INTEGER                                            :: handle, loc_sumtype
    1004              :                      LOGICAL                                            :: my_just_sum, my_local_only
    1005              : 
    1006       772670 :                      CALL timeset(routineN, handle)
    1007              : 
    1008       772670 :                      loc_sumtype = do_accurate_sum
    1009       772670 :                      IF (PRESENT(sumtype)) loc_sumtype = sumtype
    1010              : 
    1011       772670 :                      my_local_only = .FALSE.
    1012       772670 :                      IF (PRESENT(local_only)) my_local_only = local_only
    1013              : 
    1014       772670 :                      IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
    1015            0 :                         CPABORT("Grids incompatible")
    1016              :                      END IF
    1017              : 
    1018       772670 :                      my_just_sum = .FALSE.
    1019       772670 :                      IF (PRESENT(just_sum)) my_just_sum = just_sum
    1020              : 
    1021              :                      ! do standard sum
    1022       772670 :                      IF (loc_sumtype == do_standard_sum) THEN
    1023              : 
    1024              :                         ! Do standard sum
    1025              : 
    1026              :                         #:if kind=="r1d" and kind2=="r1d"
    1027          768 :                            integral_value = DOT_PRODUCT(pw1%array, pw2%array)
    1028              :                         #:elif kind=="r3d" and kind2=="r3d"
    1029   1069757308 :                            integral_value = SUM(pw1%array*pw2%array)
    1030              :                         #:elif kind[0]=="r"
    1031          384 :                            integral_value = SUM(pw1%array*REAL(pw2%array, KIND=dp)) !? complex bit
    1032              :                         #:elif kind2[0]=="r"
    1033          384 :                            integral_value = SUM(REAL(pw1%array, KIND=dp)*pw2%array) !? complex bit
    1034              :                         #:else
    1035              :                            integral_value = SUM(REAL(CONJG(pw1%array) &
    1036          768 :                                                      *pw2%array, KIND=dp)) !? complex bit
    1037              :                         #:endif
    1038              : 
    1039              :                      ELSE
    1040              : 
    1041              :                         ! Do accurate sum
    1042              :                         #:if kind[0]=="r" and kind2[0]=="r"
    1043        61826 :                            integral_value = accurate_dot_product(pw1%array, pw2%array)
    1044              :                         #:elif kind[0]=="r"
    1045          384 :                            integral_value = accurate_sum(pw1%array*REAL(pw2%array, KIND=dp)) !? complex bit
    1046              :                         #:elif kind2[0]=="r"
    1047          384 :                            integral_value = accurate_sum(REAL(pw1%array, KIND=dp)*pw2%array) !? complex bit
    1048              :                         #:else
    1049  11747070351 :                            integral_value = accurate_sum(REAL(CONJG(pw1%array)*pw2%array, KIND=dp))
    1050              :                         #:endif
    1051              : 
    1052              :                      END IF
    1053              : 
    1054              :                      #:if kind[1]=="1"
    1055              :                         ! Apply reciprocal multiplicity before scaling the integral;
    1056              :                         ! the unpaired G=0 term must receive the same volume factor.
    1057       455104 :                         IF (pw1%pw_grid%grid_span == HALFSPACE) THEN
    1058       249970 :                            integral_value = 2.0_dp*integral_value
    1059       249970 :                            IF (pw1%pw_grid%have_g0) integral_value = integral_value - &
    1060              :                            #:if kind[0]=="c"
    1061       136796 :                                                                      REAL(CONJG(pw1%array(1))*pw2%array(1), KIND=dp)
    1062              :                               #:elif kind2[0]=="r"
    1063            8 :                               pw1%array(1)*pw2%array(1)
    1064              :                               #:else
    1065            4 :                               pw1%array(1)*REAL(pw2%array(1), KIND=dp)
    1066              :                               #:endif
    1067              :                            END IF
    1068              :                         #:endif
    1069              : 
    1070       772670 :                         IF (.NOT. my_just_sum) THEN
    1071              :                            #:if space == "rs"
    1072       317456 :                               integral_value = integral_value*pw1%pw_grid%dvol
    1073              :                            #:elif space == "gs"
    1074       455072 :                               integral_value = integral_value*pw1%pw_grid%vol
    1075              :                            #:else
    1076              :                               #:stop "Unknown space: "+space
    1077              :                            #:endif
    1078              :                         END IF
    1079              : 
    1080       772670 :                         IF (.NOT. my_local_only .AND. pw1%pw_grid%para%mode == PW_MODE_DISTRIBUTED) &
    1081       444736 :                            CALL pw1%pw_grid%para%group%sum(integral_value)
    1082              : 
    1083       772670 :                         CALL timestop(handle)
    1084              : 
    1085       772670 :                      END FUNCTION pw_integral_ab_${kind}$_${kind2}$_${space}$
    1086              :                      #:endfor
    1087              : 
    1088              :                      #:if kind[1]=="1"
    1089              : ! **************************************************************************************************
    1090              : !> \brief ...
    1091              : !> \param pw1 ...
    1092              : !> \param pw2 ...
    1093              : !> \return ...
    1094              : ! **************************************************************************************************
    1095        77904 :                         FUNCTION pw_integral_a2b_${kind}$_${kind2}$ (pw1, pw2) RESULT(integral_value)
    1096              : 
    1097              :                            TYPE(pw_${kind}$_gs_type), INTENT(IN)                          :: pw1
    1098              :                            TYPE(pw_${kind2}$_gs_type), INTENT(IN) :: pw2
    1099              :                            REAL(KIND=dp)                                      :: integral_value
    1100              : 
    1101              :                            CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_integral_a2b'
    1102              : 
    1103              :                            INTEGER                                            :: handle
    1104              : 
    1105        77904 :                            CALL timeset(routineN, handle)
    1106              : 
    1107        77904 :                            IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
    1108            0 :                               CPABORT("Grids incompatible")
    1109              :                            END IF
    1110              : 
    1111              :                            #:if kind[0]=="c"
    1112              :                               #:if kind2[0]=="c"
    1113    241782972 :                                  integral_value = accurate_sum(REAL(CONJG(pw1%array)*pw2%array, KIND=dp)*pw1%pw_grid%gsq)
    1114              :                               #:else
    1115            0 :                                  integral_value = accurate_sum(REAL(CONJG(pw1%array), KIND=dp)*pw2%array*pw1%pw_grid%gsq)
    1116              :                               #:endif
    1117              :                            #:elif kind2[0]=="c"
    1118            0 :                               integral_value = accurate_sum(pw1%array*REAL(pw2%array, KIND=dp)*pw1%pw_grid%gsq)
    1119              :                            #:else
    1120            0 :                               integral_value = accurate_sum(pw1%array*pw2%array*pw1%pw_grid%gsq)
    1121              :                            #:endif
    1122        77904 :                            IF (pw1%pw_grid%grid_span == HALFSPACE) THEN
    1123        77904 :                               integral_value = 2.0_dp*integral_value
    1124              :                            END IF
    1125              : 
    1126        77904 :                            integral_value = integral_value*pw1%pw_grid%vol
    1127              : 
    1128        77904 :                            IF (pw1%pw_grid%para%mode == PW_MODE_DISTRIBUTED) &
    1129        73176 :                               CALL pw1%pw_grid%para%group%sum(integral_value)
    1130        77904 :                            CALL timestop(handle)
    1131              : 
    1132        77904 :                         END FUNCTION pw_integral_a2b_${kind}$_${kind2}$
    1133              :                      #:endif
    1134              :                   #:endfor
    1135              : 
    1136              :                   #:for kind, type, kind2, type2 in pw_list2
    1137              :                      #:for space in pw_spaces
    1138              :                         #:for space2 in pw_spaces
    1139              : 
    1140              :                            #: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"))
    1141              : ! **************************************************************************************************
    1142              : !> \brief Generic function for 3d FFT of a coefficient_type or pw_r3d_rs_type
    1143              : !> \param pw1 ...
    1144              : !> \param pw2 ...
    1145              : !> \param debug ...
    1146              : !> \par History
    1147              : !>      JGH (30-12-2000): New setup of functions and adaptation to parallelism
    1148              : !>      JGH (04-01-2001): Moved routine from pws to this module, only covers
    1149              : !>                        pw_types, no more coefficient types
    1150              : !> \author apsi
    1151              : !> \note
    1152              : !>       fft_wrap_pw1pw2
    1153              : ! **************************************************************************************************
    1154      4277541 :                               SUBROUTINE fft_wrap_pw1pw2_${kind}$_${kind2}$_${space}$_${space2}$ (pw1, pw2, debug)
    1155              : 
    1156              :                                  TYPE(pw_${kind}$_${space}$_type), INTENT(IN)                  :: pw1
    1157              :                                  TYPE(pw_${kind2}$_${space2}$_type), INTENT(INOUT)               :: pw2
    1158              :                                  LOGICAL, INTENT(IN), OPTIONAL                      :: debug
    1159              : 
    1160              :                                  CHARACTER(len=*), PARAMETER                        :: routineN = 'fft_wrap_pw1pw2'
    1161              : 
    1162      4277541 :                                  COMPLEX(KIND=dp), DIMENSION(:, :), CONTIGUOUS, POINTER         :: grays
    1163      4277541 :                                  COMPLEX(KIND=dp), DIMENSION(:, :, :), CONTIGUOUS, POINTER      :: c_in, c_out
    1164              :                                  INTEGER                                            ::  handle, handle2, my_pos, nrays, &
    1165              :                                                                                        out_unit
    1166              :                                  #:if (space=="rs" and kind=="r3d" and kind2=="c1d") or (space=="gs" and kind=="c1d" and kind2=="r3d")
    1167              :                                     INTEGER, DIMENSION(3)                              :: nloc
    1168              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1169              :                                     LOGICAL                                            :: use_pw_gpu
    1170              : #endif
    1171              :                                  #:endif
    1172      4277541 :                                  INTEGER, DIMENSION(:), POINTER                     :: n
    1173              :                                  LOGICAL                                            :: test
    1174              : 
    1175      4277541 :                                  CALL timeset(routineN, handle2)
    1176      4277541 :                                  out_unit = cp_logger_get_default_io_unit()
    1177              :                                  CALL timeset(routineN//"_"//TRIM(ADJUSTL(cp_to_string( &
    1178      4277541 :                                                                           CEILING(pw1%pw_grid%cutoff/10)*10))), handle)
    1179              : 
    1180      4277005 :                                  NULLIFY (c_in)
    1181      4277541 :                                  NULLIFY (c_out)
    1182              : 
    1183      4277541 :                                  IF (PRESENT(debug)) THEN
    1184         1072 :                                     test = debug
    1185              :                                  ELSE
    1186      4276469 :                                     test = .FALSE.
    1187              :                                  END IF
    1188              : 
    1189              :                                  !..check if grids are compatible
    1190      4277541 :                                  IF (.NOT. ASSOCIATED(pw1%pw_grid, pw2%pw_grid)) THEN
    1191            0 :                                     IF (pw1%pw_grid%dvol /= pw2%pw_grid%dvol) THEN
    1192            0 :                                        CPABORT("PW grids not compatible")
    1193              :                                     END IF
    1194            0 :                                     IF (pw1%pw_grid%para%group /= pw2%pw_grid%para%group) THEN
    1195            0 :                                        CPABORT("PW grids have not compatible MPI groups")
    1196              :                                     END IF
    1197              :                                  END IF
    1198              : 
    1199      4277541 :                                  n => pw1%pw_grid%npts
    1200              : 
    1201      4277541 :                                  IF (pw1%pw_grid%para%mode == PW_MODE_LOCAL) THEN
    1202              : 
    1203              :                                     !
    1204              :                                     !..replicated data, use local FFT
    1205              :                                     !
    1206              : 
    1207       618424 :                                     IF (test .AND. out_unit > 0) THEN
    1208            0 :                                        WRITE (out_unit, '(A)') " FFT Protocol "
    1209              :                                        #:if space=="rs"
    1210            0 :                                           WRITE (out_unit, '(A,T76,A)') "  Transform direction ", "FWFFT"
    1211            0 :                                           WRITE (out_unit, '(A,T72,A)') "  in space ", "REALSPACE"
    1212            0 :                                           WRITE (out_unit, '(A,T72,A)') "  out space ", "REALSPACE"
    1213              :                                        #:else
    1214            0 :                                           WRITE (out_unit, '(A,T76,A)') "  Transform direction ", "BWFFT"
    1215            0 :                                           WRITE (out_unit, '(A,T66,A)') "  in space ", "RECIPROCALSPACE"
    1216            0 :                                           WRITE (out_unit, '(A,T66,A)') "  out space ", "RECIPROCALSPACE"
    1217              :                                        #:endif
    1218              :                                     END IF
    1219              : 
    1220              :                                     #:if space=="rs"
    1221              :                                        #:if kind==kind2=="c3d"
    1222            0 :                                           c_in => pw1%array
    1223            0 :                                           c_out => pw2%array
    1224            0 :                                           CALL fft3d(FWFFT, n, c_in, c_out, debug=test)
    1225              :                                        #:elif kind=="r3d" and kind2=="c3d"
    1226            0 :                                           pw2%array = CMPLX(pw1%array, 0.0_dp, KIND=dp)
    1227            0 :                                           c_out => pw2%array
    1228            0 :                                           CALL fft3d(FWFFT, n, c_out, debug=test)
    1229              :                                        #:elif kind=="c3d" and kind2=="c1d"
    1230            0 :                                           c_in => pw1%array
    1231            0 :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1232              :                                           ! transform
    1233            0 :                                           CALL fft3d(FWFFT, n, c_in, c_out, debug=test)
    1234              :                                           ! gather results
    1235            0 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  PW_GATHER : 3d -> 1d "
    1236            0 :                                           CALL pw_gather_s_${kind2}$_c3d(pw2, c_out)
    1237            0 :                                           DEALLOCATE (c_out)
    1238              :                                        #:elif kind=="r3d" and kind2=="c1d"
    1239              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1240              :                                           CALL pw_gpu_r3dc1d_3d(pw1, pw2)
    1241              : #elif defined (__PW_FPGA)
    1242              :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1243              :                                           ! check if bitstream for the fft size is present
    1244              :                                           ! if not, perform fft3d in CPU
    1245              :                                           IF (pw_fpga_init_bitstream(n) == 1) THEN
    1246              :                                              CALL pw_copy_to_array(pw1, c_out)
    1247              : #if (__PW_FPGA_SP && __PW_FPGA)
    1248              :                                              CALL pw_fpga_r3dc1d_3d_sp(n, c_out)
    1249              : #else
    1250              :                                              CALL pw_fpga_r3dc1d_3d_dp(n, c_out)
    1251              : #endif
    1252              :                                              CALL zdscal(n(1)*n(2)*n(3), 1.0_dp/pw1%pw_grid%ngpts, c_out, 1)
    1253              :                                              CALL pw_gather_s_${kind2}$_c3d(pw2, c_out)
    1254              :                                           ELSE
    1255              :                                              CALL pw_copy_to_array(pw1, c_out)
    1256              :                                              CALL fft3d(FWFFT, n, c_out, debug=test)
    1257              :                                              CALL pw_gather_s_${kind2}$_c3d(pw2, c_out)
    1258              :                                           END IF
    1259              :                                           DEALLOCATE (c_out)
    1260              : #else
    1261      1504035 :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1262       300807 :                                           c_out = 0.0_dp
    1263       300807 :                                           CALL pw_copy_to_array(pw1, c_out)
    1264       300807 :                                           CALL fft3d(FWFFT, n, c_out, debug=test)
    1265       300807 :                                           CALL pw_gather_s_${kind2}$_c3d(pw2, c_out)
    1266       300807 :                                           DEALLOCATE (c_out)
    1267              : #endif
    1268              :                                        #:endif
    1269              :                                     #:else
    1270              :                                        #:if kind=="c3d" and kind2=="c3d"
    1271            0 :                                           c_in => pw1%array
    1272            0 :                                           c_out => pw2%array
    1273            0 :                                           CALL fft3d(BWFFT, n, c_in, c_out, debug=test)
    1274              :                                        #:elif kind=="c3d" and kind2=="r3d"
    1275            0 :                                           c_in => pw1%array
    1276            0 :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1277            0 :                                           CALL fft3d(BWFFT, n, c_in, c_out, debug=test)
    1278              :                                           ! use real part only
    1279            0 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  REAL part "
    1280            0 :                                           pw2%array = REAL(c_out, KIND=dp)
    1281            0 :                                           DEALLOCATE (c_out)
    1282              :                                        #:elif kind=="c1d" and kind2=="c3d"
    1283            0 :                                           c_out => pw2%array
    1284            0 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  PW_SCATTER : 3d -> 1d "
    1285            0 :                                           CALL pw_scatter_s_${kind}$_c3d(pw1, c_out)
    1286            0 :                                           CALL fft3d(BWFFT, n, c_out, debug=test)
    1287              :                                        #:elif kind=="c1d" and kind2=="r3d"
    1288              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1289              :                                           CALL pw_gpu_c1dr3d_3d(pw1, pw2)
    1290              : #elif defined (__PW_FPGA)
    1291              :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1292              :                                           ! check if bitstream for the fft size is present
    1293              :                                           ! if not, perform fft3d in CPU
    1294              :                                           IF (pw_fpga_init_bitstream(n) == 1) THEN
    1295              :                                              CALL pw_scatter_s_${kind}$_c3d(pw1, c_out)
    1296              :                                              ! transform using FPGA
    1297              : #if (__PW_FPGA_SP && __PW_FPGA)
    1298              :                                              CALL pw_fpga_c1dr3d_3d_sp(n, c_out)
    1299              : #else
    1300              :                                              CALL pw_fpga_c1dr3d_3d_dp(n, c_out)
    1301              : #endif
    1302              :                                              CALL zdscal(n(1)*n(2)*n(3), 1.0_dp, c_out, 1)
    1303              :                                              ! use real part only
    1304              :                                              CALL pw_copy_from_array(pw2, c_out)
    1305              :                                           ELSE
    1306              :                                              IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  PW_SCATTER : 3d -> 1d "
    1307              :                                              CALL pw_scatter_s_${kind}$_c3d(pw1, c_out)
    1308              :                                              ! transform
    1309              :                                              CALL fft3d(BWFFT, n, c_out, debug=test)
    1310              :                                              ! use real part only
    1311              :                                              IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  REAL part "
    1312              :                                              CALL pw_copy_from_array(pw2, c_out)
    1313              :                                           END IF
    1314              :                                           DEALLOCATE (c_out)
    1315              : #else
    1316      1588085 :                                           ALLOCATE (c_out(n(1), n(2), n(3)))
    1317       317617 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  PW_SCATTER : 3d -> 1d "
    1318       317617 :                                           CALL pw_scatter_s_${kind}$_c3d(pw1, c_out)
    1319              :                                           ! transform
    1320       317617 :                                           CALL fft3d(BWFFT, n, c_out, debug=test)
    1321              :                                           ! use real part only
    1322       317617 :                                           IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') "  REAL part "
    1323       317617 :                                           CALL pw_copy_from_array(pw2, c_out)
    1324       317617 :                                           DEALLOCATE (c_out)
    1325              : #endif
    1326              :                                        #:endif
    1327              :                                     #:endif
    1328              : 
    1329       618424 :                                     IF (test .AND. out_unit > 0) WRITE (out_unit, '(A)') " End of FFT Protocol "
    1330              : 
    1331              :                                  ELSE
    1332              : 
    1333              :                                     !
    1334              :                                     !..parallel FFT
    1335              :                                     !
    1336              : 
    1337      3659117 :                                     IF (test .AND. out_unit > 0) THEN
    1338            8 :                                        WRITE (out_unit, '(A)') " FFT Protocol "
    1339              :                                        #:if space=="rs"
    1340            4 :                                           WRITE (out_unit, '(A,T76,A)') "  Transform direction ", "FWFFT"
    1341            4 :                                           WRITE (out_unit, '(A,T72,A)') "  in space ", "REALSPACE"
    1342            4 :                                           WRITE (out_unit, '(A,T72,A)') "  out space ", "REALSPACE"
    1343              :                                        #:else
    1344            4 :                                           WRITE (out_unit, '(A,T76,A)') "  Transform direction ", "BWFFT"
    1345            4 :                                           WRITE (out_unit, '(A,T66,A)') "  in space ", "RECIPROCALSPACE"
    1346            4 :                                           WRITE (out_unit, '(A,T66,A)') "  out space ", "RECIPROCALSPACE"
    1347              :                                        #:endif
    1348              :                                     END IF
    1349              : 
    1350      3659117 :                                     my_pos = pw1%pw_grid%para%group%mepos
    1351      3659117 :                                     nrays = pw1%pw_grid%para%nyzray(my_pos)
    1352      3659117 :                                     grays => pw1%pw_grid%grays
    1353              : 
    1354              :                                     #:if space=="rs"
    1355              :                                        #:if kind=="c3d" and kind2=="c1d"
    1356              :                                           !..prepare input
    1357          536 :                                           c_in => pw1%array
    1358          536 :                                           grays = z_zero
    1359              :                                           !..transform
    1360          536 :                                           IF (pw1%pw_grid%para%ray_distribution) THEN
    1361              :                                              CALL fft3d(FWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1362              :                                                         pw1%pw_grid%para%yzp, pw1%pw_grid%para%nyzray, &
    1363          432 :                                                         pw1%pw_grid%para%bo, debug=test)
    1364              :                                           ELSE
    1365              :                                              CALL fft3d(FWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1366          104 :                                                         pw1%pw_grid%para%bo, debug=test)
    1367              :                                           END IF
    1368              :                                           !..prepare output
    1369          536 :                                           IF (test .AND. out_unit > 0) &
    1370            4 :                                              WRITE (out_unit, '(A)') "  PW_GATHER : 2d -> 1d "
    1371          536 :                                           CALL pw_gather_p_${kind2}$ (pw2, grays)
    1372              :                                        #:elif kind=="r3d" and kind2=="c1d"
    1373              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1374              :                                           ! (no ray dist. is not efficient in CUDA)
    1375              :                                           use_pw_gpu = pw1%pw_grid%para%ray_distribution
    1376              :                                           IF (use_pw_gpu) THEN
    1377              :                                              CALL pw_gpu_r3dc1d_3d_ps(pw1, pw2)
    1378              :                                           ELSE
    1379              : #endif
    1380              : !..   prepare input
    1381      7319716 :                                              nloc = pw1%pw_grid%npts_local
    1382      9149645 :                                              ALLOCATE (c_in(nloc(1), nloc(2), nloc(3)))
    1383      1829929 :                                              CALL pw_copy_to_array(pw1, c_in)
    1384      1829929 :                                              grays = z_zero
    1385              :                                              !..transform
    1386      1829929 :                                              IF (pw1%pw_grid%para%ray_distribution) THEN
    1387              :                                                 CALL fft3d(FWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1388              :                                                            pw1%pw_grid%para%yzp, pw1%pw_grid%para%nyzray, &
    1389      1829929 :                                                            pw1%pw_grid%para%bo, debug=test)
    1390              :                                              ELSE
    1391              :                                                 CALL fft3d(FWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1392            0 :                                                            pw1%pw_grid%para%bo, debug=test)
    1393              :                                              END IF
    1394              :                                              !..prepare output
    1395      1829929 :                                              IF (test .AND. out_unit > 0) &
    1396            0 :                                                 WRITE (out_unit, '(A)') "  PW_GATHER : 2d -> 1d "
    1397      1829929 :                                              CALL pw_gather_p_${kind2}$ (pw2, grays)
    1398      1829929 :                                              DEALLOCATE (c_in)
    1399              : 
    1400              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1401              :                                           END IF
    1402              : #endif
    1403              :                                        #:endif
    1404              :                                     #:else
    1405              :                                        #:if kind=="c1d" and kind2=="c3d"
    1406              :                                           !..prepare input
    1407          536 :                                           IF (test .AND. out_unit > 0) &
    1408            4 :                                              WRITE (out_unit, '(A)') "  PW_SCATTER : 2d -> 1d "
    1409          536 :                                           grays = z_zero
    1410          536 :                                           CALL pw_scatter_p_${kind}$ (pw1, grays)
    1411          536 :                                           c_in => pw2%array
    1412              :                                           !..transform
    1413          536 :                                           IF (pw1%pw_grid%para%ray_distribution) THEN
    1414              :                                              CALL fft3d(BWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1415              :                                                         pw1%pw_grid%para%yzp, pw1%pw_grid%para%nyzray, &
    1416          432 :                                                         pw1%pw_grid%para%bo, debug=test)
    1417              :                                           ELSE
    1418              :                                              CALL fft3d(BWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1419          104 :                                                         pw1%pw_grid%para%bo, debug=test)
    1420              :                                           END IF
    1421              :                                           !..prepare output (nothing to do)
    1422              :                                        #:elif kind=="c1d" and kind2=="r3d"
    1423              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1424              :                                           ! (no ray dist. is not efficient in CUDA)
    1425              :                                           use_pw_gpu = pw1%pw_grid%para%ray_distribution
    1426              :                                           IF (use_pw_gpu) THEN
    1427              :                                              CALL pw_gpu_c1dr3d_3d_ps(pw1, pw2)
    1428              :                                           ELSE
    1429              : #endif
    1430              : !..   prepare input
    1431      1828116 :                                              IF (test .AND. out_unit > 0) &
    1432            0 :                                                 WRITE (out_unit, '(A)') "  PW_SCATTER : 2d -> 1d "
    1433      1828116 :                                              grays = z_zero
    1434      1828116 :                                              CALL pw_scatter_p_${kind}$ (pw1, grays)
    1435      7312464 :                                              nloc = pw2%pw_grid%npts_local
    1436      9140580 :                                              ALLOCATE (c_in(nloc(1), nloc(2), nloc(3)))
    1437              :                                              !..transform
    1438      1828116 :                                              IF (pw1%pw_grid%para%ray_distribution) THEN
    1439              :                                                 CALL fft3d(BWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1440              :                                                            pw1%pw_grid%para%yzp, pw1%pw_grid%para%nyzray, &
    1441      1828116 :                                                            pw1%pw_grid%para%bo, debug=test)
    1442              :                                              ELSE
    1443              :                                                 CALL fft3d(BWFFT, n, c_in, grays, pw1%pw_grid%para%group, &
    1444            0 :                                                            pw1%pw_grid%para%bo, debug=test)
    1445              :                                              END IF
    1446              :                                              !..prepare output
    1447      1828116 :                                              IF (test .AND. out_unit > 0) &
    1448            0 :                                                 WRITE (out_unit, '(A)') "  Real part "
    1449      1828116 :                                              CALL pw_copy_from_array(pw2, c_in)
    1450      1828116 :                                              DEALLOCATE (c_in)
    1451              : #if defined(__OFFLOAD) && !defined(__NO_OFFLOAD_PW)
    1452              :                                           END IF
    1453              : #endif
    1454              :                                        #:endif
    1455              :                                     #:endif
    1456              :                                  END IF
    1457              : 
    1458      4277541 :                                  IF (test .AND. out_unit > 0) THEN
    1459            8 :                                     WRITE (out_unit, '(A)') " End of FFT Protocol "
    1460              :                                  END IF
    1461              : 
    1462      4277541 :                                  CALL timestop(handle)
    1463      4277541 :                                  CALL timestop(handle2)
    1464              : 
    1465      4277541 :                               END SUBROUTINE fft_wrap_pw1pw2_${kind}$_${kind2}$_${space}$_${space2}$
    1466              :                            #:endif
    1467              :                         #:endfor
    1468              :                      #:endfor
    1469              : 
    1470              :                      #:if kind[1]=='1' and kind2[1]=='3'
    1471              : 
    1472              : ! **************************************************************************************************
    1473              : !> \brief Gathers the pw vector from a 3d data field
    1474              : !> \param pw ...
    1475              : !> \param c ...
    1476              : !> \param scale ...
    1477              : !> \par History
    1478              : !>      none
    1479              : !> \author JGH
    1480              : ! **************************************************************************************************
    1481            0 :                         SUBROUTINE pw_gather_s_${kind}$_${kind2}$_2(pw1, pw2, scale)
    1482              : 
    1483              :                            TYPE(pw_${kind2}$_gs_type), INTENT(IN)                       :: pw1
    1484              :                            TYPE(pw_${kind}$_gs_type), INTENT(INOUT)   :: pw2
    1485              :                            REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
    1486              : 
    1487            0 :                            CALL pw_gather_s_${kind}$_${kind2}$ (pw2, pw1%array, scale)
    1488              : 
    1489            0 :                         END SUBROUTINE pw_gather_s_${kind}$_${kind2}$_2
    1490              : 
    1491              : ! **************************************************************************************************
    1492              : !> \brief Gathers the pw vector from a 3d data field
    1493              : !> \param pw ...
    1494              : !> \param c ...
    1495              : !> \param scale ...
    1496              : !> \par History
    1497              : !>      none
    1498              : !> \author JGH
    1499              : ! **************************************************************************************************
    1500       300807 :                         SUBROUTINE pw_gather_s_${kind}$_${kind2}$ (pw, c, scale)
    1501              : 
    1502              :                            TYPE(pw_${kind}$_gs_type), INTENT(INOUT)                       :: pw
    1503              :                            ${type2}$, CONTIGUOUS, INTENT(IN), TARGET                      :: c
    1504              :                            REAL(KIND=dp), INTENT(IN), OPTIONAL                            :: scale
    1505              : 
    1506              :                            CHARACTER(len=*), PARAMETER                                    :: routineN = 'pw_gather_s'
    1507              : 
    1508              :                            INTEGER                                                        :: gpt, handle
    1509              :                            #:if kind2[0] == "c"
    1510       300807 :                               COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:), POINTER         :: c_1d
    1511              :                            #:else
    1512            0 :                               REAL(KIND=dp), CONTIGUOUS, DIMENSION(:), POINTER            :: c_1d
    1513              :                            #:endif
    1514              : 
    1515       300807 :                            CALL timeset(routineN, handle)
    1516              : 
    1517              :                            ! Rank-1 pointer remap of contiguous c for flat g_hatmap indexing
    1518      1203228 :                            c_1d(1:SIZE(c)) => c
    1519              :                            ASSOCIATE (ngpts => SIZE(pw%pw_grid%gsq), g_hatmap => pw%pw_grid%g_hatmap)
    1520              : 
    1521       300807 :                               IF (PRESENT(scale)) THEN
    1522            0 : !$OMP PARALLEL DO PRIVATE(gpt) DEFAULT(NONE) SHARED(c_1d, pw, scale)
    1523              :                                  DO gpt = 1, ngpts
    1524              :                                     pw%array(gpt) = scale*${type2type("c_1d(g_hatmap(gpt, 1) + 1)", kind2, kind)}$
    1525              :                                  END DO
    1526              : !$OMP END PARALLEL DO
    1527              :                               ELSE
    1528       300807 : !$OMP PARALLEL DO PRIVATE(gpt) DEFAULT(NONE) SHARED(c_1d, pw)
    1529              :                                  DO gpt = 1, ngpts
    1530              :                                     pw%array(gpt) = ${type2type("c_1d(g_hatmap(gpt, 1) + 1)", kind2, kind)}$
    1531              :                                  END DO
    1532              : !$OMP END PARALLEL DO
    1533              :                               END IF
    1534              : 
    1535              :                            END ASSOCIATE
    1536              : 
    1537       300807 :                            CALL timestop(handle)
    1538              : 
    1539       300807 :                         END SUBROUTINE pw_gather_s_${kind}$_${kind2}$
    1540              : 
    1541              : ! **************************************************************************************************
    1542              : !> \brief Scatters a pw vector to a 3d data field
    1543              : !> \param pw ...
    1544              : !> \param c ...
    1545              : !> \param scale ...
    1546              : !> \par History
    1547              : !>      none
    1548              : !> \author JGH
    1549              : ! **************************************************************************************************
    1550            0 :                         SUBROUTINE pw_scatter_s_${kind}$_${kind2}$_2(pw1, pw2, scale)
    1551              : 
    1552              :                            TYPE(pw_${kind}$_gs_type), INTENT(IN)                 :: pw1
    1553              :                            TYPE(pw_${kind2}$_gs_type), INTENT(INOUT)               :: pw2
    1554              :                            REAL(KIND=dp), INTENT(IN), OPTIONAL                :: scale
    1555              : 
    1556            0 :                            CALL pw_scatter_s_${kind}$_${kind2}$ (pw1, pw2%array, scale)
    1557              : 
    1558            0 :                         END SUBROUTINE pw_scatter_s_${kind}$_${kind2}$_2
    1559              : 
    1560              : ! **************************************************************************************************
    1561              : !> \brief Scatters a pw vector to a 3d data field
    1562              : !> \param pw ...
    1563              : !> \param c ...
    1564              : !> \param scale ...
    1565              : !> \par History
    1566              : !>      none
    1567              : !> \author JGH
    1568              : ! **************************************************************************************************
    1569       317617 :                         SUBROUTINE pw_scatter_s_${kind}$_${kind2}$ (pw, c, scale)
    1570              : 
    1571              :                            TYPE(pw_${kind}$_gs_type), INTENT(IN)                          :: pw
    1572              :                            ${type2}$, CONTIGUOUS, INTENT(INOUT), TARGET                   :: c
    1573              :                            REAL(KIND=dp), INTENT(IN), OPTIONAL                            :: scale
    1574              : 
    1575              :                            CHARACTER(len=*), PARAMETER                                    :: routineN = 'pw_scatter_s'
    1576              : 
    1577              :                            INTEGER                                                        :: gpt, handle
    1578              :                            #:if kind2[0] == "c"
    1579       317617 :                               COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:), POINTER         :: c_1d
    1580              :                            #:else
    1581            0 :                               REAL(KIND=dp), CONTIGUOUS, DIMENSION(:), POINTER            :: c_1d
    1582              :                            #:endif
    1583              : 
    1584       317617 :                            CALL timeset(routineN, handle)
    1585              : 
    1586              :                            ! Rank-1 pointer remap of contiguous c for flat g_hatmap indexing
    1587      1270468 :                            c_1d(1:SIZE(c)) => c
    1588              :                            ASSOCIATE (g_hatmap => pw%pw_grid%g_hatmap, ngpts => SIZE(pw%pw_grid%gsq))
    1589              : 
    1590              :                               ! should only zero the unused bits (but the zero is needed)
    1591   2787135072 :                               IF (.NOT. PRESENT(scale)) c = 0.0_dp
    1592              : 
    1593              :                               IF (PRESENT(scale)) THEN
    1594            0 : !$OMP PARALLEL DO PRIVATE(gpt) DEFAULT(NONE) SHARED(c_1d, pw, scale)
    1595              :                                  DO gpt = 1, ngpts
    1596              :                                     c_1d(g_hatmap(gpt, 1) + 1) = scale*${type2type("pw%array(gpt)", kind, kind2)}$
    1597              :                                  END DO
    1598              : !$OMP END PARALLEL DO
    1599              :                               ELSE
    1600       317617 : !$OMP PARALLEL DO PRIVATE(gpt) DEFAULT(NONE) SHARED(c_1d, pw)
    1601              :                                  DO gpt = 1, ngpts
    1602              :                                     c_1d(g_hatmap(gpt, 1) + 1) = ${type2type("pw%array(gpt)", kind, kind2)}$
    1603              :                                  END DO
    1604              : !$OMP END PARALLEL DO
    1605              :                               END IF
    1606              : 
    1607       635234 :                               IF (pw%pw_grid%grid_span == HALFSPACE) THEN
    1608              : 
    1609        10134 :                                  IF (PRESENT(scale)) THEN
    1610            0 : !$OMP PARALLEL DO PRIVATE(gpt) DEFAULT(NONE) SHARED(c_1d, pw, scale)
    1611              :                                     DO gpt = 1, ngpts
    1612              :                                        c_1d(g_hatmap(gpt, 2) + 1) = scale*#{if kind[0]=="c" and kind2[0]=="c"}#CONJG#{endif}#(${type2type("pw%array(gpt)", kind, kind2)}$)
    1613              :                                     END DO
    1614              : !$OMP END PARALLEL DO
    1615              :                                  ELSE
    1616        10134 : !$OMP PARALLEL DO PRIVATE(gpt) DEFAULT(NONE) SHARED(c_1d, pw)
    1617              :                                     DO gpt = 1, ngpts
    1618              :                                        c_1d(g_hatmap(gpt, 2) + 1) = #{if kind[0]=="c" and kind2[0]=="c"}#CONJG#{endif}#(${type2type("pw%array(gpt)", kind, kind2)}$)
    1619              :                                     END DO
    1620              : !$OMP END PARALLEL DO
    1621              :                                  END IF
    1622              : 
    1623              :                               END IF
    1624              : 
    1625              :                            END ASSOCIATE
    1626              : 
    1627       317617 :                            CALL timestop(handle)
    1628              : 
    1629       317617 :                         END SUBROUTINE pw_scatter_s_${kind}$_${kind2}$
    1630              :                      #:endif
    1631              :                   #:endfor
    1632              : 
    1633              : ! **************************************************************************************************
    1634              : !> \brief Multiply all data points with a Gaussian damping factor
    1635              : !>        Needed for longrange Coulomb potential
    1636              : !>        V(\vec r)=erf(omega*r)/r
    1637              : !>        V(\vec g)=\frac{4*\pi}{g**2}*exp(-g**2/omega**2)
    1638              : !> \param pw ...
    1639              : !> \param omega ...
    1640              : !> \par History
    1641              : !>      Frederick Stein (12-04-2019) created
    1642              : !> \author Frederick Stein (12-Apr-2019)
    1643              : !> \note
    1644              : !>      Performs a Gaussian damping
    1645              : ! **************************************************************************************************
    1646         3841 :                   SUBROUTINE pw_gauss_damp(pw, omega)
    1647              : 
    1648              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1649              :                      REAL(KIND=dp), INTENT(IN)                          :: omega
    1650              : 
    1651              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_gauss_damp'
    1652              : 
    1653              :                      INTEGER                                            :: handle, i
    1654              :                      REAL(KIND=dp)                                      :: omega_2, tmp
    1655              : 
    1656         3841 :                      CALL timeset(routineN, handle)
    1657         3841 :                      CPASSERT(omega >= 0)
    1658              : 
    1659         3841 :                      omega_2 = omega*omega
    1660         3841 :                      omega_2 = 0.25_dp/omega_2
    1661              : 
    1662         3841 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp) SHARED(pw,omega_2)
    1663              :                      DO i = 1, SIZE(pw%array)
    1664              :                         tmp = EXP(-pw%pw_grid%gsq(i)*omega_2)
    1665              :                         pw%array(i) = pw%array(i)*tmp
    1666              :                      END DO
    1667              : !$OMP END PARALLEL DO
    1668              : 
    1669         3841 :                      CALL timestop(handle)
    1670              : 
    1671         3841 :                   END SUBROUTINE pw_gauss_damp
    1672              : 
    1673              : ! **************************************************************************************************
    1674              : !> \brief Multiply all data points with the logarithmic derivative of a Gaussian
    1675              : !> \param pw ...
    1676              : !> \param omega ...
    1677              : !> \note
    1678              : !>      Performs a Gaussian damping
    1679              : ! **************************************************************************************************
    1680         1329 :                   SUBROUTINE pw_log_deriv_gauss(pw, omega)
    1681              : 
    1682              :                      TYPE(pw_c1d_gs_type), INTENT(IN)                          :: pw
    1683              :                      REAL(KIND=dp), INTENT(IN)                          :: omega
    1684              : 
    1685              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_log_deriv_gauss'
    1686              : 
    1687              :                      INTEGER                                            :: handle, i
    1688              :                      REAL(KIND=dp)                                      :: omega_2, tmp
    1689              : 
    1690         1329 :                      CALL timeset(routineN, handle)
    1691         1329 :                      CPASSERT(omega >= 0)
    1692              : 
    1693         1329 :                      omega_2 = omega*omega
    1694         1329 :                      omega_2 = 0.25_dp/omega_2
    1695              : 
    1696         1329 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp) SHARED(pw,omega_2)
    1697              :                      DO i = 1, SIZE(pw%array)
    1698              :                         tmp = 1.0_dp + omega_2*pw%pw_grid%gsq(i)
    1699              :                         pw%array(i) = pw%array(i)*tmp
    1700              :                      END DO
    1701              : !$OMP END PARALLEL DO
    1702              : 
    1703         1329 :                      CALL timestop(handle)
    1704         1329 :                   END SUBROUTINE pw_log_deriv_gauss
    1705              : 
    1706              : ! **************************************************************************************************
    1707              : !> \brief Multiply all data points with a Gaussian damping factor
    1708              : !>        Needed for longrange Coulomb potential
    1709              : !>        V(\vec r)=erf(omega*r)/r
    1710              : !>        V(\vec g)=\frac{4*\pi}{g**2}*exp(-g**2/omega**2)
    1711              : !> \param pw ...
    1712              : !> \param omega ...
    1713              : !> \par History
    1714              : !>      Frederick Stein (12-04-2019) created
    1715              : !> \author Frederick Stein (12-Apr-2019)
    1716              : !> \note
    1717              : !>      Performs a Gaussian damping
    1718              : ! **************************************************************************************************
    1719            0 :                   SUBROUTINE pw_compl_gauss_damp(pw, omega)
    1720              : 
    1721              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1722              :                      REAL(KIND=dp), INTENT(IN)                          :: omega
    1723              : 
    1724              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_compl_gauss_damp'
    1725              : 
    1726              :                      INTEGER                                            :: cnt, handle, i
    1727              :                      REAL(KIND=dp)                                      :: omega_2, tmp, tmp2
    1728              : 
    1729            0 :                      CALL timeset(routineN, handle)
    1730              : 
    1731            0 :                      omega_2 = omega*omega
    1732            0 :                      omega_2 = 0.25_dp/omega_2
    1733              : 
    1734            0 :                      cnt = SIZE(pw%array)
    1735              : 
    1736            0 : !$OMP PARALLEL DO PRIVATE(i, tmp, tmp2) DEFAULT(NONE) SHARED(cnt, pw,omega_2)
    1737              :                      DO i = 1, cnt
    1738              :                         tmp = -omega_2*pw%pw_grid%gsq(i)
    1739              :                         IF (ABS(tmp) > 1.0E-5_dp) THEN
    1740              :                            tmp2 = 1.0_dp - EXP(tmp)
    1741              :                         ELSE
    1742              :                            tmp2 = tmp + 0.5_dp*tmp*(tmp + (1.0_dp/3.0_dp)*tmp**2)
    1743              :                         END IF
    1744              :                         pw%array(i) = pw%array(i)*tmp2
    1745              :                      END DO
    1746              : !$OMP END PARALLEL DO
    1747              : 
    1748            0 :                      CALL timestop(handle)
    1749              : 
    1750            0 :                   END SUBROUTINE pw_compl_gauss_damp
    1751              : 
    1752              : ! **************************************************************************************************
    1753              : !> \brief Multiply all data points with the logarithmic derivative of the complementary Gaussian damping factor
    1754              : !> \param pw ...
    1755              : !> \param omega ...
    1756              : !> \note
    1757              : ! **************************************************************************************************
    1758            0 :                   SUBROUTINE pw_log_deriv_compl_gauss(pw, omega)
    1759              : 
    1760              :                      TYPE(pw_c1d_gs_type), INTENT(IN)                          :: pw
    1761              :                      REAL(KIND=dp), INTENT(IN)                          :: omega
    1762              : 
    1763              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_log_deriv_compl_gauss'
    1764              : 
    1765              :                      INTEGER                                            :: handle, i
    1766              :                      REAL(KIND=dp)                                      :: omega_2, tmp, tmp2
    1767              : 
    1768            0 :                      CALL timeset(routineN, handle)
    1769              : 
    1770            0 :                      omega_2 = omega*omega
    1771            0 :                      omega_2 = 0.25_dp/omega_2
    1772              : 
    1773              : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp,tmp2) &
    1774            0 : !$OMP             SHARED(pw,omega_2)
    1775              :                      DO i = 1, SIZE(pw%array)
    1776              :                         tmp = omega_2*pw%pw_grid%gsq(i)
    1777              :                         ! For too small arguments, use the Taylor polynomial to prevent division by zero
    1778              :                         IF (ABS(tmp) >= 0.003_dp) THEN
    1779              :                            tmp2 = 1.0_dp - tmp*EXP(-tmp)/(1.0_dp - EXP(-tmp))
    1780              :                         ELSE
    1781              :                            tmp2 = 0.5_dp*tmp - tmp**2/12.0_dp
    1782              :                         END IF
    1783              :                         pw%array(i) = pw%array(i)*tmp2
    1784              :                      END DO
    1785              : !$OMP END PARALLEL DO
    1786              : 
    1787            0 :                      CALL timestop(handle)
    1788              : 
    1789            0 :                   END SUBROUTINE pw_log_deriv_compl_gauss
    1790              : 
    1791              : ! **************************************************************************************************
    1792              : !> \brief Multiply all data points with a Gaussian damping factor and mixes it with the original function
    1793              : !>        Needed for mixed longrange/Coulomb potential
    1794              : !>        V(\vec r)=(a+b*erf(omega*r))/r
    1795              : !>        V(\vec g)=\frac{4*\pi}{g**2}*(a+b*exp(-g**2/omega**2))
    1796              : !> \param pw ...
    1797              : !> \param omega ...
    1798              : !> \param scale_coul ...
    1799              : !> \param scale_long ...
    1800              : !> \par History
    1801              : !>      Frederick Stein (16-Dec-2021) created
    1802              : !> \author Frederick Stein (16-Dec-2021)
    1803              : !> \note
    1804              : !>      Performs a Gaussian damping
    1805              : ! **************************************************************************************************
    1806          332 :                   SUBROUTINE pw_gauss_damp_mix(pw, omega, scale_coul, scale_long)
    1807              : 
    1808              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1809              :                      REAL(KIND=dp), INTENT(IN)                          :: omega, scale_coul, scale_long
    1810              : 
    1811              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_gauss_damp_mix'
    1812              : 
    1813              :                      INTEGER                                            :: handle, i
    1814              :                      REAL(KIND=dp)                                      :: omega_2, tmp
    1815              : 
    1816          332 :                      CALL timeset(routineN, handle)
    1817              : 
    1818          332 :                      omega_2 = omega*omega
    1819          332 :                      omega_2 = 0.25_dp/omega_2
    1820              : 
    1821          332 : !$OMP PARALLEL DO DEFAULT(NONE) SHARED(pw, omega_2, scale_coul, scale_long) PRIVATE(i,tmp)
    1822              :                      DO i = 1, SIZE(pw%array)
    1823              :                         tmp = scale_coul + scale_long*EXP(-pw%pw_grid%gsq(i)*omega_2)
    1824              :                         pw%array(i) = pw%array(i)*tmp
    1825              :                      END DO
    1826              : !$OMP END PARALLEL DO
    1827              : 
    1828          332 :                      CALL timestop(handle)
    1829              : 
    1830          332 :                   END SUBROUTINE pw_gauss_damp_mix
    1831              : 
    1832              : ! **************************************************************************************************
    1833              : !> \brief Multiply all data points with the logarithmic derivative of the mixed longrange/Coulomb potential
    1834              : !>        Needed for mixed longrange/Coulomb potential
    1835              : !> \param pw ...
    1836              : !> \param omega ...
    1837              : !> \param scale_coul ...
    1838              : !> \param scale_long ...
    1839              : !> \note
    1840              : ! **************************************************************************************************
    1841          249 :                   SUBROUTINE pw_log_deriv_mix_cl(pw, omega, scale_coul, scale_long)
    1842              : 
    1843              :                      TYPE(pw_c1d_gs_type), INTENT(IN)                          :: pw
    1844              :                      REAL(KIND=dp), INTENT(IN)                          :: omega, scale_coul, scale_long
    1845              : 
    1846              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_log_deriv_mix_cl'
    1847              : 
    1848              :                      INTEGER                                            :: handle, i
    1849              :                      REAL(KIND=dp)                                      :: omega_2, tmp, tmp2
    1850              : 
    1851          249 :                      CALL timeset(routineN, handle)
    1852              : 
    1853          249 :                      omega_2 = omega*omega
    1854          249 :                      omega_2 = 0.25_dp/omega_2
    1855              : 
    1856              : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp,tmp2) &
    1857          249 : !$OMP             SHARED(pw,omega_2,scale_long,scale_coul)
    1858              :                      DO i = 1, SIZE(pw%array)
    1859              :                         tmp = omega_2*pw%pw_grid%gsq(i)
    1860              :                         tmp2 = 1.0_dp + scale_long*tmp*EXP(-tmp)/(scale_coul + scale_long*EXP(-tmp))
    1861              :                         pw%array(i) = pw%array(i)*tmp2
    1862              :                      END DO
    1863              : !$OMP END PARALLEL DO
    1864              : 
    1865          249 :                      CALL timestop(handle)
    1866              : 
    1867          249 :                   END SUBROUTINE pw_log_deriv_mix_cl
    1868              : 
    1869              : ! **************************************************************************************************
    1870              : !> \brief Multiply all data points with a complementary cosine
    1871              : !>        Needed for truncated Coulomb potential
    1872              : !>        V(\vec r)=1/r if r<rc, 0 else
    1873              : !>        V(\vec g)=\frac{4*\pi}{g**2}*(1-cos(g*rc))
    1874              : !> \param pw ...
    1875              : !> \param rcutoff ...
    1876              : !> \par History
    1877              : !>      Frederick Stein (07-06-2021) created
    1878              : !> \author Frederick Stein (07-Jun-2021)
    1879              : !> \note
    1880              : !>      Multiplies by complementary cosine
    1881              : ! **************************************************************************************************
    1882            0 :                   SUBROUTINE pw_truncated(pw, rcutoff)
    1883              : 
    1884              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1885              :                      REAL(KIND=dp), INTENT(IN)                          :: rcutoff
    1886              : 
    1887              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_truncated'
    1888              : 
    1889              :                      INTEGER                                            :: handle, i
    1890              :                      REAL(KIND=dp)                                      :: tmp, tmp2
    1891              : 
    1892            0 :                      CALL timeset(routineN, handle)
    1893            0 :                      CPASSERT(rcutoff >= 0)
    1894              : 
    1895            0 : !$OMP PARALLEL DO PRIVATE(i,tmp,tmp2) DEFAULT(NONE) SHARED(pw, rcutoff)
    1896              :                      DO i = 1, SIZE(pw%array)
    1897              :                         tmp = SQRT(pw%pw_grid%gsq(i))*rcutoff
    1898              :                         IF (tmp >= 0.005_dp) THEN
    1899              :                            tmp2 = 1.0_dp - COS(tmp)
    1900              :                         ELSE
    1901              :                            tmp2 = tmp**2/2.0_dp*(1.0_dp - tmp**2/12.0_dp)
    1902              :                         END IF
    1903              :                         pw%array(i) = pw%array(i)*tmp2
    1904              :                      END DO
    1905              : !$OMP END PARALLEL DO
    1906              : 
    1907            0 :                      CALL timestop(handle)
    1908              : 
    1909            0 :                   END SUBROUTINE pw_truncated
    1910              : 
    1911              : ! **************************************************************************************************
    1912              : !> \brief Multiply all data points with the logarithmic derivative of the complementary cosine
    1913              : !>        This function is needed for virials using truncated Coulomb potentials
    1914              : !> \param pw ...
    1915              : !> \param rcutoff ...
    1916              : !> \note
    1917              : ! **************************************************************************************************
    1918            0 :                   SUBROUTINE pw_log_deriv_trunc(pw, rcutoff)
    1919              : 
    1920              :                      TYPE(pw_c1d_gs_type), INTENT(IN)                          :: pw
    1921              :                      REAL(KIND=dp), INTENT(IN)                          :: rcutoff
    1922              : 
    1923              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_log_deriv_trunc'
    1924              : 
    1925              :                      INTEGER                                            :: handle, i
    1926              :                      REAL(KIND=dp)                                      :: rchalf, tmp, tmp2
    1927              : 
    1928            0 :                      CALL timeset(routineN, handle)
    1929            0 :                      CPASSERT(rcutoff >= 0)
    1930              : 
    1931            0 :                      rchalf = 0.5_dp*rcutoff
    1932              : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(i,tmp,tmp2) &
    1933            0 : !$OMP             SHARED(pw,rchalf)
    1934              :                      DO i = 1, SIZE(pw%array)
    1935              :                         tmp = rchalf*SQRT(pw%pw_grid%gsq(i))
    1936              :                         ! For too small arguments, use the Taylor polynomial to prevent division by zero
    1937              :                         IF (ABS(tmp) >= 0.0001_dp) THEN
    1938              :                            tmp2 = 1.0_dp - tmp/TAN(tmp)
    1939              :                         ELSE
    1940              :                            tmp2 = tmp**2*(1.0_dp + tmp**2/15.0_dp)/3.0_dp
    1941              :                         END IF
    1942              :                         pw%array(i) = pw%array(i)*tmp2
    1943              :                      END DO
    1944              : !$OMP END PARALLEL DO
    1945              : 
    1946            0 :                      CALL timestop(handle)
    1947              : 
    1948            0 :                   END SUBROUTINE pw_log_deriv_trunc
    1949              : 
    1950              : ! **************************************************************************************************
    1951              : !> \brief Calculate the derivative of a plane wave vector
    1952              : !> \param pw ...
    1953              : !> \param n ...
    1954              : !> \par History
    1955              : !>      JGH (06-10-2002) allow only for inplace derivatives
    1956              : !> \author JGH (25-Feb-2001)
    1957              : !> \note
    1958              : !>      Calculate the derivative dx^n(1) dy^n(2) dz^n(3) PW
    1959              : ! **************************************************************************************************
    1960      1674918 :                   SUBROUTINE pw_derive(pw, n)
    1961              : 
    1962              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    1963              :                      INTEGER, DIMENSION(3), INTENT(IN)                  :: n
    1964              : 
    1965              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_derive'
    1966              : 
    1967              :                      COMPLEX(KIND=dp)                                   :: im
    1968              :                      INTEGER                                            :: handle, m, idx, idir
    1969              : 
    1970      1674918 :                      CALL timeset(routineN, handle)
    1971              : 
    1972      6699672 :                      IF (ANY(n < 0)) &
    1973            0 :                         CPABORT("Nonnegative exponents are not supported!")
    1974              : 
    1975      6699672 :                      m = SUM(n)
    1976      1674918 :                      im = gaussi**m
    1977              : 
    1978      6699672 :                      DO idir = 1, 3
    1979      6699672 :                         IF (n(idir) == 1) THEN
    1980      1674918 : !$OMP PARALLEL DO DEFAULT(NONE) SHARED(pw,idir) PRIVATE(idx)
    1981              :                            DO idx = 1, SIZE(pw%array)
    1982              :                               pw%array(idx) = pw%array(idx)*pw%pw_grid%g(idir, idx)
    1983              :                            END DO
    1984              : !$OMP END PARALLEL DO
    1985      3349836 :                         ELSE IF (n(idir) > 1) THEN
    1986          432 : !$OMP PARALLEL DO DEFAULT(NONE) SHARED(n, pw,idir) PRIVATE(idx)
    1987              :                            DO idx = 1, SIZE(pw%array)
    1988              :                               pw%array(idx) = pw%array(idx)*pw%pw_grid%g(idir, idx)**n(idir)
    1989              :                            END DO
    1990              : !$OMP END PARALLEL DO
    1991              :                         END IF
    1992              :                      END DO
    1993              : 
    1994              :                      ! im can take the values 1, -1, i, -i
    1995              :                      ! skip this if im == 1
    1996      1674918 :                      IF (ABS(REAL(im, KIND=dp) - 1.0_dp) > 1.0E-10_dp) THEN
    1997      1674918 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(im, pw)
    1998              :                         pw%array(:) = im*pw%array(:)
    1999              : !$OMP END PARALLEL WORKSHARE
    2000              :                      END IF
    2001              : 
    2002      1674918 :                      CALL timestop(handle)
    2003              : 
    2004      1674918 :                   END SUBROUTINE pw_derive
    2005              : 
    2006              : ! **************************************************************************************************
    2007              : !> \brief Calculate the Laplacian of a plane wave vector
    2008              : !> \param pw ...
    2009              : !> \par History
    2010              : !>      Frederick Stein (01-02-2022) created
    2011              : !> \author JGH (25-Feb-2001)
    2012              : !> \note
    2013              : !>      Calculate the derivative DELTA PW
    2014              : ! **************************************************************************************************
    2015         3770 :                   SUBROUTINE pw_laplace(pw)
    2016              : 
    2017              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    2018              : 
    2019              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_laplace'
    2020              : 
    2021              :                      INTEGER                                            :: handle
    2022              : 
    2023         3770 :                      CALL timeset(routineN, handle)
    2024              : 
    2025         3770 : !$OMP PARALLEL WORKSHARE DEFAULT(NONE) SHARED(pw)
    2026              :                      pw%array(:) = -pw%array(:)*pw%pw_grid%gsq(:)
    2027              : !$OMP END PARALLEL WORKSHARE
    2028              : 
    2029         3770 :                      CALL timestop(handle)
    2030              : 
    2031         3770 :                   END SUBROUTINE pw_laplace
    2032              : 
    2033              : ! **************************************************************************************************
    2034              : !> \brief Calculate the tensorial 2nd derivative of a plane wave vector
    2035              : !> \param pw ...
    2036              : !> \param pwdr2 ...
    2037              : !> \param i ...
    2038              : !> \param j ...
    2039              : !> \par History
    2040              : !>      none
    2041              : !> \author JGH (05-May-2006)
    2042              : !> \note
    2043              : ! **************************************************************************************************
    2044          198 :                   SUBROUTINE pw_dr2(pw, pwdr2, i, j)
    2045              : 
    2046              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw, pwdr2
    2047              :                      INTEGER, INTENT(IN)                                :: i, j
    2048              : 
    2049              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_dr2'
    2050              : 
    2051              :                      INTEGER                                            :: cnt, handle, ig
    2052              :                      REAL(KIND=dp)                                      :: gg, o3
    2053              : 
    2054          198 :                      CALL timeset(routineN, handle)
    2055              : 
    2056          198 :                      o3 = 1.0_dp/3.0_dp
    2057              : 
    2058          198 :                      cnt = SIZE(pw%array)
    2059              : 
    2060          198 :                      IF (i == j) THEN
    2061          108 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(ig,gg) SHARED(cnt, i, o3, pw, pwdr2)
    2062              :                         DO ig = 1, cnt
    2063              :                            gg = pw%pw_grid%g(i, ig)**2 - o3*pw%pw_grid%gsq(ig)
    2064              :                            pwdr2%array(ig) = gg*pw%array(ig)
    2065              :                         END DO
    2066              : !$OMP END PARALLEL DO
    2067              :                      ELSE
    2068           90 : !$OMP PARALLEL DO PRIVATE (ig) DEFAULT(NONE) SHARED(cnt, i, j, pw, pwdr2)
    2069              :                         DO ig = 1, cnt
    2070              :                            pwdr2%array(ig) = pw%array(ig)*(pw%pw_grid%g(i, ig)*pw%pw_grid%g(j, ig))
    2071              :                         END DO
    2072              : !$OMP END PARALLEL DO
    2073              :                      END IF
    2074              : 
    2075          198 :                      CALL timestop(handle)
    2076              : 
    2077          198 :                   END SUBROUTINE pw_dr2
    2078              : 
    2079              : ! **************************************************************************************************
    2080              : !> \brief Calculate the tensorial 2nd derivative of a plane wave vector
    2081              : !>      and divides by |G|^2. pwdr2_gg(G=0) is put to zero.
    2082              : !> \param pw ...
    2083              : !> \param pwdr2_gg ...
    2084              : !> \param i ...
    2085              : !> \param j ...
    2086              : !> \par History
    2087              : !>      none
    2088              : !> \author RD (20-Nov-2006)
    2089              : !> \note
    2090              : !>      Adapted from pw_dr2
    2091              : ! **************************************************************************************************
    2092           12 :                   SUBROUTINE pw_dr2_gg(pw, pwdr2_gg, i, j)
    2093              : 
    2094              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw, pwdr2_gg
    2095              :                      INTEGER, INTENT(IN)                                :: i, j
    2096              : 
    2097              :                      INTEGER                                            :: cnt, handle, ig
    2098              :                      REAL(KIND=dp)                                      :: gg, o3
    2099              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_dr2_gg'
    2100              : 
    2101           12 :                      CALL timeset(routineN, handle)
    2102              : 
    2103           12 :                      o3 = 1.0_dp/3.0_dp
    2104              : 
    2105           12 :                      cnt = SIZE(pw%array)
    2106              : 
    2107           12 :                      IF (i == j) THEN
    2108            6 : !$OMP PARALLEL DO PRIVATE (ig) DEFAULT(NONE) PRIVATE(gg) SHARED(cnt, i, o3, pw, pwdr2_gg)
    2109              :                         DO ig = pw%pw_grid%first_gne0, cnt
    2110              :                            gg = pw%pw_grid%g(i, ig)**2 - o3*pw%pw_grid%gsq(ig)
    2111              :                            pwdr2_gg%array(ig) = gg/pw%pw_grid%gsq(ig)*pw%array(ig)
    2112              :                         END DO
    2113              : !$OMP END PARALLEL DO
    2114              :                      ELSE
    2115            6 : !$OMP PARALLEL DO PRIVATE (ig) DEFAULT(NONE) SHARED(cnt, i, j, pw, pwdr2_gg)
    2116              :                         DO ig = pw%pw_grid%first_gne0, cnt
    2117              :                            pwdr2_gg%array(ig) = pw%array(ig)*((pw%pw_grid%g(i, ig)*pw%pw_grid%g(j, ig)) &
    2118              :                                                               /pw%pw_grid%gsq(ig))
    2119              :                         END DO
    2120              : !$OMP END PARALLEL DO
    2121              :                      END IF
    2122              : 
    2123           12 :                      IF (pw%pw_grid%have_g0) pwdr2_gg%array(1) = 0.0_dp
    2124              : 
    2125           12 :                      CALL timestop(handle)
    2126              : 
    2127           12 :                   END SUBROUTINE pw_dr2_gg
    2128              : 
    2129              : ! **************************************************************************************************
    2130              : !> \brief Multiplies a G-space function with a smoothing factor of the form
    2131              : !>      f(|G|) = exp((ecut - G^2)/sigma)/(1+exp((ecut - G^2)/sigma))
    2132              : !> \param pw ...
    2133              : !> \param ecut ...
    2134              : !> \param sigma ...
    2135              : !> \par History
    2136              : !>      none
    2137              : !> \author JGH (09-June-2006)
    2138              : !> \note
    2139              : ! **************************************************************************************************
    2140           30 :                   SUBROUTINE pw_smoothing(pw, ecut, sigma)
    2141              : 
    2142              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: pw
    2143              :                      REAL(KIND=dp), INTENT(IN)                          :: ecut, sigma
    2144              : 
    2145              :                      CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_smoothing'
    2146              : 
    2147              :                      INTEGER                                            :: cnt, handle, ig
    2148              :                      REAL(KIND=dp)                                      :: arg, f
    2149              : 
    2150           30 :                      CALL timeset(routineN, handle)
    2151              : 
    2152           30 :                      cnt = SIZE(pw%array)
    2153              : 
    2154           30 : !$OMP PARALLEL DO DEFAULT(NONE) PRIVATE(ig, arg, f) SHARED(cnt, ecut, pw, sigma)
    2155              :                      DO ig = 1, cnt
    2156              :                         arg = (ecut - pw%pw_grid%gsq(ig))/sigma
    2157              :                         f = EXP(arg)/(1 + EXP(arg))
    2158              :                         pw%array(ig) = f*pw%array(ig)
    2159              :                      END DO
    2160              : !$OMP END PARALLEL DO
    2161              : 
    2162           30 :                      CALL timestop(handle)
    2163              : 
    2164           30 :                   END SUBROUTINE pw_smoothing
    2165              : 
    2166              : ! **************************************************************************************************
    2167              : !> \brief ...
    2168              : !> \param grida ...
    2169              : !> \param gridb ...
    2170              : !> \return ...
    2171              : ! **************************************************************************************************
    2172       938232 :                   ELEMENTAL FUNCTION pw_compatible(grida, gridb) RESULT(compat)
    2173              : 
    2174              :                      TYPE(pw_grid_type), INTENT(IN)                     :: grida, gridb
    2175              :                      LOGICAL                                            :: compat
    2176              : 
    2177       938232 :                      compat = .FALSE.
    2178              : 
    2179       938232 :                      IF (grida%id_nr == gridb%id_nr) THEN
    2180              :                         compat = .TRUE.
    2181       938232 :                      ELSE IF (grida%reference == gridb%id_nr) THEN
    2182              :                         compat = .TRUE.
    2183         2084 :                      ELSE IF (gridb%reference == grida%id_nr) THEN
    2184         1554 :                         compat = .TRUE.
    2185              :                      END IF
    2186              : 
    2187       938232 :                   END FUNCTION pw_compatible
    2188              : 
    2189              : ! **************************************************************************************************
    2190              : !> \brief Calculate the structure factor for point r
    2191              : !> \param sf ...
    2192              : !> \param r ...
    2193              : !> \par History
    2194              : !>      none
    2195              : !> \author JGH (05-May-2006)
    2196              : !> \note
    2197              : ! **************************************************************************************************
    2198           76 :                   SUBROUTINE pw_structure_factor(sf, r)
    2199              : 
    2200              :                      TYPE(pw_c1d_gs_type), INTENT(INOUT)                       :: sf
    2201              :                      REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: r
    2202              : 
    2203              :                      CHARACTER(len=*), PARAMETER :: routineN = 'pw_structure_factor'
    2204              : 
    2205              :                      INTEGER                                            :: cnt, handle, ig
    2206              :                      REAL(KIND=dp)                                      :: arg
    2207              : 
    2208           76 :                      CALL timeset(routineN, handle)
    2209              : 
    2210           76 :                      cnt = SIZE(sf%array)
    2211              : 
    2212           76 : !$OMP PARALLEL DO PRIVATE (ig, arg) DEFAULT(NONE) SHARED(cnt, r, sf)
    2213              :                      DO ig = 1, cnt
    2214              :                         arg = DOT_PRODUCT(sf%pw_grid%g(:, ig), r)
    2215              :                         sf%array(ig) = CMPLX(COS(arg), -SIN(arg), KIND=dp)
    2216              :                      END DO
    2217              : !$OMP END PARALLEL DO
    2218              : 
    2219           76 :                      CALL timestop(handle)
    2220              : 
    2221           76 :                   END SUBROUTINE pw_structure_factor
    2222              : 
    2223              :                   END MODULE pw_methods
        

Generated by: LCOV version 2.0-1