LCOV - code coverage report
Current view: top level - src - ed_analysis.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:b1f098b) Lines: 541 563 96.1 %
Date: 2024-05-05 06:30:09 Functions: 6 6 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 Energy Decomposition analysis
      10             : !> \par History
      11             : !>      07.2023 created [JGH]
      12             : !> \author JGH
      13             : ! **************************************************************************************************
      14             : MODULE ed_analysis
      15             :    USE admm_types,                      ONLY: admm_type
      16             :    USE atomic_kind_types,               ONLY: atomic_kind_type
      17             :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      18             :                                               gto_basis_set_type
      19             :    USE bibliography,                    ONLY: Eriksen2020,&
      20             :                                               cite_reference
      21             :    USE cell_types,                      ONLY: cell_type
      22             :    USE core_ae,                         ONLY: build_erfc
      23             :    USE cp_control_types,                ONLY: dft_control_type
      24             :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_plus_fm_fm_t,&
      25             :                                               cp_dbcsr_sm_fm_multiply
      26             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      27             :                                               cp_fm_struct_release,&
      28             :                                               cp_fm_struct_type
      29             :    USE cp_fm_types,                     ONLY: &
      30             :         cp_fm_create, cp_fm_get_diag, cp_fm_get_element, cp_fm_get_info, cp_fm_get_submatrix, &
      31             :         cp_fm_release, cp_fm_set_all, cp_fm_set_element, cp_fm_set_submatrix, cp_fm_to_fm, &
      32             :         cp_fm_type
      33             :    USE dbcsr_api,                       ONLY: &
      34             :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_distribution_type, dbcsr_dot, dbcsr_get_info, &
      35             :         dbcsr_p_type, dbcsr_release, dbcsr_reserve_diag_blocks, dbcsr_scale, dbcsr_set, &
      36             :         dbcsr_type, dbcsr_type_symmetric
      37             :    USE hartree_local_methods,           ONLY: Vh_1c_gg_integrals
      38             :    USE hartree_local_types,             ONLY: ecoul_1center_type
      39             :    USE hfx_admm_utils,                  ONLY: tddft_hfx_matrix
      40             :    USE iao_analysis,                    ONLY: iao_calculate_dmat,&
      41             :                                               iao_charges,&
      42             :                                               iao_wfn_analysis,&
      43             :                                               print_center_spread
      44             :    USE iao_types,                       ONLY: iao_env_type,&
      45             :                                               iao_set_default
      46             :    USE input_constants,                 ONLY: do_admm_aux_exch_func_none
      47             :    USE input_section_types,             ONLY: section_vals_get,&
      48             :                                               section_vals_get_subs_vals,&
      49             :                                               section_vals_type,&
      50             :                                               section_vals_val_get
      51             :    USE kinds,                           ONLY: dp
      52             :    USE mathconstants,                   ONLY: pi
      53             :    USE message_passing,                 ONLY: mp_comm_type,&
      54             :                                               mp_para_env_type
      55             :    USE mulliken,                        ONLY: mulliken_charges
      56             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      57             :    USE particle_methods,                ONLY: get_particle_set
      58             :    USE particle_types,                  ONLY: particle_type
      59             :    USE physcon,                         ONLY: angstrom
      60             :    USE pw_env_types,                    ONLY: pw_env_get,&
      61             :                                               pw_env_type
      62             :    USE pw_methods,                      ONLY: pw_axpy,&
      63             :                                               pw_scale,&
      64             :                                               pw_transfer
      65             :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      66             :    USE pw_poisson_types,                ONLY: pw_poisson_type
      67             :    USE pw_pool_types,                   ONLY: pw_pool_type
      68             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      69             :                                               pw_r3d_rs_type
      70             :    USE qs_collocate_density,            ONLY: calculate_rho_core
      71             :    USE qs_core_energies,                ONLY: calculate_ecore_alpha,&
      72             :                                               calculate_ecore_overlap,&
      73             :                                               calculate_ecore_self
      74             :    USE qs_dispersion_pairpot,           ONLY: calculate_dispersion_pairpot
      75             :    USE qs_dispersion_types,             ONLY: qs_dispersion_type
      76             :    USE qs_energy_types,                 ONLY: qs_energy_type
      77             :    USE qs_environment_types,            ONLY: get_qs_env,&
      78             :                                               qs_environment_type
      79             :    USE qs_gcp_method,                   ONLY: calculate_gcp_pairpot
      80             :    USE qs_gcp_types,                    ONLY: qs_gcp_type
      81             :    USE qs_integrate_potential,          ONLY: integrate_v_core_rspace,&
      82             :                                               integrate_v_gaussian_rspace,&
      83             :                                               integrate_v_rspace
      84             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      85             :                                               qs_kind_type
      86             :    USE qs_ks_atom,                      ONLY: update_ks_atom
      87             :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      88             :    USE qs_local_rho_types,              ONLY: local_rho_type
      89             :    USE qs_mo_methods,                   ONLY: calculate_subspace_eigenvalues
      90             :    USE qs_mo_types,                     ONLY: deallocate_mo_set,&
      91             :                                               duplicate_mo_set,&
      92             :                                               get_mo_set,&
      93             :                                               mo_set_type
      94             :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      95             :    USE qs_rho0_ggrid,                   ONLY: integrate_vhg0_rspace
      96             :    USE qs_rho_atom_types,               ONLY: rho_atom_type,&
      97             :                                               zero_rho_atom_integrals
      98             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      99             :                                               qs_rho_type
     100             :    USE qs_vxc,                          ONLY: qs_xc_density
     101             :    USE qs_vxc_atom,                     ONLY: calculate_vxc_atom
     102             :    USE xc_derivatives,                  ONLY: xc_functionals_get_needs
     103             :    USE xc_rho_cflags_types,             ONLY: xc_rho_cflags_type
     104             : #include "./base/base_uses.f90"
     105             : 
     106             :    IMPLICIT NONE
     107             :    PRIVATE
     108             : 
     109             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ed_analysis'
     110             : 
     111             :    PUBLIC ::  edmf_analysis
     112             : 
     113             : ! **************************************************************************************************
     114             : 
     115             : CONTAINS
     116             : 
     117             : ! **************************************************************************************************
     118             : !> \brief ...
     119             : !> \param qs_env ...
     120             : !> \param input_section ...
     121             : !> \param unit_nr ...
     122             : ! **************************************************************************************************
     123          58 :    SUBROUTINE edmf_analysis(qs_env, input_section, unit_nr)
     124             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     125             :       TYPE(section_vals_type), POINTER                   :: input_section
     126             :       INTEGER, INTENT(IN)                                :: unit_nr
     127             : 
     128             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'edmf_analysis'
     129             : 
     130             :       INTEGER                                            :: handle, iatom, ikind, iorb, ispin, jorb, &
     131             :                                                             nao, natom, nimages, nkind, no, norb, &
     132             :                                                             nref, nspin
     133             :       INTEGER, DIMENSION(2)                              :: nocc
     134          58 :       INTEGER, DIMENSION(:), POINTER                     :: refbas_blk_sizes
     135             :       LOGICAL :: detailed_ener, do_hfx, ewald_correction, explicit, gapw, gapw_xc, &
     136             :          ref_orb_canonical, skip_localize, uniform_occupation, uocc
     137             :       REAL(KIND=dp)                                      :: ateps, checksum, e1, e2, e_pot, ealpha, &
     138             :                                                             ecc, egcp, ehfx, ekts, evdw, focc, &
     139             :                                                             sum_energy
     140          58 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: amval, ate1h, ate1xc, atecc, ateks, &
     141          58 :                                                             atener, atewald, odiag
     142          58 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: atdet, atmul, mcharge, mweight
     143          58 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: bcenter
     144          58 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: occupation_numbers
     145             :       TYPE(cell_type), POINTER                           :: cell
     146             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     147             :       TYPE(cp_fm_type)                                   :: cvec, cvec2, smo
     148          58 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: c_iao_coef, ciao, fij_mat, orb_weight, &
     149          58 :                                                             rotmat
     150             :       TYPE(cp_fm_type), POINTER                          :: cloc, moref
     151             :       TYPE(dbcsr_distribution_type)                      :: dbcsr_dist
     152             :       TYPE(dbcsr_p_type)                                 :: dve_mat
     153          58 :       TYPE(dbcsr_p_type), ALLOCATABLE, DIMENSION(:)      :: exc_mat, ks_mat, vhxc_mat
     154          58 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_h, matrix_hfx, matrix_ks, &
     155          58 :                                                             matrix_p, matrix_s, matrix_t
     156             :       TYPE(dbcsr_type)                                   :: dkmat, dmat
     157             :       TYPE(dbcsr_type), POINTER                          :: smat
     158             :       TYPE(dft_control_type), POINTER                    :: dft_control
     159          58 :       TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER  :: ref_basis_set_list
     160             :       TYPE(gto_basis_set_type), POINTER                  :: refbasis
     161             :       TYPE(iao_env_type)                                 :: iao_env
     162          58 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos, mos_loc
     163             :       TYPE(mp_comm_type)                                 :: group
     164             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     165          58 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     166             :       TYPE(qs_dispersion_type), POINTER                  :: dispersion_env
     167             :       TYPE(qs_energy_type), POINTER                      :: energy
     168             :       TYPE(qs_gcp_type), POINTER                         :: gcp_env
     169          58 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     170             :       TYPE(qs_kind_type), POINTER                        :: qs_kind
     171             :       TYPE(qs_rho_type), POINTER                         :: rho
     172             :       TYPE(section_vals_type), POINTER                   :: hfx_sections, input
     173             : 
     174          58 :       CALL section_vals_get(input_section, explicit=explicit)
     175          58 :       IF (.NOT. explicit) RETURN
     176             : 
     177          30 :       CALL timeset(routineN, handle)
     178             : 
     179          30 :       IF (unit_nr > 0) THEN
     180             :          WRITE (UNIT=unit_nr, FMT="(/,4(T2,A))") &
     181          15 :             "!-----------------------------------------------------------------------------!", &
     182          15 :             "!                        ENERGY DECOMPOSITION ANALYSIS                        !", &
     183          15 :             "!                    Janus J Eriksen, JCP 153 214109 (2020)                   !", &
     184          30 :             "!-----------------------------------------------------------------------------!"
     185             :       END IF
     186          30 :       CALL cite_reference(Eriksen2020)
     187             : 
     188             :       ! input options
     189          30 :       CALL section_vals_val_get(input_section, "REFERENCE_ORB_CANONICAL", l_val=ref_orb_canonical)
     190          30 :       CALL section_vals_val_get(input_section, "DETAILED_ENERGY", l_val=detailed_ener)
     191          30 :       CALL section_vals_val_get(input_section, "SKIP_LOCALIZATION", l_val=skip_localize)
     192          30 :       CALL section_vals_val_get(input_section, "EWALD_ALPHA_PARAMETER", r_val=ealpha)
     193          30 :       ewald_correction = (ealpha /= 0.0_dp)
     194             :       ! k-points?
     195          30 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     196          30 :       nimages = dft_control%nimages
     197          30 :       IF (nimages > 1) THEN
     198           0 :          IF (unit_nr > 0) THEN
     199             :             WRITE (UNIT=unit_nr, FMT="(T2,A)") &
     200           0 :                "K-Points: MAO's determined and analyzed using Gamma-Point only."
     201             :          END IF
     202             :       END IF
     203          30 :       gapw = dft_control%qs_control%gapw
     204          30 :       gapw_xc = dft_control%qs_control%gapw_xc
     205          30 :       IF (ewald_correction) THEN
     206           2 :          IF (gapw .OR. gapw_xc) THEN
     207           0 :             CALL cp_warn(__LOCATION__, "Ewald Correction for GAPW and GAPW_XC not available.")
     208           0 :             CPABORT("Ewald Correction")
     209             :          END IF
     210             :       END IF
     211          30 :       CALL get_qs_env(qs_env, input=input)
     212          30 :       hfx_sections => section_vals_get_subs_vals(input, "DFT%XC%HF")
     213          30 :       CALL section_vals_get(hfx_sections, explicit=do_hfx)
     214             : 
     215          30 :       CALL get_qs_env(qs_env, mos=mos)
     216          30 :       nspin = dft_control%nspins
     217         122 :       ALLOCATE (mos_loc(nspin))
     218             : 
     219             :       ! do we have a uniform occupation
     220          30 :       uocc = .TRUE.
     221          62 :       DO ispin = 1, nspin
     222          32 :          CALL get_mo_set(mos(ispin), uniform_occupation=uniform_occupation)
     223          62 :          IF (.NOT. uniform_occupation) uocc = .FALSE.
     224             :       END DO
     225          30 :       IF (unit_nr > 0) THEN
     226          15 :          IF (uocc) THEN
     227             :             WRITE (UNIT=unit_nr, FMT="(T2,A)") &
     228          14 :                "MO's have a uniform occupation pattern"
     229             :          ELSE
     230             :             WRITE (UNIT=unit_nr, FMT="(T2,A)") &
     231           1 :                "MO's have varying occupations"
     232             :          END IF
     233             :       END IF
     234             : 
     235             :       ! perform IAO analysis
     236          30 :       CALL iao_set_default(iao_env)
     237          30 :       iao_env%do_iao = .TRUE.
     238          30 :       iao_env%do_charges = .TRUE.
     239          30 :       IF (skip_localize) THEN
     240           2 :          iao_env%do_bondorbitals = .FALSE.
     241           2 :          iao_env%do_center = .FALSE.
     242             :       ELSE
     243          28 :          iao_env%do_bondorbitals = .TRUE.
     244          28 :          iao_env%do_center = .TRUE.
     245             :       END IF
     246          30 :       iao_env%eps_occ = 1.0E-4_dp
     247          30 :       CALL get_qs_env(qs_env, cell=cell)
     248          36 :       iao_env%pos_periodic = .NOT. ALL(cell%perd == 0)
     249          30 :       no = 0
     250          30 :       nocc = 0
     251          62 :       DO ispin = 1, nspin
     252          32 :          CALL duplicate_mo_set(mos_loc(ispin), mos(ispin))
     253          32 :          CALL get_mo_set(mos_loc(ispin), nmo=norb)
     254          32 :          no = MAX(no, norb)
     255          32 :          nocc(ispin) = norb
     256          62 :          IF (ref_orb_canonical) THEN
     257          32 :             CALL get_mo_set(mos_loc(ispin), mo_coeff=moref)
     258          32 :             CALL get_qs_env(qs_env, matrix_ks=matrix_ks)
     259             :             CALL calculate_subspace_eigenvalues(moref, matrix_ks(ispin)%matrix, &
     260          32 :                                                 do_rotation=.TRUE.)
     261             :          END IF
     262             :       END DO
     263         120 :       ALLOCATE (bcenter(5, no, nspin))
     264        1154 :       bcenter = 0.0_dp
     265             :       CALL iao_wfn_analysis(qs_env, iao_env, unit_nr, &
     266          30 :                             c_iao_coef=c_iao_coef, mos=mos_loc, bond_centers=bcenter)
     267             : 
     268             :       ! output bond centers
     269          30 :       IF (iao_env%do_bondorbitals .AND. iao_env%do_center) THEN
     270          28 :          CALL print_center_spread(bcenter, nocc, iounit=unit_nr)
     271             :       END IF
     272             : 
     273             :       ! Calculate orbital rotation matrix
     274          30 :       CALL get_qs_env(qs_env, matrix_s=matrix_s)
     275          30 :       smat => matrix_s(1)%matrix
     276         122 :       ALLOCATE (rotmat(nspin))
     277          62 :       DO ispin = 1, nspin
     278          32 :          CALL get_mo_set(mos_loc(ispin), mo_coeff=cloc)
     279          32 :          CALL get_mo_set(mos(ispin), mo_coeff=moref)
     280          32 :          CALL cp_fm_get_info(cloc, nrow_global=nao, ncol_global=norb)
     281          32 :          CALL cp_fm_create(smo, cloc%matrix_struct)
     282          32 :          NULLIFY (fm_struct)
     283             :          CALL cp_fm_struct_create(fm_struct, nrow_global=norb, ncol_global=norb, &
     284          32 :                                   template_fmstruct=cloc%matrix_struct)
     285          32 :          CALL cp_fm_create(rotmat(ispin), fm_struct)
     286          32 :          CALL cp_fm_struct_release(fm_struct)
     287             :          ! ROTMAT = Cref(T)*S*Cloc
     288          32 :          CALL cp_dbcsr_sm_fm_multiply(smat, cloc, smo, ncol=norb)
     289             :          CALL parallel_gemm('T', 'N', norb, norb, nao, 1.0_dp, moref, &
     290          32 :                             smo, 0.0_dp, rotmat(ispin))
     291          94 :          CALL cp_fm_release(smo)
     292             :       END DO
     293             : 
     294             :       ! calculate occupation matrix
     295          30 :       IF (.NOT. uocc) THEN
     296           6 :          ALLOCATE (fij_mat(nspin))
     297           4 :          DO ispin = 1, nspin
     298           2 :             CALL cp_fm_create(fij_mat(ispin), rotmat(ispin)%matrix_struct)
     299           2 :             CALL cp_fm_set_all(fij_mat(ispin), 0.0_dp)
     300           2 :             CALL cp_fm_create(smo, rotmat(ispin)%matrix_struct)
     301             :             ! fii = f
     302           2 :             CALL get_mo_set(mos(ispin), nmo=norb, occupation_numbers=occupation_numbers)
     303          54 :             DO iorb = 1, norb
     304          54 :                CALL cp_fm_set_element(fij_mat(ispin), iorb, iorb, occupation_numbers(iorb))
     305             :             END DO
     306             :             ! fij = U(T)*f*U
     307             :             CALL parallel_gemm('N', 'N', norb, norb, norb, 1.0_dp, fij_mat(ispin), &
     308           2 :                                rotmat(ispin), 0.0_dp, smo)
     309             :             CALL parallel_gemm('T', 'N', norb, norb, norb, 1.0_dp, rotmat(ispin), &
     310           2 :                                smo, 0.0_dp, fij_mat(ispin))
     311           6 :             CALL cp_fm_release(smo)
     312             :          END DO
     313             :       END IF
     314             : 
     315             :       ! localized orbitals in IAO basis => CIAO
     316          92 :       ALLOCATE (ciao(nspin))
     317          62 :       DO ispin = 1, nspin
     318          32 :          CALL get_mo_set(mos_loc(ispin), mo_coeff=cloc)
     319          32 :          CALL cp_fm_get_info(cloc, nrow_global=nao, ncol_global=norb)
     320          32 :          CALL cp_fm_get_info(c_iao_coef(ispin), ncol_global=nref)
     321          32 :          CALL cp_fm_create(smo, cloc%matrix_struct)
     322          32 :          NULLIFY (fm_struct)
     323             :          CALL cp_fm_struct_create(fm_struct, nrow_global=nref, &
     324          32 :                                   template_fmstruct=cloc%matrix_struct)
     325          32 :          CALL cp_fm_create(ciao(ispin), fm_struct)
     326          32 :          CALL cp_fm_struct_release(fm_struct)
     327             :          ! CIAO = A(T)*S*C
     328          32 :          CALL cp_dbcsr_sm_fm_multiply(smat, cloc, smo, ncol=norb)
     329             :          CALL parallel_gemm('T', 'N', nref, norb, nao, 1.0_dp, c_iao_coef(ispin), &
     330          32 :                             smo, 0.0_dp, ciao(ispin))
     331          94 :          CALL cp_fm_release(smo)
     332             :       END DO
     333             : 
     334             :       ! Reference basis set
     335          30 :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set)
     336          30 :       nkind = SIZE(qs_kind_set)
     337         148 :       ALLOCATE (ref_basis_set_list(nkind))
     338          88 :       DO ikind = 1, nkind
     339          58 :          qs_kind => qs_kind_set(ikind)
     340          58 :          NULLIFY (ref_basis_set_list(ikind)%gto_basis_set)
     341          58 :          NULLIFY (refbasis)
     342          58 :          CALL get_qs_kind(qs_kind=qs_kind, basis_set=refbasis, basis_type="MIN")
     343          88 :          IF (ASSOCIATED(refbasis)) ref_basis_set_list(ikind)%gto_basis_set => refbasis
     344             :       END DO
     345          30 :       CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, natom=natom)
     346          90 :       ALLOCATE (refbas_blk_sizes(natom))
     347             :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=refbas_blk_sizes, &
     348          30 :                             basis=ref_basis_set_list)
     349             : 
     350             :       ! Atomic orbital weights
     351          92 :       ALLOCATE (orb_weight(nspin))
     352          90 :       ALLOCATE (mcharge(natom, 1))
     353          62 :       DO ispin = 1, nspin
     354          32 :          CALL get_mo_set(mos_loc(ispin), mo_coeff=cloc)
     355          32 :          NULLIFY (fm_struct)
     356             :          CALL cp_fm_struct_create(fm_struct, nrow_global=natom, &
     357          32 :                                   template_fmstruct=cloc%matrix_struct)
     358          32 :          CALL cp_fm_create(orb_weight(ispin), fm_struct)
     359          32 :          CALL cp_fm_struct_release(fm_struct)
     360          62 :          CALL cp_fm_set_all(orb_weight(ispin), 0.0_dp)
     361             :       END DO
     362             :       !
     363          30 :       CALL dbcsr_get_info(smat, distribution=dbcsr_dist)
     364             :       CALL dbcsr_create(matrix=dmat, name="DMAT", &
     365             :                         dist=dbcsr_dist, matrix_type=dbcsr_type_symmetric, &
     366             :                         row_blk_size=refbas_blk_sizes, col_blk_size=refbas_blk_sizes, &
     367          30 :                         nze=0)
     368          30 :       CALL dbcsr_reserve_diag_blocks(dmat)
     369             :       !
     370          30 :       NULLIFY (fm_struct)
     371             :       CALL cp_fm_struct_create(fm_struct, ncol_global=1, &
     372          30 :                                template_fmstruct=ciao(1)%matrix_struct)
     373          30 :       CALL cp_fm_create(cvec, fm_struct)
     374          30 :       CALL cp_fm_create(cvec2, fm_struct)
     375          30 :       CALL cp_fm_struct_release(fm_struct)
     376             :       !
     377          62 :       DO ispin = 1, nspin
     378             :          CALL get_mo_set(mos_loc(ispin), &
     379             :                          mo_coeff=cloc, nmo=norb, &
     380          32 :                          occupation_numbers=occupation_numbers)
     381          62 :          IF (uocc) THEN
     382             :             ! uniform occupation
     383         158 :             DO iorb = 1, norb
     384         128 :                CALL cp_fm_to_fm(ciao(ispin), cvec, ncol=1, source_start=iorb, target_start=1)
     385         128 :                focc = occupation_numbers(iorb)
     386         128 :                CALL dbcsr_set(dmat, 0.0_dp)
     387         128 :                CALL cp_dbcsr_plus_fm_fm_t(dmat, cvec, ncol=1, alpha=focc)
     388         128 :                CALL iao_charges(dmat, mcharge(:, 1))
     389             :                CALL cp_fm_set_submatrix(orb_weight(ispin), mcharge, start_row=1, &
     390         128 :                                         start_col=iorb, n_rows=natom, n_cols=1)
     391         560 :                checksum = SUM(mcharge(:, 1))
     392         158 :                IF (ABS(focc - checksum) > 1.E-6_dp) THEN
     393           0 :                   CALL cp_warn(__LOCATION__, "Sum of atomic orbital weights is incorrect")
     394           0 :                   IF (unit_nr > 0) THEN
     395             :                      WRITE (UNIT=unit_nr, FMT="(T2,A,F10.6,T40,A,F10.6)") &
     396           0 :                         "Orbital occupation:", focc, &
     397           0 :                         "Sum of atomic orbital weights:", checksum
     398             :                   END IF
     399             :                END IF
     400             :             END DO
     401             :          ELSE
     402             :             ! non-diagonal occupation matrix
     403           6 :             ALLOCATE (odiag(norb))
     404           2 :             CALL cp_fm_get_diag(fij_mat(ispin), odiag)
     405          54 :             DO iorb = 1, norb
     406          52 :                IF (odiag(iorb) < 1.E-8_dp) CYCLE
     407          44 :                CALL dbcsr_set(dmat, 0.0_dp)
     408          44 :                CALL cp_fm_to_fm(ciao(ispin), cvec, ncol=1, source_start=iorb, target_start=1)
     409        1188 :                DO jorb = 1, norb
     410        1144 :                   CALL cp_fm_get_element(fij_mat(ispin), iorb, jorb, focc)
     411        1144 :                   IF (focc < 1.E-12_dp) CYCLE
     412         542 :                   CALL cp_fm_to_fm(ciao(ispin), cvec2, ncol=1, source_start=jorb, target_start=1)
     413        1730 :                   CALL cp_dbcsr_plus_fm_fm_t(dmat, cvec, cvec2, 1, alpha=focc, symmetry_mode=1)
     414             :                END DO
     415          44 :                CALL iao_charges(dmat, mcharge(:, 1))
     416         396 :                checksum = SUM(mcharge(:, 1))
     417          44 :                focc = odiag(iorb)
     418          44 :                IF (ABS(focc - checksum) > 1.E-6_dp) THEN
     419           0 :                   CALL cp_warn(__LOCATION__, "Sum of atomic orbital weights is incorrect")
     420           0 :                   IF (unit_nr > 0) THEN
     421             :                      WRITE (UNIT=unit_nr, FMT="(T2,A,F10.6,T40,A,F10.6)") &
     422           0 :                         "Orbital occupation:", focc, &
     423           0 :                         "Sum of atomic orbital weights:", checksum
     424             :                   END IF
     425             :                END IF
     426         396 :                mcharge(:, 1) = mcharge(:, 1)/focc
     427             :                CALL cp_fm_set_submatrix(orb_weight(ispin), mcharge, start_row=1, &
     428          54 :                                         start_col=iorb, n_rows=natom, n_cols=1)
     429             :             END DO
     430           2 :             DEALLOCATE (odiag)
     431             :          END IF
     432             :       END DO
     433          30 :       DEALLOCATE (mcharge)
     434          30 :       CALL dbcsr_release(dmat)
     435          30 :       CALL cp_fm_release(cvec)
     436          30 :       CALL cp_fm_release(cvec2)
     437             : 
     438             :       ! energy arrays
     439         150 :       ALLOCATE (atener(natom), ateks(natom), atecc(natom))
     440         120 :       ALLOCATE (ate1xc(natom), ate1h(natom), atewald(natom))
     441         136 :       atener = 0.0_dp
     442         136 :       ateks = 0.0_dp
     443         136 :       atecc = 0.0_dp
     444         136 :       ate1xc = 0.0_dp
     445         136 :       ate1h = 0.0_dp
     446         136 :       atewald = 0.0_dp
     447          30 :       IF (detailed_ener) THEN
     448          30 :          ALLOCATE (atdet(natom, 10), atmul(natom, 10), amval(natom))
     449         246 :          atdet = 0.0_dp
     450         246 :          atmul = 0.0_dp
     451             :       END IF
     452             :       ! atom dependent density matrix
     453          30 :       CALL dbcsr_create(dkmat, template=smat)
     454          30 :       CALL dbcsr_copy(dkmat, smat)
     455          30 :       CALL dbcsr_set(dkmat, 0.0_dp)
     456             :       ! KS matrix + correction
     457          30 :       CALL get_qs_env(qs_env, matrix_h=matrix_h, matrix_ks=matrix_ks, kinetic=matrix_t)
     458         214 :       ALLOCATE (ks_mat(nspin), vhxc_mat(nspin), exc_mat(1))
     459          62 :       DO ispin = 1, nspin
     460          32 :          ALLOCATE (ks_mat(ispin)%matrix)
     461          32 :          CALL dbcsr_create(ks_mat(ispin)%matrix, template=matrix_h(1)%matrix)
     462          32 :          CALL dbcsr_copy(ks_mat(ispin)%matrix, matrix_h(1)%matrix)
     463          32 :          CALL dbcsr_add(ks_mat(ispin)%matrix, matrix_ks(ispin)%matrix, 1.0_dp, 1.0_dp)
     464          32 :          CALL dbcsr_scale(ks_mat(ispin)%matrix, 0.5_dp)
     465             :          !
     466          32 :          ALLOCATE (vhxc_mat(ispin)%matrix)
     467          32 :          CALL dbcsr_create(vhxc_mat(ispin)%matrix, template=smat)
     468          32 :          CALL dbcsr_copy(vhxc_mat(ispin)%matrix, smat)
     469          62 :          CALL dbcsr_set(vhxc_mat(ispin)%matrix, 0.0_dp)
     470             :       END DO
     471          30 :       ALLOCATE (exc_mat(1)%matrix)
     472          30 :       CALL dbcsr_create(exc_mat(1)%matrix, template=smat)
     473          30 :       CALL dbcsr_copy(exc_mat(1)%matrix, smat)
     474          30 :       CALL dbcsr_set(exc_mat(1)%matrix, 0.0_dp)
     475             :       !
     476          30 :       CALL vhxc_correction(qs_env, vhxc_mat, exc_mat, atecc, ate1xc, ate1h)
     477             :       !
     478          30 :       IF (ewald_correction) THEN
     479           2 :          ALLOCATE (dve_mat%matrix)
     480           2 :          CALL dbcsr_create(dve_mat%matrix, template=matrix_h(1)%matrix)
     481           2 :          CALL dbcsr_copy(dve_mat%matrix, matrix_h(1)%matrix)
     482           2 :          CALL dbcsr_set(dve_mat%matrix, 0.0_dp)
     483           2 :          CALL vh_ewald_correction(qs_env, ealpha, dve_mat, atewald)
     484             :       END IF
     485             :       !
     486          62 :       DO ispin = 1, nspin
     487          62 :          CALL dbcsr_add(ks_mat(ispin)%matrix, vhxc_mat(ispin)%matrix, 1.0_dp, 1.0_dp)
     488             :       END DO
     489             :       !
     490          30 :       IF (detailed_ener .AND. do_hfx) THEN
     491           6 :          ALLOCATE (matrix_hfx(nspin))
     492           4 :          DO ispin = 1, nspin
     493           2 :             ALLOCATE (matrix_hfx(nspin)%matrix)
     494           2 :             CALL dbcsr_create(matrix_hfx(ispin)%matrix, template=smat)
     495           2 :             CALL dbcsr_copy(matrix_hfx(ispin)%matrix, smat)
     496           4 :             CALL dbcsr_set(matrix_hfx(ispin)%matrix, 0.0_dp)
     497             :          END DO
     498           2 :          CALL get_hfx_ks_matrix(qs_env, matrix_hfx)
     499             :       END IF
     500             :       ! Loop over spins and atoms
     501          62 :       DO ispin = 1, nspin
     502          32 :          CALL get_mo_set(mos_loc(ispin), mo_coeff=cloc, nmo=norb)
     503          96 :          ALLOCATE (mweight(1, norb))
     504         144 :          DO iatom = 1, natom
     505             :             CALL cp_fm_get_submatrix(orb_weight(ispin), mweight, start_row=iatom, &
     506         112 :                                      start_col=1, n_rows=1, n_cols=norb)
     507         112 :             IF (uocc) THEN
     508          96 :                CALL iao_calculate_dmat(cloc, dkmat, mweight(1, :), .FALSE.)
     509             :             ELSE
     510          16 :                CALL iao_calculate_dmat(cloc, dkmat, mweight(1, :), fij_mat(ispin))
     511             :             END IF
     512         112 :             CALL dbcsr_dot(dkmat, ks_mat(ispin)%matrix, ecc)
     513         112 :             ateks(iatom) = ateks(iatom) + ecc
     514             :             !
     515         112 :             IF (detailed_ener) THEN
     516          18 :                CALL dbcsr_dot(dkmat, matrix_t(1)%matrix, e1)
     517          18 :                atdet(iatom, 1) = atdet(iatom, 1) + e1
     518          18 :                CALL dbcsr_dot(dkmat, matrix_h(1)%matrix, e2)
     519          18 :                atdet(iatom, 2) = atdet(iatom, 2) + (e2 - e1)
     520          18 :                IF (do_hfx) THEN
     521           6 :                   CALL dbcsr_scale(matrix_hfx(ispin)%matrix, 0.5_dp)
     522           6 :                   CALL dbcsr_dot(dkmat, matrix_hfx(ispin)%matrix, ehfx)
     523           6 :                   atdet(iatom, 5) = atdet(iatom, 5) + ehfx
     524           6 :                   CALL dbcsr_scale(matrix_hfx(ispin)%matrix, 2.0_dp)
     525             :                ELSE
     526          12 :                   ehfx = 0.0_dp
     527             :                END IF
     528          18 :                CALL dbcsr_dot(dkmat, exc_mat(1)%matrix, e1)
     529          18 :                atdet(iatom, 3) = atdet(iatom, 3) + ecc - e2 - e1 - ehfx
     530          18 :                atdet(iatom, 4) = atdet(iatom, 4) + e1
     531             :             END IF
     532         144 :             IF (ewald_correction) THEN
     533           6 :                CALL dbcsr_dot(dkmat, dve_mat%matrix, ecc)
     534           6 :                atewald(iatom) = atewald(iatom) + ecc
     535             :             END IF
     536             :             !
     537             :          END DO
     538          94 :          DEALLOCATE (mweight)
     539             :       END DO
     540             :       !
     541          30 :       IF (detailed_ener) THEN
     542             :          ! Mulliken
     543           6 :          CALL get_qs_env(qs_env, rho=rho, para_env=para_env)
     544           6 :          CALL qs_rho_get(rho, rho_ao=matrix_p)
     545             :          ! kinetic energy
     546          12 :          DO ispin = 1, nspin
     547             :             CALL mulliken_charges(matrix_p(ispin)%matrix, matrix_t(1)%matrix, &
     548           6 :                                   para_env, amval)
     549          24 :             atmul(1:natom, 1) = atmul(1:natom, 1) + amval(1:natom)
     550             :             CALL mulliken_charges(matrix_p(ispin)%matrix, matrix_h(1)%matrix, &
     551           6 :                                   para_env, amval)
     552          24 :             atmul(1:natom, 2) = atmul(1:natom, 2) + amval(1:natom)
     553          24 :             atmul(1:natom, 3) = atmul(1:natom, 3) - amval(1:natom)
     554             :             CALL mulliken_charges(matrix_p(ispin)%matrix, ks_mat(ispin)%matrix, &
     555           6 :                                   para_env, amval)
     556          24 :             atmul(1:natom, 3) = atmul(1:natom, 3) + amval(1:natom)
     557           6 :             IF (do_hfx) THEN
     558             :                CALL mulliken_charges(matrix_p(ispin)%matrix, matrix_hfx(ispin)%matrix, &
     559           2 :                                      para_env, amval)
     560           8 :                atmul(1:natom, 5) = atmul(1:natom, 5) + 0.5_dp*amval(1:natom)
     561           8 :                atmul(1:natom, 3) = atmul(1:natom, 3) - 0.5_dp*amval(1:natom)
     562             :             END IF
     563             :             CALL mulliken_charges(matrix_p(ispin)%matrix, exc_mat(1)%matrix, &
     564           6 :                                   para_env, amval)
     565          24 :             atmul(1:natom, 4) = atmul(1:natom, 4) + amval(1:natom)
     566          30 :             atmul(1:natom, 3) = atmul(1:natom, 3) - amval(1:natom)
     567             :          END DO
     568          24 :          atmul(1:natom, 2) = atmul(1:natom, 2) - atmul(1:natom, 1)
     569             :       END IF
     570             :       !
     571          30 :       CALL dbcsr_release(dkmat)
     572          62 :       DO ispin = 1, nspin
     573          32 :          CALL dbcsr_release(ks_mat(ispin)%matrix)
     574          32 :          CALL dbcsr_release(vhxc_mat(ispin)%matrix)
     575          32 :          DEALLOCATE (ks_mat(ispin)%matrix, vhxc_mat(ispin)%matrix)
     576          62 :          CALL deallocate_mo_set(mos_loc(ispin))
     577             :       END DO
     578          30 :       CALL dbcsr_release(exc_mat(1)%matrix)
     579          30 :       DEALLOCATE (exc_mat(1)%matrix)
     580          30 :       DEALLOCATE (ks_mat, vhxc_mat, exc_mat)
     581          30 :       DEALLOCATE (mos_loc)
     582          30 :       DEALLOCATE (refbas_blk_sizes)
     583          30 :       DEALLOCATE (ref_basis_set_list)
     584          30 :       IF (detailed_ener .AND. do_hfx) THEN
     585           4 :          DO ispin = 1, nspin
     586           2 :             CALL dbcsr_release(matrix_hfx(ispin)%matrix)
     587           4 :             DEALLOCATE (matrix_hfx(ispin)%matrix)
     588             :          END DO
     589           2 :          DEALLOCATE (matrix_hfx)
     590             :       END IF
     591          30 :       IF (ewald_correction) THEN
     592           2 :          CALL dbcsr_release(dve_mat%matrix)
     593           2 :          DEALLOCATE (dve_mat%matrix)
     594             :       END IF
     595          30 :       CALL cp_fm_release(orb_weight)
     596          30 :       CALL cp_fm_release(ciao)
     597          30 :       CALL cp_fm_release(rotmat)
     598          30 :       CALL cp_fm_release(c_iao_coef)
     599          30 :       IF (.NOT. uocc) THEN
     600           2 :          CALL cp_fm_release(fij_mat)
     601             :       END IF
     602             : 
     603          30 :       CALL get_qs_env(qs_env, para_env=para_env)
     604          30 :       group = para_env
     605             :       ! KS energy
     606         136 :       atener(1:natom) = ateks(1:natom)
     607             :       ! core energy corrections
     608          30 :       CALL group%sum(atecc)
     609         136 :       atener(1:natom) = atener(1:natom) + atecc(1:natom)
     610          48 :       IF (detailed_ener) atdet(1:natom, 6) = atdet(1:natom, 6) + atecc(1:natom)
     611             :       ! one center terms (GAPW)
     612          30 :       CALL group%sum(ate1xc)
     613          30 :       CALL group%sum(ate1h)
     614         136 :       atener(1:natom) = atener(1:natom) + ate1xc(1:natom) + ate1h(1:natom)
     615          30 :       IF (detailed_ener) THEN
     616           6 :          IF (gapw .OR. gapw_xc) atdet(1:natom, 8) = atdet(1:natom, 8) + ate1xc(1:natom)
     617           0 :          IF (gapw) atdet(1:natom, 9) = atdet(1:natom, 9) + ate1h(1:natom)
     618             :       END IF
     619             :       ! core correction
     620         136 :       atecc(1:natom) = 0.0_dp
     621          30 :       CALL calculate_ecore_overlap(qs_env, para_env, .FALSE., atecc=atecc)
     622          30 :       CALL group%sum(atecc)
     623         136 :       atener(1:natom) = atener(1:natom) + atecc(1:natom)
     624          48 :       IF (detailed_ener) atdet(1:natom, 7) = atdet(1:natom, 7) + atecc(1:natom)
     625          30 :       IF (ewald_correction) THEN
     626           8 :          atewald(1:natom) = atewald(1:natom) - atecc(1:natom)
     627             :       END IF
     628             :       ! e self
     629         136 :       atecc(1:natom) = 0.0_dp
     630          30 :       CALL calculate_ecore_self(qs_env, atecc=atecc)
     631          30 :       CALL group%sum(atecc)
     632         136 :       atener(1:natom) = atener(1:natom) + atecc(1:natom)
     633          48 :       IF (detailed_ener) atdet(1:natom, 7) = atdet(1:natom, 7) + atecc(1:natom)
     634          30 :       IF (ewald_correction) THEN
     635           8 :          atewald(1:natom) = atewald(1:natom) - atecc(1:natom)
     636           2 :          CALL calculate_ecore_alpha(qs_env, ealpha, atewald)
     637             :       END IF
     638             :       ! vdW pair-potentials
     639         136 :       atecc(1:natom) = 0.0_dp
     640          30 :       CALL get_qs_env(qs_env=qs_env, dispersion_env=dispersion_env)
     641          30 :       CALL calculate_dispersion_pairpot(qs_env, dispersion_env, evdw, .FALSE., atevdw=atecc)
     642             :       ! Pair potential gCP energy
     643          30 :       CALL get_qs_env(qs_env=qs_env, gcp_env=gcp_env)
     644          30 :       IF (ASSOCIATED(gcp_env)) THEN
     645          30 :          CALL calculate_gcp_pairpot(qs_env, gcp_env, egcp, .FALSE., ategcp=atecc)
     646             :       END IF
     647          30 :       CALL group%sum(atecc)
     648         136 :       atener(1:natom) = atener(1:natom) + atecc(1:natom)
     649          48 :       IF (detailed_ener) atdet(1:natom, 10) = atdet(1:natom, 10) + atecc(1:natom)
     650             :       ! distribute the entropic energy
     651          30 :       CALL get_qs_env(qs_env, energy=energy)
     652          30 :       ekts = energy%kts/REAL(natom, KIND=dp)
     653         136 :       atener(1:natom) = atener(1:natom) + ekts
     654             : 
     655          30 :       IF (detailed_ener) THEN
     656           6 :          IF (unit_nr > 0) THEN
     657           3 :             WRITE (unit_nr, FMT="(/,T2,A)") "Detailed IAO Atomic Energy Components "
     658           3 :             CALL write_atdet(unit_nr, atdet(:, 1), "Kinetic Energy")
     659           3 :             CALL write_atdet(unit_nr, atdet(:, 2), "Short-Range Core and/or PP Energy")
     660           3 :             CALL write_atdet(unit_nr, atdet(:, 3), "Hartree Energy (long-ranged part)")
     661           3 :             CALL write_atdet(unit_nr, atdet(:, 5), "Exact Exchange Energy")
     662           3 :             CALL write_atdet(unit_nr, atdet(:, 4), "Exchange-Correlation Energy")
     663           3 :             CALL write_atdet(unit_nr, atdet(:, 6), "Atomic Core Hartree: Int(nc V(n+nc) dx")
     664           3 :             CALL write_atdet(unit_nr, atdet(:, 7), "Core Self Energy Corrections")
     665           3 :             IF (gapw) THEN
     666           0 :                CALL write_atdet(unit_nr, atdet(:, 9), "GAPW: 1-center Hartree Energy")
     667             :             END IF
     668           3 :             IF (gapw .OR. gapw_xc) THEN
     669           0 :                CALL write_atdet(unit_nr, atdet(:, 8), "GAPW: 1-center XC Energy")
     670             :             END IF
     671           3 :             IF (ABS(evdw) > 1.E-14_dp) THEN
     672           0 :                CALL write_atdet(unit_nr, atdet(:, 10), "vdW Pairpotential Energy")
     673             :             END IF
     674          12 :             DO iatom = 1, natom
     675         102 :                atecc(iatom) = SUM(atdet(iatom, 1:10)) - atener(iatom)
     676             :             END DO
     677           3 :             CALL write_atdet(unit_nr, atecc(:), "Missing Energy")
     678             :             !
     679           3 :             WRITE (unit_nr, FMT="(/,T2,A)") "Detailed Mulliken Atomic Energy Components "
     680           3 :             CALL write_atdet(unit_nr, atmul(:, 1), "Kinetic Energy")
     681           3 :             CALL write_atdet(unit_nr, atmul(:, 2), "Short-Range Core and/or PP Energy")
     682           3 :             CALL write_atdet(unit_nr, atmul(:, 3), "Hartree Energy (long-ranged part)")
     683           3 :             CALL write_atdet(unit_nr, atmul(:, 5), "Exact Exchange Energy")
     684           3 :             CALL write_atdet(unit_nr, atmul(:, 4), "Exchange-Correlation Energy")
     685           3 :             CALL write_atdet(unit_nr, atdet(:, 6), "Atomic Core Hartree: Int(nc V(n+nc) dx")
     686           3 :             CALL write_atdet(unit_nr, atdet(:, 7), "Core Self Energy Corrections")
     687           3 :             IF (gapw) THEN
     688           0 :                CALL write_atdet(unit_nr, atdet(:, 9), "GAPW: 1-center Hartree Energy")
     689             :             END IF
     690           3 :             IF (gapw .OR. gapw_xc) THEN
     691           0 :                CALL write_atdet(unit_nr, atdet(:, 8), "GAPW: 1-center XC Energy")
     692             :             END IF
     693           3 :             IF (ABS(evdw) > 1.E-14_dp) THEN
     694           0 :                CALL write_atdet(unit_nr, atdet(:, 10), "vdW Pairpotential Energy")
     695             :             END IF
     696             :          END IF
     697             :       END IF
     698             : 
     699          30 :       IF (unit_nr > 0) THEN
     700          15 :          e_pot = energy%total
     701          15 :          ateps = 1.E-6_dp
     702          15 :          CALL write_atener(unit_nr, particle_set, atener, "Atomic Energy Decomposition")
     703          68 :          sum_energy = SUM(atener(:))
     704          15 :          checksum = ABS(e_pot - sum_energy)
     705             :          WRITE (UNIT=unit_nr, FMT="((T2,A,T56,F25.13))") &
     706          15 :             "Potential energy (Atomic):", sum_energy, &
     707          15 :             "Potential energy (Total) :", e_pot, &
     708          30 :             "Difference               :", checksum
     709          15 :          CPASSERT((checksum < ateps*ABS(e_pot)))
     710             :          !
     711          15 :          IF (ewald_correction) THEN
     712           1 :             WRITE (UNIT=unit_nr, FMT="(/,(T2,A,F10.3,A))") "Universal Ewald Parameter: ", ealpha, " [Angstrom]"
     713           1 :             CALL write_atener(unit_nr, particle_set, atewald, "Change in Atomic Energy Decomposition")
     714           4 :             sum_energy = SUM(atewald(:))
     715             :             WRITE (UNIT=unit_nr, FMT="((T2,A,T56,F25.13))") &
     716           1 :                "Total Change in Potential energy:", sum_energy
     717             :          END IF
     718             :       END IF
     719             : 
     720          30 :       IF (detailed_ener) THEN
     721           6 :          DEALLOCATE (atdet, atmul, amval)
     722             :       END IF
     723             : 
     724          30 :       IF (unit_nr > 0) THEN
     725             :          WRITE (UNIT=unit_nr, FMT="(/,T2,A)") &
     726          15 :             "!--------------------------- END OF ED ANALYSIS ------------------------------!"
     727             :       END IF
     728          30 :       DEALLOCATE (bcenter)
     729          30 :       DEALLOCATE (atener, ateks, atecc, ate1xc, ate1h, atewald)
     730             : 
     731          30 :       CALL timestop(handle)
     732             : 
     733         266 :    END SUBROUTINE edmf_analysis
     734             : 
     735             : ! **************************************************************************************************
     736             : !> \brief ...
     737             : !> \param qs_env ...
     738             : !> \param vhxc_mat ...
     739             : !> \param exc_mat ...
     740             : !> \param atecc ...
     741             : !> \param ate1xc ...
     742             : !> \param ate1h ...
     743             : ! **************************************************************************************************
     744          30 :    SUBROUTINE vhxc_correction(qs_env, vhxc_mat, exc_mat, atecc, ate1xc, ate1h)
     745             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     746             :       TYPE(dbcsr_p_type), DIMENSION(:)                   :: vhxc_mat, exc_mat
     747             :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: atecc, ate1xc, ate1h
     748             : 
     749             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'vhxc_correction'
     750             : 
     751             :       INTEGER                                            :: handle, iatom, ispin, natom, nspins
     752             :       LOGICAL                                            :: do_admm_corr, gapw, gapw_xc
     753             :       REAL(KIND=dp)                                      :: eh1, exc1
     754             :       TYPE(admm_type), POINTER                           :: admm_env
     755          30 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     756          30 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_p
     757             :       TYPE(dft_control_type), POINTER                    :: dft_control
     758          30 :       TYPE(ecoul_1center_type), DIMENSION(:), POINTER    :: ecoul_1c
     759             :       TYPE(local_rho_type), POINTER                      :: local_rho_set
     760             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     761             :       TYPE(pw_env_type), POINTER                         :: pw_env
     762             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     763             :       TYPE(pw_r3d_rs_type)                               :: xc_den
     764          30 :       TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:)    :: vtau, vxc
     765             :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
     766             :       TYPE(qs_dispersion_type), POINTER                  :: dispersion_env
     767          30 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     768             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     769             :       TYPE(qs_rho_type), POINTER                         :: rho_struct
     770          30 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho_atom_set
     771             :       TYPE(section_vals_type), POINTER                   :: xc_fun_section, xc_section
     772             :       TYPE(xc_rho_cflags_type)                           :: needs
     773             : 
     774          30 :       CALL timeset(routineN, handle)
     775             : 
     776          30 :       CALL get_qs_env(qs_env, ks_env=ks_env, dft_control=dft_control, pw_env=pw_env)
     777             : 
     778          30 :       nspins = dft_control%nspins
     779          30 :       gapw = dft_control%qs_control%gapw
     780          30 :       gapw_xc = dft_control%qs_control%gapw_xc
     781          30 :       do_admm_corr = .FALSE.
     782          30 :       IF (dft_control%do_admm) THEN
     783           0 :          IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) do_admm_corr = .TRUE.
     784             :       END IF
     785             :       IF (do_admm_corr) THEN
     786           0 :          CALL get_qs_env(qs_env, admm_env=admm_env)
     787           0 :          xc_section => admm_env%xc_section_aux
     788             :       ELSE
     789          30 :          xc_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC")
     790             :       END IF
     791          30 :       xc_fun_section => section_vals_get_subs_vals(xc_section, "XC_FUNCTIONAL")
     792          30 :       needs = xc_functionals_get_needs(xc_fun_section, (nspins == 2), .TRUE.)
     793             : 
     794          30 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
     795          30 :       CALL auxbas_pw_pool%create_pw(xc_den)
     796         122 :       ALLOCATE (vxc(nspins))
     797          62 :       DO ispin = 1, nspins
     798          62 :          CALL auxbas_pw_pool%create_pw(vxc(ispin))
     799             :       END DO
     800          30 :       IF (needs%tau .OR. needs%tau_spin) THEN
     801          24 :          ALLOCATE (vtau(nspins))
     802          16 :          DO ispin = 1, nspins
     803          38 :             CALL auxbas_pw_pool%create_pw(vtau(ispin))
     804             :          END DO
     805             :       END IF
     806             : 
     807             :       ! Nuclear charge correction
     808          30 :       CALL get_qs_env(qs_env, v_hartree_rspace=v_hartree_rspace)
     809          30 :       CALL integrate_v_core_rspace(v_hartree_rspace, qs_env, atecc=atecc)
     810          30 :       IF (gapw .OR. gapw_xc) THEN
     811             :          CALL get_qs_env(qs_env=qs_env, local_rho_set=local_rho_set, &
     812             :                          rho_atom_set=rho_atom_set, ecoul_1c=ecoul_1c, &
     813           8 :                          natom=natom, para_env=para_env)
     814           8 :          CALL zero_rho_atom_integrals(rho_atom_set)
     815           8 :          CALL calculate_vxc_atom(qs_env, .FALSE., exc1)
     816           8 :          IF (gapw) THEN
     817           6 :             CALL Vh_1c_gg_integrals(qs_env, eh1, ecoul_1c, local_rho_set, para_env, tddft=.FALSE.)
     818           6 :             CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set)
     819             :             CALL integrate_vhg0_rspace(qs_env, v_hartree_rspace, para_env, calculate_forces=.FALSE., &
     820           6 :                                        local_rho_set=local_rho_set, atener=atecc)
     821             :          END IF
     822             :       END IF
     823             : 
     824           8 :       IF (gapw_xc) THEN
     825           2 :          CALL get_qs_env(qs_env, rho_xc=rho_struct, dispersion_env=dispersion_env)
     826             :       ELSE
     827          28 :          CALL get_qs_env(qs_env, rho=rho_struct, dispersion_env=dispersion_env)
     828             :       END IF
     829             :       !
     830          30 :       CPASSERT(.NOT. do_admm_corr)
     831             :       !
     832          30 :       IF (needs%tau .OR. needs%tau_spin) THEN
     833             :          CALL qs_xc_density(ks_env, rho_struct, xc_section, dispersion_env=dispersion_env, &
     834           8 :                             xc_den=xc_den, vxc=vxc, vtau=vtau)
     835             :       ELSE
     836             :          CALL qs_xc_density(ks_env, rho_struct, xc_section, dispersion_env=dispersion_env, &
     837          22 :                             xc_den=xc_den, vxc=vxc)
     838             :       END IF
     839          62 :       DO ispin = 1, nspins
     840          32 :          CALL pw_scale(vxc(ispin), -0.5_dp)
     841          32 :          CALL pw_axpy(xc_den, vxc(ispin))
     842          32 :          CALL pw_scale(vxc(ispin), vxc(ispin)%pw_grid%dvol)
     843             :          CALL integrate_v_rspace(qs_env=qs_env, v_rspace=vxc(ispin), &
     844             :                                  hmat=vhxc_mat(ispin), calculate_forces=.FALSE., &
     845          32 :                                  gapw=(gapw .OR. gapw_xc))
     846          62 :          IF (needs%tau .OR. needs%tau_spin) THEN
     847           8 :             CALL pw_scale(vtau(ispin), -0.5_dp*vtau(ispin)%pw_grid%dvol)
     848             :             CALL integrate_v_rspace(qs_env=qs_env, v_rspace=vtau(ispin), &
     849             :                                     hmat=vhxc_mat(ispin), calculate_forces=.FALSE., &
     850           8 :                                     compute_tau=.TRUE., gapw=(gapw .OR. gapw_xc))
     851             :          END IF
     852             :       END DO
     853          30 :       CALL pw_scale(xc_den, xc_den%pw_grid%dvol)
     854             :       CALL integrate_v_rspace(qs_env=qs_env, v_rspace=xc_den, &
     855             :                               hmat=exc_mat(1), calculate_forces=.FALSE., &
     856          30 :                               gapw=(gapw .OR. gapw_xc))
     857             : 
     858          30 :       IF (gapw .OR. gapw_xc) THEN
     859             :          ! remove one-center potential matrix part
     860           8 :          CALL qs_rho_get(rho_struct, rho_ao_kp=matrix_p)
     861           8 :          CALL update_ks_atom(qs_env, vhxc_mat, matrix_p, forces=.FALSE., kscale=-0.5_dp)
     862             :          !
     863          32 :          DO iatom = 1, natom
     864             :             ate1xc(iatom) = ate1xc(iatom) + &
     865          32 :                             rho_atom_set(iatom)%exc_h - rho_atom_set(iatom)%exc_s
     866             :          END DO
     867           8 :          IF (gapw) THEN
     868          24 :             DO iatom = 1, natom
     869             :                ate1h(iatom) = ate1h(iatom) + &
     870             :                               ecoul_1c(iatom)%ecoul_1_h - ecoul_1c(iatom)%ecoul_1_s + &
     871          24 :                               ecoul_1c(iatom)%ecoul_1_z - ecoul_1c(iatom)%ecoul_1_0
     872             :             END DO
     873             :          END IF
     874             :       END IF
     875             : 
     876          30 :       CALL auxbas_pw_pool%give_back_pw(xc_den)
     877          62 :       DO ispin = 1, nspins
     878          62 :          CALL auxbas_pw_pool%give_back_pw(vxc(ispin))
     879             :       END DO
     880          30 :       IF (needs%tau .OR. needs%tau_spin) THEN
     881          16 :          DO ispin = 1, nspins
     882          38 :             CALL auxbas_pw_pool%give_back_pw(vtau(ispin))
     883             :          END DO
     884             :       END IF
     885             : 
     886          30 :       CALL timestop(handle)
     887             : 
     888          60 :    END SUBROUTINE vhxc_correction
     889             : 
     890             : ! **************************************************************************************************
     891             : !> \brief ...
     892             : !> \param qs_env ...
     893             : !> \param ealpha ...
     894             : !> \param vh_mat ...
     895             : !> \param atewd ...
     896             : ! **************************************************************************************************
     897           2 :    SUBROUTINE vh_ewald_correction(qs_env, ealpha, vh_mat, atewd)
     898             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     899             :       REAL(KIND=dp), INTENT(IN)                          :: ealpha
     900             :       TYPE(dbcsr_p_type)                                 :: vh_mat
     901             :       REAL(KIND=dp), DIMENSION(:), INTENT(INOUT)         :: atewd
     902             : 
     903             :       CHARACTER(len=*), PARAMETER :: routineN = 'vh_ewald_correction'
     904             : 
     905             :       INTEGER                                            :: handle, ikind, ispin, natom, nkind
     906             :       REAL(KIND=dp)                                      :: eps_core_charge, rhotot, zeff
     907             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: alpha, atecc, ccore
     908           2 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     909             :       TYPE(dft_control_type), POINTER                    :: dft_control
     910             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     911           2 :          POINTER                                         :: sab_orb, sac_ae
     912           2 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     913             :       TYPE(pw_c1d_gs_type)                               :: rho_tot_ewd_g, v_hewd_gspace
     914             :       TYPE(pw_env_type), POINTER                         :: pw_env
     915             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     916             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
     917             :       TYPE(pw_r3d_rs_type)                               :: rho_tot_ewd_r, v_hewd_rspace
     918           2 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r
     919             :       TYPE(pw_r3d_rs_type), POINTER                      :: v_hartree_rspace
     920           2 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     921             :       TYPE(qs_rho_type), POINTER                         :: rho
     922             : 
     923           2 :       CALL timeset(routineN, handle)
     924             : 
     925           2 :       natom = SIZE(atewd)
     926           6 :       ALLOCATE (atecc(natom))
     927             :       CALL get_qs_env(qs_env=qs_env, nkind=nkind, qs_kind_set=qs_kind_set, &
     928           2 :                       dft_control=dft_control)
     929           8 :       ALLOCATE (alpha(nkind), ccore(nkind))
     930           6 :       DO ikind = 1, nkind
     931           4 :          CALL get_qs_kind(qs_kind_set(ikind), zeff=zeff)
     932           4 :          alpha(ikind) = ealpha
     933           6 :          ccore(ikind) = zeff*(ealpha/pi)**1.5_dp
     934             :       END DO
     935             :       !
     936           2 :       CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
     937             :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
     938           2 :                       poisson_env=poisson_env)
     939             :       !
     940           2 :       CALL auxbas_pw_pool%create_pw(v_hewd_gspace)
     941           2 :       CALL auxbas_pw_pool%create_pw(v_hewd_rspace)
     942           2 :       CALL auxbas_pw_pool%create_pw(rho_tot_ewd_g)
     943           2 :       CALL auxbas_pw_pool%create_pw(rho_tot_ewd_r)
     944             :       rhotot = 0.0_dp
     945           2 :       CALL calculate_rho_core(rho_tot_ewd_r, rhotot, qs_env, calpha=alpha, ccore=ccore)
     946             :       ! Get the total density in g-space [ions + electrons]
     947           2 :       CALL get_qs_env(qs_env=qs_env, rho=rho)
     948           2 :       CALL qs_rho_get(rho, rho_r=rho_r)
     949           4 :       DO ispin = 1, dft_control%nspins
     950           4 :          CALL pw_axpy(rho_r(ispin), rho_tot_ewd_r)
     951             :       END DO
     952           2 :       CALL pw_transfer(rho_tot_ewd_r, rho_tot_ewd_g)
     953             :       !
     954           2 :       CALL pw_poisson_solve(poisson_env, density=rho_tot_ewd_g, vhartree=v_hewd_gspace)
     955           2 :       CALL pw_transfer(v_hewd_gspace, v_hewd_rspace)
     956           2 :       CALL pw_scale(v_hewd_rspace, v_hewd_rspace%pw_grid%dvol)
     957           8 :       atecc = 0.0_dp
     958           2 :       CALL integrate_v_gaussian_rspace(v_hewd_rspace, qs_env, alpha, ccore, atecc)
     959           8 :       atewd(1:natom) = atewd(1:natom) + atecc(1:natom)
     960             :       !
     961           8 :       atecc = 0.0_dp
     962           2 :       CALL get_qs_env(qs_env, v_hartree_rspace=v_hartree_rspace)
     963           2 :       CALL integrate_v_core_rspace(v_hartree_rspace, qs_env, atecc=atecc)
     964           8 :       atewd(1:natom) = atewd(1:natom) - atecc(1:natom)
     965             :       !
     966           2 :       CALL pw_axpy(v_hartree_rspace, v_hewd_rspace, -1.0_dp)
     967           2 :       CALL dbcsr_set(vh_mat%matrix, 0.0_dp)
     968             :       CALL integrate_v_rspace(qs_env=qs_env, v_rspace=v_hewd_rspace, hmat=vh_mat, &
     969           2 :                               calculate_forces=.FALSE.)
     970             :       !
     971           2 :       CALL dbcsr_scale(vh_mat%matrix, 0.5_dp)
     972             :       !
     973             :       ! delta erfc
     974           2 :       eps_core_charge = dft_control%qs_control%eps_core_charge
     975             :       CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, &
     976           2 :                       particle_set=particle_set, sab_orb=sab_orb, sac_ppl=sac_ae)
     977             :       CALL build_erfc(vh_mat, qs_kind_set, atomic_kind_set, particle_set, &
     978           2 :                       alpha, ccore, eps_core_charge, sab_orb, sac_ae)
     979           2 :       CALL dbcsr_scale(vh_mat%matrix, -1.0_dp)
     980           6 :       DO ikind = 1, nkind
     981             :          CALL get_qs_kind(qs_kind_set(ikind), alpha_core_charge=alpha(ikind), &
     982           6 :                           ccore_charge=ccore(ikind))
     983             :       END DO
     984             :       CALL build_erfc(vh_mat, qs_kind_set, atomic_kind_set, particle_set, &
     985           2 :                       alpha, ccore, eps_core_charge, sab_orb, sac_ae)
     986           2 :       CALL dbcsr_scale(vh_mat%matrix, -1.0_dp)
     987             :       !
     988           2 :       CALL auxbas_pw_pool%give_back_pw(v_hewd_gspace)
     989           2 :       CALL auxbas_pw_pool%give_back_pw(v_hewd_rspace)
     990           2 :       CALL auxbas_pw_pool%give_back_pw(rho_tot_ewd_g)
     991           2 :       CALL auxbas_pw_pool%give_back_pw(rho_tot_ewd_r)
     992           2 :       DEALLOCATE (atecc)
     993           2 :       DEALLOCATE (alpha, ccore)
     994             : 
     995           2 :       CALL timestop(handle)
     996             : 
     997           4 :    END SUBROUTINE vh_ewald_correction
     998             : 
     999             : ! **************************************************************************************************
    1000             : !> \brief ...
    1001             : !> \param qs_env ...
    1002             : !> \param matrix_hfx ...
    1003             : ! **************************************************************************************************
    1004           2 :    SUBROUTINE get_hfx_ks_matrix(qs_env, matrix_hfx)
    1005             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1006             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_hfx
    1007             : 
    1008             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'get_hfx_ks_matrix'
    1009             : 
    1010             :       INTEGER                                            :: handle
    1011           2 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_p
    1012             :       TYPE(qs_rho_type), POINTER                         :: rho
    1013             : 
    1014           2 :       CALL timeset(routineN, handle)
    1015             : 
    1016           2 :       CALL get_qs_env(qs_env, rho=rho)
    1017           2 :       CALL qs_rho_get(rho, rho_ao=matrix_p)
    1018             :       CALL tddft_hfx_matrix(matrix_hfx, matrix_p, qs_env, update_energy=.FALSE., &
    1019           2 :                             recalc_integrals=.FALSE.)
    1020             : 
    1021           2 :       CALL timestop(handle)
    1022             : 
    1023           2 :    END SUBROUTINE get_hfx_ks_matrix
    1024             : ! **************************************************************************************************
    1025             : !> \brief Write the atomic coordinates, types, and energies
    1026             : !> \param iounit ...
    1027             : !> \param particle_set ...
    1028             : !> \param atener ...
    1029             : !> \param label ...
    1030             : !> \date    05.06.2023
    1031             : !> \author  JGH
    1032             : !> \version 1.0
    1033             : ! **************************************************************************************************
    1034          16 :    SUBROUTINE write_atener(iounit, particle_set, atener, label)
    1035             : 
    1036             :       INTEGER, INTENT(IN)                                :: iounit
    1037             :       TYPE(particle_type), DIMENSION(:)                  :: particle_set
    1038             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: atener
    1039             :       CHARACTER(LEN=*), INTENT(IN)                       :: label
    1040             : 
    1041             :       INTEGER                                            :: i, natom
    1042             : 
    1043          16 :       IF (iounit > 0) THEN
    1044          16 :          WRITE (UNIT=iounit, FMT="(/,T2,A)") TRIM(label)
    1045             :          WRITE (UNIT=iounit, FMT="(T4,A,T30,A,T42,A,T54,A,T69,A)") &
    1046          16 :             "Atom  Element", "X", "Y", "Z", "Energy[a.u.]"
    1047          16 :          natom = SIZE(atener)
    1048          72 :          DO i = 1, natom
    1049          56 :             WRITE (UNIT=iounit, FMT="(I6,T12,A2,T24,3F12.6,F21.10)") i, &
    1050          56 :                TRIM(ADJUSTL(particle_set(i)%atomic_kind%element_symbol)), &
    1051         296 :                particle_set(i)%r(1:3)*angstrom, atener(i)
    1052             :          END DO
    1053          16 :          WRITE (UNIT=iounit, FMT="(A)") ""
    1054             :       END IF
    1055             : 
    1056          16 :    END SUBROUTINE write_atener
    1057             : 
    1058             : ! **************************************************************************************************
    1059             : !> \brief Write the one component of atomic energies
    1060             : !> \param iounit ...
    1061             : !> \param atener ...
    1062             : !> \param label ...
    1063             : !> \date    18.08.2023
    1064             : !> \author  JGH
    1065             : !> \version 1.0
    1066             : ! **************************************************************************************************
    1067          45 :    SUBROUTINE write_atdet(iounit, atener, label)
    1068             :       INTEGER, INTENT(IN)                                :: iounit
    1069             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: atener
    1070             :       CHARACTER(LEN=*), INTENT(IN)                       :: label
    1071             : 
    1072             :       INTEGER                                            :: natom
    1073             : 
    1074          45 :       IF (iounit > 0) THEN
    1075          45 :          natom = SIZE(atener)
    1076          45 :          WRITE (UNIT=iounit, FMT="(T2,A)") TRIM(label)
    1077          45 :          WRITE (UNIT=iounit, FMT="(5G16.8)") atener(1:natom)
    1078             :       END IF
    1079             : 
    1080          45 :    END SUBROUTINE write_atdet
    1081             : 
    1082             : END MODULE ed_analysis

Generated by: LCOV version 1.15