LCOV - code coverage report
Current view: top level - src - pw_env_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:cccd2f3) Lines: 95.4 % 392 374
Test Date: 2026-05-06 07:07:47 Functions: 100.0 % 5 5

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief methods of pw_env that have dependence on qs_env
      10              : !> \par History
      11              : !>      10.2002 created [fawzi]
      12              : !>      JGH (22-Feb-03) PW grid options added
      13              : !>      04.2003 added rs grid pools [fawzi]
      14              : !>      02.2004 added commensurate grids
      15              : !> \author Fawzi Mohamed
      16              : ! **************************************************************************************************
      17              : MODULE pw_env_methods
      18              :    USE ao_util,                         ONLY: exp_radius
      19              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
      20              :                                               gto_basis_set_type
      21              :    USE cell_types,                      ONLY: cell_type
      22              :    USE cp_control_types,                ONLY: dft_control_type
      23              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      24              :                                               cp_logger_type
      25              :    USE cp_output_handling,              ONLY: cp_p_file,&
      26              :                                               cp_print_key_finished_output,&
      27              :                                               cp_print_key_should_output,&
      28              :                                               cp_print_key_unit_nr
      29              :    USE cp_realspace_grid_init,          ONLY: init_input_type
      30              :    USE cube_utils,                      ONLY: destroy_cube_info,&
      31              :                                               init_cube_info,&
      32              :                                               return_cube_max_iradius
      33              :    USE d3_poly,                         ONLY: init_d3_poly_module
      34              :    USE dct,                             ONLY: neumannX,&
      35              :                                               neumannXY,&
      36              :                                               neumannXYZ,&
      37              :                                               neumannXZ,&
      38              :                                               neumannY,&
      39              :                                               neumannYZ,&
      40              :                                               neumannZ,&
      41              :                                               setup_dct_pw_grids
      42              :    USE dielectric_types,                ONLY: derivative_cd3,&
      43              :                                               derivative_cd5,&
      44              :                                               derivative_cd7,&
      45              :                                               rho_dependent
      46              :    USE fft_tools,                       ONLY: init_fft_scratch_pool
      47              :    USE gaussian_gridlevels,             ONLY: destroy_gaussian_gridlevel,&
      48              :                                               gaussian_gridlevel,&
      49              :                                               init_gaussian_gridlevel
      50              :    USE input_constants,                 ONLY: do_method_gapw,&
      51              :                                               do_method_gapw_xc,&
      52              :                                               do_method_gpw,&
      53              :                                               do_method_lrigpw,&
      54              :                                               do_method_ofgpw,&
      55              :                                               do_method_rigpw,&
      56              :                                               xc_vdw_fun_nonloc
      57              :    USE input_section_types,             ONLY: section_get_ival,&
      58              :                                               section_vals_get,&
      59              :                                               section_vals_get_subs_vals,&
      60              :                                               section_vals_type,&
      61              :                                               section_vals_val_get
      62              :    USE kinds,                           ONLY: dp
      63              :    USE message_passing,                 ONLY: mp_para_env_type
      64              :    USE ps_implicit_types,               ONLY: MIXED_BC,&
      65              :                                               MIXED_PERIODIC_BC,&
      66              :                                               NEUMANN_BC,&
      67              :                                               PERIODIC_BC
      68              :    USE ps_wavelet_types,                ONLY: WAVELET0D,&
      69              :                                               WAVELET2D,&
      70              :                                               WAVELET3D
      71              :    USE pw_env_types,                    ONLY: pw_env_type
      72              :    USE pw_grid_info,                    ONLY: pw_grid_init_setup
      73              :    USE pw_grid_types,                   ONLY: FULLSPACE,&
      74              :                                               HALFSPACE,&
      75              :                                               pw_grid_type
      76              :    USE pw_grids,                        ONLY: do_pw_grid_blocked_false,&
      77              :                                               pw_grid_change,&
      78              :                                               pw_grid_create,&
      79              :                                               pw_grid_release,&
      80              :                                               pw_grid_retain
      81              :    USE pw_poisson_methods,              ONLY: pw_poisson_set
      82              :    USE pw_poisson_read_input,           ONLY: pw_poisson_read_parameters
      83              :    USE pw_poisson_types,                ONLY: pw_poisson_analytic,&
      84              :                                               pw_poisson_implicit,&
      85              :                                               pw_poisson_mt,&
      86              :                                               pw_poisson_multipole,&
      87              :                                               pw_poisson_none,&
      88              :                                               pw_poisson_parameter_type,&
      89              :                                               pw_poisson_periodic,&
      90              :                                               pw_poisson_wavelet
      91              :    USE pw_pool_types,                   ONLY: pw_pool_create,&
      92              :                                               pw_pool_p_type,&
      93              :                                               pw_pool_release,&
      94              :                                               pw_pools_dealloc
      95              :    USE qs_cneo_types,                   ONLY: cneo_potential_type
      96              :    USE qs_dispersion_types,             ONLY: qs_dispersion_type
      97              :    USE qs_environment_types,            ONLY: get_qs_env,&
      98              :                                               qs_environment_type
      99              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
     100              :                                               qs_kind_type
     101              :    USE qs_rho0_types,                   ONLY: get_rho0_mpole,&
     102              :                                               rho0_mpole_type
     103              :    USE realspace_grid_types,            ONLY: &
     104              :         realspace_grid_desc_p_type, realspace_grid_desc_type, realspace_grid_input_type, &
     105              :         realspace_grid_type, rs_grid_create, rs_grid_create_descriptor, rs_grid_print, &
     106              :         rs_grid_release, rs_grid_release_descriptor
     107              :    USE xc_input_constants,              ONLY: &
     108              :         xc_deriv_collocate, xc_deriv_nn10_smooth, xc_deriv_nn50_smooth, xc_deriv_pw, &
     109              :         xc_deriv_spline2, xc_deriv_spline2_smooth, xc_deriv_spline3, xc_deriv_spline3_smooth, &
     110              :         xc_rho_nn10, xc_rho_nn50, xc_rho_no_smooth, xc_rho_spline2_smooth, xc_rho_spline3_smooth
     111              : #include "./base/base_uses.f90"
     112              : 
     113              :    IMPLICIT NONE
     114              :    PRIVATE
     115              : 
     116              :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .TRUE.
     117              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pw_env_methods'
     118              : 
     119              :    PUBLIC :: pw_env_create, pw_env_rebuild
     120              : 
     121              : ! **************************************************************************************************
     122              : 
     123              : CONTAINS
     124              : 
     125              : ! **************************************************************************************************
     126              : !> \brief creates a pw_env, if qs_env is given calls pw_env_rebuild
     127              : !> \param pw_env the pw_env that gets created
     128              : !> \par History
     129              : !>      10.2002 created [fawzi]
     130              : !> \author Fawzi Mohamed
     131              : ! **************************************************************************************************
     132         9101 :    SUBROUTINE pw_env_create(pw_env)
     133              :       TYPE(pw_env_type), POINTER                         :: pw_env
     134              : 
     135              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_env_create'
     136              : 
     137              :       INTEGER                                            :: handle
     138              : 
     139         9101 :       CALL timeset(routineN, handle)
     140              : 
     141         9101 :       CPASSERT(.NOT. ASSOCIATED(pw_env))
     142       127414 :       ALLOCATE (pw_env)
     143              :       NULLIFY (pw_env%pw_pools, pw_env%gridlevel_info, pw_env%poisson_env, &
     144              :                pw_env%cube_info, pw_env%rs_descs, pw_env%rs_grids, &
     145              :                pw_env%xc_pw_pool, pw_env%vdw_pw_pool, &
     146              :                pw_env%interp_section)
     147         9101 :       pw_env%auxbas_grid = -1
     148         9101 :       pw_env%ref_count = 1
     149              : 
     150         9101 :       CALL timestop(handle)
     151              : 
     152         9101 :    END SUBROUTINE pw_env_create
     153              : 
     154              : ! **************************************************************************************************
     155              : !> \brief rebuilds the pw_env data (necessary if cell or cutoffs change)
     156              : !> \param pw_env the environment to rebuild
     157              : !> \param qs_env the qs_env where to get the cell, cutoffs,...
     158              : !> \param external_para_env ...
     159              : !> \par History
     160              : !>      10.2002 created [fawzi]
     161              : !> \author Fawzi Mohamed
     162              : ! **************************************************************************************************
     163        10959 :    SUBROUTINE pw_env_rebuild(pw_env, qs_env, external_para_env)
     164              :       TYPE(pw_env_type), POINTER                         :: pw_env
     165              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     166              :       TYPE(mp_para_env_type), INTENT(IN), OPTIONAL, &
     167              :          TARGET                                          :: external_para_env
     168              : 
     169              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'pw_env_rebuild'
     170              : 
     171              :       CHARACTER(LEN=3)                                   :: string
     172              :       INTEGER :: blocked_id, blocked_id_input, boundary_condition, grid_span, handle, i, &
     173              :          igrid_level, iounit, ncommensurate, ngrid_level, xc_deriv_method_id, xc_smooth_method_id
     174              :       INTEGER, DIMENSION(2)                              :: distribution_layout
     175              :       INTEGER, DIMENSION(3)                              :: higher_grid_layout
     176              :       LOGICAL :: do_io, efg_present, linres_present, odd, set_vdw_pool, should_output, &
     177              :          smooth_required, spherical, uf_grid, use_ref_cell
     178              :       REAL(KIND=dp)                                      :: cutilev, fine_grid_factor, rel_cutoff
     179        10959 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: radius
     180        10959 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: cutoff
     181              :       TYPE(cell_type), POINTER                           :: cell, cell_ref, my_cell
     182              :       TYPE(cp_logger_type), POINTER                      :: logger
     183              :       TYPE(dft_control_type), POINTER                    :: dft_control
     184              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     185              :       TYPE(pw_grid_type), POINTER :: dct_pw_grid, mt_super_ref_grid, old_pw_grid, pw_grid, &
     186              :          super_ref_grid, vdw_grid, vdw_ref_grid, xc_super_ref_grid
     187              :       TYPE(pw_poisson_parameter_type)                    :: poisson_params
     188        10959 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
     189              :       TYPE(qs_dispersion_type), POINTER                  :: dispersion_env
     190        10959 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     191              :       TYPE(realspace_grid_desc_p_type), DIMENSION(:), &
     192        10959 :          POINTER                                         :: rs_descs
     193              :       TYPE(realspace_grid_input_type)                    :: input_settings
     194        10959 :       TYPE(realspace_grid_type), DIMENSION(:), POINTER   :: rs_grids
     195              :       TYPE(section_vals_type), POINTER                   :: efg_section, input, linres_section, &
     196              :                                                             poisson_section, print_section, &
     197              :                                                             rs_grid_section, xc_section
     198              : 
     199              :       ! a very small safety factor might be needed for roundoff issues
     200              :       ! e.g. radius being computed here as 12.998 (13) and 13.002 (14) during the collocation
     201              :       ! the latter can happen due to the lower precision in the computation of the radius in collocate
     202              :       ! parallel cost of rs_pw_transfer goes as safety_factor**3 so it is worthwhile keeping it tight
     203              :       ! Edit: Safety Factor was unused
     204              : 
     205        10959 :       CALL timeset(routineN, handle)
     206              : 
     207              :       !
     208              :       !
     209              :       ! Part one, deallocate old data if needed
     210              :       !
     211              :       !
     212        10959 :       NULLIFY (cutoff, cell, pw_grid, old_pw_grid, dft_control, qs_kind_set, &
     213        10959 :                pw_pools, rs_descs, para_env, cell_ref, vdw_ref_grid, &
     214        10959 :                mt_super_ref_grid, input, poisson_section, xc_super_ref_grid, &
     215        10959 :                dct_pw_grid, vdw_grid, super_ref_grid, my_cell, rs_grids, dispersion_env)
     216              : 
     217              :       CALL get_qs_env(qs_env=qs_env, &
     218              :                       dft_control=dft_control, &
     219              :                       qs_kind_set=qs_kind_set, &
     220              :                       cell_ref=cell_ref, &
     221              :                       cell=cell, &
     222              :                       para_env=para_env, &
     223              :                       input=input, &
     224        10959 :                       dispersion_env=dispersion_env)
     225              : 
     226        10959 :       CPASSERT(ASSOCIATED(pw_env))
     227        10959 :       CPASSERT(pw_env%ref_count > 0)
     228        10959 :       CALL pw_pool_release(pw_env%vdw_pw_pool)
     229        10959 :       CALL pw_pool_release(pw_env%xc_pw_pool)
     230        10959 :       CALL pw_pools_dealloc(pw_env%pw_pools)
     231        10959 :       IF (ASSOCIATED(pw_env%rs_descs)) THEN
     232         5224 :          DO i = 1, SIZE(pw_env%rs_descs)
     233         5224 :             CALL rs_grid_release_descriptor(pw_env%rs_descs(i)%rs_desc)
     234              :          END DO
     235         1880 :          DEALLOCATE (pw_env%rs_descs)
     236              :       END IF
     237        10959 :       IF (ASSOCIATED(pw_env%rs_grids)) THEN
     238         5224 :          DO i = 1, SIZE(pw_env%rs_grids)
     239         5224 :             CALL rs_grid_release(pw_env%rs_grids(i))
     240              :          END DO
     241         1880 :          DEALLOCATE (pw_env%rs_grids)
     242              :       END IF
     243        10959 :       IF (ASSOCIATED(pw_env%gridlevel_info)) THEN
     244         1880 :          CALL destroy_gaussian_gridlevel(pw_env%gridlevel_info)
     245              :       ELSE
     246         9079 :          ALLOCATE (pw_env%gridlevel_info)
     247              :       END IF
     248              : 
     249        10959 :       IF (ASSOCIATED(pw_env%cube_info)) THEN
     250         5224 :          DO igrid_level = 1, SIZE(pw_env%cube_info)
     251         5224 :             CALL destroy_cube_info(pw_env%cube_info(igrid_level))
     252              :          END DO
     253         1880 :          DEALLOCATE (pw_env%cube_info)
     254              :       END IF
     255        10959 :       NULLIFY (pw_env%pw_pools, pw_env%cube_info)
     256              : 
     257              :       ! remove fft scratch pool, as it depends on pw_env mpi group handles
     258        10959 :       CALL init_fft_scratch_pool()
     259              : 
     260              :       !
     261              :       !
     262              :       ! Part two, setup the pw_grids
     263              :       !
     264              :       !
     265              : 
     266        10959 :       do_io = .TRUE.
     267        10959 :       IF (PRESENT(external_para_env)) THEN
     268         1108 :          para_env => external_para_env
     269              :          CPASSERT(ASSOCIATED(para_env))
     270         1108 :          do_io = .FALSE. !multiple MPI subgroups mess-up the output file
     271              :       END IF
     272              :       ! interpolation section
     273        10959 :       pw_env%interp_section => section_vals_get_subs_vals(input, "DFT%MGRID%INTERPOLATOR")
     274              : 
     275        10959 :       CALL get_qs_env(qs_env, use_ref_cell=use_ref_cell)
     276        10959 :       IF (use_ref_cell) THEN
     277           64 :          my_cell => cell_ref
     278              :       ELSE
     279        10895 :          my_cell => cell
     280              :       END IF
     281        10959 :       rel_cutoff = dft_control%qs_control%relative_cutoff
     282        10959 :       cutoff => dft_control%qs_control%e_cutoff
     283        10959 :       CALL section_vals_val_get(input, "DFT%XC%XC_GRID%USE_FINER_GRID", l_val=uf_grid)
     284        10959 :       CALL section_vals_val_get(input, "DFT%XC%XC_GRID%FINE_GRID_FACTOR", r_val=fine_grid_factor)
     285        10959 :       IF (uf_grid .AND. fine_grid_factor <= 1.0_dp) THEN
     286            0 :          CPABORT("FINE_GRID_FACTOR must be larger than one when USE_FINER_GRID is enabled")
     287              :       END IF
     288        10959 :       ngrid_level = SIZE(cutoff)
     289              : 
     290              :       ! init gridlevel_info XXXXXXXXX setup mapping to the effective cutoff ?
     291              :       !                     XXXXXXXXX the cutoff array here is more a 'wish-list'
     292              :       !                     XXXXXXXXX same holds for radius
     293              :       print_section => section_vals_get_subs_vals(input, &
     294        10959 :                                                   "PRINT%GRID_INFORMATION")
     295              :       CALL init_gaussian_gridlevel(pw_env%gridlevel_info, &
     296              :                                    ngrid_levels=ngrid_level, cutoff=cutoff, rel_cutoff=rel_cutoff, &
     297        10959 :                                    print_section=print_section)
     298              :       ! init pw_grids and pools
     299        65506 :       ALLOCATE (pw_pools(ngrid_level))
     300              : 
     301        10959 :       IF (dft_control%qs_control%commensurate_mgrids) THEN
     302          274 :          ncommensurate = ngrid_level
     303              :       ELSE
     304        10685 :          ncommensurate = 0
     305              :       END IF
     306              :       !
     307              :       ! If Tuckerman is present let's perform the set-up of the super-reference-grid
     308              :       !
     309        10959 :       cutilev = cutoff(1)
     310        10959 :       IF (dft_control%qs_control%pw_grid_opt%spherical) THEN
     311            0 :          grid_span = HALFSPACE
     312            0 :          spherical = .TRUE.
     313        10959 :       ELSE IF (dft_control%qs_control%pw_grid_opt%fullspace) THEN
     314        10959 :          grid_span = FULLSPACE
     315        10959 :          spherical = .FALSE.
     316              :       ELSE
     317            0 :          grid_span = HALFSPACE
     318            0 :          spherical = .FALSE.
     319              :       END IF
     320              : 
     321        10959 :       poisson_section => section_vals_get_subs_vals(qs_env%input, "DFT%POISSON")
     322              :       CALL setup_super_ref_grid(super_ref_grid, mt_super_ref_grid, &
     323              :                                 xc_super_ref_grid, cutilev, grid_span, spherical, my_cell, para_env, &
     324              :                                 poisson_section, ncommensurate, uf_grid=uf_grid, &
     325              :                                 fine_grid_factor=fine_grid_factor, &
     326        10959 :                                 print_section=print_section)
     327        10959 :       old_pw_grid => super_ref_grid
     328        10959 :       IF (.NOT. ASSOCIATED(mt_super_ref_grid)) vdw_ref_grid => super_ref_grid
     329              :       !
     330              :       ! Setup of the multi-grid pw_grid and pw_pools
     331              :       !
     332              : 
     333        10959 :       IF (do_io) THEN
     334         9851 :          logger => cp_get_default_logger()
     335         9851 :          iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.Log')
     336              :       ELSE
     337         1108 :          iounit = 0
     338              :       END IF
     339              : 
     340        10959 :       IF (dft_control%qs_control%pw_grid_opt%spherical) THEN
     341            0 :          grid_span = HALFSPACE
     342            0 :          spherical = .TRUE.
     343            0 :          odd = .TRUE.
     344        10959 :       ELSE IF (dft_control%qs_control%pw_grid_opt%fullspace) THEN
     345        10959 :          grid_span = FULLSPACE
     346        10959 :          spherical = .FALSE.
     347        10959 :          odd = .FALSE.
     348              :       ELSE
     349            0 :          grid_span = HALFSPACE
     350            0 :          spherical = .FALSE.
     351            0 :          odd = .TRUE.
     352              :       END IF
     353              : 
     354              :       ! use input suggestion for blocked
     355        10959 :       blocked_id_input = dft_control%qs_control%pw_grid_opt%blocked
     356              : 
     357              :       ! methods that require smoothing or nearest neighbor have to use a plane distributed setup
     358              :       ! find the xc properties (FIXME this could miss other xc sections that operate on the grid ...)
     359        10959 :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
     360        10959 :       xc_deriv_method_id = section_get_ival(xc_section, "XC_GRID%XC_DERIV")
     361        10959 :       xc_smooth_method_id = section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO")
     362        10959 :       smooth_required = .FALSE.
     363              :       SELECT CASE (xc_deriv_method_id)
     364              :       CASE (xc_deriv_pw, xc_deriv_collocate, xc_deriv_spline3, xc_deriv_spline2)
     365           84 :          smooth_required = smooth_required .OR. .FALSE.
     366              :       CASE (xc_deriv_spline2_smooth, &
     367              :             xc_deriv_spline3_smooth, xc_deriv_nn10_smooth, xc_deriv_nn50_smooth)
     368           84 :          smooth_required = smooth_required .OR. .TRUE.
     369              :       CASE DEFAULT
     370        10959 :          CPABORT("")
     371              :       END SELECT
     372              :       SELECT CASE (xc_smooth_method_id)
     373              :       CASE (xc_rho_no_smooth)
     374           42 :          smooth_required = smooth_required .OR. .FALSE.
     375              :       CASE (xc_rho_spline2_smooth, xc_rho_spline3_smooth, xc_rho_nn10, xc_rho_nn50)
     376           42 :          smooth_required = smooth_required .OR. .TRUE.
     377              :       CASE DEFAULT
     378        10959 :          CPABORT("")
     379              :       END SELECT
     380              :       ! EPR, NMR, EFG can require splines. If the linres/EFG section is present we assume
     381              :       ! it could be on and splines might be used (not quite sure if this is due to their use of splines or something else)
     382              :       linres_section => section_vals_get_subs_vals(section_vals=input, &
     383        10959 :                                                    subsection_name="PROPERTIES%LINRES")
     384        10959 :       CALL section_vals_get(linres_section, explicit=linres_present)
     385        10959 :       IF (linres_present) THEN
     386          292 :          smooth_required = smooth_required .OR. .TRUE.
     387              :       END IF
     388              : 
     389              :       efg_section => section_vals_get_subs_vals(section_vals=input, &
     390        10959 :                                                 subsection_name="DFT%PRINT%ELECTRIC_FIELD_GRADIENT")
     391        10959 :       CALL section_vals_get(efg_section, explicit=efg_present)
     392        10959 :       IF (efg_present) THEN
     393            2 :          smooth_required = smooth_required .OR. .TRUE.
     394              :       END IF
     395              : 
     396        43588 :       DO igrid_level = 1, ngrid_level
     397        32629 :          cutilev = cutoff(igrid_level)
     398              : 
     399              :          ! the whole of QS seems to work fine with either blocked/non-blocked distribution in g-space
     400              :          ! the default choice should be made free
     401        32629 :          blocked_id = blocked_id_input
     402              : 
     403        97887 :          distribution_layout = dft_control%qs_control%pw_grid_opt%distribution_layout
     404              : 
     405              :          ! qmmm does not support a ray distribution
     406              :          ! FIXME ... check if a plane distributed lower grid is sufficient
     407        32629 :          IF (qs_env%qmmm) THEN
     408         3606 :             distribution_layout = [para_env%num_pe, 1]
     409              :          END IF
     410              : 
     411              :          ! If splines are required
     412              :          ! FIXME.... should only be true for the highest grid
     413        32629 :          IF (smooth_required) THEN
     414         4326 :             distribution_layout = [para_env%num_pe, 1]
     415              :          END IF
     416              : 
     417        32629 :          IF (igrid_level == 1) THEN
     418        10959 :             IF (ASSOCIATED(old_pw_grid)) THEN
     419              :                CALL pw_grid_create(pw_grid, para_env, my_cell%hmat, grid_span=grid_span, &
     420              :                                    cutoff=cutilev, &
     421              :                                    spherical=spherical, odd=odd, fft_usage=.TRUE., &
     422              :                                    ncommensurate=ncommensurate, icommensurate=igrid_level, &
     423              :                                    blocked=do_pw_grid_blocked_false, &
     424              :                                    ref_grid=old_pw_grid, &
     425              :                                    rs_dims=distribution_layout, &
     426         1414 :                                    iounit=iounit)
     427         1414 :                old_pw_grid => pw_grid
     428              :             ELSE
     429              :                CALL pw_grid_create(pw_grid, para_env, my_cell%hmat, grid_span=grid_span, &
     430              :                                    cutoff=cutilev, &
     431              :                                    spherical=spherical, odd=odd, fft_usage=.TRUE., &
     432              :                                    ncommensurate=ncommensurate, icommensurate=igrid_level, &
     433              :                                    blocked=blocked_id, &
     434              :                                    rs_dims=distribution_layout, &
     435         9545 :                                    iounit=iounit)
     436         9545 :                old_pw_grid => pw_grid
     437              :             END IF
     438              :          ELSE
     439              :             CALL pw_grid_create(pw_grid, para_env, my_cell%hmat, grid_span=grid_span, &
     440              :                                 cutoff=cutilev, &
     441              :                                 spherical=spherical, odd=odd, fft_usage=.TRUE., &
     442              :                                 ncommensurate=ncommensurate, icommensurate=igrid_level, &
     443              :                                 blocked=do_pw_grid_blocked_false, &
     444              :                                 ref_grid=old_pw_grid, &
     445              :                                 rs_dims=distribution_layout, &
     446        21670 :                                 iounit=iounit)
     447              :          END IF
     448              : 
     449              :          ! init pw_pools
     450        32629 :          NULLIFY (pw_pools(igrid_level)%pool)
     451        32629 :          CALL pw_pool_create(pw_pools(igrid_level)%pool, pw_grid=pw_grid)
     452              : 
     453        43588 :          CALL pw_grid_release(pw_grid)
     454              : 
     455              :       END DO
     456              : 
     457        10959 :       pw_env%pw_pools => pw_pools
     458              : 
     459              :       ! init auxbas_grid
     460        43588 :       DO i = 1, ngrid_level
     461        43588 :          IF (cutoff(i) == dft_control%qs_control%cutoff) pw_env%auxbas_grid = i
     462              :       END DO
     463              : 
     464              :       ! init xc_pool
     465        10959 :       IF (ASSOCIATED(xc_super_ref_grid)) THEN
     466              :          CALL pw_pool_create(pw_env%xc_pw_pool, &
     467           48 :                              pw_grid=xc_super_ref_grid)
     468           48 :          CALL pw_grid_release(xc_super_ref_grid)
     469              :       ELSE
     470        10911 :          pw_env%xc_pw_pool => pw_pools(pw_env%auxbas_grid)%pool
     471        10911 :          CALL pw_env%xc_pw_pool%retain()
     472              :       END IF
     473              : 
     474              :       ! init vdw_pool
     475        10959 :       set_vdw_pool = .FALSE.
     476        10959 :       IF (ASSOCIATED(dispersion_env)) THEN
     477        10551 :          IF (dispersion_env%type == xc_vdw_fun_nonloc) THEN
     478           78 :             IF (dispersion_env%pw_cutoff > 0._dp) set_vdw_pool = .TRUE.
     479              :          END IF
     480              :       END IF
     481              :       IF (set_vdw_pool) THEN
     482           70 :          CPASSERT(ASSOCIATED(old_pw_grid))
     483           70 :          IF (.NOT. ASSOCIATED(vdw_ref_grid)) vdw_ref_grid => old_pw_grid
     484           70 :          IF (iounit > 0) WRITE (iounit, "(/,T2,A)") "PW_GRID| Grid for non-local vdW functional"
     485              :          CALL pw_grid_create(vdw_grid, para_env, my_cell%hmat, grid_span=grid_span, &
     486              :                              cutoff=dispersion_env%pw_cutoff, &
     487              :                              spherical=spherical, odd=odd, fft_usage=.TRUE., &
     488              :                              ncommensurate=0, icommensurate=0, &
     489              :                              blocked=do_pw_grid_blocked_false, &
     490              :                              ref_grid=vdw_ref_grid, &
     491              :                              rs_dims=distribution_layout, &
     492           70 :                              iounit=iounit)
     493           70 :          CALL pw_pool_create(pw_env%vdw_pw_pool, pw_grid=vdw_grid)
     494           70 :          CALL pw_grid_release(vdw_grid)
     495              :       ELSE
     496        10889 :          pw_env%vdw_pw_pool => pw_pools(pw_env%auxbas_grid)%pool
     497        10889 :          CALL pw_env%vdw_pw_pool%retain()
     498              :       END IF
     499              : 
     500        10959 :       IF (do_io) CALL cp_print_key_finished_output(iounit, logger, print_section, '')
     501              : 
     502              :       ! complete init of the poisson_env
     503        10959 :       IF (.NOT. ASSOCIATED(pw_env%poisson_env)) THEN
     504       145264 :          ALLOCATE (pw_env%poisson_env)
     505         9079 :          CALL pw_env%poisson_env%create()
     506              :       END IF
     507              :       ! poisson_section => section_vals_get_subs_vals(input, "DFT%POISSON")
     508              : 
     509        10959 :       CALL pw_poisson_read_parameters(poisson_section, poisson_params)
     510              :       CALL pw_poisson_set(pw_env%poisson_env, cell_hmat=my_cell%hmat, pw_pools=pw_env%pw_pools, &
     511              :                           parameters=poisson_params, mt_super_ref_pw_grid=mt_super_ref_grid, &
     512        10959 :                           dct_pw_grid=dct_pw_grid, use_level=pw_env%auxbas_grid)
     513        10959 :       CALL pw_grid_release(mt_super_ref_grid)
     514        10959 :       CALL pw_grid_release(dct_pw_grid)
     515              : !
     516              : ! If reference cell is present, then use pw_grid_change to keep bounds constant...
     517              : ! do not re-init the Gaussian grid level (fix the gridlevel on which the pgf should go.
     518              : !
     519        10959 :       IF (use_ref_cell) THEN
     520          284 :          DO igrid_level = 1, SIZE(pw_pools)
     521          284 :             CALL pw_grid_change(cell%hmat, pw_pools(igrid_level)%pool%pw_grid)
     522              :          END DO
     523           64 :          IF (set_vdw_pool) CALL pw_grid_change(cell%hmat, pw_env%vdw_pw_pool%pw_grid)
     524           64 :          CALL pw_poisson_read_parameters(poisson_section, poisson_params)
     525              :          CALL pw_poisson_set(pw_env%poisson_env, cell_hmat=cell%hmat, pw_pools=pw_env%pw_pools, &
     526              :                              parameters=poisson_params, mt_super_ref_pw_grid=mt_super_ref_grid, &
     527           64 :                              dct_pw_grid=dct_pw_grid, use_level=pw_env%auxbas_grid)
     528              :       END IF
     529              : 
     530        10959 :       IF ((poisson_params%ps_implicit_params%boundary_condition == MIXED_PERIODIC_BC) .OR. &
     531              :           (poisson_params%ps_implicit_params%boundary_condition == MIXED_BC)) THEN
     532              :          pw_env%poisson_env%parameters%dbc_params%do_dbc_cube = &
     533              :             BTEST(cp_print_key_should_output(logger%iter_info, input, &
     534           38 :                                              "DFT%PRINT%IMPLICIT_PSOLVER%DIRICHLET_BC_CUBE"), cp_p_file)
     535              :       END IF
     536              :       ! setup dct_pw_grid (an extended pw_grid) for Discrete Cosine Transformation (DCT)
     537        10959 :       IF ((poisson_params%ps_implicit_params%boundary_condition == NEUMANN_BC) .OR. &
     538              :           (poisson_params%ps_implicit_params%boundary_condition == MIXED_BC)) THEN
     539              :          CALL setup_dct_pw_grids(pw_env%poisson_env%pw_pools(pw_env%poisson_env%pw_level)%pool%pw_grid, &
     540              :                                  my_cell%hmat, poisson_params%ps_implicit_params%neumann_directions, &
     541           22 :                                  pw_env%poisson_env%dct_pw_grid)
     542              :       END IF
     543              :       ! setup real space grid for finite difference derivatives of dielectric constant function
     544        10959 :       IF (poisson_params%has_dielectric .AND. &
     545              :           ((poisson_params%dielectric_params%derivative_method == derivative_cd3) .OR. &
     546              :            (poisson_params%dielectric_params%derivative_method == derivative_cd5) .OR. &
     547              :            (poisson_params%dielectric_params%derivative_method == derivative_cd7))) THEN
     548              : 
     549           70 :          SELECT CASE (poisson_params%ps_implicit_params%boundary_condition)
     550              :          CASE (NEUMANN_BC, MIXED_BC)
     551              :             CALL setup_diel_rs_grid(pw_env%poisson_env%diel_rs_grid, &
     552              :                                     poisson_params%dielectric_params%derivative_method, input, &
     553           20 :                                     pw_env%poisson_env%dct_pw_grid)
     554              :          CASE (PERIODIC_BC, MIXED_PERIODIC_BC)
     555              :             CALL setup_diel_rs_grid(pw_env%poisson_env%diel_rs_grid, &
     556              :                                     poisson_params%dielectric_params%derivative_method, input, &
     557           50 :                                     pw_env%poisson_env%pw_pools(pw_env%poisson_env%pw_level)%pool%pw_grid)
     558              :          END SELECT
     559              : 
     560              :       END IF
     561              : 
     562              : !
     563              : !
     564              : !    determine the maximum radii for mapped gaussians, needed to
     565              : !    set up distributed rs grids
     566              : !
     567              : !
     568              : 
     569        32877 :       ALLOCATE (radius(ngrid_level))
     570              : 
     571        10959 :       CALL compute_max_radius(radius, pw_env, qs_env)
     572              : 
     573              : !
     574              : !
     575              : !    set up the rs_grids and the cubes, requires 'radius' to be set up correctly
     576              : !
     577              : !
     578        65506 :       ALLOCATE (rs_descs(ngrid_level))
     579              : 
     580       229891 :       ALLOCATE (rs_grids(ngrid_level))
     581              : 
     582       361399 :       ALLOCATE (pw_env%cube_info(ngrid_level))
     583        10959 :       higher_grid_layout = [-1, -1, -1]
     584              : 
     585        43588 :       DO igrid_level = 1, ngrid_level
     586        32629 :          pw_grid => pw_pools(igrid_level)%pool%pw_grid
     587              : 
     588        32629 :          CALL init_d3_poly_module() ! a fairly arbitrary but sufficient spot to do this
     589              :          CALL init_cube_info(pw_env%cube_info(igrid_level), &
     590              :                              pw_grid%dr(:), pw_grid%dh(:, :), pw_grid%dh_inv(:, :), pw_grid%orthorhombic, &
     591        32629 :                              radius(igrid_level))
     592              : 
     593        32629 :          rs_grid_section => section_vals_get_subs_vals(input, "DFT%MGRID%RS_GRID")
     594              : 
     595              :          CALL init_input_type(input_settings, nsmax=2*MAX(1, return_cube_max_iradius(pw_env%cube_info(igrid_level))) + 1, &
     596              :                               rs_grid_section=rs_grid_section, ilevel=igrid_level, &
     597        32629 :                               higher_grid_layout=higher_grid_layout)
     598              : 
     599        32629 :          NULLIFY (rs_descs(igrid_level)%rs_desc)
     600        32629 :          CALL rs_grid_create_descriptor(rs_descs(igrid_level)%rs_desc, pw_grid, input_settings)
     601              : 
     602        32707 :          IF (rs_descs(igrid_level)%rs_desc%distributed) higher_grid_layout = rs_descs(igrid_level)%rs_desc%group_dim
     603              : 
     604        43588 :          CALL rs_grid_create(rs_grids(igrid_level), rs_descs(igrid_level)%rs_desc)
     605              :       END DO
     606        10959 :       pw_env%rs_descs => rs_descs
     607        10959 :       pw_env%rs_grids => rs_grids
     608              : 
     609        10959 :       DEALLOCATE (radius)
     610              : 
     611              :       ! Print grid information
     612              : 
     613        10959 :       IF (do_io) THEN
     614         9851 :          logger => cp_get_default_logger()
     615         9851 :          iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.Log')
     616              :       END IF
     617        10959 :       IF (iounit > 0) THEN
     618         3872 :          SELECT CASE (poisson_params%solver)
     619              :          CASE (pw_poisson_periodic)
     620              :             WRITE (UNIT=iounit, FMT="(/,T2,A,T51,A30)") &
     621         1688 :                "POISSON| Solver", "PERIODIC"
     622              :          CASE (pw_poisson_analytic)
     623              :             WRITE (UNIT=iounit, FMT="(/,T2,A,T51,A30)") &
     624           18 :                "POISSON| Solver", "ANALYTIC"
     625              :          CASE (pw_poisson_mt)
     626              :             WRITE (UNIT=iounit, FMT="(/,T2,A,T51,A30)") &
     627          290 :                "POISSON| Solver", ADJUSTR("Martyna-Tuckerman (MT)")
     628              :             WRITE (UNIT=iounit, FMT="(T2,A,T71,F10.3,/,T2,A,T71,F10.1)") &
     629          290 :                "POISSON| MT| Alpha", poisson_params%mt_alpha, &
     630          580 :                "POISSON| MT| Relative cutoff", poisson_params%mt_rel_cutoff
     631              :          CASE (pw_poisson_multipole)
     632              :             WRITE (UNIT=iounit, FMT="(/,T2,A,T51,A30)") &
     633            9 :                "POISSON| Solver", "MULTIPOLE (Bloechl)"
     634              :          CASE (pw_poisson_wavelet)
     635              :             WRITE (UNIT=iounit, FMT="(/,T2,A,T51,A30)") &
     636          152 :                "POISSON| Solver", "WAVELET"
     637              :             WRITE (UNIT=iounit, FMT="(T2,A,T71,I10)") &
     638          152 :                "POISSON| Wavelet| Scaling function", poisson_params%wavelet_scf_type
     639          304 :             SELECT CASE (poisson_params%wavelet_method)
     640              :             CASE (WAVELET0D)
     641              :                WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") &
     642          125 :                   "POISSON| Periodicity", "NONE"
     643              :             CASE (WAVELET2D)
     644            3 :                string = ""
     645            3 :                IF (poisson_params%periodic(1) == 1) string = TRIM(string)//"X"
     646            3 :                IF (poisson_params%periodic(2) == 1) string = TRIM(string)//"Y"
     647            3 :                IF (poisson_params%periodic(3) == 1) string = TRIM(string)//"Z"
     648              :                WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") &
     649            3 :                   "POISSON| Periodicity", ADJUSTR(string)
     650              :             CASE (WAVELET3D)
     651              :                WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") &
     652           24 :                   "POISSON| Periodicity", "XYZ"
     653              :             CASE DEFAULT
     654          152 :                CPABORT("Invalid periodicity for wavelet solver selected")
     655              :             END SELECT
     656              :          CASE (pw_poisson_implicit)
     657              :             WRITE (UNIT=iounit, FMT="(/,T2,A,T51,A30)") &
     658           27 :                "POISSON| Solver", "IMPLICIT (GENERALIZED)"
     659           27 :             boundary_condition = poisson_params%ps_implicit_params%boundary_condition
     660            5 :             SELECT CASE (boundary_condition)
     661              :             CASE (PERIODIC_BC)
     662              :                WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") &
     663            5 :                   "POISSON| Boundary Condition", "PERIODIC"
     664              :             CASE (NEUMANN_BC, MIXED_BC)
     665           11 :                IF (boundary_condition == NEUMANN_BC) THEN
     666              :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") &
     667            3 :                      "POISSON| Boundary Condition", "NEUMANN"
     668              :                ELSE
     669              :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") &
     670            8 :                      "POISSON| Boundary Condition", "MIXED"
     671              :                END IF
     672           30 :                SELECT CASE (poisson_params%ps_implicit_params%neumann_directions)
     673              :                CASE (neumannXYZ)
     674            8 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| homogeneous Neumann directions", "X, Y, Z"
     675            8 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| periodic directions", "NONE"
     676              :                CASE (neumannXY)
     677            0 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| homogeneous Neumann directions", "X, Y"
     678            0 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| periodic directions", "Z"
     679              :                CASE (neumannXZ)
     680            0 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| homogeneous Neumann directions", "X, Z"
     681            0 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| periodic directions", "Y"
     682              :                CASE (neumannYZ)
     683            1 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| homogeneous Neumann directions", "Y, Z"
     684            1 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| periodic directions", "X"
     685              :                CASE (neumannX)
     686            1 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| homogeneous Neumann directions", "X"
     687            1 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| periodic directions", "Y, Z"
     688              :                CASE (neumannY)
     689            0 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| homogeneous Neumann directions", "Y"
     690            0 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| periodic directions", "X, Z"
     691              :                CASE (neumannZ)
     692            1 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| homogeneous Neumann directions", "Z"
     693            1 :                   WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") "POISSON| periodic directions", "X, Y"
     694              :                CASE DEFAULT
     695           11 :                   CPABORT("Invalid combination of Neumann and periodic conditions.")
     696              :                END SELECT
     697              :             CASE (MIXED_PERIODIC_BC)
     698              :                WRITE (UNIT=iounit, FMT="(T2,A,T51,A30)") &
     699           11 :                   "POISSON| Boundary Condition", "PERIODIC & DIRICHLET"
     700              :             CASE DEFAULT
     701           27 :                CPABORT("Invalid boundary conditions for the implicit (generalized) poisson solver.")
     702              :             END SELECT
     703              :             WRITE (UNIT=iounit, FMT="(T2,A,T71,I10)") &
     704           27 :                "POISSON| Maximum number of iterations", poisson_params%ps_implicit_params%max_iter
     705              :             WRITE (UNIT=iounit, FMT="(T2,A,T51,ES30.2)") &
     706           27 :                "POISSON| Convergence threshold", poisson_params%ps_implicit_params%tol
     707           27 :             IF (poisson_params%dielectric_params%dielec_functiontype == rho_dependent) THEN
     708              :                WRITE (UNIT=iounit, FMT="(T2,A,T51,F30.2)") &
     709           25 :                   "POISSON| Dielectric Constant", poisson_params%dielectric_params%eps0
     710              :             ELSE
     711              :                WRITE (UNIT=iounit, FMT="(T2,A,T31,F9.2)", ADVANCE='NO') &
     712            2 :                   "POISSON| Dielectric Constants", poisson_params%dielectric_params%eps0
     713            3 :                DO i = 1, poisson_params%dielectric_params%n_aa_cuboidal
     714              :                   WRITE (UNIT=iounit, FMT="(F9.2)", ADVANCE='NO') &
     715            3 :                      poisson_params%dielectric_params%aa_cuboidal_eps(i)
     716              :                END DO
     717            4 :                DO i = 1, poisson_params%dielectric_params%n_xaa_annular
     718              :                   WRITE (UNIT=iounit, FMT="(F9.2)", ADVANCE='NO') &
     719            4 :                      poisson_params%dielectric_params%xaa_annular_eps(i)
     720              :                END DO
     721            2 :                WRITE (UNIT=iounit, FMT='(A1,/)')
     722              :             END IF
     723              :             WRITE (UNIT=iounit, FMT="(T2,A,T51,ES30.2)") &
     724           27 :                "POISSON| Relaxation parameter", poisson_params%ps_implicit_params%omega
     725              :          CASE (pw_poisson_none)
     726              :             WRITE (UNIT=iounit, FMT="(/,T2,A,T51,A30)") &
     727            0 :                "POISSON| Solver", "NONE"
     728              :          CASE default
     729         2184 :             CPABORT("Invalid Poisson solver selected")
     730              :          END SELECT
     731         2184 :          IF ((poisson_params%solver /= pw_poisson_wavelet) .AND. &
     732              :              (poisson_params%solver /= pw_poisson_implicit)) THEN
     733         8020 :             IF (SUM(poisson_params%periodic(1:3)) == 0) THEN
     734              :                WRITE (UNIT=iounit, FMT="(T2,A,T77,A4)") &
     735          309 :                   "POISSON| Periodicity", "NONE"
     736              :             ELSE
     737         1696 :                string = ""
     738         1696 :                IF (poisson_params%periodic(1) == 1) string = TRIM(string)//"X"
     739         1696 :                IF (poisson_params%periodic(2) == 1) string = TRIM(string)//"Y"
     740         1696 :                IF (poisson_params%periodic(3) == 1) string = TRIM(string)//"Z"
     741              :                WRITE (UNIT=iounit, FMT="(T2,A,T78,A3)") &
     742         1696 :                   "POISSON| Periodicity", ADJUSTR(string)
     743              :             END IF
     744              :          END IF
     745              :       END IF
     746              : 
     747              :       IF ((dft_control%qs_control%method_id == do_method_gpw) .OR. &
     748              :           (dft_control%qs_control%method_id == do_method_gapw) .OR. &
     749              :           (dft_control%qs_control%method_id == do_method_gapw_xc) .OR. &
     750              :           (dft_control%qs_control%method_id == do_method_lrigpw) .OR. &
     751        10959 :           (dft_control%qs_control%method_id == do_method_rigpw) .OR. &
     752              :           (dft_control%qs_control%method_id == do_method_ofgpw)) THEN
     753         7282 :          IF (poisson_params%solver /= pw_poisson_implicit) THEN
     754        27008 :             IF (ANY(my_cell%perd(1:3) /= poisson_params%periodic(1:3))) THEN
     755              :                CALL cp_warn(__LOCATION__, &
     756          650 :                             "The selected periodicities in the sections &CELL and &POISSON do not match")
     757              :             END IF
     758              :          END IF
     759              :       END IF
     760              : 
     761        10959 :       IF (do_io) THEN
     762              :          should_output = BTEST(cp_print_key_should_output(logger%iter_info, &
     763         9851 :                                                           print_section, ''), cp_p_file)
     764         9851 :          IF (should_output) THEN
     765        17042 :             DO igrid_level = 1, ngrid_level
     766        17042 :                CALL rs_grid_print(rs_grids(igrid_level), iounit)
     767              :             END DO
     768              :          END IF
     769         9851 :          CALL cp_print_key_finished_output(iounit, logger, print_section, "")
     770              :       END IF
     771              : 
     772        10959 :       CALL timestop(handle)
     773              : 
     774       120549 :    END SUBROUTINE pw_env_rebuild
     775              : 
     776              : ! **************************************************************************************************
     777              : !> \brief computes the maximum radius
     778              : !> \param radius ...
     779              : !> \param pw_env ...
     780              : !> \param qs_env ...
     781              : !> \par History
     782              : !>      10.2010 refactored [Joost VandeVondele]
     783              : !>      01.2020 igrid_zet0_s initialisation code is reused in rho0_s_grid_create() [Sergey Chulkov]
     784              : !> \author Joost VandeVondele
     785              : ! **************************************************************************************************
     786        10959 :    SUBROUTINE compute_max_radius(radius, pw_env, qs_env)
     787              :       REAL(KIND=dp), DIMENSION(:), INTENT(OUT)           :: radius
     788              :       TYPE(pw_env_type), POINTER                         :: pw_env
     789              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     790              : 
     791              :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_max_radius'
     792              :       CHARACTER(LEN=8), DIMENSION(10), PARAMETER :: sbas = ["ORB     ", "AUX     ", "RI_AUX  ", &
     793              :          "MAO     ", "HARRIS  ", "RI_HXC  ", "RI_K    ", "LRI_AUX ", "RHOIN   ", "NUC     "]
     794              :       CHARACTER(LEN=8), DIMENSION(5), PARAMETER :: &
     795              :          pbas = ["ORB     ", "AUX_FIT ", "MAO     ", "HARRIS  ", "NUC     "]
     796              :       REAL(KIND=dp), PARAMETER                           :: safety_factor = 1.015_dp
     797              : 
     798              :       INTEGER :: handle, ibasis_set_type, igrid_level, igrid_zet0_s, ikind, ipgf, iset, ishell, &
     799              :          jkind, jpgf, jset, jshell, la, lb, lgrid_level, ngrid_level, nkind, nseta, nsetb
     800        10959 :       INTEGER, DIMENSION(:), POINTER                     :: npgfa, npgfb, nshella, nshellb
     801        10959 :       INTEGER, DIMENSION(:, :), POINTER                  :: lshella, lshellb
     802              :       REAL(KIND=dp)                                      :: alpha, core_charge, eps_gvg, eps_rho, &
     803              :                                                             max_rpgf0_s, maxradius, zet0_h, zetp
     804        10959 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: zeta, zetb
     805              :       TYPE(cneo_potential_type), POINTER                 :: cneo_potential
     806              :       TYPE(dft_control_type), POINTER                    :: dft_control
     807              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis_set
     808        10959 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     809              :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     810              :       TYPE(rho0_mpole_type), POINTER                     :: rho0_mpole
     811              : 
     812              :       ! a very small safety factor might be needed for roundoff issues
     813              :       ! e.g. radius being computed here as 12.998 (13) and 13.002 (14) during the collocation
     814              :       ! the latter can happen due to the lower precision in the computation of the radius in collocate
     815              :       ! parallel cost of rs_pw_transfer goes as safety_factor**3 so it is worthwhile keeping it tight
     816              : 
     817        10959 :       CALL timeset(routineN, handle)
     818        10959 :       NULLIFY (dft_control, qs_kind_set, rho0_mpole)
     819              : 
     820        10959 :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, dft_control=dft_control)
     821              : 
     822        10959 :       eps_rho = dft_control%qs_control%eps_rho_rspace
     823        10959 :       eps_gvg = dft_control%qs_control%eps_gvg_rspace
     824              : 
     825        10959 :       IF (dft_control%qs_control%gapw) THEN
     826         1216 :          CALL get_qs_env(qs_env=qs_env, rho0_mpole=rho0_mpole)
     827         1216 :          CPASSERT(ASSOCIATED(rho0_mpole))
     828              : 
     829         1216 :          CALL get_rho0_mpole(rho0_mpole=rho0_mpole, max_rpgf0_s=max_rpgf0_s, zet0_h=zet0_h)
     830         1216 :          igrid_zet0_s = gaussian_gridlevel(pw_env%gridlevel_info, 2.0_dp*zet0_h)
     831         1216 :          rho0_mpole%igrid_zet0_s = igrid_zet0_s
     832              :       END IF
     833              : 
     834        10959 :       ngrid_level = SIZE(radius)
     835        10959 :       nkind = SIZE(qs_kind_set)
     836              : 
     837              :       ! try to predict the maximum radius of the gaussians to be mapped on the grid
     838              :       ! up to now, it is not yet very good
     839        43588 :       radius = 0.0_dp
     840        43588 :       DO igrid_level = 1, ngrid_level
     841              : 
     842        32629 :          maxradius = 0.0_dp
     843              :          ! Take into account the radius of the soft compensation charge rho0_soft1
     844        32629 :          IF (dft_control%qs_control%gapw) THEN
     845         4588 :             IF (igrid_zet0_s == igrid_level) maxradius = MAX(maxradius, max_rpgf0_s)
     846              :          END IF
     847              : 
     848              :          ! this is to be sure that the core charge is mapped ok
     849              :          ! right now, the core is mapped on the auxiliary basis,
     850              :          ! this should, at a give point be changed
     851              :          ! so that also for the core a multigrid is used
     852        92242 :          DO ikind = 1, nkind
     853        59613 :             NULLIFY (cneo_potential)
     854        59613 :             CALL get_qs_kind(qs_kind_set(ikind), cneo_potential=cneo_potential)
     855        59613 :             IF (ASSOCIATED(cneo_potential)) CYCLE
     856              :             CALL get_qs_kind(qs_kind_set(ikind), &
     857        59599 :                              alpha_core_charge=alpha, ccore_charge=core_charge)
     858        92228 :             IF (alpha > 0.0_dp .AND. core_charge /= 0.0_dp) THEN
     859        58997 :                maxradius = MAX(maxradius, exp_radius(0, alpha, eps_rho, core_charge, rlow=maxradius))
     860              :                ! forces
     861        58997 :                maxradius = MAX(maxradius, exp_radius(1, alpha, eps_rho, core_charge, rlow=maxradius))
     862              :             END IF
     863              :          END DO
     864              : 
     865              :          ! loop over basis sets that are used in grid collocation directly (no product)
     866              :          ! e.g. for calculating a wavefunction or a RI density
     867       358919 :          DO ibasis_set_type = 1, SIZE(sbas)
     868       955049 :             DO ikind = 1, nkind
     869       596130 :                qs_kind => qs_kind_set(ikind)
     870       596130 :                NULLIFY (orb_basis_set)
     871              :                CALL get_qs_kind(qs_kind=qs_kind, &
     872       596130 :                                 basis_set=orb_basis_set, basis_type=sbas(ibasis_set_type))
     873       596130 :                IF (.NOT. ASSOCIATED(orb_basis_set)) CYCLE
     874              :                CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     875        71973 :                                       npgf=npgfa, nset=nseta, zet=zeta, l=lshella, nshell=nshella)
     876       660803 :                DO iset = 1, nseta
     877      1373518 :                   DO ipgf = 1, npgfa(iset)
     878      1698298 :                      DO ishell = 1, nshella(iset)
     879       920910 :                         zetp = zeta(ipgf, iset)
     880       920910 :                         la = lshella(ishell, iset)
     881       920910 :                         lgrid_level = gaussian_gridlevel(pw_env%gridlevel_info, zetp)
     882      1435758 :                         IF (lgrid_level == igrid_level) THEN
     883       300343 :                            maxradius = MAX(maxradius, exp_radius(la, zetp, eps_rho, 1.0_dp, rlow=maxradius))
     884              :                         END IF
     885              :                      END DO
     886              :                   END DO
     887              :                END DO
     888              :             END DO
     889              :          END DO
     890              :          ! loop over basis sets that are used in product function grid collocation
     891       195774 :          DO ibasis_set_type = 1, SIZE(pbas)
     892       493839 :             DO ikind = 1, nkind
     893       298065 :                qs_kind => qs_kind_set(ikind)
     894       298065 :                NULLIFY (orb_basis_set)
     895              :                CALL get_qs_kind(qs_kind=qs_kind, &
     896       298065 :                                 basis_set=orb_basis_set, basis_type=pbas(ibasis_set_type))
     897       298065 :                IF (.NOT. ASSOCIATED(orb_basis_set)) CYCLE
     898              :                CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     899        64749 :                                       npgf=npgfa, nset=nseta, zet=zeta, l=lshella, nshell=nshella)
     900              : 
     901       364019 :                DO jkind = 1, nkind
     902       136125 :                   qs_kind => qs_kind_set(jkind)
     903              :                   CALL get_qs_kind(qs_kind=qs_kind, &
     904       136125 :                                    basis_set=orb_basis_set, basis_type=pbas(ibasis_set_type))
     905       136125 :                   IF (.NOT. ASSOCIATED(orb_basis_set)) CYCLE
     906              :                   CALL get_gto_basis_set(gto_basis_set=orb_basis_set, &
     907       136111 :                                          npgf=npgfb, nset=nsetb, zet=zetb, l=lshellb, nshell=nshellb)
     908       723576 :                   DO iset = 1, nseta
     909      1280993 :                   DO ipgf = 1, npgfa(iset)
     910      2798630 :                   DO ishell = 1, nshella(iset)
     911      1653762 :                      la = lshella(ishell, iset)
     912      5919468 :                      DO jset = 1, nsetb
     913     16728600 :                      DO jpgf = 1, npgfb(jset)
     914     46036900 :                      DO jshell = 1, nshellb(jset)
     915     30962062 :                         zetp = zeta(ipgf, iset) + zetb(jpgf, jset)
     916     30962062 :                         lb = lshellb(jshell, jset) + la
     917     30962062 :                         lgrid_level = gaussian_gridlevel(pw_env%gridlevel_info, zetp)
     918     42626662 :                         IF (lgrid_level == igrid_level) THEN
     919              :                            ! density (scale is at most 2)
     920     12503103 :                            maxradius = MAX(maxradius, exp_radius(lb, zetp, eps_rho, 2.0_dp, rlow=maxradius))
     921              :                            ! tau, properties?
     922     12503103 :                            maxradius = MAX(maxradius, exp_radius(lb + 1, zetp, eps_rho, 2.0_dp, rlow=maxradius))
     923              :                            ! potential
     924     12503103 :                            maxradius = MAX(maxradius, exp_radius(lb, zetp, eps_gvg, 2.0_dp, rlow=maxradius))
     925              :                            ! forces
     926     12503103 :                            maxradius = MAX(maxradius, exp_radius(lb + 1, zetp, eps_gvg, 2.0_dp, rlow=maxradius))
     927              :                         END IF
     928              :                      END DO
     929              :                      END DO
     930              :                      END DO
     931              :                   END DO
     932              :                   END DO
     933              :                   END DO
     934              :                END DO
     935              :             END DO
     936              :          END DO
     937              : 
     938              :          ! this is a bit of hack, but takes into account numerics and rounding
     939        32629 :          maxradius = maxradius*safety_factor
     940        43588 :          radius(igrid_level) = maxradius
     941              :       END DO
     942              : 
     943        10959 :       CALL timestop(handle)
     944              : 
     945        10959 :    END SUBROUTINE compute_max_radius
     946              : 
     947              : ! **************************************************************************************************
     948              : !> \brief Initialize the super-reference grid for Tuckerman or xc
     949              : !> \param super_ref_pw_grid ...
     950              : !> \param mt_super_ref_pw_grid ...
     951              : !> \param xc_super_ref_pw_grid ...
     952              : !> \param cutilev ...
     953              : !> \param grid_span ...
     954              : !> \param spherical ...
     955              : !> \param cell_ref ...
     956              : !> \param para_env ...
     957              : !> \param poisson_section ...
     958              : !> \param my_ncommensurate ...
     959              : !> \param uf_grid ...
     960              : !> \param fine_grid_factor ...
     961              : !> \param print_section ...
     962              : !> \author 03-2005 Teodoro Laino [teo]
     963              : !> \note
     964              : !>      move somewere else?
     965              : ! **************************************************************************************************
     966        21918 :    SUBROUTINE setup_super_ref_grid(super_ref_pw_grid, mt_super_ref_pw_grid, &
     967              :                                    xc_super_ref_pw_grid, cutilev, grid_span, spherical, &
     968              :                                    cell_ref, para_env, poisson_section, my_ncommensurate, uf_grid, &
     969              :                                    fine_grid_factor, print_section)
     970              :       TYPE(pw_grid_type), POINTER                        :: super_ref_pw_grid, mt_super_ref_pw_grid, &
     971              :                                                             xc_super_ref_pw_grid
     972              :       REAL(KIND=dp), INTENT(IN)                          :: cutilev
     973              :       INTEGER, INTENT(IN)                                :: grid_span
     974              :       LOGICAL, INTENT(in)                                :: spherical
     975              :       TYPE(cell_type), POINTER                           :: cell_ref
     976              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     977              :       TYPE(section_vals_type), POINTER                   :: poisson_section
     978              :       INTEGER, INTENT(IN)                                :: my_ncommensurate
     979              :       LOGICAL, INTENT(in)                                :: uf_grid
     980              :       REAL(KIND=dp), INTENT(IN)                          :: fine_grid_factor
     981              :       TYPE(section_vals_type), POINTER                   :: print_section
     982              : 
     983              :       INTEGER                                            :: iounit, my_val, nn(3), no(3)
     984              :       LOGICAL                                            :: mt_s_grid
     985              :       REAL(KIND=dp)                                      :: mt_rel_cutoff, my_cutilev
     986              :       TYPE(cp_logger_type), POINTER                      :: logger
     987              : 
     988        10959 :       CPASSERT(.NOT. ASSOCIATED(mt_super_ref_pw_grid))
     989        10959 :       CPASSERT(.NOT. ASSOCIATED(xc_super_ref_pw_grid))
     990        10959 :       CPASSERT(.NOT. ASSOCIATED(super_ref_pw_grid))
     991        10959 :       CALL section_vals_val_get(poisson_section, "POISSON_SOLVER", i_val=my_val)
     992              :       !
     993              :       ! Check if grids will be the same... In this case we don't use a super-reference grid
     994              :       !
     995        10959 :       mt_s_grid = .FALSE.
     996        10959 :       IF (my_val == pw_poisson_mt) THEN
     997              :          CALL section_vals_val_get(poisson_section, "MT%REL_CUTOFF", &
     998         1374 :                                    r_val=mt_rel_cutoff)
     999         1374 :          IF (mt_rel_cutoff > 1._dp) mt_s_grid = .TRUE.
    1000              :       END IF
    1001              : 
    1002        10959 :       logger => cp_get_default_logger()
    1003              :       iounit = cp_print_key_unit_nr(logger, print_section, "", &
    1004        10959 :                                     extension=".Log")
    1005              : 
    1006        10959 :       IF (uf_grid) THEN
    1007           48 :          my_cutilev = fine_grid_factor*cutilev
    1008           48 :          IF (mt_s_grid) my_cutilev = MAX(my_cutilev, cutilev*mt_rel_cutoff)
    1009              :          CALL pw_grid_create(xc_super_ref_pw_grid, para_env, cell_ref%hmat, grid_span=grid_span, &
    1010              :                              cutoff=my_cutilev, spherical=spherical, odd=.FALSE., fft_usage=.TRUE., &
    1011              :                              ncommensurate=my_ncommensurate, icommensurate=1, &
    1012              :                              blocked=do_pw_grid_blocked_false, rs_dims=[para_env%num_pe, 1], &
    1013          144 :                              iounit=iounit)
    1014           48 :          super_ref_pw_grid => xc_super_ref_pw_grid
    1015              :       END IF
    1016        10959 :       IF (mt_s_grid) THEN
    1017         1368 :          my_cutilev = cutilev*mt_rel_cutoff
    1018         1368 :          IF (ASSOCIATED(xc_super_ref_pw_grid)) my_cutilev = MAX(my_cutilev, fine_grid_factor*cutilev)
    1019              : 
    1020              :          no = pw_grid_init_setup(cell_ref%hmat, cutoff=cutilev, spherical=spherical, &
    1021         1368 :                                  odd=.FALSE., fft_usage=.TRUE., ncommensurate=0, icommensurate=1)
    1022              :          nn = pw_grid_init_setup(cell_ref%hmat, cutoff=my_cutilev, spherical=spherical, &
    1023         1368 :                                  odd=.FALSE., fft_usage=.TRUE., ncommensurate=0, icommensurate=1)
    1024              : 
    1025              :          ! bug appears for nn==no, also in old versions
    1026         5472 :          CPASSERT(ALL(nn > no))
    1027         1368 :          IF (ASSOCIATED(xc_super_ref_pw_grid)) THEN
    1028            2 :             mt_super_ref_pw_grid => xc_super_ref_pw_grid
    1029            2 :             CALL pw_grid_retain(mt_super_ref_pw_grid)
    1030              :          ELSE
    1031              :             CALL pw_grid_create(mt_super_ref_pw_grid, para_env, cell_ref%hmat, &
    1032              :                                 cutoff=my_cutilev, spherical=spherical, fft_usage=.TRUE., &
    1033              :                                 blocked=do_pw_grid_blocked_false, rs_dims=[para_env%num_pe, 1], &
    1034         4098 :                                 iounit=iounit)
    1035         1366 :             super_ref_pw_grid => mt_super_ref_pw_grid
    1036              :          END IF
    1037              :       END IF
    1038              :       CALL cp_print_key_finished_output(iounit, logger, print_section, &
    1039        10959 :                                         "")
    1040        10959 :    END SUBROUTINE setup_super_ref_grid
    1041              : 
    1042              : ! **************************************************************************************************
    1043              : !> \brief   sets up a real-space grid for finite difference derivative of dielectric
    1044              : !>          constant function
    1045              : !> \param diel_rs_grid real space grid to be created
    1046              : !> \param method preferred finite difference derivative method
    1047              : !> \param input input file
    1048              : !> \param pw_grid plane-wave grid
    1049              : !> \par History
    1050              : !>       12.2014 created [Hossein Bani-Hashemian]
    1051              : !> \author Mohammad Hossein Bani-Hashemian
    1052              : ! **************************************************************************************************
    1053           50 :    SUBROUTINE setup_diel_rs_grid(diel_rs_grid, method, input, pw_grid)
    1054              : 
    1055              :       TYPE(realspace_grid_type), POINTER                 :: diel_rs_grid
    1056              :       INTEGER, INTENT(IN)                                :: method
    1057              :       TYPE(section_vals_type), POINTER                   :: input
    1058              :       TYPE(pw_grid_type), POINTER                        :: pw_grid
    1059              : 
    1060              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'setup_diel_rs_grid'
    1061              : 
    1062              :       INTEGER                                            :: border_points, handle
    1063              :       TYPE(realspace_grid_desc_type), POINTER            :: rs_desc
    1064              :       TYPE(realspace_grid_input_type)                    :: input_settings
    1065              :       TYPE(section_vals_type), POINTER                   :: rs_grid_section
    1066              : 
    1067           50 :       CALL timeset(routineN, handle)
    1068              : 
    1069           50 :       NULLIFY (rs_desc)
    1070           50 :       rs_grid_section => section_vals_get_subs_vals(input, "DFT%MGRID%RS_GRID")
    1071           74 :       SELECT CASE (method)
    1072              :       CASE (derivative_cd3)
    1073           24 :          border_points = 1
    1074              :       CASE (derivative_cd5)
    1075           14 :          border_points = 2
    1076              :       CASE (derivative_cd7)
    1077           50 :          border_points = 3
    1078              :       END SELECT
    1079              :       CALL init_input_type(input_settings, 2*border_points + 1, rs_grid_section, &
    1080           50 :                            1, [-1, -1, -1])
    1081              :       CALL rs_grid_create_descriptor(rs_desc, pw_grid, input_settings, &
    1082           50 :                                      border_points=border_points)
    1083         1050 :       ALLOCATE (diel_rs_grid)
    1084           50 :       CALL rs_grid_create(diel_rs_grid, rs_desc)
    1085           50 :       CALL rs_grid_release_descriptor(rs_desc)
    1086              : 
    1087           50 :       CALL timestop(handle)
    1088              : 
    1089          200 :    END SUBROUTINE setup_diel_rs_grid
    1090              : 
    1091              : END MODULE pw_env_methods
        

Generated by: LCOV version 2.0-1