LCOV - code coverage report
Current view: top level - src - hirshfeld_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:34ef472) Lines: 250 257 97.3 %
Date: 2024-04-26 08:30:29 Functions: 8 8 100.0 %

          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 Calculate Hirshfeld charges and related functions
      10             : !> \par History
      11             : !>      11.2014 created [JGH]
      12             : !> \author JGH
      13             : ! **************************************************************************************************
      14             : MODULE hirshfeld_methods
      15             :    USE ao_util,                         ONLY: exp_radius_very_extended
      16             :    USE atom_kind_orbitals,              ONLY: calculate_atomic_density
      17             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      18             :                                               get_atomic_kind
      19             :    USE cell_types,                      ONLY: cell_type,&
      20             :                                               pbc
      21             :    USE cp_control_types,                ONLY: dft_control_type
      22             :    USE cp_result_methods,               ONLY: cp_results_erase,&
      23             :                                               put_results
      24             :    USE cp_result_types,                 ONLY: cp_result_type
      25             :    USE cp_units,                        ONLY: cp_unit_to_cp2k
      26             :    USE grid_api,                        ONLY: GRID_FUNC_AB,&
      27             :                                               collocate_pgf_product,&
      28             :                                               integrate_pgf_product
      29             :    USE hirshfeld_types,                 ONLY: get_hirshfeld_info,&
      30             :                                               hirshfeld_type,&
      31             :                                               set_hirshfeld_info
      32             :    USE input_constants,                 ONLY: radius_covalent,&
      33             :                                               radius_default,&
      34             :                                               radius_single,&
      35             :                                               radius_user,&
      36             :                                               radius_vdw,&
      37             :                                               shape_function_density,&
      38             :                                               shape_function_gaussian
      39             :    USE kinds,                           ONLY: default_string_length,&
      40             :                                               dp
      41             :    USE mathconstants,                   ONLY: pi
      42             :    USE message_passing,                 ONLY: mp_para_env_type
      43             :    USE particle_types,                  ONLY: particle_type
      44             :    USE periodic_table,                  ONLY: get_ptable_info
      45             :    USE pw_env_types,                    ONLY: pw_env_get,&
      46             :                                               pw_env_type
      47             :    USE pw_methods,                      ONLY: pw_integrate_function
      48             :    USE pw_pool_types,                   ONLY: pw_pool_type
      49             :    USE pw_types,                        ONLY: pw_r3d_rs_type
      50             :    USE qs_environment_types,            ONLY: get_qs_env,&
      51             :                                               qs_environment_type
      52             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      53             :                                               qs_kind_type
      54             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      55             :                                               qs_rho_type
      56             :    USE realspace_grid_types,            ONLY: realspace_grid_desc_type,&
      57             :                                               realspace_grid_type,&
      58             :                                               rs_grid_zero,&
      59             :                                               transfer_pw2rs,&
      60             :                                               transfer_rs2pw
      61             : #include "./base/base_uses.f90"
      62             : 
      63             :    IMPLICIT NONE
      64             :    PRIVATE
      65             : 
      66             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'hirshfeld_methods'
      67             : 
      68             :    PUBLIC :: create_shape_function, comp_hirshfeld_charges, &
      69             :              comp_hirshfeld_i_charges, write_hirshfeld_charges, &
      70             :              save_hirshfeld_charges
      71             : 
      72             : ! **************************************************************************************************
      73             : 
      74             : CONTAINS
      75             : 
      76             : ! **************************************************************************************************
      77             : !> \brief ...
      78             : !> \param charges ...
      79             : !> \param hirshfeld_env ...
      80             : !> \param particle_set ...
      81             : !> \param qs_kind_set ...
      82             : !> \param unit_nr ...
      83             : ! **************************************************************************************************
      84        2257 :    SUBROUTINE write_hirshfeld_charges(charges, hirshfeld_env, particle_set, &
      85             :                                       qs_kind_set, unit_nr)
      86             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(inout)      :: charges
      87             :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
      88             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
      89             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
      90             :       INTEGER, INTENT(IN)                                :: unit_nr
      91             : 
      92             :       CHARACTER(len=2)                                   :: element_symbol
      93             :       INTEGER                                            :: iatom, ikind, natom, nspin
      94             :       REAL(KIND=dp)                                      :: refc, tc1, zeff
      95             : 
      96        2257 :       natom = SIZE(charges, 1)
      97        2257 :       nspin = SIZE(charges, 2)
      98        2257 :       WRITE (unit_nr, '(/,T2,A)') '!-----------------------------------------------------------------------------!'
      99        2257 :       WRITE (UNIT=unit_nr, FMT="(T28,A)") "Hirshfeld Charges"
     100        2257 :       IF (nspin == 1) THEN
     101             :          WRITE (UNIT=unit_nr, FMT="(/,T3,A,A)") &
     102        1875 :             "#Atom  Element  Kind ", " Ref Charge     Population                    Net charge"
     103             :       ELSE
     104             :          WRITE (UNIT=unit_nr, FMT="(/,T3,A,A)") &
     105         382 :             "#Atom  Element  Kind ", " Ref Charge     Population       Spin moment  Net charge"
     106             :       END IF
     107        2257 :       tc1 = 0.0_dp
     108       11806 :       DO iatom = 1, natom
     109             :          CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
     110        9549 :                               element_symbol=element_symbol, kind_number=ikind)
     111        9549 :          refc = hirshfeld_env%charges(iatom)
     112        9549 :          CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
     113        9549 :          IF (nspin == 1) THEN
     114             :             WRITE (UNIT=unit_nr, FMT="(i7,T15,A2,T20,i3,T27,F8.3,T42,F8.3,T72,F8.3)") &
     115        8090 :                iatom, element_symbol, ikind, refc, charges(iatom, 1), zeff - charges(iatom, 1)
     116             :          ELSE
     117             :             WRITE (UNIT=unit_nr, FMT="(i7,T15,A2,T20,i3,T27,F8.3,T36,2F8.3,T61,F8.3,T72,F8.3)") &
     118        1459 :                iatom, element_symbol, ikind, refc, charges(iatom, 1), charges(iatom, 2), &
     119        5836 :                charges(iatom, 1) - charges(iatom, 2), zeff - SUM(charges(iatom, :))
     120             :          END IF
     121       32363 :          tc1 = tc1 + (zeff - SUM(charges(iatom, :)))
     122             :       END DO
     123        2257 :       WRITE (UNIT=unit_nr, FMT="(/,T3,A,T72,F8.3)") "Total Charge ", tc1
     124        2257 :       WRITE (unit_nr, '(T2,A)') '!-----------------------------------------------------------------------------!'
     125             : 
     126        2257 :    END SUBROUTINE write_hirshfeld_charges
     127             : 
     128             : ! **************************************************************************************************
     129             : !> \brief saves the Hirshfeld charges to the results structure
     130             : !> \param charges the calculated Hirshfeld charges
     131             : !> \param particle_set the particle set
     132             : !> \param qs_kind_set the kind set
     133             : !> \param qs_env the environment
     134             : ! **************************************************************************************************
     135        4486 :    SUBROUTINE save_hirshfeld_charges(charges, particle_set, qs_kind_set, qs_env)
     136             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(inout)      :: charges
     137             :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     138             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     139             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     140             : 
     141             :       CHARACTER(LEN=default_string_length)               :: description
     142             :       INTEGER                                            :: iatom, ikind, natom
     143             :       REAL(KIND=dp)                                      :: zeff
     144             :       REAL(KIND=dp), DIMENSION(:), POINTER               :: charges_save
     145             :       TYPE(cp_result_type), POINTER                      :: results
     146             : 
     147        4486 :       NULLIFY (results)
     148        4486 :       CALL get_qs_env(qs_env, results=results)
     149             : 
     150        4486 :       natom = SIZE(charges, 1)
     151       13458 :       ALLOCATE (charges_save(natom))
     152             : 
     153       23528 :       DO iatom = 1, natom
     154             :          CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
     155       19042 :                               kind_number=ikind)
     156       19042 :          CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
     157       45488 :          charges_save(iatom) = zeff - SUM(charges(iatom, :))
     158             :       END DO
     159             : 
     160             :       ! Store charges in results
     161        4486 :       description = "[HIRSHFELD-CHARGES]"
     162        4486 :       CALL cp_results_erase(results=results, description=description)
     163             :       CALL put_results(results=results, description=description, &
     164        4486 :                        values=charges_save)
     165             : 
     166        4486 :       DEALLOCATE (charges_save)
     167             : 
     168        4486 :    END SUBROUTINE save_hirshfeld_charges
     169             : 
     170             : ! **************************************************************************************************
     171             : !> \brief creates kind specific shape functions for Hirshfeld charges
     172             : !> \param hirshfeld_env the env that holds information about Hirshfeld
     173             : !> \param qs_kind_set the qs_kind_set
     174             : !> \param atomic_kind_set the atomic_kind_set
     175             : !> \param radius optional radius parameter to use for all atomic kinds
     176             : !> \param radii_list optional list of radii to use for different atomic kinds
     177             : ! **************************************************************************************************
     178        4668 :    SUBROUTINE create_shape_function(hirshfeld_env, qs_kind_set, atomic_kind_set, radius, radii_list)
     179             :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
     180             :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     181             :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     182             :       REAL(KIND=dp), OPTIONAL                            :: radius
     183             :       REAL(KIND=dp), DIMENSION(:), OPTIONAL, POINTER     :: radii_list
     184             : 
     185             :       INTEGER, PARAMETER                                 :: ngto = 8
     186             : 
     187             :       CHARACTER(len=2)                                   :: esym
     188             :       INTEGER                                            :: ikind, nkind
     189             :       LOGICAL                                            :: found
     190             :       REAL(KIND=dp)                                      :: al, rco, zeff
     191             :       REAL(KIND=dp), DIMENSION(ngto, 2)                  :: ppdens
     192             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     193             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     194             : 
     195        4668 :       CPASSERT(ASSOCIATED(hirshfeld_env))
     196             : 
     197        4668 :       nkind = SIZE(qs_kind_set)
     198       14004 :       ALLOCATE (hirshfeld_env%kind_shape_fn(nkind))
     199             : 
     200        4668 :       SELECT CASE (hirshfeld_env%shape_function_type)
     201             :       CASE (shape_function_gaussian)
     202       12718 :          DO ikind = 1, nkind
     203        8068 :             hirshfeld_env%kind_shape_fn(ikind)%numexp = 1
     204        8068 :             ALLOCATE (hirshfeld_env%kind_shape_fn(ikind)%zet(1))
     205        8068 :             ALLOCATE (hirshfeld_env%kind_shape_fn(ikind)%coef(1))
     206        8068 :             CALL get_qs_kind(qs_kind_set(ikind), element_symbol=esym)
     207        8068 :             rco = 2.0_dp
     208        8068 :             SELECT CASE (hirshfeld_env%radius_type)
     209             :             CASE (radius_default)
     210           8 :                CALL get_ptable_info(symbol=esym, covalent_radius=rco, found=found)
     211           8 :                rco = MAX(rco, 1.0_dp)
     212             :             CASE (radius_user)
     213           4 :                CPASSERT(PRESENT(radii_list))
     214           4 :                CPASSERT(ASSOCIATED(radii_list))
     215           4 :                CPASSERT(SIZE(radii_list) == nkind)
     216             :                ! Note we assume that radii_list is correctly ordered
     217           4 :                rco = radii_list(ikind)
     218             :             CASE (radius_vdw)
     219         276 :                CALL get_ptable_info(symbol=esym, vdw_radius=rco, found=found)
     220         276 :                IF (.NOT. found) THEN
     221           0 :                   rco = MAX(rco, 1.0_dp)
     222             :                ELSE
     223         276 :                   IF (hirshfeld_env%use_bohr) &
     224           0 :                      rco = cp_unit_to_cp2k(rco, "angstrom")
     225             :                END IF
     226             :             CASE (radius_covalent)
     227        7776 :                CALL get_ptable_info(symbol=esym, covalent_radius=rco, found=found)
     228        7776 :                IF (.NOT. found) THEN
     229           0 :                   rco = MAX(rco, 1.0_dp)
     230             :                ELSE
     231        7776 :                   IF (hirshfeld_env%use_bohr) &
     232           0 :                      rco = cp_unit_to_cp2k(rco, "angstrom")
     233             :                END IF
     234             :             CASE (radius_single)
     235           4 :                CPASSERT(PRESENT(radius))
     236        8064 :                rco = radius
     237             :             END SELECT
     238        8068 :             al = 0.5_dp/rco**2
     239        8068 :             hirshfeld_env%kind_shape_fn(ikind)%zet(1) = al
     240       12718 :             hirshfeld_env%kind_shape_fn(ikind)%coef(1) = (al/pi)**1.5_dp
     241             :          END DO
     242             :       CASE (shape_function_density)
     243             :          ! calculate atomic density
     244          54 :          DO ikind = 1, nkind
     245          36 :             atomic_kind => atomic_kind_set(ikind)
     246          36 :             qs_kind => qs_kind_set(ikind)
     247             :             CALL calculate_atomic_density(ppdens(:, :), atomic_kind, qs_kind, ngto, &
     248          36 :                                           confine=.FALSE.)
     249          36 :             hirshfeld_env%kind_shape_fn(ikind)%numexp = ngto
     250          36 :             ALLOCATE (hirshfeld_env%kind_shape_fn(ikind)%zet(ngto))
     251          36 :             ALLOCATE (hirshfeld_env%kind_shape_fn(ikind)%coef(ngto))
     252         324 :             hirshfeld_env%kind_shape_fn(ikind)%zet(:) = ppdens(:, 1)
     253          36 :             CALL get_qs_kind(qs_kind, zeff=zeff)
     254         342 :             hirshfeld_env%kind_shape_fn(ikind)%coef(:) = ppdens(:, 2)/zeff
     255             :          END DO
     256             : 
     257             :       CASE DEFAULT
     258        4668 :          CPABORT("Unknown shape function")
     259             :       END SELECT
     260             : 
     261        4668 :    END SUBROUTINE create_shape_function
     262             : 
     263             : ! **************************************************************************************************
     264             : !> \brief ...
     265             : !> \param qs_env ...
     266             : !> \param hirshfeld_env ...
     267             : !> \param charges ...
     268             : ! **************************************************************************************************
     269        4464 :    SUBROUTINE comp_hirshfeld_charges(qs_env, hirshfeld_env, charges)
     270             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     271             :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
     272             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(inout)      :: charges
     273             : 
     274             :       INTEGER                                            :: is
     275             :       LOGICAL                                            :: rho_r_valid
     276             :       REAL(KIND=dp)                                      :: tnfun
     277             :       TYPE(pw_env_type), POINTER                         :: pw_env
     278             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     279             :       TYPE(pw_r3d_rs_type)                               :: rhonorm
     280        4464 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
     281             :       TYPE(qs_rho_type), POINTER                         :: rho
     282             : 
     283        4464 :       NULLIFY (rho_r)
     284             :       ! normalization function on grid
     285        4464 :       CALL calculate_hirshfeld_normalization(qs_env, hirshfeld_env)
     286             :       ! check normalization
     287        4464 :       tnfun = pw_integrate_function(hirshfeld_env%fnorm)
     288       23440 :       tnfun = ABS(tnfun - SUM(hirshfeld_env%charges))
     289             :       !
     290        4464 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho=rho)
     291        4464 :       CALL qs_rho_get(rho, rho_r=rho_r, rho_r_valid=rho_r_valid)
     292        4464 :       CALL pw_env_get(pw_env=pw_env, auxbas_pw_pool=auxbas_pw_pool)
     293        4464 :       CALL auxbas_pw_pool%create_pw(rhonorm)
     294             :       ! loop over spins
     295        9680 :       DO is = 1, SIZE(rho_r)
     296        5216 :          IF (rho_r_valid) THEN
     297             :             CALL hfun_scale(rhonorm%array, rho_r(is)%array, &
     298        5216 :                             hirshfeld_env%fnorm%array)
     299             :          ELSE
     300           0 :             CPABORT("We need rho in real space")
     301             :          END IF
     302        5216 :          CALL hirshfeld_integration(qs_env, hirshfeld_env, rhonorm, charges(:, is))
     303       31538 :          charges(:, is) = charges(:, is)*hirshfeld_env%charges(:)
     304             :       END DO
     305        4464 :       CALL auxbas_pw_pool%give_back_pw(rhonorm)
     306             : 
     307        4464 :    END SUBROUTINE comp_hirshfeld_charges
     308             : ! **************************************************************************************************
     309             : !> \brief Calculate fout = fun1/fun2
     310             : !> \param fout ...
     311             : !> \param fun1 ...
     312             : !> \param fun2 ...
     313             : ! **************************************************************************************************
     314        5418 :    SUBROUTINE hfun_scale(fout, fun1, fun2)
     315             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(OUT)     :: fout
     316             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN)      :: fun1, fun2
     317             : 
     318             :       REAL(KIND=dp), PARAMETER                           :: small = 1.0e-12_dp
     319             : 
     320             :       INTEGER                                            :: i1, i2, i3, n1, n2, n3
     321             : 
     322        5418 :       n1 = SIZE(fout, 1)
     323        5418 :       n2 = SIZE(fout, 2)
     324        5418 :       n3 = SIZE(fout, 3)
     325        5418 :       CPASSERT(n1 == SIZE(fun1, 1))
     326        5418 :       CPASSERT(n2 == SIZE(fun1, 2))
     327        5418 :       CPASSERT(n3 == SIZE(fun1, 3))
     328        5418 :       CPASSERT(n1 == SIZE(fun2, 1))
     329        5418 :       CPASSERT(n2 == SIZE(fun2, 2))
     330        5418 :       CPASSERT(n3 == SIZE(fun2, 3))
     331             : 
     332      252450 :       DO i3 = 1, n3
     333    11958084 :          DO i2 = 1, n2
     334   332287670 :             DO i1 = 1, n1
     335   332040638 :                IF (fun2(i1, i2, i3) > small) THEN
     336   108020976 :                   fout(i1, i2, i3) = fun1(i1, i2, i3)/fun2(i1, i2, i3)
     337             :                ELSE
     338   212314028 :                   fout(i1, i2, i3) = 0.0_dp
     339             :                END IF
     340             :             END DO
     341             :          END DO
     342             :       END DO
     343             : 
     344        5418 :    END SUBROUTINE hfun_scale
     345             : 
     346             : ! **************************************************************************************************
     347             : !> \brief ...
     348             : !> \param qs_env ...
     349             : !> \param hirshfeld_env ...
     350             : !> \param charges ...
     351             : !> \param ounit ...
     352             : ! **************************************************************************************************
     353          22 :    SUBROUTINE comp_hirshfeld_i_charges(qs_env, hirshfeld_env, charges, ounit)
     354             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     355             :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
     356             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(inout)      :: charges
     357             :       INTEGER, INTENT(IN)                                :: ounit
     358             : 
     359             :       INTEGER, PARAMETER                                 :: maxloop = 100
     360             :       REAL(KIND=dp), PARAMETER                           :: maxres = 1.0e-2_dp
     361             : 
     362             :       CHARACTER(len=3)                                   :: yesno
     363             :       INTEGER                                            :: iat, iloop, is, natom
     364             :       LOGICAL                                            :: rho_r_valid
     365             :       REAL(KIND=dp)                                      :: res, tnfun
     366             :       TYPE(pw_env_type), POINTER                         :: pw_env
     367             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     368             :       TYPE(pw_r3d_rs_type)                               :: rhonorm
     369          22 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
     370             :       TYPE(qs_rho_type), POINTER                         :: rho
     371             : 
     372          22 :       NULLIFY (rho_r)
     373             : 
     374          22 :       natom = SIZE(charges, 1)
     375             : 
     376          11 :       IF (ounit > 0) WRITE (ounit, "(/,T2,A)") "Hirshfeld charge iterations: Residuals ..."
     377             :       !
     378          22 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, rho=rho)
     379          22 :       CALL qs_rho_get(rho, rho_r=rho_r, rho_r_valid=rho_r_valid)
     380          22 :       CALL pw_env_get(pw_env=pw_env, auxbas_pw_pool=auxbas_pw_pool)
     381          22 :       CALL auxbas_pw_pool%create_pw(rhonorm)
     382             :       !
     383         130 :       DO iloop = 1, maxloop
     384             : 
     385             :          ! normalization function on grid
     386         130 :          CALL calculate_hirshfeld_normalization(qs_env, hirshfeld_env)
     387             :          ! check normalization
     388         130 :          tnfun = pw_integrate_function(hirshfeld_env%fnorm)
     389         520 :          tnfun = ABS(tnfun - SUM(hirshfeld_env%charges))
     390             :          ! loop over spins
     391         332 :          DO is = 1, SIZE(rho_r)
     392         202 :             IF (rho_r_valid) THEN
     393             :                CALL hfun_scale(rhonorm%array, rho_r(is)%array, &
     394         202 :                                hirshfeld_env%fnorm%array)
     395             :             ELSE
     396           0 :                CPABORT("We need rho in real space")
     397             :             END IF
     398         202 :             CALL hirshfeld_integration(qs_env, hirshfeld_env, rhonorm, charges(:, is))
     399         938 :             charges(:, is) = charges(:, is)*hirshfeld_env%charges(:)
     400             :          END DO
     401             :          ! residual
     402         130 :          res = 0.0_dp
     403         520 :          DO iat = 1, natom
     404        1126 :             res = res + (SUM(charges(iat, :)) - hirshfeld_env%charges(iat))**2
     405             :          END DO
     406         130 :          res = SQRT(res/REAL(natom, KIND=dp))
     407         130 :          IF (ounit > 0) THEN
     408          65 :             yesno = "NO "
     409          65 :             IF (MOD(iloop, 10) == 0) yesno = "YES"
     410          65 :             WRITE (ounit, FMT="(F8.3)", ADVANCE=yesno) res
     411             :          END IF
     412             :          ! update
     413         520 :          DO iat = 1, natom
     414        1126 :             hirshfeld_env%charges(iat) = SUM(charges(iat, :))
     415             :          END DO
     416         130 :          IF (res < maxres) EXIT
     417             : 
     418             :       END DO
     419             :       !
     420          22 :       CALL auxbas_pw_pool%give_back_pw(rhonorm)
     421             : 
     422          22 :    END SUBROUTINE comp_hirshfeld_i_charges
     423             : 
     424             : ! **************************************************************************************************
     425             : !> \brief ...
     426             : !> \param qs_env ...
     427             : !> \param hirshfeld_env ...
     428             : ! **************************************************************************************************
     429        4594 :    SUBROUTINE calculate_hirshfeld_normalization(qs_env, hirshfeld_env)
     430             : 
     431             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     432             :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
     433             : 
     434             :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_hirshfeld_normalization'
     435             : 
     436             :       INTEGER                                            :: atom_a, handle, iatom, iex, ikind, &
     437             :                                                             ithread, j, natom, npme, nthread, &
     438             :                                                             numexp, subpatch_pattern
     439        4594 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list, cores
     440             :       REAL(KIND=dp)                                      :: alpha, coef, eps_rho_rspace, radius
     441             :       REAL(KIND=dp), DIMENSION(3)                        :: ra
     442        4594 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: pab
     443        4594 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     444             :       TYPE(cell_type), POINTER                           :: cell
     445             :       TYPE(dft_control_type), POINTER                    :: dft_control
     446        4594 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     447             :       TYPE(pw_env_type), POINTER                         :: pw_env
     448             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     449             :       TYPE(pw_r3d_rs_type), POINTER                      :: fnorm
     450             :       TYPE(realspace_grid_desc_type), POINTER            :: auxbas_rs_desc
     451             :       TYPE(realspace_grid_type), POINTER                 :: rs_rho
     452             : 
     453        4594 :       CALL timeset(routineN, handle)
     454             : 
     455             :       CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, cell=cell, &
     456        4594 :                       dft_control=dft_control, particle_set=particle_set, pw_env=pw_env)
     457             :       CALL pw_env_get(pw_env, auxbas_rs_desc=auxbas_rs_desc, auxbas_rs_grid=rs_rho, &
     458        4594 :                       auxbas_pw_pool=auxbas_pw_pool)
     459             :       ! be careful in parallel nsmax is chosen with multigrid in mind!
     460        4594 :       CALL rs_grid_zero(rs_rho)
     461             : 
     462        4594 :       eps_rho_rspace = dft_control%qs_control%eps_rho_rspace
     463        4594 :       ALLOCATE (pab(1, 1))
     464        4594 :       nthread = 1
     465        4594 :       ithread = 0
     466             : 
     467       12582 :       DO ikind = 1, SIZE(atomic_kind_set)
     468        7988 :          numexp = hirshfeld_env%kind_shape_fn(ikind)%numexp
     469        7988 :          IF (numexp <= 0) CYCLE
     470        7988 :          CALL get_atomic_kind(atomic_kind_set(ikind), natom=natom, atom_list=atom_list)
     471       23964 :          ALLOCATE (cores(natom))
     472             : 
     473       17152 :          DO iex = 1, numexp
     474        9164 :             alpha = hirshfeld_env%kind_shape_fn(ikind)%zet(iex)
     475        9164 :             coef = hirshfeld_env%kind_shape_fn(ikind)%coef(iex)
     476        9164 :             npme = 0
     477       30294 :             cores = 0
     478       30294 :             DO iatom = 1, natom
     479       21130 :                atom_a = atom_list(iatom)
     480       21130 :                ra(:) = pbc(particle_set(atom_a)%r, cell)
     481       30294 :                IF (rs_rho%desc%parallel .AND. .NOT. rs_rho%desc%distributed) THEN
     482             :                   ! replicated realspace grid, split the atoms up between procs
     483       20972 :                   IF (MODULO(iatom, rs_rho%desc%group_size) == rs_rho%desc%my_pos) THEN
     484       10486 :                      npme = npme + 1
     485       10486 :                      cores(npme) = iatom
     486             :                   END IF
     487             :                ELSE
     488         158 :                   npme = npme + 1
     489         158 :                   cores(npme) = iatom
     490             :                END IF
     491             :             END DO
     492       27796 :             DO j = 1, npme
     493       10644 :                iatom = cores(j)
     494       10644 :                atom_a = atom_list(iatom)
     495       10644 :                pab(1, 1) = hirshfeld_env%charges(atom_a)*coef
     496       10644 :                ra(:) = pbc(particle_set(atom_a)%r, cell)
     497       10644 :                subpatch_pattern = 0
     498             :                radius = exp_radius_very_extended(la_min=0, la_max=0, lb_min=0, lb_max=0, &
     499             :                                                  ra=ra, rb=ra, rp=ra, zetp=alpha, eps=eps_rho_rspace, &
     500             :                                                  pab=pab, o1=0, o2=0, &  ! without map_consistent
     501       10644 :                                                  prefactor=1.0_dp, cutoff=0.0_dp)
     502             : 
     503             :                ! la_max==0 so set lmax_global to 0
     504             :                CALL collocate_pgf_product(0, alpha, 0, 0, 0.0_dp, 0, ra, &
     505             :                                           (/0.0_dp, 0.0_dp, 0.0_dp/), 1.0_dp, pab, 0, 0, rs_rho, &
     506             :                                           radius=radius, ga_gb_function=GRID_FUNC_AB, &
     507       19808 :                                           use_subpatch=.TRUE., subpatch_pattern=subpatch_pattern)
     508             :             END DO
     509             :          END DO
     510             : 
     511       20570 :          DEALLOCATE (cores)
     512             :       END DO
     513        4594 :       DEALLOCATE (pab)
     514             : 
     515        4594 :       NULLIFY (fnorm)
     516        4594 :       CALL get_hirshfeld_info(hirshfeld_env, fnorm=fnorm)
     517        4594 :       IF (ASSOCIATED(fnorm)) THEN
     518         108 :          CALL fnorm%release()
     519         108 :          DEALLOCATE (fnorm)
     520             :       END IF
     521        4594 :       ALLOCATE (fnorm)
     522        4594 :       CALL auxbas_pw_pool%create_pw(fnorm)
     523        4594 :       CALL set_hirshfeld_info(hirshfeld_env, fnorm=fnorm)
     524             : 
     525        4594 :       CALL transfer_rs2pw(rs_rho, fnorm)
     526             : 
     527        4594 :       CALL timestop(handle)
     528             : 
     529        4594 :    END SUBROUTINE calculate_hirshfeld_normalization
     530             : 
     531             : ! **************************************************************************************************
     532             : !> \brief ...
     533             : !> \param qs_env ...
     534             : !> \param hirshfeld_env ...
     535             : !> \param rfun ...
     536             : !> \param fval ...
     537             : !> \param fderiv ...
     538             : ! **************************************************************************************************
     539        5418 :    SUBROUTINE hirshfeld_integration(qs_env, hirshfeld_env, rfun, fval, fderiv)
     540             : 
     541             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     542             :       TYPE(hirshfeld_type), POINTER                      :: hirshfeld_env
     543             :       TYPE(pw_r3d_rs_type)                               :: rfun
     544             :       REAL(KIND=dp), DIMENSION(:), INTENT(inout)         :: fval
     545             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(inout), &
     546             :          OPTIONAL                                        :: fderiv
     547             : 
     548             :       CHARACTER(len=*), PARAMETER :: routineN = 'hirshfeld_integration'
     549             : 
     550             :       INTEGER                                            :: atom_a, handle, iatom, iex, ikind, &
     551             :                                                             ithread, j, natom, npme, nthread, &
     552             :                                                             numexp
     553        5418 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: cores
     554        5418 :       INTEGER, DIMENSION(:), POINTER                     :: atom_list
     555             :       LOGICAL                                            :: do_force
     556             :       REAL(KIND=dp)                                      :: alpha, coef, dvol, eps_rho_rspace, radius
     557             :       REAL(KIND=dp), DIMENSION(3)                        :: force_a, force_b, ra
     558        5418 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: hab, pab
     559        5418 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     560             :       TYPE(cell_type), POINTER                           :: cell
     561             :       TYPE(dft_control_type), POINTER                    :: dft_control
     562             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     563        5418 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     564             :       TYPE(pw_env_type), POINTER                         :: pw_env
     565             :       TYPE(realspace_grid_desc_type), POINTER            :: auxbas_rs_desc
     566             :       TYPE(realspace_grid_type), POINTER                 :: rs_v
     567             : 
     568        5418 :       CALL timeset(routineN, handle)
     569             : 
     570        5418 :       do_force = PRESENT(fderiv)
     571       27882 :       fval = 0.0_dp
     572        5418 :       dvol = rfun%pw_grid%dvol
     573             : 
     574        5418 :       NULLIFY (pw_env, auxbas_rs_desc)
     575        5418 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
     576             :       CALL pw_env_get(pw_env=pw_env, auxbas_rs_desc=auxbas_rs_desc, &
     577        5418 :                       auxbas_rs_grid=rs_v)
     578        5418 :       CALL transfer_pw2rs(rs_v, rfun)
     579             : 
     580             :       CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, cell=cell, &
     581        5418 :                       dft_control=dft_control, particle_set=particle_set)
     582        5418 :       eps_rho_rspace = dft_control%qs_control%eps_rho_rspace
     583             : 
     584        5418 :       nthread = 1
     585        5418 :       ithread = 0
     586        5418 :       ALLOCATE (hab(1, 1), pab(1, 1))
     587             : 
     588       14712 :       DO ikind = 1, SIZE(atomic_kind_set)
     589        9294 :          numexp = hirshfeld_env%kind_shape_fn(ikind)%numexp
     590        9294 :          IF (numexp <= 0) CYCLE
     591        9294 :          CALL get_atomic_kind(atomic_kind_set(ikind), natom=natom, atom_list=atom_list)
     592       27882 :          ALLOCATE (cores(natom))
     593             : 
     594       20520 :          DO iex = 1, numexp
     595       11226 :             alpha = hirshfeld_env%kind_shape_fn(ikind)%zet(iex)
     596       11226 :             coef = hirshfeld_env%kind_shape_fn(ikind)%coef(iex)
     597       11226 :             npme = 0
     598       36588 :             cores = 0
     599       36588 :             DO iatom = 1, natom
     600       25362 :                atom_a = atom_list(iatom)
     601       25362 :                ra(:) = pbc(particle_set(atom_a)%r, cell)
     602       36588 :                IF (rs_v%desc%parallel .AND. .NOT. rs_v%desc%distributed) THEN
     603             :                   ! replicated realspace grid, split the atoms up between procs
     604       25204 :                   IF (MODULO(iatom, rs_v%desc%group_size) == rs_v%desc%my_pos) THEN
     605       12602 :                      npme = npme + 1
     606       12602 :                      cores(npme) = iatom
     607             :                   END IF
     608             :                ELSE
     609         158 :                   npme = npme + 1
     610         158 :                   cores(npme) = iatom
     611             :                END IF
     612             :             END DO
     613             : 
     614       33280 :             DO j = 1, npme
     615       12760 :                iatom = cores(j)
     616       12760 :                atom_a = atom_list(iatom)
     617       12760 :                ra(:) = pbc(particle_set(atom_a)%r, cell)
     618       12760 :                pab(1, 1) = coef
     619       12760 :                hab(1, 1) = 0.0_dp
     620       12760 :                force_a(:) = 0.0_dp
     621       12760 :                force_b(:) = 0.0_dp
     622             : 
     623             :                radius = exp_radius_very_extended(la_min=0, la_max=0, lb_min=0, lb_max=0, &
     624             :                                                  ra=ra, rb=ra, rp=ra, &
     625             :                                                  zetp=alpha, eps=eps_rho_rspace, &
     626             :                                                  pab=pab, o1=0, o2=0, &  ! without map_consistent
     627       12760 :                                                  prefactor=1.0_dp, cutoff=1.0_dp)
     628             : 
     629             :                CALL integrate_pgf_product(0, alpha, 0, &
     630             :                                           0, 0.0_dp, 0, ra, (/0.0_dp, 0.0_dp, 0.0_dp/), &
     631             :                                           rs_v, hab, pab=pab, o1=0, o2=0, &
     632             :                                           radius=radius, calculate_forces=do_force, &
     633             :                                           force_a=force_a, force_b=force_b, use_virial=.FALSE., &
     634       12760 :                                           use_subpatch=.TRUE., subpatch_pattern=0)
     635       12760 :                fval(atom_a) = fval(atom_a) + hab(1, 1)*dvol*coef
     636       23986 :                IF (do_force) THEN
     637           0 :                   fderiv(:, atom_a) = fderiv(:, atom_a) + force_a(:)*dvol
     638             :                END IF
     639             :             END DO
     640             : 
     641             :          END DO
     642       24006 :          DEALLOCATE (cores)
     643             : 
     644             :       END DO
     645             : 
     646        5418 :       DEALLOCATE (hab, pab)
     647             : 
     648        5418 :       CALL get_qs_env(qs_env=qs_env, para_env=para_env)
     649       50346 :       CALL para_env%sum(fval)
     650             : 
     651        5418 :       CALL timestop(handle)
     652             : 
     653       10836 :    END SUBROUTINE hirshfeld_integration
     654             : 
     655             : END MODULE hirshfeld_methods

Generated by: LCOV version 1.15