LCOV - code coverage report
Current view: top level - src/pw - pw_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:e7e05ae) Lines: 368 514 71.6 %
Date: 2024-04-18 06:59:28 Functions: 42 199 21.1 %

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

Generated by: LCOV version 1.15