LCOV - code coverage report
Current view: top level - src - hfx_pw_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 94 95 98.9 %
Date: 2024-12-21 06:28:57 Functions: 1 1 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 Test routines for HFX caclulations using PW
      10             : !>
      11             : !>
      12             : !> \par History
      13             : !>     refactoring 03-2011 [MI]
      14             : !>     Made GAPW compatible 12.2019 (A. Bussy)
      15             : !>     Refactored from hfx_admm_utils (JGH)
      16             : !> \author MI
      17             : ! **************************************************************************************************
      18             : MODULE hfx_pw_methods
      19             :    USE atomic_kind_types,               ONLY: atomic_kind_type
      20             :    USE cell_types,                      ONLY: cell_type
      21             :    USE cp_control_types,                ONLY: dft_control_type
      22             :    USE cp_dbcsr_api,                    ONLY: dbcsr_type
      23             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm
      24             :    USE cp_fm_types,                     ONLY: cp_fm_get_info,&
      25             :                                               cp_fm_type
      26             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      27             :                                               cp_logger_type
      28             :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      29             :                                               cp_print_key_unit_nr
      30             :    USE input_constants,                 ONLY: do_potential_coulomb,&
      31             :                                               do_potential_short,&
      32             :                                               do_potential_truncated
      33             :    USE input_section_types,             ONLY: section_vals_get,&
      34             :                                               section_vals_get_subs_vals,&
      35             :                                               section_vals_type,&
      36             :                                               section_vals_val_get
      37             :    USE kinds,                           ONLY: dp
      38             :    USE mathconstants,                   ONLY: fourpi
      39             :    USE particle_types,                  ONLY: particle_type
      40             :    USE pw_env_types,                    ONLY: pw_env_type
      41             :    USE pw_grid_types,                   ONLY: pw_grid_type
      42             :    USE pw_methods,                      ONLY: pw_copy,&
      43             :                                               pw_multiply,&
      44             :                                               pw_transfer,&
      45             :                                               pw_zero
      46             :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      47             :    USE pw_poisson_types,                ONLY: pw_poisson_type
      48             :    USE pw_pool_types,                   ONLY: pw_pool_type
      49             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      50             :                                               pw_r3d_rs_type
      51             :    USE qs_collocate_density,            ONLY: calculate_wavefunction
      52             :    USE qs_environment_types,            ONLY: get_qs_env,&
      53             :                                               qs_environment_type
      54             :    USE qs_kind_types,                   ONLY: qs_kind_type
      55             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      56             :                                               mo_set_type
      57             : #include "./base/base_uses.f90"
      58             : 
      59             :    IMPLICIT NONE
      60             : 
      61             :    PRIVATE
      62             : 
      63             :    ! *** Public subroutines ***
      64             :    PUBLIC :: pw_hfx
      65             : 
      66             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'hfx_pw_methods'
      67             : 
      68             : CONTAINS
      69             : 
      70             : ! **************************************************************************************************
      71             : !> \brief computes the Hartree-Fock energy brute force in a pw basis
      72             : !> \param qs_env ...
      73             : !> \param ehfx ...
      74             : !> \param hfx_section ...
      75             : !> \param poisson_env ...
      76             : !> \param auxbas_pw_pool ...
      77             : !> \param irep ...
      78             : !> \par History
      79             : !>      12.2007 created [Joost VandeVondele]
      80             : !> \note
      81             : !>      only computes the HFX energy, no derivatives as yet
      82             : ! **************************************************************************************************
      83       23162 :    SUBROUTINE pw_hfx(qs_env, ehfx, hfx_section, poisson_env, auxbas_pw_pool, irep)
      84             :       TYPE(qs_environment_type), POINTER                 :: qs_env
      85             :       REAL(KIND=dp), INTENT(IN)                          :: ehfx
      86             :       TYPE(section_vals_type), POINTER                   :: hfx_section
      87             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
      88             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
      89             :       INTEGER                                            :: irep
      90             : 
      91             :       CHARACTER(*), PARAMETER                            :: routineN = 'pw_hfx'
      92             : 
      93             :       INTEGER                                            :: blocksize, handle, ig, iloc, iorb, &
      94             :                                                             iorb_block, ispin, iw, jloc, jorb, &
      95             :                                                             jorb_block, norb, potential_type
      96             :       LOGICAL                                            :: do_kpoints, do_pw_hfx, explicit
      97             :       REAL(KIND=dp)                                      :: exchange_energy, fraction, g2, g3d, gg, &
      98             :                                                             omega, pair_energy, rcut, scaling
      99       23162 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     100             :       TYPE(cell_type), POINTER                           :: cell
     101             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     102             :       TYPE(cp_logger_type), POINTER                      :: logger
     103             :       TYPE(dbcsr_type), POINTER                          :: mo_coeff_b
     104             :       TYPE(dft_control_type), POINTER                    :: dft_control
     105       23162 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mo_array
     106       23162 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     107             :       TYPE(pw_c1d_gs_type)                               :: greenfn, pot_g, rho_g
     108             :       TYPE(pw_env_type), POINTER                         :: pw_env
     109             :       TYPE(pw_grid_type), POINTER                        :: grid
     110             :       TYPE(pw_r3d_rs_type)                               :: rho_r
     111       23162 :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: rho_i, rho_j
     112       23162 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     113             :       TYPE(section_vals_type), POINTER                   :: ip_section
     114             : 
     115       23162 :       CALL timeset(routineN, handle)
     116       23162 :       logger => cp_get_default_logger()
     117             : 
     118       23162 :       CALL section_vals_val_get(hfx_section, "PW_HFX", l_val=do_pw_hfx, i_rep_section=irep)
     119             : 
     120       23162 :       IF (do_pw_hfx) THEN
     121          20 :          CALL section_vals_val_get(hfx_section, "FRACTION", r_val=fraction)
     122          20 :          CALL section_vals_val_get(hfx_section, "PW_HFX_BLOCKSIZE", i_val=blocksize)
     123             : 
     124             :          CALL get_qs_env(qs_env, mos=mo_array, pw_env=pw_env, dft_control=dft_control, &
     125             :                          cell=cell, particle_set=particle_set, do_kpoints=do_kpoints, &
     126          20 :                          atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set)
     127          20 :          IF (do_kpoints) CPABORT("PW HFX not implemented with K-points")
     128             : 
     129             :          ! limit the blocksize by the number of orbitals
     130          20 :          CALL get_mo_set(mo_set=mo_array(1), mo_coeff=mo_coeff)
     131          20 :          CALL cp_fm_get_info(mo_coeff, ncol_global=norb)
     132          20 :          blocksize = MAX(1, MIN(blocksize, norb))
     133             : 
     134          20 :          CALL auxbas_pw_pool%create_pw(rho_r)
     135          20 :          CALL auxbas_pw_pool%create_pw(rho_g)
     136          20 :          CALL auxbas_pw_pool%create_pw(pot_g)
     137             : 
     138         134 :          ALLOCATE (rho_i(blocksize))
     139         114 :          ALLOCATE (rho_j(blocksize))
     140             : 
     141          20 :          CALL auxbas_pw_pool%create_pw(greenfn)
     142          20 :          ip_section => section_vals_get_subs_vals(hfx_section, "INTERACTION_POTENTIAL")
     143          20 :          CALL section_vals_get(ip_section, explicit=explicit)
     144          20 :          potential_type = do_potential_coulomb
     145          20 :          IF (explicit) THEN
     146          14 :             CALL section_vals_val_get(ip_section, "POTENTIAL_TYPE", i_val=potential_type)
     147             :          END IF
     148          20 :          IF (potential_type == do_potential_coulomb) THEN
     149           8 :             CALL pw_copy(poisson_env%green_fft%influence_fn, greenfn)
     150          12 :          ELSEIF (potential_type == do_potential_truncated) THEN
     151           6 :             CALL section_vals_val_get(ip_section, "CUTOFF_RADIUS", r_val=rcut)
     152           6 :             grid => poisson_env%green_fft%influence_fn%pw_grid
     153     1119747 :             DO ig = grid%first_gne0, grid%ngpts_cut_local
     154     1119741 :                g2 = grid%gsq(ig)
     155     1119741 :                gg = SQRT(g2)
     156     1119741 :                g3d = fourpi/g2
     157     1119747 :                greenfn%array(ig) = g3d*(1.0_dp - COS(rcut*gg))
     158             :             END DO
     159           6 :             IF (grid%have_g0) &
     160           3 :                greenfn%array(1) = 0.5_dp*fourpi*rcut*rcut
     161           6 :          ELSEIF (potential_type == do_potential_short) THEN
     162           6 :             CALL section_vals_val_get(ip_section, "OMEGA", r_val=omega)
     163           6 :             IF (omega > 0.0_dp) omega = 0.25_dp/(omega*omega)
     164           6 :             grid => poisson_env%green_fft%influence_fn%pw_grid
     165     1119747 :             DO ig = grid%first_gne0, grid%ngpts_cut_local
     166     1119741 :                g2 = grid%gsq(ig)
     167     1119741 :                gg = -omega*g2
     168     1119741 :                g3d = fourpi/g2
     169     1119747 :                greenfn%array(ig) = g3d*(1.0_dp - EXP(gg))
     170             :             END DO
     171           6 :             IF (grid%have_g0) greenfn%array(1) = 0.0_dp
     172             :          ELSE
     173           0 :             CPWARN("PW_SCF: Potential type not supported, calculation uses Coulomb potential.")
     174             :          END IF
     175             : 
     176          94 :          DO iorb_block = 1, blocksize
     177          74 :             CALL rho_i(iorb_block)%create(rho_r%pw_grid)
     178          94 :             CALL rho_j(iorb_block)%create(rho_r%pw_grid)
     179             :          END DO
     180             : 
     181          20 :          exchange_energy = 0.0_dp
     182             : 
     183          40 :          DO ispin = 1, SIZE(mo_array)
     184          20 :             CALL get_mo_set(mo_set=mo_array(ispin), mo_coeff=mo_coeff, mo_coeff_b=mo_coeff_b)
     185             : 
     186          20 :             IF (mo_array(ispin)%use_mo_coeff_b) THEN !fm->dbcsr
     187          20 :                CALL copy_dbcsr_to_fm(mo_coeff_b, mo_coeff) !fm->dbcsr
     188             :             END IF !fm->dbcsr
     189             : 
     190          20 :             CALL cp_fm_get_info(mo_coeff, ncol_global=norb)
     191             : 
     192          60 :             DO iorb_block = 1, norb, blocksize
     193             : 
     194          94 :                DO iorb = iorb_block, MIN(iorb_block + blocksize - 1, norb)
     195             : 
     196          74 :                   iloc = iorb - iorb_block + 1
     197             :                   CALL calculate_wavefunction(mo_coeff, iorb, rho_i(iloc), rho_g, &
     198             :                                               atomic_kind_set, qs_kind_set, cell, dft_control, particle_set, &
     199          94 :                                               pw_env)
     200             : 
     201             :                END DO
     202             : 
     203          60 :                DO jorb_block = iorb_block, norb, blocksize
     204             : 
     205          94 :                   DO jorb = jorb_block, MIN(jorb_block + blocksize - 1, norb)
     206             : 
     207          74 :                      jloc = jorb - jorb_block + 1
     208             :                      CALL calculate_wavefunction(mo_coeff, jorb, rho_j(jloc), rho_g, &
     209             :                                                  atomic_kind_set, qs_kind_set, cell, dft_control, particle_set, &
     210          94 :                                                  pw_env)
     211             : 
     212             :                   END DO
     213             : 
     214         114 :                   DO iorb = iorb_block, MIN(iorb_block + blocksize - 1, norb)
     215          74 :                      iloc = iorb - iorb_block + 1
     216         384 :                      DO jorb = jorb_block, MIN(jorb_block + blocksize - 1, norb)
     217         290 :                         jloc = jorb - jorb_block + 1
     218         290 :                         IF (jorb < iorb) CYCLE
     219             : 
     220             :                         ! compute the pair density
     221         182 :                         CALL pw_zero(rho_r)
     222         182 :                         CALL pw_multiply(rho_r, rho_i(iloc), rho_j(jloc))
     223             : 
     224             :                         ! go the g-space and compute hartree energy
     225         182 :                         CALL pw_transfer(rho_r, rho_g)
     226             :                         CALL pw_poisson_solve(poisson_env, rho_g, pair_energy, pot_g, &
     227         182 :                                               greenfn=greenfn)
     228             : 
     229             :                         ! sum up to the full energy
     230         182 :                         scaling = fraction
     231         182 :                         IF (SIZE(mo_array) == 1) scaling = scaling*2.0_dp
     232         182 :                         IF (iorb /= jorb) scaling = scaling*2.0_dp
     233             : 
     234         546 :                         exchange_energy = exchange_energy - scaling*pair_energy
     235             : 
     236             :                      END DO
     237             :                   END DO
     238             : 
     239             :                END DO
     240             :             END DO
     241             :          END DO
     242             : 
     243          94 :          DO iorb_block = 1, blocksize
     244          74 :             CALL rho_i(iorb_block)%release()
     245          94 :             CALL rho_j(iorb_block)%release()
     246             :          END DO
     247             : 
     248          20 :          CALL auxbas_pw_pool%give_back_pw(rho_r)
     249          20 :          CALL auxbas_pw_pool%give_back_pw(rho_g)
     250          20 :          CALL auxbas_pw_pool%give_back_pw(pot_g)
     251          20 :          CALL auxbas_pw_pool%give_back_pw(greenfn)
     252             : 
     253             :          iw = cp_print_key_unit_nr(logger, hfx_section, "HF_INFO", &
     254          20 :                                    extension=".scfLog")
     255             : 
     256          20 :          IF (iw > 0) THEN
     257             :             WRITE (UNIT=iw, FMT="((T3,A,T61,F20.10))") &
     258          10 :                "HF_PW_HFX| PW exchange energy:", exchange_energy
     259             :             WRITE (UNIT=iw, FMT="((T3,A,T61,F20.10),/)") &
     260          10 :                "HF_PW_HFX| Gaussian exchange energy:", ehfx
     261             :          END IF
     262             : 
     263          80 :          CALL cp_print_key_finished_output(iw, logger, hfx_section, "HF_INFO")
     264             : 
     265             :       END IF
     266             : 
     267       23162 :       CALL timestop(handle)
     268             : 
     269       46324 :    END SUBROUTINE pw_hfx
     270             : 
     271             : END MODULE hfx_pw_methods

Generated by: LCOV version 1.15