LCOV - code coverage report
Current view: top level - src - qs_local_properties.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:9843133) Lines: 93 96 96.9 %
Date: 2024-05-10 06:53:45 Functions: 2 2 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 Routines for calculating local energy and stress tensor
      10             : !> \author JGH
      11             : !> \par History
      12             : !>      - 07.2019 created
      13             : ! **************************************************************************************************
      14             : MODULE qs_local_properties
      15             :    USE bibliography,                    ONLY: Cohen2000,&
      16             :                                               Filippetti2000,&
      17             :                                               Rogers2002,&
      18             :                                               cite_reference
      19             :    USE cp_control_types,                ONLY: dft_control_type
      20             :    USE cp_dbcsr_operations,             ONLY: dbcsr_allocate_matrix_set
      21             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      22             :                                               cp_logger_get_default_io_unit,&
      23             :                                               cp_logger_type
      24             :    USE dbcsr_api,                       ONLY: dbcsr_copy,&
      25             :                                               dbcsr_p_type,&
      26             :                                               dbcsr_set,&
      27             :                                               dbcsr_type
      28             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      29             :                                               section_vals_type
      30             :    USE kinds,                           ONLY: dp
      31             :    USE mathlib,                         ONLY: det_3x3
      32             :    USE pw_env_types,                    ONLY: pw_env_get,&
      33             :                                               pw_env_type
      34             :    USE pw_methods,                      ONLY: pw_axpy,&
      35             :                                               pw_copy,&
      36             :                                               pw_derive,&
      37             :                                               pw_integrate_function,&
      38             :                                               pw_multiply,&
      39             :                                               pw_transfer,&
      40             :                                               pw_zero
      41             :    USE pw_pool_types,                   ONLY: pw_pool_type
      42             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      43             :                                               pw_r3d_rs_type
      44             :    USE qs_collocate_density,            ONLY: calculate_rho_elec
      45             :    USE qs_core_energies,                ONLY: calculate_ptrace
      46             :    USE qs_energy_matrix_w,              ONLY: qs_energies_compute_w
      47             :    USE qs_energy_types,                 ONLY: qs_energy_type
      48             :    USE qs_environment_types,            ONLY: get_qs_env,&
      49             :                                               qs_environment_type
      50             :    USE qs_ks_methods,                   ONLY: calc_rho_tot_gspace
      51             :    USE qs_ks_types,                     ONLY: qs_ks_env_type,&
      52             :                                               set_ks_env
      53             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      54             :                                               qs_rho_type
      55             :    USE qs_vxc,                          ONLY: qs_xc_density
      56             :    USE virial_types,                    ONLY: virial_type
      57             : #include "./base/base_uses.f90"
      58             : 
      59             :    IMPLICIT NONE
      60             : 
      61             :    PRIVATE
      62             : 
      63             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_local_properties'
      64             : 
      65             :    PUBLIC :: qs_local_energy, qs_local_stress
      66             : 
      67             : ! **************************************************************************************************
      68             : 
      69             : CONTAINS
      70             : 
      71             : ! **************************************************************************************************
      72             : !> \brief Routine to calculate the local energy
      73             : !> \param qs_env the qs_env to update
      74             : !> \param energy_density ...
      75             : !> \par History
      76             : !>      07.2019 created
      77             : !> \author JGH
      78             : ! **************************************************************************************************
      79          64 :    SUBROUTINE qs_local_energy(qs_env, energy_density)
      80             :       TYPE(qs_environment_type), POINTER                 :: qs_env
      81             :       TYPE(pw_r3d_rs_type), INTENT(INOUT)                :: energy_density
      82             : 
      83             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_local_energy'
      84             : 
      85             :       INTEGER                                            :: handle, img, iounit, ispin, nimages, &
      86             :                                                             nkind, nspins
      87             :       LOGICAL                                            :: gapw, gapw_xc
      88             :       REAL(KIND=dp)                                      :: eban, eband, eh, exc, ovol
      89             :       TYPE(cp_logger_type), POINTER                      :: logger
      90          32 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao
      91          32 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s, matrix_w, rho_ao_kp
      92             :       TYPE(dbcsr_type), POINTER                          :: matrix
      93             :       TYPE(dft_control_type), POINTER                    :: dft_control
      94             :       TYPE(pw_c1d_gs_type)                               :: edens_g
      95             :       TYPE(pw_c1d_gs_type), POINTER                      :: rho_core, rho_tot_gspace
      96             :       TYPE(pw_env_type), POINTER                         :: pw_env
      97             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
      98             :       TYPE(pw_r3d_rs_type)                               :: band_density, edens_r, hartree_density, &
      99             :                                                             xc_density
     100          32 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
     101             :       TYPE(pw_r3d_rs_type), POINTER                      :: rho_tot_rspace, v_hartree_rspace
     102             :       TYPE(qs_energy_type), POINTER                      :: energy
     103             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     104             :       TYPE(qs_rho_type), POINTER                         :: rho, rho_struct
     105             :       TYPE(section_vals_type), POINTER                   :: input, xc_section
     106             : 
     107          32 :       CALL timeset(routineN, handle)
     108             : 
     109          32 :       CALL cite_reference(Cohen2000)
     110             : 
     111          32 :       CPASSERT(ASSOCIATED(qs_env))
     112          32 :       logger => cp_get_default_logger()
     113          32 :       iounit = cp_logger_get_default_io_unit()
     114             : 
     115             :       ! Check for GAPW method : additional terms for local densities
     116          32 :       CALL get_qs_env(qs_env, nkind=nkind, dft_control=dft_control)
     117          32 :       gapw = dft_control%qs_control%gapw
     118          32 :       gapw_xc = dft_control%qs_control%gapw_xc
     119             : 
     120          32 :       nimages = dft_control%nimages
     121          32 :       nspins = dft_control%nspins
     122             : 
     123             :       ! get working arrays
     124          32 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
     125          32 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     126          32 :       CALL auxbas_pw_pool%create_pw(band_density)
     127          32 :       CALL auxbas_pw_pool%create_pw(hartree_density)
     128          32 :       CALL auxbas_pw_pool%create_pw(xc_density)
     129             : 
     130             :       ! w matrix
     131          32 :       CALL get_qs_env(qs_env, matrix_w_kp=matrix_w)
     132          32 :       IF (.NOT. ASSOCIATED(matrix_w)) THEN
     133             :          CALL get_qs_env(qs_env, &
     134             :                          ks_env=ks_env, &
     135           2 :                          matrix_s_kp=matrix_s)
     136           2 :          matrix => matrix_s(1, 1)%matrix
     137           2 :          CALL dbcsr_allocate_matrix_set(matrix_w, nspins, nimages)
     138           4 :          DO ispin = 1, nspins
     139           6 :             DO img = 1, nimages
     140           2 :                ALLOCATE (matrix_w(ispin, img)%matrix)
     141           2 :                CALL dbcsr_copy(matrix_w(ispin, img)%matrix, matrix, name="W MATRIX")
     142           4 :                CALL dbcsr_set(matrix_w(ispin, img)%matrix, 0.0_dp)
     143             :             END DO
     144             :          END DO
     145           2 :          CALL set_ks_env(ks_env, matrix_w_kp=matrix_w)
     146             :       END IF
     147             :       ! band structure energy density
     148          32 :       CALL qs_energies_compute_w(qs_env, .TRUE.)
     149          32 :       CALL get_qs_env(qs_env, ks_env=ks_env, matrix_w_kp=matrix_w)
     150          32 :       CALL auxbas_pw_pool%create_pw(edens_r)
     151          32 :       CALL auxbas_pw_pool%create_pw(edens_g)
     152          32 :       CALL pw_zero(band_density)
     153          64 :       DO ispin = 1, nspins
     154          32 :          rho_ao => matrix_w(ispin, :)
     155             :          CALL calculate_rho_elec(matrix_p_kp=rho_ao, &
     156             :                                  rho=edens_r, &
     157             :                                  rho_gspace=edens_g, &
     158          32 :                                  ks_env=ks_env, soft_valid=(gapw .OR. gapw_xc))
     159          64 :          CALL pw_axpy(edens_r, band_density)
     160             :       END DO
     161          32 :       CALL auxbas_pw_pool%give_back_pw(edens_r)
     162          32 :       CALL auxbas_pw_pool%give_back_pw(edens_g)
     163             : 
     164             :       ! Hartree energy density correction = -0.5 * V_H(r) * [rho(r) - rho_core(r)]
     165          32 :       ALLOCATE (rho_tot_gspace, rho_tot_rspace)
     166          32 :       CALL auxbas_pw_pool%create_pw(rho_tot_gspace)
     167          32 :       CALL auxbas_pw_pool%create_pw(rho_tot_rspace)
     168          32 :       NULLIFY (rho_core)
     169             :       CALL get_qs_env(qs_env, &
     170             :                       v_hartree_rspace=v_hartree_rspace, &
     171          32 :                       rho_core=rho_core, rho=rho)
     172          32 :       CALL qs_rho_get(rho, rho_r=rho_r)
     173          32 :       IF (ASSOCIATED(rho_core)) THEN
     174          32 :          CALL calc_rho_tot_gspace(rho_tot_gspace, qs_env, rho)
     175          32 :          CALL pw_transfer(rho_core, rho_tot_rspace)
     176             :       ELSE
     177           0 :          CALL pw_zero(rho_tot_rspace)
     178             :       END IF
     179          64 :       DO ispin = 1, nspins
     180          64 :          CALL pw_axpy(rho_r(ispin), rho_tot_rspace, alpha=-1.0_dp)
     181             :       END DO
     182          32 :       CALL pw_zero(hartree_density)
     183          32 :       ovol = 0.5_dp/hartree_density%pw_grid%dvol
     184          32 :       CALL pw_multiply(hartree_density, v_hartree_rspace, rho_tot_rspace, alpha=ovol)
     185          32 :       CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
     186          32 :       CALL auxbas_pw_pool%give_back_pw(rho_tot_rspace)
     187          32 :       DEALLOCATE (rho_tot_gspace, rho_tot_rspace)
     188             : 
     189          32 :       IF (dft_control%do_admm) THEN
     190           0 :          CALL cp_warn(__LOCATION__, "ADMM not supported for local energy calculation")
     191             :       END IF
     192          32 :       IF (gapw_xc .OR. gapw) THEN
     193           0 :          CALL cp_warn(__LOCATION__, "GAPW/GAPW_XC not supported for local energy calculation")
     194             :       END IF
     195             :       ! XC energy density correction = E_xc(r) - V_xc(r)*rho(r)
     196          32 :       CALL get_qs_env(qs_env, input=input)
     197          32 :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
     198          32 :       CALL get_qs_env(qs_env=qs_env, rho=rho_struct)
     199             :       !
     200          32 :       CALL qs_xc_density(ks_env, rho_struct, xc_section, xc_ener=xc_density)
     201             :       !
     202             :       ! energies
     203          32 :       CALL get_qs_env(qs_env=qs_env, energy=energy)
     204          32 :       eban = pw_integrate_function(band_density)
     205          32 :       eh = pw_integrate_function(hartree_density)
     206          32 :       exc = pw_integrate_function(xc_density)
     207             : 
     208             :       ! band energy
     209          32 :       CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks)
     210          32 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
     211          32 :       CALL calculate_ptrace(matrix_ks, rho_ao_kp, eband, nspins)
     212             : 
     213             :       ! get full density
     214          32 :       CALL pw_copy(band_density, energy_density)
     215          32 :       CALL pw_axpy(hartree_density, energy_density)
     216          32 :       CALL pw_axpy(xc_density, energy_density)
     217             : 
     218          32 :       IF (iounit > 0) THEN
     219          16 :          WRITE (UNIT=iounit, FMT="(/,T3,A)") REPEAT("=", 78)
     220          16 :          WRITE (UNIT=iounit, FMT="(T4,A,T52,A,T75,A)") "Local Energy Calculation", "GPW/GAPW", "Local"
     221          16 :          WRITE (UNIT=iounit, FMT="(T4,A,T45,F15.8,T65,F15.8)") "Band Energy", eband, eban
     222          16 :          WRITE (UNIT=iounit, FMT="(T4,A,T65,F15.8)") "Hartree Energy Correction", eh
     223          16 :          WRITE (UNIT=iounit, FMT="(T4,A,T65,F15.8)") "XC Energy Correction", exc
     224          16 :          WRITE (UNIT=iounit, FMT="(T4,A,T45,F15.8,T65,F15.8)") "Total Energy", &
     225          32 :             energy%total, eban + eh + exc + energy%core_overlap + energy%core_self + energy%dispersion
     226          16 :          WRITE (UNIT=iounit, FMT="(T3,A)") REPEAT("=", 78)
     227             :       END IF
     228             : 
     229             :       ! return temp arrays
     230          32 :       CALL auxbas_pw_pool%give_back_pw(band_density)
     231          32 :       CALL auxbas_pw_pool%give_back_pw(hartree_density)
     232          32 :       CALL auxbas_pw_pool%give_back_pw(xc_density)
     233             : 
     234          32 :       CALL timestop(handle)
     235             : 
     236          32 :    END SUBROUTINE qs_local_energy
     237             : 
     238             : ! **************************************************************************************************
     239             : !> \brief Routine to calculate the local stress
     240             : !> \param qs_env the qs_env to update
     241             : !> \param stress_tensor ...
     242             : !> \param beta ...
     243             : !> \par History
     244             : !>      07.2019 created
     245             : !> \author JGH
     246             : ! **************************************************************************************************
     247          30 :    SUBROUTINE qs_local_stress(qs_env, stress_tensor, beta)
     248             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     249             :       TYPE(pw_r3d_rs_type), DIMENSION(:, :), &
     250             :          INTENT(INOUT), OPTIONAL                         :: stress_tensor
     251             :       REAL(KIND=dp), INTENT(IN), OPTIONAL                :: beta
     252             : 
     253             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_local_stress'
     254             : 
     255             :       INTEGER                                            :: handle, i, iounit, j, nimages, nkind, &
     256             :                                                             nspins
     257             :       LOGICAL                                            :: do_stress, gapw, gapw_xc, use_virial
     258             :       REAL(KIND=dp)                                      :: my_beta
     259             :       REAL(KIND=dp), DIMENSION(3, 3)                     :: pv_loc
     260             :       TYPE(cp_logger_type), POINTER                      :: logger
     261             :       TYPE(dft_control_type), POINTER                    :: dft_control
     262             :       TYPE(pw_c1d_gs_type)                               :: v_hartree_gspace
     263         120 :       TYPE(pw_c1d_gs_type), DIMENSION(3)                 :: efield
     264             :       TYPE(pw_env_type), POINTER                         :: pw_env
     265             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     266             :       TYPE(pw_r3d_rs_type)                               :: xc_density
     267             :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
     268             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     269             :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     270             :       TYPE(section_vals_type), POINTER                   :: input, xc_section
     271             :       TYPE(virial_type), POINTER                         :: virial
     272             : 
     273          30 :       CALL cp_warn(__LOCATION__, "Local Stress Tensor code is not working, skipping")
     274          30 :       RETURN
     275             : 
     276             :       CALL timeset(routineN, handle)
     277             : 
     278             :       CALL cite_reference(Filippetti2000)
     279             :       CALL cite_reference(Rogers2002)
     280             : 
     281             :       CPASSERT(ASSOCIATED(qs_env))
     282             : 
     283             :       IF (PRESENT(stress_tensor)) THEN
     284             :          do_stress = .TRUE.
     285             :       ELSE
     286             :          do_stress = .FALSE.
     287             :       END IF
     288             :       IF (PRESENT(beta)) THEN
     289             :          my_beta = beta
     290             :       ELSE
     291             :          my_beta = 0.0_dp
     292             :       END IF
     293             : 
     294             :       logger => cp_get_default_logger()
     295             :       iounit = cp_logger_get_default_io_unit()
     296             : 
     297             :       !!!!!!
     298             :       CALL cp_warn(__LOCATION__, "Local Stress Tensor code is not tested")
     299             :       !!!!!!
     300             : 
     301             :       ! Check for GAPW method : additional terms for local densities
     302             :       CALL get_qs_env(qs_env, nkind=nkind, dft_control=dft_control)
     303             :       gapw = dft_control%qs_control%gapw
     304             :       gapw_xc = dft_control%qs_control%gapw_xc
     305             : 
     306             :       nimages = dft_control%nimages
     307             :       nspins = dft_control%nspins
     308             : 
     309             :       ! get working arrays
     310             :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
     311             :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     312             :       CALL auxbas_pw_pool%create_pw(xc_density)
     313             : 
     314             :       ! init local stress tensor
     315             :       IF (do_stress) THEN
     316             :          DO i = 1, 3
     317             :             DO j = 1, 3
     318             :                CALL pw_zero(stress_tensor(i, j))
     319             :             END DO
     320             :          END DO
     321             :       END IF
     322             : 
     323             :       IF (dft_control%do_admm) THEN
     324             :          CALL cp_warn(__LOCATION__, "ADMM not supported for local energy calculation")
     325             :       END IF
     326             :       IF (gapw_xc .OR. gapw) THEN
     327             :          CALL cp_warn(__LOCATION__, "GAPW/GAPW_XC not supported for local energy calculation")
     328             :       END IF
     329             :       ! XC energy density correction = E_xc(r) - V_xc(r)*rho(r)
     330             :       CALL get_qs_env(qs_env, ks_env=ks_env, input=input, rho=rho_struct)
     331             :       xc_section => section_vals_get_subs_vals(input, "DFT%XC")
     332             :       !
     333             :       CALL qs_xc_density(ks_env, rho_struct, xc_section, xc_ener=xc_density)
     334             : 
     335             :       ! Electrical field terms
     336             :       CALL get_qs_env(qs_env, v_hartree_rspace=v_hartree_rspace)
     337             :       CALL auxbas_pw_pool%create_pw(v_hartree_gspace)
     338             :       CALL pw_transfer(v_hartree_rspace, v_hartree_gspace)
     339             :       DO i = 1, 3
     340             :          CALL auxbas_pw_pool%create_pw(efield(i))
     341             :          CALL pw_copy(v_hartree_gspace, efield(i))
     342             :       END DO
     343             :       CALL pw_derive(efield(1), (/1, 0, 0/))
     344             :       CALL pw_derive(efield(2), (/0, 1, 0/))
     345             :       CALL pw_derive(efield(3), (/0, 0, 1/))
     346             :       CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
     347             :       DO i = 1, 3
     348             :          CALL auxbas_pw_pool%give_back_pw(efield(i))
     349             :       END DO
     350             : 
     351             :       pv_loc = 0.0_dp
     352             : 
     353             :       CALL get_qs_env(qs_env=qs_env, virial=virial)
     354             :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     355             :       IF (.NOT. use_virial) THEN
     356             :          CALL cp_warn(__LOCATION__, "Local stress should be used with standard stress calculation.")
     357             :       END IF
     358             :       IF (iounit > 0 .AND. use_virial) THEN
     359             :          WRITE (UNIT=iounit, FMT="(/,T3,A)") REPEAT("=", 78)
     360             :          WRITE (UNIT=iounit, FMT="(T4,A)") "Local Stress Calculation"
     361             :          WRITE (UNIT=iounit, FMT="(T42,A,T64,A)") "       1/3 Trace", "     Determinant"
     362             :          WRITE (UNIT=iounit, FMT="(T4,A,T42,F16.8,T64,F16.8)") "Total Stress", &
     363             :             (pv_loc(1, 1) + pv_loc(2, 2) + pv_loc(3, 3))/3.0_dp, det_3x3(pv_loc)
     364             :          WRITE (UNIT=iounit, FMT="(T3,A)") REPEAT("=", 78)
     365             :       END IF
     366             : 
     367             :       CALL timestop(handle)
     368             : 
     369          30 :    END SUBROUTINE qs_local_stress
     370             : 
     371             : ! **************************************************************************************************
     372             : 
     373             : END MODULE qs_local_properties

Generated by: LCOV version 1.15