LCOV - code coverage report
Current view: top level - src - qs_2nd_kernel_ao.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 115 121 95.0 %
Date: 2024-12-21 06:28:57 Functions: 4 4 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 to calculate 2nd order kernels from a given response density in ao basis
      10             : !>      linear response scf
      11             : !> \par History
      12             : !>      created 08-2020 [Frederick Stein], Code by M. Iannuzzi
      13             : !> \author Frederick Stein
      14             : ! **************************************************************************************************
      15             : MODULE qs_2nd_kernel_ao
      16             :    USE admm_types,                      ONLY: admm_type,&
      17             :                                               get_admm_env
      18             :    USE cp_control_types,                ONLY: dft_control_type
      19             :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      20             :                                               dbcsr_copy,&
      21             :                                               dbcsr_create,&
      22             :                                               dbcsr_p_type,&
      23             :                                               dbcsr_release,&
      24             :                                               dbcsr_set
      25             :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_plus_fm_fm_t,&
      26             :                                               dbcsr_allocate_matrix_set,&
      27             :                                               dbcsr_deallocate_matrix_set
      28             :    USE cp_fm_types,                     ONLY: cp_fm_get_info,&
      29             :                                               cp_fm_type
      30             :    USE hfx_admm_utils,                  ONLY: tddft_hfx_matrix
      31             :    USE input_constants,                 ONLY: do_admm_aux_exch_func_none,&
      32             :                                               do_admm_basis_projection,&
      33             :                                               do_admm_exch_scaling_none,&
      34             :                                               do_admm_purify_none
      35             :    USE input_section_types,             ONLY: section_vals_get,&
      36             :                                               section_vals_get_subs_vals,&
      37             :                                               section_vals_type
      38             :    USE kinds,                           ONLY: dp
      39             :    USE pw_env_types,                    ONLY: pw_env_get,&
      40             :                                               pw_env_type
      41             :    USE pw_methods,                      ONLY: pw_scale
      42             :    USE pw_pool_types,                   ONLY: pw_pool_type
      43             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      44             :                                               pw_r3d_rs_type
      45             :    USE qs_environment_types,            ONLY: get_qs_env,&
      46             :                                               qs_environment_type
      47             :    USE qs_integrate_potential,          ONLY: integrate_v_rspace
      48             :    USE qs_kpp1_env_methods,             ONLY: calc_kpp1
      49             :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      50             :    USE qs_linres_types,                 ONLY: linres_control_type
      51             :    USE qs_p_env_methods,                ONLY: p_env_finish_kpp1
      52             :    USE qs_p_env_types,                  ONLY: qs_p_env_type
      53             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      54             :                                               qs_rho_type
      55             :    USE task_list_types,                 ONLY: task_list_type
      56             :    USE xc,                              ONLY: xc_calc_2nd_deriv
      57             : #include "./base/base_uses.f90"
      58             : 
      59             :    IMPLICIT NONE
      60             : 
      61             :    PRIVATE
      62             : 
      63             :    ! *** Public subroutines ***
      64             :    PUBLIC :: build_dm_response, apply_2nd_order_kernel
      65             :    PUBLIC :: apply_hfx_ao
      66             :    PUBLIC :: apply_xc_admm_ao
      67             : 
      68             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_2nd_kernel_ao'
      69             : 
      70             : ! **************************************************************************************************
      71             : 
      72             : CONTAINS
      73             : 
      74             : ! **************************************************************************************************
      75             : !> \brief This routine builds response density in dbcsr format
      76             : !> \param c0 coefficients of unperturbed system (not changed)
      77             : !> \param c1 coefficients of response (not changed)
      78             : !> \param dm response density matrix
      79             : ! **************************************************************************************************
      80       10064 :    SUBROUTINE build_dm_response(c0, c1, dm)
      81             :       !
      82             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: c0, c1
      83             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT)    :: dm
      84             : 
      85             :       INTEGER                                            :: ispin, ncol, nspins
      86             : 
      87       10064 :       nspins = SIZE(dm, 1)
      88             : 
      89       21242 :       DO ispin = 1, nspins
      90       11178 :          CALL dbcsr_set(dm(ispin)%matrix, 0.0_dp)
      91       11178 :          CALL cp_fm_get_info(c0(ispin), ncol_global=ncol)
      92             :          CALL cp_dbcsr_plus_fm_fm_t(dm(ispin)%matrix, &
      93             :                                     matrix_v=c0(ispin), &
      94             :                                     matrix_g=c1(ispin), &
      95             :                                     ncol=ncol, alpha=2.0_dp, &
      96             :                                     keep_sparsity=.TRUE., &
      97       21242 :                                     symmetry_mode=1)
      98             :       END DO
      99             : 
     100       10064 :    END SUBROUTINE build_dm_response
     101             : 
     102             : ! **************************************************************************************************
     103             : !> \brief Calculate a second order kernel (DFT, HF, ADMM correction) for a given density
     104             : !> \param qs_env ...
     105             : !> \param p_env perturbation environment containing the correct density matrices p_env%p1, p_env%p1_admm,
     106             : !>        the kernel will be saved in p_env%kpp1, p_env%kpp1_admm
     107             : !> \param recalc_hfx_integrals whether to recalculate the HFX integrals
     108             : !> \param calc_forces whether to calculate forces
     109             : !> \param calc_virial whether to calculate virials
     110             : !> \param virial collect the virial terms from the XC + ADMM parts (terms from integration will be added to pv_virial)
     111             : ! **************************************************************************************************
     112        3468 :    SUBROUTINE apply_2nd_order_kernel(qs_env, p_env, recalc_hfx_integrals, calc_forces, calc_virial, virial)
     113             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     114             :       TYPE(qs_p_env_type)                                :: p_env
     115             :       LOGICAL, INTENT(IN), OPTIONAL                      :: recalc_hfx_integrals, calc_forces, &
     116             :                                                             calc_virial
     117             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT), &
     118             :          OPTIONAL                                        :: virial
     119             : 
     120             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'apply_2nd_order_kernel'
     121             : 
     122             :       INTEGER                                            :: handle, ispin
     123             :       LOGICAL                                            :: do_hfx, my_calc_forces, my_calc_virial, &
     124             :                                                             my_recalc_hfx_integrals
     125             :       TYPE(admm_type), POINTER                           :: admm_env
     126             :       TYPE(dft_control_type), POINTER                    :: dft_control
     127             :       TYPE(linres_control_type), POINTER                 :: linres_control
     128             :       TYPE(section_vals_type), POINTER                   :: hfx_sections, input, xc_section
     129             : 
     130        1734 :       CALL timeset(routineN, handle)
     131             : 
     132        1734 :       my_recalc_hfx_integrals = .FALSE.
     133        1734 :       IF (PRESENT(recalc_hfx_integrals)) my_recalc_hfx_integrals = recalc_hfx_integrals
     134             : 
     135        1734 :       my_calc_forces = .FALSE.
     136        1734 :       IF (PRESENT(calc_forces)) my_calc_forces = calc_forces
     137             : 
     138        1734 :       my_calc_virial = .FALSE.
     139        1734 :       IF (PRESENT(calc_virial)) my_calc_virial = calc_virial
     140             : 
     141        1734 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     142             : 
     143        4018 :       DO ispin = 1, SIZE(p_env%kpp1)
     144        2284 :          CALL dbcsr_set(p_env%kpp1(ispin)%matrix, 0.0_dp)
     145        4018 :          IF (dft_control%do_admm) CALL dbcsr_set(p_env%kpp1_admm(ispin)%matrix, 0.0_dp)
     146             :       END DO
     147             : 
     148             :       CALL get_qs_env(qs_env=qs_env, &
     149             :                       input=input, &
     150        1734 :                       linres_control=linres_control)
     151             : 
     152        1734 :       IF (dft_control%do_admm) THEN
     153         212 :          CALL get_qs_env(qs_env, admm_env=admm_env)
     154         212 :          xc_section => admm_env%xc_section_primary
     155             :       ELSE
     156        1522 :          xc_section => section_vals_get_subs_vals(input, "DFT%XC")
     157             :       END IF
     158             : 
     159             :       CALL calc_kpp1(p_env%rho1_xc, p_env%rho1, xc_section, .FALSE., &
     160             :                      .FALSE., dft_control%qs_control%lrigpw, .TRUE., linres_control%lr_triplet, &
     161        1734 :                      qs_env, p_env, calc_forces=my_calc_forces, calc_virial=my_calc_virial, virial=virial)
     162             : 
     163             :       ! hfx section
     164        1734 :       NULLIFY (hfx_sections)
     165        1734 :       hfx_sections => section_vals_get_subs_vals(input, "DFT%XC%HF")
     166        1734 :       CALL section_vals_get(hfx_sections, explicit=do_hfx)
     167        1734 :       IF (do_hfx) THEN
     168        1236 :          CALL apply_hfx_ao(qs_env, p_env, my_recalc_hfx_integrals)
     169             : 
     170        1236 :          IF (dft_control%do_admm) THEN
     171         188 :             CALL apply_xc_admm_ao(qs_env, p_env, my_calc_forces, my_calc_virial, virial)
     172         188 :             CALL p_env_finish_kpp1(qs_env, p_env)
     173             :          END IF
     174             :       END IF
     175             : 
     176        1734 :       CALL timestop(handle)
     177             : 
     178        1734 :    END SUBROUTINE apply_2nd_order_kernel
     179             : 
     180             : ! **************************************************************************************************
     181             : !> \brief This routine applies the Hartree-Fock Exchange kernel to a perturbation density matrix considering ADMM
     182             : !> \param qs_env the Quickstep environment
     183             : !> \param p_env perturbation environment from which p1/p1_admm and kpp1/kpp1_admm are taken
     184             : !> \param recalc_integrals whether the integrals are to be recalculated (default: no)
     185             : ! **************************************************************************************************
     186        1236 :    SUBROUTINE apply_hfx_ao(qs_env, p_env, recalc_integrals)
     187             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     188             :       TYPE(qs_p_env_type), INTENT(IN)                    :: p_env
     189             :       LOGICAL, INTENT(IN), OPTIONAL                      :: recalc_integrals
     190             : 
     191             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'apply_hfx_ao'
     192             : 
     193             :       INTEGER                                            :: handle, ispin, nspins
     194             :       LOGICAL                                            :: my_recalc_integrals
     195             :       REAL(KIND=dp)                                      :: alpha
     196        1236 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: h1_mat, rho1, work_hmat
     197             :       TYPE(dft_control_type), POINTER                    :: dft_control
     198             : 
     199        1236 :       CALL timeset(routineN, handle)
     200             : 
     201        1236 :       my_recalc_integrals = .FALSE.
     202        1236 :       IF (PRESENT(recalc_integrals)) my_recalc_integrals = recalc_integrals
     203             : 
     204        1236 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control)
     205             : 
     206        1236 :       IF (dft_control%do_admm) THEN
     207         188 :          IF (dft_control%admm_control%purification_method /= do_admm_purify_none) THEN
     208           0 :             CPABORT("ADMM: Linear Response needs purification_method=none")
     209             :          END IF
     210         188 :          IF (dft_control%admm_control%scaling_model /= do_admm_exch_scaling_none) THEN
     211           0 :             CPABORT("ADMM: Linear Response needs scaling_model=none")
     212             :          END IF
     213         188 :          IF (dft_control%admm_control%method /= do_admm_basis_projection) THEN
     214           0 :             CPABORT("ADMM: Linear Response needs admm_method=basis_projection")
     215             :          END IF
     216             :          !
     217             :       END IF
     218             : 
     219        1236 :       nspins = dft_control%nspins
     220             : 
     221        1236 :       IF (dft_control%do_admm) THEN
     222         188 :          rho1 => p_env%p1_admm
     223         188 :          h1_mat => p_env%kpp1_admm
     224             :       ELSE
     225        1048 :          rho1 => p_env%p1
     226        1048 :          h1_mat => p_env%kpp1
     227             :       END IF
     228             : 
     229        2788 :       DO ispin = 1, nspins
     230        1552 :          CPASSERT(ASSOCIATED(rho1(ispin)%matrix))
     231        2788 :          CPASSERT(ASSOCIATED(h1_mat(ispin)%matrix))
     232             :       END DO
     233             : 
     234        1236 :       NULLIFY (work_hmat)
     235        1236 :       CALL dbcsr_allocate_matrix_set(work_hmat, nspins)
     236        2788 :       DO ispin = 1, nspins
     237        1552 :          ALLOCATE (work_hmat(ispin)%matrix)
     238        1552 :          CALL dbcsr_create(work_hmat(ispin)%matrix, template=rho1(ispin)%matrix)
     239        1552 :          CALL dbcsr_copy(work_hmat(ispin)%matrix, rho1(ispin)%matrix)
     240        2788 :          CALL dbcsr_set(work_hmat(ispin)%matrix, 0.0_dp)
     241             :       END DO
     242             : 
     243             :       ! Calculate kernel
     244        1236 :       CALL tddft_hfx_matrix(work_hmat, rho1, qs_env, .FALSE., my_recalc_integrals)
     245             : 
     246        1236 :       alpha = 2.0_dp
     247        1236 :       IF (nspins == 2) alpha = 1.0_dp
     248             : 
     249        2788 :       DO ispin = 1, nspins
     250        2788 :          CALL dbcsr_add(h1_mat(ispin)%matrix, work_hmat(ispin)%matrix, 1.0_dp, alpha)
     251             :       END DO
     252             : 
     253        1236 :       CALL dbcsr_deallocate_matrix_set(work_hmat)
     254             : 
     255        1236 :       CALL timestop(handle)
     256             : 
     257        1236 :    END SUBROUTINE apply_hfx_ao
     258             : 
     259             : ! **************************************************************************************************
     260             : !> \brief apply the kernel from the ADMM exchange correction
     261             : !> \param qs_env ...
     262             : !> \param p_env perturbation environment
     263             : !> \param calc_forces whether to calculate forces
     264             : !> \param calc_virial whether to calculate gradients
     265             : !> \param virial collects the virial terms from the XC functional (virial terms from integration are collected in pv_virial)
     266             : ! **************************************************************************************************
     267         188 :    SUBROUTINE apply_xc_admm_ao(qs_env, p_env, calc_forces, calc_virial, virial)
     268             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     269             :       TYPE(qs_p_env_type)                                :: p_env
     270             :       LOGICAL, INTENT(IN), OPTIONAL                      :: calc_forces, calc_virial
     271             :       REAL(KIND=dp), DIMENSION(3, 3), INTENT(INOUT), &
     272             :          OPTIONAL                                        :: virial
     273             : 
     274             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'apply_xc_admm_ao'
     275             : 
     276             :       INTEGER                                            :: handle, ispin, nao, nao_aux, nspins
     277             :       LOGICAL                                            :: lsd, my_calc_forces
     278             :       REAL(KIND=dp)                                      :: alpha
     279             :       TYPE(admm_type), POINTER                           :: admm_env
     280             :       TYPE(dbcsr_p_type)                                 :: work_hmat
     281         188 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao_aux
     282             :       TYPE(dft_control_type), POINTER                    :: dft_control
     283             :       TYPE(linres_control_type), POINTER                 :: linres_control
     284         188 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho1_aux_g
     285             :       TYPE(pw_env_type), POINTER                         :: pw_env
     286             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     287         188 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho1_aux_r, tau1_aux_r, v_xc, v_xc_tau
     288             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     289             :       TYPE(qs_rho_type), POINTER                         :: rho_aux
     290             :       TYPE(section_vals_type), POINTER                   :: xc_section
     291             :       TYPE(task_list_type), POINTER                      :: task_list_aux_fit
     292             : 
     293         188 :       CALL timeset(routineN, handle)
     294             : 
     295         188 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control)
     296             : 
     297         188 :       IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
     298          92 :          CALL get_qs_env(qs_env=qs_env, linres_control=linres_control)
     299          92 :          CPASSERT(.NOT. dft_control%qs_control%gapw)
     300          92 :          CPASSERT(.NOT. dft_control%qs_control%gapw_xc)
     301          92 :          CPASSERT(.NOT. dft_control%qs_control%lrigpw)
     302          92 :          CPASSERT(.NOT. linres_control%lr_triplet)
     303          92 :          IF (.NOT. ASSOCIATED(p_env%kpp1_admm)) &
     304           0 :             CPABORT("kpp1_admm has to be associated if ADMM kernel calculations are requested")
     305             : 
     306          92 :          nspins = dft_control%nspins
     307             : 
     308          92 :          my_calc_forces = .FALSE.
     309          92 :          IF (PRESENT(calc_forces)) my_calc_forces = calc_forces
     310             : 
     311             :          ! AUX basis contribution
     312          92 :          CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
     313          92 :          CPASSERT(ASSOCIATED(pw_env))
     314          92 :          CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     315          92 :          NULLIFY (v_xc)
     316             :          ! calculate the xc potential
     317          92 :          lsd = (nspins == 2)
     318          92 :          CALL get_qs_env(qs_env=qs_env, ks_env=ks_env, admm_env=admm_env)
     319          92 :          CALL get_admm_env(admm_env, task_list_aux_fit=task_list_aux_fit)
     320             : 
     321          92 :          CALL qs_rho_get(p_env%rho1_admm, rho_r=rho1_aux_r, rho_g=rho1_aux_g, tau_r=tau1_aux_r)
     322          92 :          xc_section => admm_env%xc_section_aux
     323             : 
     324             :          CALL xc_calc_2nd_deriv(v_xc, v_xc_tau, p_env%kpp1_env%deriv_set_admm, &
     325             :                                 p_env%kpp1_env%rho_set_admm, &
     326             :                                 rho1_aux_r, rho1_aux_g, tau1_aux_r, auxbas_pw_pool, xc_section=xc_section, gapw=.FALSE., &
     327          92 :                                 compute_virial=calc_virial, virial_xc=virial)
     328             : 
     329             :          NULLIFY (work_hmat%matrix)
     330          92 :          ALLOCATE (work_hmat%matrix)
     331          92 :          CALL dbcsr_copy(work_hmat%matrix, p_env%kpp1_admm(1)%matrix)
     332             : 
     333          92 :          alpha = 1.0_dp
     334          92 :          IF (nspins == 1) alpha = 2.0_dp
     335             : 
     336          92 :          CALL get_admm_env(qs_env%admm_env, rho_aux_fit=rho_aux)
     337          92 :          CALL qs_rho_get(rho_aux, rho_ao=rho_ao_aux)
     338             : 
     339          92 :          CALL cp_fm_get_info(admm_env%A, nrow_global=nao_aux, ncol_global=nao)
     340         220 :          DO ispin = 1, nspins
     341         128 :             CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
     342         128 :             CALL dbcsr_set(work_hmat%matrix, 0.0_dp)
     343             :             CALL integrate_v_rspace(v_rspace=v_xc(ispin), hmat=work_hmat, qs_env=qs_env, &
     344             :                                     calculate_forces=my_calc_forces, basis_type="AUX_FIT", &
     345         128 :                                     task_list_external=task_list_aux_fit, pmat=rho_ao_aux(ispin))
     346         128 :             IF (ASSOCIATED(v_xc_tau)) THEN
     347           0 :                CALL pw_scale(v_xc_tau(ispin), v_xc_tau(ispin)%pw_grid%dvol)
     348             :                CALL integrate_v_rspace(v_rspace=v_xc_tau(ispin), hmat=work_hmat, qs_env=qs_env, &
     349             :                                        compute_tau=.TRUE., &
     350             :                                        calculate_forces=my_calc_forces, basis_type="AUX_FIT", &
     351           0 :                                        task_list_external=task_list_aux_fit, pmat=rho_ao_aux(ispin))
     352             :             END IF
     353         220 :             CALL dbcsr_add(p_env%kpp1_admm(ispin)%matrix, work_hmat%matrix, 1.0_dp, alpha)
     354             : 
     355             :          END DO
     356             : 
     357          92 :          CALL dbcsr_release(work_hmat%matrix)
     358          92 :          DEALLOCATE (work_hmat%matrix)
     359             : 
     360         220 :          DO ispin = 1, nspins
     361         220 :             CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
     362             :          END DO
     363          92 :          DEALLOCATE (v_xc)
     364             : 
     365             :       END IF
     366             : 
     367         188 :       CALL timestop(handle)
     368             : 
     369         188 :    END SUBROUTINE apply_xc_admm_ao
     370             : END MODULE qs_2nd_kernel_ao

Generated by: LCOV version 1.15