LCOV - code coverage report
Current view: top level - src/pw - pw_poisson_types.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 212 227 93.4 %
Date: 2024-11-21 06:45:46 Functions: 7 11 63.6 %

          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             : !> \brief functions related to the poisson solver on regular grids
      10             : !> \par History
      11             : !>      greens_fn: JGH (9-Mar-2001) : include influence_fn into
      12             : !>                         greens_fn_type add cell volume
      13             : !>                         as indicator for updates
      14             : !>      greens_fn: JGH (30-Mar-2001) : Added B-spline routines
      15             : !>      pws      : JGH (13-Mar-2001) : new pw_poisson_solver, delete
      16             : !>                         pw_greens_fn
      17             : !>      12.2004 condensed from pws, greens_fn and green_fns, by apsi and JGH,
      18             : !>              made thread safe, new input [fawzi]
      19             : !>      14-Mar-2006 : added short range screening function for SE codes
      20             : !> \author fawzi
      21             : ! **************************************************************************************************
      22             : MODULE pw_poisson_types
      23             :    USE bessel_lib,                      ONLY: bessk0,&
      24             :                                               bessk1
      25             :    USE dielectric_types,                ONLY: dielectric_parameters
      26             :    USE dirichlet_bc_types,              ONLY: dirichlet_bc_parameters
      27             :    USE kinds,                           ONLY: dp
      28             :    USE mathconstants,                   ONLY: fourpi,&
      29             :                                               twopi
      30             :    USE mt_util,                         ONLY: MT0D,&
      31             :                                               MT1D,&
      32             :                                               MT2D,&
      33             :                                               MTin_create_screen_fn
      34             :    USE ps_implicit_types,               ONLY: MIXED_BC,&
      35             :                                               NEUMANN_BC,&
      36             :                                               ps_implicit_parameters,&
      37             :                                               ps_implicit_release,&
      38             :                                               ps_implicit_type
      39             :    USE ps_wavelet_types,                ONLY: WAVELET0D,&
      40             :                                               ps_wavelet_release,&
      41             :                                               ps_wavelet_type
      42             :    USE pw_grid_types,                   ONLY: pw_grid_type
      43             :    USE pw_grids,                        ONLY: pw_grid_release
      44             :    USE pw_pool_types,                   ONLY: pw_pool_create,&
      45             :                                               pw_pool_p_type,&
      46             :                                               pw_pool_release,&
      47             :                                               pw_pool_type,&
      48             :                                               pw_pools_dealloc
      49             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      50             :                                               pw_r1d_gs_type
      51             :    USE realspace_grid_types,            ONLY: realspace_grid_type,&
      52             :                                               rs_grid_release
      53             : #include "../base/base_uses.f90"
      54             : 
      55             :    IMPLICIT NONE
      56             :    PRIVATE
      57             : 
      58             :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
      59             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pw_poisson_types'
      60             : 
      61             :    PUBLIC :: pw_poisson_type
      62             :    PUBLIC :: greens_fn_type, pw_green_create, &
      63             :              pw_green_release
      64             :    PUBLIC :: pw_poisson_parameter_type
      65             : 
      66             :    INTEGER, PARAMETER, PUBLIC               :: pw_poisson_none = 0, &
      67             :                                                pw_poisson_periodic = 1, &
      68             :                                                pw_poisson_analytic = 2, &
      69             :                                                pw_poisson_mt = 3, &
      70             :                                                pw_poisson_hockney = 5, &
      71             :                                                pw_poisson_multipole = 4, &
      72             :                                                pw_poisson_wavelet = 6, &
      73             :                                                pw_poisson_implicit = 7
      74             :    ! EWALD methods
      75             :    INTEGER, PARAMETER, PUBLIC               :: do_ewald_none = 1, &
      76             :                                                do_ewald_ewald = 2, &
      77             :                                                do_ewald_pme = 3, &
      78             :                                                do_ewald_spme = 4
      79             : 
      80             :    INTEGER, PARAMETER, PUBLIC               :: PERIODIC3D = 1000, &
      81             :                                                ANALYTIC2D = 1001, &
      82             :                                                ANALYTIC1D = 1002, &
      83             :                                                ANALYTIC0D = 1003, &
      84             :                                                HOCKNEY2D = 1201, &
      85             :                                                HOCKNEY1D = 1202, &
      86             :                                                HOCKNEY0D = 1203, &
      87             :                                                MULTIPOLE2D = 1301, &
      88             :                                                MULTIPOLE1D = 1302, &
      89             :                                                MULTIPOLE0D = 1303, &
      90             :                                                PS_IMPLICIT = 1400
      91             : 
      92             : ! **************************************************************************************************
      93             : !> \brief parameters for the poisson solver independet of input_section
      94             : !> \author Ole Schuett
      95             : ! **************************************************************************************************
      96             :    TYPE pw_poisson_parameter_type
      97             :       INTEGER                        :: solver = pw_poisson_none
      98             : 
      99             :       INTEGER, DIMENSION(3)          :: periodic = 0
     100             :       INTEGER                        :: ewald_type = do_ewald_none
     101             :       INTEGER                        :: ewald_o_spline = 0
     102             :       REAL(KIND=dp)                 :: ewald_alpha = 0.0_dp
     103             : 
     104             :       REAL(KIND=dp)                 :: mt_rel_cutoff = 0.0_dp
     105             :       REAL(KIND=dp)                 :: mt_alpha = 0.0_dp
     106             : 
     107             :       INTEGER                        :: wavelet_scf_type = 0
     108             :       INTEGER                        :: wavelet_method = WAVELET0D
     109             :       INTEGER                        :: wavelet_special_dimension = 0
     110             :       CHARACTER(LEN=1)               :: wavelet_geocode = "S"
     111             : 
     112             :       LOGICAL                        :: has_dielectric = .FALSE.
     113             :       TYPE(dielectric_parameters)    :: dielectric_params = dielectric_parameters()
     114             :       TYPE(ps_implicit_parameters)   :: ps_implicit_params = ps_implicit_parameters()
     115             :       TYPE(dirichlet_bc_parameters)  :: dbc_params = dirichlet_bc_parameters()
     116             :    END TYPE pw_poisson_parameter_type
     117             : 
     118             : ! **************************************************************************************************
     119             : !> \brief environment for the poisson solver
     120             : !> \author fawzi
     121             : ! **************************************************************************************************
     122             :    TYPE pw_poisson_type
     123             :       INTEGER :: pw_level = 0
     124             :       INTEGER :: method = pw_poisson_none
     125             :       INTEGER :: used_grid = 0
     126             :       LOGICAL :: rebuild = .TRUE.
     127             :       TYPE(greens_fn_type), POINTER               :: green_fft => NULL()
     128             :       TYPE(ps_wavelet_type), POINTER               :: wavelet => NULL()
     129             :       TYPE(pw_poisson_parameter_type)             :: parameters = pw_poisson_parameter_type()
     130             :       REAL(KIND=dp), DIMENSION(3, 3)             :: cell_hmat = 0.0_dp
     131             :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER :: pw_pools => NULL()
     132             :       TYPE(pw_grid_type), POINTER                 :: mt_super_ref_pw_grid => NULL()
     133             :       TYPE(ps_implicit_type), POINTER             :: implicit_env => NULL()
     134             :       TYPE(pw_grid_type), POINTER                 :: dct_pw_grid => NULL()
     135             :       TYPE(realspace_grid_type), POINTER          :: diel_rs_grid => NULL()
     136             :    CONTAINS
     137             :       PROCEDURE, PUBLIC, NON_OVERRIDABLE :: create => pw_poisson_create
     138             :       PROCEDURE, PUBLIC, NON_OVERRIDABLE :: release => pw_poisson_release
     139             :    END TYPE pw_poisson_type
     140             : 
     141             : ! **************************************************************************************************
     142             : !> \brief contains all the informations needed by the fft based poisson solvers
     143             : !> \author JGH,Teo,fawzi
     144             : ! **************************************************************************************************
     145             :    TYPE greens_fn_type
     146             :       INTEGER :: method = PERIODIC3D
     147             :       INTEGER :: special_dimension = 0
     148             :       REAL(KIND=dp) :: radius = 0.0_dp
     149             :       REAL(KIND=dp) :: MT_alpha = 1.0_dp
     150             :       REAL(KIND=dp) :: MT_rel_cutoff = 1.0_dp
     151             :       REAL(KIND=dp) :: slab_size = 0.0_dp
     152             :       REAL(KIND=dp) :: alpha = 0.0_dp
     153             :       LOGICAL :: p3m = .FALSE.
     154             :       INTEGER :: p3m_order = 0
     155             :       REAL(KIND=dp) :: p3m_alpha = 0.0_dp
     156             :       REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: p3m_coeff
     157             :       REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: p3m_bm2
     158             :       LOGICAL :: sr_screening = .FALSE.
     159             :       REAL(KIND=dp) :: sr_alpha = 1.0_dp
     160             :       REAL(KIND=dp) :: sr_rc = 0.0_dp
     161             :       TYPE(pw_c1d_gs_type) :: influence_fn = pw_c1d_gs_type()
     162             :       TYPE(pw_c1d_gs_type), POINTER :: dct_influence_fn => NULL()
     163             :       TYPE(pw_c1d_gs_type), POINTER :: screen_fn => NULL()
     164             :       TYPE(pw_r1d_gs_type), POINTER :: p3m_charge => NULL()
     165             :    END TYPE greens_fn_type
     166             : 
     167             : CONTAINS
     168             : 
     169             : ! **************************************************************************************************
     170             : !> \brief Allocates and sets up the green functions for the fft based poisson
     171             : !>      solvers
     172             : !> \param green ...
     173             : !> \param poisson_params ...
     174             : !> \param cell_hmat ...
     175             : !> \param pw_pool ...
     176             : !> \param mt_super_ref_pw_grid ...
     177             : !> \param dct_pw_grid ...
     178             : !> \author Fawzi, based on previous functions by JGH and Teo
     179             : ! **************************************************************************************************
     180       15388 :    SUBROUTINE pw_green_create(green, poisson_params, cell_hmat, pw_pool, &
     181             :                               mt_super_ref_pw_grid, dct_pw_grid)
     182             :       TYPE(greens_fn_type), INTENT(OUT)                  :: green
     183             :       TYPE(pw_poisson_parameter_type), INTENT(IN)        :: poisson_params
     184             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN)         :: cell_hmat
     185             :       TYPE(pw_pool_type), POINTER                        :: pw_pool
     186             :       TYPE(pw_grid_type), POINTER                        :: mt_super_ref_pw_grid, dct_pw_grid
     187             : 
     188             :       INTEGER                                            :: dim, i, ig, iz, n, nz
     189             :       REAL(KIND=dp)                                      :: g2, g3d, gg, gxy, gz, j0g, j1g, k0g, &
     190             :                                                             k1g, rlength, zlength
     191             :       REAL(KIND=dp), DIMENSION(3)                        :: abc
     192             :       TYPE(pw_c1d_gs_type), POINTER                      :: dct_gf
     193             :       TYPE(pw_grid_type), POINTER                        :: dct_grid
     194             :       TYPE(pw_pool_type), POINTER                        :: pw_pool_xpndd
     195             : 
     196             :       !CPASSERT(cell%orthorhombic)
     197       61552 :       DO i = 1, 3
     198       61552 :          abc(i) = cell_hmat(i, i)
     199             :       END DO
     200       61552 :       dim = COUNT(poisson_params%periodic == 1)
     201             : 
     202       29320 :       SELECT CASE (poisson_params%solver)
     203             :       CASE (pw_poisson_periodic)
     204             :          green%method = PERIODIC3D
     205       13932 :          IF (dim /= 3) THEN
     206           0 :             CPABORT("Illegal combination of periodicity and Poisson solver periodic3d")
     207             :          END IF
     208             :       CASE (pw_poisson_multipole)
     209          18 :          green%method = MULTIPOLE0D
     210          18 :          IF (dim /= 0) THEN
     211           0 :             CPABORT("Illegal combination of periodicity and Poisson solver mulipole0d")
     212             :          END IF
     213             :       CASE (pw_poisson_analytic)
     214        1368 :          SELECT CASE (dim)
     215             :          CASE (0)
     216         254 :             green%method = ANALYTIC0D
     217        1270 :             green%radius = 0.5_dp*MINVAL(abc)
     218             :          CASE (1)
     219           6 :             green%method = ANALYTIC1D
     220          24 :             green%special_dimension = MAXLOC(poisson_params%periodic(1:3), 1)
     221          30 :             green%radius = MAXVAL(abc(1:3))
     222          24 :             DO i = 1, 3
     223          18 :                IF (i == green%special_dimension) CYCLE
     224          24 :                green%radius = MIN(green%radius, 0.5_dp*abc(i))
     225             :             END DO
     226             :          CASE (2)
     227           8 :             green%method = ANALYTIC2D
     228          32 :             i = MINLOC(poisson_params%periodic, 1)
     229           8 :             green%special_dimension = i
     230           8 :             green%slab_size = abc(i)
     231             :          CASE (3)
     232           0 :             green%method = PERIODIC3D
     233             :          CASE DEFAULT
     234         270 :             CPABORT("")
     235             :          END SELECT
     236             :       CASE (pw_poisson_mt)
     237        1114 :          green%MT_rel_cutoff = poisson_params%mt_rel_cutoff
     238        1114 :          green%MT_alpha = poisson_params%mt_alpha
     239        5570 :          green%MT_alpha = green%MT_alpha/MINVAL(abc)
     240        1166 :          SELECT CASE (dim)
     241             :          CASE (0)
     242        1112 :             green%method = MT0D
     243        5560 :             green%radius = 0.5_dp*MINVAL(abc)
     244             :          CASE (1)
     245           0 :             green%method = MT1D
     246           0 :             green%special_dimension = MAXLOC(poisson_params%periodic(1:3), 1)
     247           0 :             green%radius = MAXVAL(abc(1:3))
     248           0 :             DO i = 1, 3
     249           0 :                IF (i == green%special_dimension) CYCLE
     250           0 :                green%radius = MIN(green%radius, 0.5_dp*abc(i))
     251             :             END DO
     252             :          CASE (2)
     253           2 :             green%method = MT2D
     254           8 :             i = MINLOC(poisson_params%periodic, 1)
     255           2 :             green%special_dimension = i
     256           2 :             green%slab_size = abc(i)
     257             :          CASE (3)
     258           0 :             CPABORT("Illegal combination of periodicity and Poisson solver (MT)")
     259             :          CASE DEFAULT
     260        1114 :             CPABORT("")
     261             :          END SELECT
     262             :       CASE (pw_poisson_implicit)
     263          54 :          green%method = PS_IMPLICIT
     264             :       CASE DEFAULT
     265       15388 :          CPABORT("An unknown Poisson solver was specified")
     266             :       END SELECT
     267             : 
     268             :       ! allocate influence function,...
     269       30776 :       SELECT CASE (green%method)
     270             :       CASE (PERIODIC3D, ANALYTIC2D, ANALYTIC1D, ANALYTIC0D, MT2D, MT1D, MT0D, MULTIPOLE0D, PS_IMPLICIT)
     271       15388 :          CALL pw_pool%create_pw(green%influence_fn)
     272             : 
     273       15388 :          IF (poisson_params%ewald_type == do_ewald_spme) THEN
     274        9570 :             green%p3m = .TRUE.
     275        9570 :             green%p3m_order = poisson_params%ewald_o_spline
     276        9570 :             green%p3m_alpha = poisson_params%ewald_alpha
     277        9570 :             n = green%p3m_order
     278       38280 :             ALLOCATE (green%p3m_coeff(-(n - 1):n - 1, 0:n - 1))
     279        9570 :             CALL spme_coeff_calculate(n, green%p3m_coeff)
     280             :             NULLIFY (green%p3m_charge)
     281        9570 :             ALLOCATE (green%p3m_charge)
     282        9570 :             CALL pw_pool%create_pw(green%p3m_charge)
     283        9570 :             CALL influence_factor(green)
     284        9570 :             CALL calc_p3m_charge(green)
     285             :          ELSE
     286        5818 :             green%p3m = .FALSE.
     287             :          END IF
     288             :          !
     289       15388 :          SELECT CASE (green%method)
     290             :          CASE (MT0D, MT1D, MT2D)
     291             :             CALL MTin_create_screen_fn(green%screen_fn, pw_pool=pw_pool, method=green%method, &
     292             :                                        alpha=green%MT_alpha, &
     293             :                                        special_dimension=green%special_dimension, slab_size=green%slab_size, &
     294        1114 :                                        super_ref_pw_grid=mt_super_ref_pw_grid)
     295             :          CASE (PS_IMPLICIT)
     296          54 :             IF ((poisson_params%ps_implicit_params%boundary_condition .EQ. MIXED_BC) .OR. &
     297             :                 (poisson_params%ps_implicit_params%boundary_condition .EQ. NEUMANN_BC)) THEN
     298          22 :                CALL pw_pool_create(pw_pool_xpndd, pw_grid=dct_pw_grid)
     299             :                NULLIFY (green%dct_influence_fn)
     300          22 :                ALLOCATE (green%dct_influence_fn)
     301          22 :                CALL pw_pool_xpndd%create_pw(green%dct_influence_fn)
     302          22 :                CALL pw_pool_release(pw_pool_xpndd)
     303             :             END IF
     304             :          END SELECT
     305             : 
     306             :       CASE DEFAULT
     307       15388 :          CPABORT("")
     308             :       END SELECT
     309             : 
     310             :       ! initialize influence function
     311             :       ASSOCIATE (gf => green%influence_fn, grid => green%influence_fn%pw_grid)
     312       29340 :          SELECT CASE (green%method)
     313             :          CASE (PERIODIC3D, MULTIPOLE0D)
     314             : 
     315   330137931 :             DO ig = grid%first_gne0, grid%ngpts_cut_local
     316   330123979 :                g2 = grid%gsq(ig)
     317   330137931 :                gf%array(ig) = fourpi/g2
     318             :             END DO
     319       13952 :             IF (grid%have_g0) gf%array(1) = 0.0_dp
     320             : 
     321             :          CASE (ANALYTIC2D)
     322             : 
     323           8 :             iz = green%special_dimension ! iz is the direction with NO PBC
     324           8 :             zlength = green%slab_size ! zlength is the thickness of the cell
     325      634372 :             DO ig = grid%first_gne0, grid%ngpts_cut_local
     326      634364 :                nz = grid%g_hat(iz, ig)
     327      634364 :                g2 = grid%gsq(ig)
     328      634364 :                g3d = fourpi/g2
     329      634364 :                gxy = MAX(0.0_dp, g2 - grid%g(iz, ig)*grid%g(iz, ig))
     330      634364 :                gg = 0.5_dp*SQRT(gxy)
     331      634372 :                gf%array(ig) = g3d*(1.0_dp - (-1.0_dp)**nz*EXP(-gg*zlength))
     332             :             END DO
     333           8 :             IF (grid%have_g0) gf%array(1) = 0.0_dp
     334             : 
     335             :          CASE (ANALYTIC1D)
     336             :             ! see 'ab initio molecular dynamics' table 3.1
     337             :             ! iz is the direction of the PBC ( can be 1,2,3 -> x,y,z )
     338           6 :             iz = green%special_dimension
     339             :             ! rlength is the radius of the tube
     340           6 :             rlength = green%radius
     341      192003 :             DO ig = grid%first_gne0, grid%ngpts_cut_local
     342      191997 :                g2 = grid%gsq(ig)
     343      191997 :                g3d = fourpi/g2
     344      191997 :                gxy = SQRT(MAX(0.0_dp, g2 - grid%g(iz, ig)*grid%g(iz, ig)))
     345      191997 :                gz = ABS(grid%g(iz, ig))
     346      191997 :                j0g = BESSEL_J0(rlength*gxy)
     347      191997 :                j1g = BESSEL_J1(rlength*gxy)
     348      191997 :                IF (gz > 0) THEN
     349      187200 :                   k0g = bessk0(rlength*gz)
     350      187200 :                   k1g = bessk1(rlength*gz)
     351             :                ELSE
     352             :                   k0g = 0
     353             :                   k1g = 0
     354             :                END IF
     355             :                gf%array(ig) = g3d*(1.0_dp + rlength* &
     356      192003 :                                    (gxy*j1g*k0g - gz*j0g*k1g))
     357             :             END DO
     358           6 :             IF (grid%have_g0) gf%array(1) = 0.0_dp
     359             : 
     360             :          CASE (ANALYTIC0D)
     361             : 
     362         254 :             rlength = green%radius ! rlength is the radius of the sphere
     363    61641490 :             DO ig = grid%first_gne0, grid%ngpts_cut_local
     364    61641236 :                g2 = grid%gsq(ig)
     365    61641236 :                gg = SQRT(g2)
     366    61641236 :                g3d = fourpi/g2
     367    61641490 :                gf%array(ig) = g3d*(1.0_dp - COS(rlength*gg))
     368             :             END DO
     369         254 :             IF (grid%have_g0) &
     370         127 :                gf%array(1) = 0.5_dp*fourpi*rlength*rlength
     371             : 
     372             :          CASE (MT2D, MT1D, MT0D)
     373             : 
     374    75332714 :             DO ig = grid%first_gne0, grid%ngpts_cut_local
     375    75331600 :                g2 = grid%gsq(ig)
     376    75331600 :                g3d = fourpi/g2
     377    75332714 :                gf%array(ig) = g3d + green%screen_fn%array(ig)
     378             :             END DO
     379        1114 :             IF (grid%have_g0) &
     380         563 :                gf%array(1) = green%screen_fn%array(1)
     381             : 
     382             :          CASE (PS_IMPLICIT)
     383             : 
     384     6554816 :             DO ig = grid%first_gne0, grid%ngpts_cut_local
     385     6554762 :                g2 = grid%gsq(ig)
     386     6554816 :                gf%array(ig) = fourpi/g2
     387             :             END DO
     388          54 :             IF (grid%have_g0) gf%array(1) = 0.0_dp
     389             : 
     390          54 :             IF (ASSOCIATED(green%dct_influence_fn)) THEN
     391          22 :                dct_gf => green%dct_influence_fn
     392          22 :                dct_grid => green%dct_influence_fn%pw_grid
     393             : 
     394     9851771 :                DO ig = dct_grid%first_gne0, dct_grid%ngpts_cut_local
     395     9851749 :                   g2 = dct_grid%gsq(ig)
     396     9851771 :                   dct_gf%array(ig) = fourpi/g2
     397             :                END DO
     398          22 :                IF (dct_grid%have_g0) dct_gf%array(1) = 0.0_dp
     399             :             END IF
     400             : 
     401             :          CASE DEFAULT
     402       15388 :             CPABORT("")
     403             :          END SELECT
     404             :       END ASSOCIATE
     405             : 
     406       15388 :    END SUBROUTINE pw_green_create
     407             : 
     408             : ! **************************************************************************************************
     409             : !> \brief destroys the type (deallocates data)
     410             : !> \param gftype ...
     411             : !> \param pw_pool ...
     412             : !> \par History
     413             : !>      none
     414             : !> \author Joost VandeVondele
     415             : !>      Teodoro Laino
     416             : ! **************************************************************************************************
     417       15388 :    SUBROUTINE pw_green_release(gftype, pw_pool)
     418             :       TYPE(greens_fn_type), INTENT(INOUT)                :: gftype
     419             :       TYPE(pw_pool_type), OPTIONAL, POINTER              :: pw_pool
     420             : 
     421             :       LOGICAL                                            :: can_give_back
     422             : 
     423       15388 :       can_give_back = PRESENT(pw_pool)
     424       15388 :       IF (can_give_back) can_give_back = ASSOCIATED(pw_pool)
     425       15388 :       IF (can_give_back) THEN
     426        7764 :          CALL pw_pool%give_back_pw(gftype%influence_fn)
     427        7764 :          IF (ASSOCIATED(gftype%dct_influence_fn)) THEN
     428           0 :             CALL pw_pool%give_back_pw(gftype%dct_influence_fn)
     429           0 :             DEALLOCATE (gftype%dct_influence_fn)
     430             :          END IF
     431        7764 :          IF (ASSOCIATED(gftype%screen_fn)) THEN
     432          56 :             CALL pw_pool%give_back_pw(gftype%screen_fn)
     433          56 :             DEALLOCATE (gftype%screen_fn)
     434             :          END IF
     435        7764 :          IF (ASSOCIATED(gftype%p3m_charge)) THEN
     436        7412 :             CALL pw_pool%give_back_pw(gftype%p3m_charge)
     437        7412 :             DEALLOCATE (gftype%p3m_charge)
     438             :          END IF
     439             :       ELSE
     440        7624 :          CALL gftype%influence_fn%release()
     441        7624 :          IF (ASSOCIATED(gftype%dct_influence_fn)) THEN
     442          22 :             CALL gftype%dct_influence_fn%release()
     443          22 :             DEALLOCATE (gftype%dct_influence_fn)
     444             :          END IF
     445        7624 :          IF (ASSOCIATED(gftype%screen_fn)) THEN
     446        1058 :             CALL gftype%screen_fn%release()
     447        1058 :             DEALLOCATE (gftype%screen_fn)
     448             :          END IF
     449        7624 :          IF (ASSOCIATED(gftype%p3m_charge)) THEN
     450        2158 :             CALL gftype%p3m_charge%release()
     451        2158 :             DEALLOCATE (gftype%p3m_charge)
     452             :          END IF
     453             :       END IF
     454       15388 :       IF (ALLOCATED(gftype%p3m_bm2)) &
     455        9570 :          DEALLOCATE (gftype%p3m_bm2)
     456       15388 :       IF (ALLOCATED(gftype%p3m_coeff)) &
     457        9570 :          DEALLOCATE (gftype%p3m_coeff)
     458       15388 :    END SUBROUTINE pw_green_release
     459             : 
     460             : ! **************************************************************************************************
     461             : !> \brief Calculates the influence_factor for the
     462             : !>      SPME Green's function in reciprocal space'''
     463             : !> \param gftype ...
     464             : !> \par History
     465             : !>      none
     466             : !> \author DH (29-Mar-2001)
     467             : ! **************************************************************************************************
     468        9570 :    SUBROUTINE influence_factor(gftype)
     469             :       TYPE(greens_fn_type), INTENT(INOUT)                :: gftype
     470             : 
     471             :       COMPLEX(KIND=dp)                                   :: b_m, exp_m, sum_m
     472             :       INTEGER                                            :: dim, j, k, l, n, pt
     473             :       INTEGER, DIMENSION(3)                              :: npts
     474        9570 :       INTEGER, DIMENSION(:), POINTER                     :: lb, ub
     475             :       REAL(KIND=dp)                                      :: l_arg, prod_arg, val
     476        9570 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: m_assign
     477             : 
     478        9570 :       n = gftype%p3m_order
     479             : 
     480             :       ! calculate the assignment function values
     481             : 
     482        9570 :       lb => gftype%influence_fn%pw_grid%bounds(1, :)
     483        9570 :       ub => gftype%influence_fn%pw_grid%bounds(2, :)
     484        9570 :       IF (ALLOCATED(gftype%p3m_bm2)) THEN
     485           0 :          IF (LBOUND(gftype%p3m_bm2, 2) /= MINVAL(lb(:)) .OR. &
     486             :              UBOUND(gftype%p3m_bm2, 2) /= MAXVAL(ub(:))) THEN
     487           0 :             DEALLOCATE (gftype%p3m_bm2)
     488             :          END IF
     489             :       END IF
     490        9570 :       IF (.NOT. ALLOCATED(gftype%p3m_bm2)) THEN
     491       86130 :          ALLOCATE (gftype%p3m_bm2(3, MINVAL(lb(:)):MAXVAL(ub(:))))
     492             :       END IF
     493             : 
     494       28710 :       ALLOCATE (m_assign(0:n - 2))
     495       56704 :       m_assign = 0.0_dp
     496       56704 :       DO k = 0, n - 2
     497       47134 :          j = -(n - 1) + 2*k
     498      337440 :          DO l = 0, n - 1
     499      280736 :             l_arg = 0.5_dp**l
     500      280736 :             prod_arg = gftype%p3m_coeff(j, l)*l_arg
     501      327870 :             m_assign(k) = m_assign(k) + prod_arg
     502             :          END DO
     503             :       END DO
     504             : 
     505             :       ! calculate the absolute b values
     506             : 
     507       38280 :       npts(:) = ub(:) - lb(:) + 1
     508       38280 :       DO dim = 1, 3
     509      913346 :          DO pt = lb(dim), ub(dim)
     510      875066 :             val = twopi*(REAL(pt, KIND=dp)/REAL(npts(dim), KIND=dp))
     511      875066 :             exp_m = CMPLX(COS(val), -SIN(val), KIND=dp)
     512      875066 :             sum_m = CMPLX(0.0_dp, 0.0_dp, KIND=dp)
     513     5182296 :             DO k = 0, n - 2
     514     5182296 :                sum_m = sum_m + m_assign(k)*exp_m**k
     515             :             END DO
     516      875066 :             b_m = exp_m**(n - 1)/sum_m
     517      903776 :             gftype%p3m_bm2(dim, pt) = SQRT(REAL(b_m*CONJG(b_m), KIND=dp))
     518             :          END DO
     519             :       END DO
     520             : 
     521        9570 :       DEALLOCATE (m_assign)
     522        9570 :    END SUBROUTINE influence_factor
     523             : 
     524             : ! **************************************************************************************************
     525             : !> \brief ...
     526             : !> \param gf ...
     527             : ! **************************************************************************************************
     528        9570 :    PURE SUBROUTINE calc_p3m_charge(gf)
     529             : 
     530             :       TYPE(greens_fn_type), INTENT(INOUT)                :: gf
     531             : 
     532             :       INTEGER                                            :: ig, l, m, n
     533             :       REAL(KIND=dp)                                      :: arg, novol
     534             : 
     535             :       ! check if charge function is consistent with current box volume
     536             : 
     537             :       ASSOCIATE (grid => gf%influence_fn%pw_grid, bm2 => gf%p3m_bm2)
     538        9570 :          arg = 1.0_dp/(8.0_dp*gf%p3m_alpha**2)
     539        9570 :          novol = REAL(grid%ngpts, KIND=dp)/grid%vol
     540    56914483 :          DO ig = 1, grid%ngpts_cut_local
     541    56904913 :             l = grid%g_hat(1, ig)
     542    56904913 :             m = grid%g_hat(2, ig)
     543    56904913 :             n = grid%g_hat(3, ig)
     544             :             gf%p3m_charge%array(ig) = novol*EXP(-arg*grid%gsq(ig))* &
     545    56914483 :                                       bm2(1, l)*bm2(2, m)*bm2(3, n)
     546             :          END DO
     547             :       END ASSOCIATE
     548             : 
     549        9570 :    END SUBROUTINE calc_p3m_charge
     550             : 
     551             : ! **************************************************************************************************
     552             : !> \brief Initialize the poisson solver
     553             : !>      You should call this just before calling the work routine
     554             : !>      pw_poisson_solver
     555             : !>      Call pw_poisson_release when you have finished
     556             : !> \param poisson_env ...
     557             : !> \par History
     558             : !>      none
     559             : !> \author JGH (12-Mar-2001)
     560             : ! **************************************************************************************************
     561       10160 :    SUBROUTINE pw_poisson_create(poisson_env)
     562             : 
     563             :       CLASS(pw_poisson_type), INTENT(INOUT)              :: poisson_env
     564             : 
     565             :       ! Cleanup a potential previous poisson_env
     566       10160 :       CALL poisson_env%release()
     567             : 
     568       10160 :    END SUBROUTINE pw_poisson_create
     569             : 
     570             : ! **************************************************************************************************
     571             : !> \brief releases the poisson solver
     572             : !> \param poisson_env ...
     573             : !> \par History
     574             : !>      none
     575             : !> \author fawzi (11.2002)
     576             : ! **************************************************************************************************
     577       20320 :    SUBROUTINE pw_poisson_release(poisson_env)
     578             : 
     579             :       CLASS(pw_poisson_type), INTENT(INOUT)               :: poisson_env
     580             : 
     581       20320 :       IF (ASSOCIATED(poisson_env%pw_pools)) THEN
     582       10160 :          CALL pw_pools_dealloc(poisson_env%pw_pools)
     583             :       END IF
     584             : 
     585       20320 :       IF (ASSOCIATED(poisson_env%green_fft)) THEN
     586        7624 :          CALL pw_green_release(poisson_env%green_fft)
     587        7624 :          DEALLOCATE (poisson_env%green_fft)
     588             :       END IF
     589       20320 :       CALL pw_grid_release(poisson_env%mt_super_ref_pw_grid)
     590       20320 :       CALL ps_wavelet_release(poisson_env%wavelet)
     591             :       CALL ps_implicit_release(poisson_env%implicit_env, &
     592       20320 :                                poisson_env%parameters%ps_implicit_params)
     593       20320 :       CALL pw_grid_release(poisson_env%dct_pw_grid)
     594       20320 :       IF (ASSOCIATED(poisson_env%diel_rs_grid)) THEN
     595          50 :          CALL rs_grid_release(poisson_env%diel_rs_grid)
     596          50 :          DEALLOCATE (poisson_env%diel_rs_grid)
     597             :       END IF
     598             : 
     599       20320 :    END SUBROUTINE pw_poisson_release
     600             : 
     601             : ! **************************************************************************************************
     602             : !> \brief Calculates the coefficients for the charge assignment function
     603             : !> \param n ...
     604             : !> \param coeff ...
     605             : !> \par History
     606             : !>      none
     607             : !> \author DG (29-Mar-2001)
     608             : ! **************************************************************************************************
     609        9570 :    SUBROUTINE spme_coeff_calculate(n, coeff)
     610             : 
     611             :       INTEGER, INTENT(IN)                                :: n
     612             :       REAL(KIND=dp), DIMENSION(-(n-1):n-1, 0:n-1), &
     613             :          INTENT(OUT)                                     :: coeff
     614             : 
     615             :       INTEGER                                            :: i, j, l, m
     616             :       REAL(KIND=dp)                                      :: b
     617        9570 :       REAL(KIND=dp), DIMENSION(n, -n:n, 0:n-1)           :: a
     618             : 
     619     5164834 :       a = 0.0_dp
     620        9570 :       a(1, 0, 0) = 1.0_dp
     621             : 
     622       56704 :       DO i = 2, n
     623       47134 :          m = i - 1
     624      244206 :          DO j = -m, m, 2
     625      840190 :             DO l = 0, m - 1
     626             :                b = (a(m, j - 1, l) + &
     627             :                     REAL((-1)**l, KIND=dp)*a(m, j + 1, l))/ &
     628      652688 :                    REAL((l + 1)*2**(l + 1), KIND=dp)
     629      840190 :                a(i, j, 0) = a(i, j, 0) + b
     630             :             END DO
     631      887324 :             DO l = 0, m - 1
     632             :                a(i, j, l + 1) = (a(m, j + 1, l) - &
     633      840190 :                                  a(m, j - 1, l))/REAL(l + 1, KIND=dp)
     634             :             END DO
     635             :          END DO
     636             :       END DO
     637             : 
     638      684450 :       coeff = 0.0_dp
     639       66274 :       DO i = 0, n - 1
     640       66274 :          DO j = -(n - 1), n - 1, 2
     641      337440 :             coeff(j, i) = a(n, j, i)
     642             :          END DO
     643             :       END DO
     644             : 
     645        9570 :    END SUBROUTINE spme_coeff_calculate
     646             : 
     647           0 : END MODULE pw_poisson_types

Generated by: LCOV version 1.15