LCOV - code coverage report
Current view: top level - src - mp2.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:3db43b4) Lines: 95.5 % 381 364
Test Date: 2026-04-03 06:55:30 Functions: 100.0 % 3 3

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines to calculate MP2 energy
      10              : !> \par History
      11              : !>      05.2011 created [Mauro Del Ben]
      12              : !> \author Mauro Del Ben
      13              : ! **************************************************************************************************
      14              : MODULE mp2
      15              :    USE admm_types,                      ONLY: admm_type
      16              :    USE admm_utils,                      ONLY: admm_correct_for_eigenvalues,&
      17              :                                               admm_uncorrect_for_eigenvalues
      18              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      19              :                                               get_atomic_kind_set
      20              :    USE bibliography,                    ONLY: Bussy2023,&
      21              :                                               DelBen2012,&
      22              :                                               DelBen2015b,&
      23              :                                               Rybkin2016,&
      24              :                                               Stein2022,&
      25              :                                               Stein2024,&
      26              :                                               cite_reference
      27              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      28              :    USE cp_control_types,                ONLY: dft_control_type
      29              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      30              :                                               dbcsr_create,&
      31              :                                               dbcsr_get_info,&
      32              :                                               dbcsr_p_type
      33              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      34              :                                               dbcsr_allocate_matrix_set
      35              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale,&
      36              :                                               cp_fm_syrk,&
      37              :                                               cp_fm_triangular_invert,&
      38              :                                               cp_fm_uplo_to_full
      39              :    USE cp_fm_cholesky,                  ONLY: cp_fm_cholesky_decompose
      40              :    USE cp_fm_diag,                      ONLY: choose_eigv_solver
      41              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      42              :                                               cp_fm_struct_release,&
      43              :                                               cp_fm_struct_type
      44              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      45              :                                               cp_fm_get_submatrix,&
      46              :                                               cp_fm_release,&
      47              :                                               cp_fm_set_all,&
      48              :                                               cp_fm_to_fm,&
      49              :                                               cp_fm_type
      50              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      51              :                                               cp_logger_type
      52              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      53              :                                               cp_print_key_unit_nr
      54              :    USE exstates_types,                  ONLY: excited_energy_type
      55              :    USE hfx_exx,                         ONLY: calculate_exx
      56              :    USE hfx_types,                       ONLY: &
      57              :         alloc_containers, dealloc_containers, hfx_basis_info_type, hfx_basis_type, &
      58              :         hfx_container_type, hfx_create_basis_types, hfx_init_container, hfx_release_basis_types, &
      59              :         hfx_type
      60              :    USE input_constants,                 ONLY: cholesky_inverse,&
      61              :                                               cholesky_off,&
      62              :                                               do_eri_gpw,&
      63              :                                               do_eri_mme,&
      64              :                                               rpa_exchange_axk,&
      65              :                                               rpa_exchange_none,&
      66              :                                               rpa_exchange_sosex,&
      67              :                                               sigma_none
      68              :    USE input_section_types,             ONLY: section_vals_get,&
      69              :                                               section_vals_get_subs_vals,&
      70              :                                               section_vals_type
      71              :    USE kinds,                           ONLY: dp,&
      72              :                                               int_8
      73              :    USE kpoint_types,                    ONLY: kpoint_type
      74              :    USE machine,                         ONLY: m_flush,&
      75              :                                               m_memory,&
      76              :                                               m_walltime
      77              :    USE message_passing,                 ONLY: mp_para_env_type
      78              :    USE mp2_direct_method,               ONLY: mp2_direct_energy
      79              :    USE mp2_gpw,                         ONLY: mp2_gpw_main
      80              :    USE mp2_optimize_ri_basis,           ONLY: optimize_ri_basis_main
      81              :    USE mp2_types,                       ONLY: mp2_biel_type,&
      82              :                                               mp2_method_direct,&
      83              :                                               mp2_method_gpw,&
      84              :                                               mp2_ri_optimize_basis,&
      85              :                                               mp2_type,&
      86              :                                               ri_mp2_laplace,&
      87              :                                               ri_mp2_method_gpw,&
      88              :                                               ri_rpa_method_gpw
      89              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      90              :    USE particle_types,                  ONLY: particle_type
      91              :    USE qs_energy_types,                 ONLY: qs_energy_type
      92              :    USE qs_environment_types,            ONLY: get_qs_env,&
      93              :                                               qs_environment_type
      94              :    USE qs_kind_types,                   ONLY: qs_kind_type
      95              :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
      96              :                                               deallocate_mo_set,&
      97              :                                               get_mo_set,&
      98              :                                               init_mo_set,&
      99              :                                               mo_set_type
     100              :    USE qs_scf_methods,                  ONLY: eigensolver,&
     101              :                                               eigensolver_symm
     102              :    USE qs_scf_types,                    ONLY: qs_scf_env_type
     103              :    USE rpa_gw_sigma_x,                  ONLY: compute_vec_Sigma_x_minus_vxc_gw
     104              :    USE scf_control_types,               ONLY: scf_control_type
     105              :    USE virial_types,                    ONLY: virial_type
     106              : 
     107              : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num, omp_get_num_threads
     108              : 
     109              : #include "./base/base_uses.f90"
     110              : 
     111              :    IMPLICIT NONE
     112              : 
     113              :    PRIVATE
     114              : 
     115              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mp2'
     116              : 
     117              :    PUBLIC :: mp2_main
     118              : 
     119              : CONTAINS
     120              : 
     121              : ! **************************************************************************************************
     122              : !> \brief the main entry point for MP2 calculations
     123              : !> \param qs_env ...
     124              : !> \param calc_forces ...
     125              : !> \author Mauro Del Ben
     126              : ! **************************************************************************************************
     127          696 :    SUBROUTINE mp2_main(qs_env, calc_forces)
     128              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     129              :       LOGICAL, INTENT(IN)                                :: calc_forces
     130              : 
     131              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'mp2_main'
     132              : 
     133              :       INTEGER :: bin, cholesky_method, dimen, handle, handle2, i, i_thread, iatom, ii, ikind, &
     134              :          irep, ispin, max_nset, my_bin_size, n_rep_hf, n_threads, nao, natom, ndep, &
     135              :          nfullcols_total, nfullrows_total, nkind, nmo, nspins, unit_nr
     136              :       INTEGER(KIND=int_8)                                :: mem
     137          696 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: kind_of, nelec
     138              :       LOGICAL :: calc_ex, do_admm, do_admm_rpa_exx, do_dynamic_load_balancing, do_exx, do_gw, &
     139              :          do_im_time, do_kpoints_cubic_RPA, free_hfx_buffer, reuse_hfx, update_xc_energy
     140              :       REAL(KIND=dp) :: E_admm_from_GW(2), E_ex_from_GW, Emp2, Emp2_AA, Emp2_AA_Cou, Emp2_AA_ex, &
     141              :          Emp2_AB, Emp2_AB_Cou, Emp2_AB_ex, Emp2_BB, Emp2_BB_Cou, Emp2_BB_ex, Emp2_Cou, Emp2_ex, &
     142              :          Emp2_S, Emp2_T, maxocc, mem_real, t1, t2, t3
     143          696 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: evals
     144          696 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Auto
     145          696 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: C
     146          696 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: mo_eigenvalues
     147              :       TYPE(admm_type), POINTER                           :: admm_env
     148          696 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     149              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     150              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     151              :       TYPE(cp_fm_type)                                   :: evecs, fm_matrix_ks, fm_matrix_s, &
     152              :                                                             fm_matrix_work
     153              :       TYPE(cp_fm_type), POINTER                          :: fm_matrix_ks_red, fm_matrix_s_red, &
     154              :                                                             fm_work_red, mo_coeff
     155              :       TYPE(cp_logger_type), POINTER                      :: logger
     156          696 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     157          696 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks_transl, matrix_s_kp
     158              :       TYPE(dft_control_type), POINTER                    :: dft_control
     159              :       TYPE(excited_energy_type), POINTER                 :: ex_env
     160              :       TYPE(hfx_basis_info_type)                          :: basis_info
     161          696 :       TYPE(hfx_basis_type), DIMENSION(:), POINTER        :: basis_parameter
     162          696 :       TYPE(hfx_container_type), DIMENSION(:), POINTER    :: integral_containers
     163              :       TYPE(hfx_container_type), POINTER                  :: maxval_container
     164              :       TYPE(hfx_type), POINTER                            :: actual_x_data
     165              :       TYPE(kpoint_type), POINTER                         :: kpoints
     166          696 :       TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:)       :: mos_mp2
     167          696 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     168          696 :       TYPE(mp2_biel_type)                                :: mp2_biel
     169              :       TYPE(mp2_type), POINTER                            :: mp2_env
     170              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     171          696 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     172              :       TYPE(qs_energy_type), POINTER                      :: energy
     173          696 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     174              :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     175              :       TYPE(scf_control_type), POINTER                    :: scf_control
     176              :       TYPE(section_vals_type), POINTER                   :: hfx_sections, input
     177              :       TYPE(virial_type), POINTER                         :: virial
     178              : 
     179              :       ! If SCF has not converged we should abort MP2 calculation
     180          696 :       IF (qs_env%mp2_env%hf_fail) THEN
     181              :          CALL cp_abort(__LOCATION__, "SCF not converged: "// &
     182            0 :                        "not possible to run MP2")
     183              :       END IF
     184              : 
     185          696 :       NULLIFY (virial, dft_control, blacs_env, kpoints, fm_matrix_s_red, fm_matrix_ks_red, fm_work_red)
     186          696 :       CALL timeset(routineN, handle)
     187          696 :       logger => cp_get_default_logger()
     188              : 
     189          696 :       CALL cite_reference(DelBen2012)
     190              : 
     191          696 :       do_kpoints_cubic_RPA = qs_env%mp2_env%ri_rpa_im_time%do_im_time_kpoints
     192              : 
     193              :       ! for cubic RPA and GW, we have kpoints and therefore, we get other matrices later
     194          696 :       IF (do_kpoints_cubic_RPA) THEN
     195              : 
     196              :          CALL get_qs_env(qs_env, &
     197              :                          input=input, &
     198              :                          atomic_kind_set=atomic_kind_set, &
     199              :                          qs_kind_set=qs_kind_set, &
     200              :                          dft_control=dft_control, &
     201              :                          particle_set=particle_set, &
     202              :                          para_env=para_env, &
     203              :                          blacs_env=blacs_env, &
     204              :                          energy=energy, &
     205              :                          kpoints=kpoints, &
     206              :                          scf_env=scf_env, &
     207              :                          scf_control=scf_control, &
     208              :                          matrix_ks_kp=matrix_ks_transl, &
     209              :                          matrix_s_kp=matrix_s_kp, &
     210            4 :                          mp2_env=mp2_env)
     211              : 
     212              :          CALL get_gamma(matrix_s, matrix_ks, mos, &
     213            4 :                         matrix_s_kp, matrix_ks_transl, kpoints)
     214              : 
     215              :       ELSE
     216              : 
     217              :          CALL get_qs_env(qs_env, &
     218              :                          input=input, &
     219              :                          atomic_kind_set=atomic_kind_set, &
     220              :                          qs_kind_set=qs_kind_set, &
     221              :                          dft_control=dft_control, &
     222              :                          particle_set=particle_set, &
     223              :                          para_env=para_env, &
     224              :                          blacs_env=blacs_env, &
     225              :                          energy=energy, &
     226              :                          mos=mos, &
     227              :                          scf_env=scf_env, &
     228              :                          scf_control=scf_control, &
     229              :                          virial=virial, &
     230              :                          matrix_ks=matrix_ks, &
     231              :                          matrix_s=matrix_s, &
     232              :                          mp2_env=mp2_env, &
     233          692 :                          admm_env=admm_env)
     234              : 
     235              :       END IF
     236              : 
     237              :       ! IF DO_BSE In TDDFT, SAVE ks_matrix to ex_env
     238          696 :       IF (dft_control%tddfpt2_control%do_bse .OR. dft_control%tddfpt2_control%do_bse_w_only .OR. &
     239              :           dft_control%tddfpt2_control%do_bse_gw_only) THEN
     240            4 :          NULLIFY (ex_env)
     241            4 :          CALL get_qs_env(qs_env, exstate_env=ex_env)
     242            4 :          nspins = 1 ! for now only open-shell
     243            4 :          CALL dbcsr_allocate_matrix_set(ex_env%matrix_ks, nspins)
     244            8 :          DO ispin = 1, nspins
     245            4 :             ALLOCATE (ex_env%matrix_ks(ispin)%matrix)
     246            4 :             CALL dbcsr_create(ex_env%matrix_ks(ispin)%matrix, template=matrix_s(1)%matrix)
     247          700 :             CALL dbcsr_copy(ex_env%matrix_ks(ispin)%matrix, matrix_ks(ispin)%matrix)
     248              :          END DO
     249              :       END IF
     250              : 
     251              :       unit_nr = cp_print_key_unit_nr(logger, input, "DFT%XC%WF_CORRELATION%PRINT", &
     252          696 :                                      extension=".mp2Log")
     253              : 
     254          696 :       IF (unit_nr > 0) THEN
     255          348 :          IF (mp2_env%method /= ri_rpa_method_gpw) THEN
     256          225 :             WRITE (unit_nr, *)
     257          225 :             WRITE (unit_nr, *)
     258          225 :             WRITE (unit_nr, '(T2,A)') 'MP2 section'
     259          225 :             WRITE (unit_nr, '(T2,A)') '-----------'
     260          225 :             WRITE (unit_nr, *)
     261              :          ELSE
     262          123 :             WRITE (unit_nr, *)
     263          123 :             WRITE (unit_nr, *)
     264          123 :             WRITE (unit_nr, '(T2,A)') 'RI-RPA section'
     265          123 :             WRITE (unit_nr, '(T2,A)') '--------------'
     266          123 :             WRITE (unit_nr, *)
     267              :          END IF
     268              :       END IF
     269              : 
     270          696 :       IF (calc_forces) THEN
     271          322 :          CALL cite_reference(DelBen2015b)
     272          322 :          CALL cite_reference(Rybkin2016)
     273          322 :          CALL cite_reference(Stein2022)
     274          322 :          CALL cite_reference(Bussy2023)
     275          322 :          CALL cite_reference(Stein2024)
     276              :          !Gradients available for RI-MP2, and low-scaling Laplace MP2/RPA
     277          322 :          IF (.NOT. (mp2_env%method == ri_mp2_method_gpw .OR. &
     278              :                     mp2_env%method == ri_rpa_method_gpw .OR. mp2_env%method == ri_mp2_laplace)) THEN
     279            0 :             CPABORT("No forces/gradients for the selected method.")
     280              :          END IF
     281              :       END IF
     282              : 
     283          696 :       IF (.NOT. do_kpoints_cubic_RPA) THEN
     284          692 :          IF (virial%pv_availability .AND. (.NOT. virial%pv_numer) .AND. mp2_env%eri_method == do_eri_mme) THEN
     285            0 :             CPABORT("analytical stress not implemented with ERI_METHOD = MME")
     286              :          END IF
     287              :       END IF
     288              : 
     289          696 :       IF (mp2_env%do_im_time .AND. mp2_env%eri_method /= do_eri_gpw) THEN
     290          122 :          mp2_env%mp2_num_proc = 1
     291              :       END IF
     292              : 
     293          696 :       IF (mp2_env%mp2_num_proc < 1 .OR. mp2_env%mp2_num_proc > para_env%num_pe) THEN
     294            0 :          CPWARN("GROUP_SIZE is reset because of a too small or too large value.")
     295            0 :          mp2_env%mp2_num_proc = MAX(MIN(para_env%num_pe, mp2_env%mp2_num_proc), 1)
     296              :       END IF
     297              : 
     298          696 :       IF (MOD(para_env%num_pe, mp2_env%mp2_num_proc) /= 0) THEN
     299            0 :          CPABORT("GROUP_SIZE must be a divisor of the total number of MPI ranks!")
     300              :       END IF
     301              : 
     302          696 :       IF (.NOT. mp2_env%do_im_time) THEN
     303          562 :          IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T76,I5)') 'Used number of processes per group:', mp2_env%mp2_num_proc
     304          843 :          IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T68,F9.2,A4)') 'Maximum allowed memory usage per MPI process:', &
     305          562 :             mp2_env%mp2_memory, ' MiB'
     306              :       END IF
     307              : 
     308              :       IF ((mp2_env%method /= mp2_method_gpw) .AND. &
     309              :           (mp2_env%method /= ri_mp2_method_gpw) .AND. &
     310          696 :           (mp2_env%method /= ri_rpa_method_gpw) .AND. &
     311              :           (mp2_env%method /= ri_mp2_laplace)) THEN
     312           24 :          CALL m_memory(mem)
     313           24 :          mem_real = (mem + 1024*1024 - 1)/(1024*1024)
     314           24 :          CALL para_env%max(mem_real)
     315           24 :          mp2_env%mp2_memory = MIN(mp2_env%mp2_memory, mem_real)
     316           24 :          IF (mp2_env%mp2_memory < 0.0_dp) mp2_env%mp2_memory = 1.0_dp
     317              : 
     318           36 :          IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T68,F9.2,A4)') 'Available memory per MPI process for MP2:', &
     319           24 :             mp2_env%mp2_memory, ' MiB'
     320              :       END IF
     321              : 
     322          696 :       IF (unit_nr > 0) CALL m_flush(unit_nr)
     323              : 
     324          696 :       nspins = dft_control%nspins
     325          696 :       natom = SIZE(particle_set, 1)
     326              : 
     327          696 :       CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
     328          696 :       nkind = SIZE(atomic_kind_set, 1)
     329              : 
     330          696 :       do_admm_rpa_exx = mp2_env%ri_rpa%do_admm
     331          696 :       IF (do_admm_rpa_exx .AND. .NOT. dft_control%do_admm) THEN
     332            0 :          CPABORT("Need an ADMM input section for ADMM RI_RPA EXX to work")
     333              :       END IF
     334              :       IF (do_admm_rpa_exx) THEN
     335           18 :          CALL hfx_create_basis_types(basis_parameter, basis_info, qs_kind_set, "AUX_FIT")
     336              :       ELSE
     337          678 :          CALL hfx_create_basis_types(basis_parameter, basis_info, qs_kind_set, "ORB")
     338              :       END IF
     339              : 
     340          696 :       dimen = 0
     341          696 :       max_nset = 0
     342         2722 :       DO iatom = 1, natom
     343         2026 :          ikind = kind_of(iatom)
     344         7844 :          dimen = dimen + SUM(basis_parameter(ikind)%nsgf)
     345         2722 :          max_nset = MAX(max_nset, basis_parameter(ikind)%nset)
     346              :       END DO
     347              : 
     348          696 :       CALL get_mo_set(mo_set=mos(1), nao=nao)
     349              : 
     350              :       ! diagonalize the KS matrix in order to have the full set of MO's
     351              :       ! get S and KS matrices in fm_type (create also a working array)
     352          696 :       NULLIFY (fm_struct)
     353          696 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nfullrows_total, nfullcols_total=nfullcols_total)
     354              :       CALL cp_fm_struct_create(fm_struct, context=blacs_env, nrow_global=nfullrows_total, &
     355          696 :                                ncol_global=nfullcols_total, para_env=para_env)
     356          696 :       CALL cp_fm_create(fm_matrix_s, fm_struct, name="fm_matrix_s")
     357          696 :       CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, fm_matrix_s)
     358              : 
     359          696 :       CALL cp_fm_create(fm_matrix_ks, fm_struct, name="fm_matrix_ks")
     360              : 
     361          696 :       CALL cp_fm_create(fm_matrix_work, fm_struct, name="fm_matrix_work")
     362          696 :       CALL cp_fm_set_all(matrix=fm_matrix_work, alpha=0.0_dp)
     363              : 
     364          696 :       CALL cp_fm_struct_release(fm_struct)
     365              : 
     366          696 :       nmo = nao
     367         2088 :       ALLOCATE (nelec(nspins))
     368          696 :       IF (scf_env%cholesky_method == cholesky_off) THEN
     369           42 :          ALLOCATE (evals(nao))
     370          296 :          evals = 0
     371              : 
     372           14 :          CALL cp_fm_create(evecs, fm_matrix_s%matrix_struct)
     373              : 
     374              :          ! Perform an EVD
     375           14 :          CALL choose_eigv_solver(fm_matrix_s, evecs, evals)
     376              : 
     377              :          ! Determine the number of neglectable eigenvalues assuming that the eigenvalues are in ascending order
     378              :          ! (Required by Lapack)
     379           14 :          ndep = 0
     380           40 :          DO ii = 1, nao
     381           40 :             IF (evals(ii) > scf_control%eps_eigval) THEN
     382           14 :                ndep = ii - 1
     383           14 :                EXIT
     384              :             END IF
     385              :          END DO
     386           14 :          nmo = nao - ndep
     387              : 
     388           30 :          DO ispin = 1, nspins
     389           30 :             CALL get_mo_set(mo_set=mos(ispin), nelectron=nelec(ispin))
     390              :          END DO
     391           30 :          IF (MAXVAL(nelec)/(3 - nspins) > nmo) THEN
     392              :             ! Should not happen as the following MO calculation is the same as during the SCF steps
     393            0 :             CPABORT("Not enough MOs found!")
     394              :          END IF
     395              : 
     396              :          ! Set the eigenvalue of the eigenvectors belonging to the linear subspace to zero
     397           40 :          evals(1:ndep) = 0.0_dp
     398              :          ! Determine the eigenvalues of the inverse square root
     399          270 :          evals(ndep + 1:nao) = 1.0_dp/SQRT(evals(ndep + 1:nao))
     400              : 
     401           14 :          IF (ndep > 0) THEN
     402           14 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T76,I5)') 'Number of removed MOs:', ndep
     403           14 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T76,I5)') 'Number of available MOs:', nmo
     404              : 
     405              :             ! Create reduced matrices
     406           14 :             NULLIFY (fm_struct)
     407           14 :             CALL cp_fm_struct_create(fm_struct, template_fmstruct=fm_matrix_s%matrix_struct, ncol_global=nmo)
     408              : 
     409           14 :             ALLOCATE (fm_matrix_s_red, fm_work_red)
     410           14 :             CALL cp_fm_create(fm_matrix_s_red, fm_struct)
     411           14 :             CALL cp_fm_create(fm_work_red, fm_struct)
     412           14 :             CALL cp_fm_struct_release(fm_struct)
     413              : 
     414           14 :             ALLOCATE (fm_matrix_ks_red)
     415              :             CALL cp_fm_struct_create(fm_struct, template_fmstruct=fm_matrix_s%matrix_struct, &
     416           14 :                                      nrow_global=nmo, ncol_global=nmo)
     417           14 :             CALL cp_fm_create(fm_matrix_ks_red, fm_struct)
     418           14 :             CALL cp_fm_struct_release(fm_struct)
     419              : 
     420              :             ! Scale the eigenvalues and copy them to
     421           14 :             CALL cp_fm_to_fm(evecs, fm_matrix_s_red, nmo, ndep + 1)
     422           14 :             CALL cp_fm_column_scale(fm_matrix_s_red, evals(ndep + 1:))
     423              : 
     424              :             ! Obtain ortho from (P)DGEMM, skip the linear dependent columns
     425              :             CALL parallel_gemm("N", "T", nao, nao, nmo, 1.0_dp, fm_matrix_s_red, evecs, &
     426           14 :                                0.0_dp, fm_matrix_s, b_first_col=ndep + 1)
     427              :          ELSE
     428              :             ! Take the square roots of the target values to allow application of SYRK
     429            0 :             evals = SQRT(evals)
     430            0 :             CALL cp_fm_column_scale(evecs, evals)
     431            0 :             CALL cp_fm_syrk("U", "N", nao, 1.0_dp, evecs, 1, 1, 0.0_dp, fm_matrix_s)
     432            0 :             CALL cp_fm_uplo_to_full(fm_matrix_s, fm_matrix_work)
     433              :          END IF
     434              : 
     435           14 :          CALL cp_fm_release(evecs)
     436           28 :          cholesky_method = cholesky_off
     437              :       ELSE
     438              :          ! calculate S^(-1/2) (cholesky decomposition)
     439          682 :          CALL cp_fm_cholesky_decompose(fm_matrix_s)
     440          682 :          CALL cp_fm_triangular_invert(fm_matrix_s)
     441          682 :          cholesky_method = cholesky_inverse
     442              :       END IF
     443              : 
     444         2942 :       ALLOCATE (mos_mp2(nspins))
     445         1550 :       DO ispin = 1, nspins
     446              : 
     447          854 :          CALL get_mo_set(mo_set=mos(ispin), maxocc=maxocc, nelectron=nelec(ispin))
     448              : 
     449              :          CALL allocate_mo_set(mo_set=mos_mp2(ispin), &
     450              :                               nao=nao, &
     451              :                               nmo=nmo, &
     452              :                               nelectron=nelec(ispin), &
     453              :                               n_el_f=REAL(nelec(ispin), dp), &
     454              :                               maxocc=maxocc, &
     455          854 :                               flexible_electron_count=dft_control%relax_multiplicity)
     456              : 
     457          854 :          CALL get_mo_set(mos_mp2(ispin), nao=nao)
     458              :          CALL cp_fm_struct_create(fm_struct, nrow_global=nao, &
     459              :                                   ncol_global=nmo, para_env=para_env, &
     460          854 :                                   context=blacs_env)
     461              : 
     462              :          CALL init_mo_set(mos_mp2(ispin), &
     463              :                           fm_struct=fm_struct, &
     464          854 :                           name="mp2_mos")
     465         3258 :          CALL cp_fm_struct_release(fm_struct)
     466              :       END DO
     467              : 
     468         1550 :       DO ispin = 1, nspins
     469              : 
     470              :          ! If ADMM we should make the ks matrix up-to-date
     471          854 :          IF (dft_control%do_admm) THEN
     472           94 :             CALL admm_correct_for_eigenvalues(ispin, admm_env, matrix_ks(ispin)%matrix)
     473              :          END IF
     474              : 
     475          854 :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, fm_matrix_ks)
     476              : 
     477          854 :          IF (dft_control%do_admm) THEN
     478           94 :             CALL admm_uncorrect_for_eigenvalues(ispin, admm_env, matrix_ks(ispin)%matrix)
     479              :          END IF
     480              : 
     481          854 :          IF (cholesky_method == cholesky_inverse) THEN
     482              : 
     483              :             ! diagonalize KS matrix
     484              :             CALL eigensolver(matrix_ks_fm=fm_matrix_ks, &
     485              :                              mo_set=mos_mp2(ispin), &
     486              :                              ortho=fm_matrix_s, &
     487              :                              work=fm_matrix_work, &
     488              :                              cholesky_method=cholesky_method, &
     489              :                              do_level_shift=.FALSE., &
     490              :                              level_shift=0.0_dp, &
     491          838 :                              use_jacobi=.FALSE.)
     492              : 
     493           16 :          ELSE IF (cholesky_method == cholesky_off) THEN
     494              : 
     495           16 :             IF (ASSOCIATED(fm_matrix_s_red)) THEN
     496              :                CALL eigensolver_symm(matrix_ks_fm=fm_matrix_ks, &
     497              :                                      mo_set=mos_mp2(ispin), &
     498              :                                      ortho=fm_matrix_s, &
     499              :                                      work=fm_matrix_work, &
     500              :                                      do_level_shift=.FALSE., &
     501              :                                      level_shift=0.0_dp, &
     502              :                                      use_jacobi=.FALSE., &
     503              :                                      jacobi_threshold=0.0_dp, &
     504              :                                      ortho_red=fm_matrix_s_red, &
     505              :                                      matrix_ks_fm_red=fm_matrix_ks_red, &
     506           16 :                                      work_red=fm_work_red)
     507              :             ELSE
     508              :                CALL eigensolver_symm(matrix_ks_fm=fm_matrix_ks, &
     509              :                                      mo_set=mos_mp2(ispin), &
     510              :                                      ortho=fm_matrix_s, &
     511              :                                      work=fm_matrix_work, &
     512              :                                      do_level_shift=.FALSE., &
     513              :                                      level_shift=0.0_dp, &
     514              :                                      use_jacobi=.FALSE., &
     515            0 :                                      jacobi_threshold=0.0_dp)
     516              :             END IF
     517              :          END IF
     518              : 
     519         1550 :          CALL get_mo_set(mos_mp2(ispin), mo_coeff=mo_coeff)
     520              :       END DO
     521              : 
     522          696 :       CALL cp_fm_release(fm_matrix_s)
     523          696 :       CALL cp_fm_release(fm_matrix_ks)
     524          696 :       CALL cp_fm_release(fm_matrix_work)
     525          696 :       IF (ASSOCIATED(fm_matrix_s_red)) THEN
     526           14 :          CALL cp_fm_release(fm_matrix_s_red)
     527           14 :          DEALLOCATE (fm_matrix_s_red)
     528              :       END IF
     529          696 :       IF (ASSOCIATED(fm_matrix_ks_red)) THEN
     530           14 :          CALL cp_fm_release(fm_matrix_ks_red)
     531           14 :          DEALLOCATE (fm_matrix_ks_red)
     532              :       END IF
     533          696 :       IF (ASSOCIATED(fm_work_red)) THEN
     534           14 :          CALL cp_fm_release(fm_work_red)
     535           14 :          DEALLOCATE (fm_work_red)
     536              :       END IF
     537              : 
     538          696 :       hfx_sections => section_vals_get_subs_vals(input, "DFT%XC%HF")
     539              : 
     540              :       !   build the table of index
     541          696 :       t1 = m_walltime()
     542         2784 :       ALLOCATE (mp2_biel%index_table(natom, max_nset))
     543              : 
     544          696 :       CALL build_index_table(natom, max_nset, mp2_biel%index_table, basis_parameter, kind_of)
     545              : 
     546              :       ! free the hfx_container (for now if forces are required we don't release the HFX stuff)
     547          696 :       free_hfx_buffer = .FALSE.
     548          696 :       IF (ASSOCIATED(qs_env%x_data)) THEN
     549          428 :          free_hfx_buffer = .TRUE.
     550          428 :          IF (calc_forces .AND. (.NOT. mp2_env%ri_grad%free_hfx_buffer)) free_hfx_buffer = .FALSE.
     551          428 :          IF (qs_env%x_data(1, 1)%do_hfx_ri) free_hfx_buffer = .FALSE.
     552          428 :          IF (calc_forces .AND. mp2_env%do_im_time) free_hfx_buffer = .FALSE.
     553          428 :          IF (mp2_env%ri_rpa%reuse_hfx) free_hfx_buffer = .FALSE.
     554              :       END IF
     555              : 
     556          696 :       IF (.NOT. do_kpoints_cubic_RPA) THEN
     557          692 :       IF (virial%pv_numer) THEN
     558              :          ! in the case of numerical stress we don't have to free the HFX integrals
     559           72 :          free_hfx_buffer = .FALSE.
     560           72 :          mp2_env%ri_grad%free_hfx_buffer = free_hfx_buffer
     561              :       END IF
     562              :       END IF
     563              : 
     564              :       ! calculate the matrix sigma_x - vxc for G0W0
     565          696 :       t3 = 0
     566          696 :       IF (mp2_env%ri_rpa%do_ri_g0w0) THEN
     567          108 :          CALL compute_vec_Sigma_x_minus_vxc_gw(qs_env, mp2_env, mos_mp2, E_ex_from_GW, E_admm_from_GW, t3, unit_nr)
     568              :       END IF
     569              : 
     570          696 :       IF (free_hfx_buffer) THEN
     571          224 :          CALL timeset(routineN//"_free_hfx", handle2)
     572          224 :          CALL section_vals_get(hfx_sections, n_repetition=n_rep_hf)
     573          224 :          n_threads = 1
     574          224 : !$       n_threads = omp_get_max_threads()
     575              : 
     576          448 :          DO irep = 1, n_rep_hf
     577          672 :             DO i_thread = 0, n_threads - 1
     578          224 :                actual_x_data => qs_env%x_data(irep, i_thread + 1)
     579              : 
     580          224 :                do_dynamic_load_balancing = .TRUE.
     581          224 :                IF (n_threads == 1 .OR. actual_x_data%memory_parameter%do_disk_storage) do_dynamic_load_balancing = .FALSE.
     582              : 
     583              :                IF (do_dynamic_load_balancing) THEN
     584            0 :                   my_bin_size = SIZE(actual_x_data%distribution_energy)
     585              :                ELSE
     586          224 :                   my_bin_size = 1
     587              :                END IF
     588              : 
     589          448 :                IF (.NOT. actual_x_data%memory_parameter%do_all_on_the_fly) THEN
     590          222 :                   CALL dealloc_containers(actual_x_data%store_ints, actual_x_data%memory_parameter%actual_memory_usage)
     591              :                END IF
     592              :             END DO
     593              :          END DO
     594          224 :          CALL timestop(handle2)
     595              :       END IF
     596              : 
     597          696 :       Emp2 = 0.D+00
     598          696 :       Emp2_Cou = 0.D+00
     599          696 :       Emp2_ex = 0.D+00
     600          696 :       calc_ex = .TRUE.
     601              : 
     602          696 :       t1 = m_walltime()
     603          714 :       SELECT CASE (mp2_env%method)
     604              :       CASE (mp2_method_direct)
     605           18 :          IF (unit_nr > 0) WRITE (unit_nr, *)
     606              : 
     607           72 :          ALLOCATE (Auto(dimen, nspins))
     608           90 :          ALLOCATE (C(dimen, dimen, nspins))
     609              : 
     610           40 :          DO ispin = 1, nspins
     611              :             ! get the alpha coeff and eigenvalues
     612              :             CALL get_mo_set(mo_set=mos_mp2(ispin), &
     613              :                             eigenvalues=mo_eigenvalues, &
     614           22 :                             mo_coeff=mo_coeff)
     615              : 
     616           22 :             CALL cp_fm_get_submatrix(mo_coeff, C(:, :, ispin), 1, 1, dimen, dimen, .FALSE.)
     617         1072 :             Auto(:, ispin) = mo_eigenvalues(:)
     618              :          END DO
     619              : 
     620           18 :          IF (nspins == 2) THEN
     621            4 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A)') 'Unrestricted Canonical Direct Methods:'
     622              :             ! for now, require the mos to be always present
     623              : 
     624              :             ! calculate the alpha-alpha MP2
     625            4 :             Emp2_AA = 0.0_dp
     626            4 :             Emp2_AA_Cou = 0.0_dp
     627            4 :             Emp2_AA_ex = 0.0_dp
     628              :             CALL mp2_direct_energy(dimen, nelec(1), nelec(1), mp2_biel, &
     629              :                                    mp2_env, C(:, :, 1), Auto(:, 1), Emp2_AA, Emp2_AA_Cou, Emp2_AA_ex, &
     630            4 :                                    qs_env, para_env, unit_nr)
     631            4 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'MP2 Energy Alpha-Alpha = ', Emp2_AA
     632            4 :             IF (unit_nr > 0) WRITE (unit_nr, *)
     633              : 
     634            4 :             Emp2_BB = 0.0_dp
     635            4 :             Emp2_BB_Cou = 0.0_dp
     636            4 :             Emp2_BB_ex = 0.0_dp
     637              :             CALL mp2_direct_energy(dimen, nelec(2), nelec(2), mp2_biel, mp2_env, &
     638              :                                    C(:, :, 2), Auto(:, 2), Emp2_BB, Emp2_BB_Cou, Emp2_BB_ex, &
     639            4 :                                    qs_env, para_env, unit_nr)
     640            4 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'MP2 Energy Beta-Beta= ', Emp2_BB
     641            4 :             IF (unit_nr > 0) WRITE (unit_nr, *)
     642              : 
     643            4 :             Emp2_AB = 0.0_dp
     644            4 :             Emp2_AB_Cou = 0.0_dp
     645            4 :             Emp2_AB_ex = 0.0_dp
     646              :             CALL mp2_direct_energy(dimen, nelec(1), nelec(2), mp2_biel, mp2_env, C(:, :, 1), &
     647              :                                    Auto(:, 1), Emp2_AB, Emp2_AB_Cou, Emp2_AB_ex, &
     648            4 :                                    qs_env, para_env, unit_nr, C(:, :, 2), Auto(:, 2))
     649            4 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'MP2 Energy Alpha-Beta= ', Emp2_AB
     650            4 :             IF (unit_nr > 0) WRITE (unit_nr, *)
     651              : 
     652            4 :             Emp2 = Emp2_AA + Emp2_BB + Emp2_AB*2.0_dp !+Emp2_BA
     653            4 :             Emp2_Cou = Emp2_AA_Cou + Emp2_BB_Cou + Emp2_AB_Cou*2.0_dp !+Emp2_BA
     654            4 :             Emp2_ex = Emp2_AA_ex + Emp2_BB_ex + Emp2_AB_ex*2.0_dp !+Emp2_BA
     655              : 
     656            4 :             Emp2_S = Emp2_AB*2.0_dp
     657            4 :             Emp2_T = Emp2_AA + Emp2_BB
     658              : 
     659              :          ELSE
     660              : 
     661           14 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A)') 'Canonical Direct Methods:'
     662              : 
     663              :             CALL mp2_direct_energy(dimen, nelec(1)/2, nelec(1)/2, mp2_biel, mp2_env, &
     664              :                                    C(:, :, 1), Auto(:, 1), Emp2, Emp2_Cou, Emp2_ex, &
     665           14 :                                    qs_env, para_env, unit_nr)
     666              : 
     667              :          END IF
     668              : 
     669           18 :          DEALLOCATE (C, Auto)
     670              : 
     671              :       CASE (mp2_ri_optimize_basis)
     672              :          ! optimize ri basis set or tests for RI-MP2 gradients
     673            6 :          IF (unit_nr > 0) THEN
     674            3 :             WRITE (unit_nr, *)
     675            3 :             WRITE (unit_nr, '(T3,A)') 'Optimization of the auxiliary RI-MP2 basis'
     676            3 :             WRITE (unit_nr, *)
     677              :          END IF
     678              : 
     679           24 :          ALLOCATE (Auto(dimen, nspins))
     680           30 :          ALLOCATE (C(dimen, dimen, nspins))
     681              : 
     682           18 :          DO ispin = 1, nspins
     683              :             ! get the alpha coeff and eigenvalues
     684              :             CALL get_mo_set(mo_set=mos_mp2(ispin), &
     685              :                             eigenvalues=mo_eigenvalues, &
     686           12 :                             mo_coeff=mo_coeff)
     687              : 
     688           12 :             CALL cp_fm_get_submatrix(mo_coeff, C(:, :, ispin), 1, 1, dimen, dimen, .FALSE.)
     689          174 :             Auto(:, ispin) = mo_eigenvalues(:)
     690              :          END DO
     691              : 
     692              :          ! optimize basis
     693            6 :          IF (nspins == 2) THEN
     694              :             CALL optimize_ri_basis_main(Emp2, Emp2_Cou, Emp2_ex, Emp2_S, Emp2_T, dimen, natom, nelec(1), &
     695              :                                         mp2_biel, mp2_env, C(:, :, 1), Auto(:, 1), &
     696              :                                         kind_of, qs_env, para_env, unit_nr, &
     697            6 :                                         nelec(2), C(:, :, 2), Auto(:, 2))
     698              : 
     699              :          ELSE
     700              :             CALL optimize_ri_basis_main(Emp2, Emp2_Cou, Emp2_ex, Emp2_S, Emp2_T, dimen, natom, nelec(1)/2, &
     701              :                                         mp2_biel, mp2_env, C(:, :, 1), Auto(:, 1), &
     702            0 :                                         kind_of, qs_env, para_env, unit_nr)
     703              :          END IF
     704              : 
     705            6 :          DEALLOCATE (Auto, C)
     706              : 
     707              :       CASE (mp2_method_gpw)
     708              :          ! check if calculate the exchange contribution
     709           14 :          IF (mp2_env%scale_T == 0.0_dp .AND. (nspins == 2)) calc_ex = .FALSE.
     710              : 
     711              :          ! go with mp2_gpw
     712              :          CALL mp2_gpw_main(qs_env, mp2_env, Emp2, Emp2_Cou, Emp2_EX, Emp2_S, Emp2_T, &
     713          368 :                            mos_mp2, para_env, unit_nr, calc_forces, calc_ex)
     714              : 
     715              :       CASE (ri_mp2_method_gpw)
     716              :          ! check if calculate the exchange contribution
     717          354 :          IF (mp2_env%scale_T == 0.0_dp .AND. (nspins == 2)) calc_ex = .FALSE.
     718              : 
     719              :          ! go with mp2_gpw
     720              :          CALL mp2_gpw_main(qs_env, mp2_env, Emp2, Emp2_Cou, Emp2_EX, Emp2_S, Emp2_T, &
     721          354 :                            mos_mp2, para_env, unit_nr, calc_forces, calc_ex, do_ri_mp2=.TRUE.)
     722              : 
     723              :       CASE (ri_rpa_method_gpw)
     724              :          ! perform RI-RPA energy calculation (since most part of the calculation
     725              :          ! is actually equal to the RI-MP2-GPW we decided to put RPA in the MP2
     726              :          ! section to avoid code replication)
     727              : 
     728          246 :          calc_ex = .FALSE.
     729              : 
     730              :          ! go with ri_rpa_gpw
     731              :          CALL mp2_gpw_main(qs_env, mp2_env, Emp2, Emp2_Cou, Emp2_EX, Emp2_S, Emp2_T, &
     732          246 :                            mos_mp2, para_env, unit_nr, calc_forces, calc_ex, do_ri_rpa=.TRUE.)
     733              :          ! Scale energy contributions
     734          246 :          Emp2 = Emp2*mp2_env%ri_rpa%scale_rpa
     735          246 :          mp2_env%ri_rpa%ener_exchange = mp2_env%ri_rpa%ener_exchange*mp2_env%ri_rpa%scale_rpa
     736              : 
     737              :       CASE (ri_mp2_laplace)
     738              :          ! perform RI-SOS-Laplace-MP2 energy calculation, most part of the code in common
     739              :          ! with the RI-RPA part
     740              : 
     741              :          ! In SOS-MP2 only the coulomb-like contribution of the MP2 energy is computed
     742           58 :          calc_ex = .FALSE.
     743              : 
     744              :          ! go with sos_laplace_mp2_gpw
     745              :          CALL mp2_gpw_main(qs_env, mp2_env, Emp2, Emp2_Cou, Emp2_EX, Emp2_S, Emp2_T, &
     746           58 :                            mos_mp2, para_env, unit_nr, calc_forces, calc_ex, do_ri_sos_laplace_mp2=.TRUE.)
     747              : 
     748              :       CASE DEFAULT
     749          710 :          CPABORT("")
     750              :       END SELECT
     751              : 
     752          696 :       t2 = m_walltime()
     753          696 :       IF (unit_nr > 0) WRITE (unit_nr, *)
     754          696 :       IF (mp2_env%method /= ri_rpa_method_gpw) THEN
     755          450 :          IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.6)') 'Total MP2 Time=', t2 - t1
     756          450 :          IF (mp2_env%method == ri_mp2_laplace) THEN
     757           58 :             Emp2_S = Emp2
     758           58 :             Emp2_T = 0.0_dp
     759           58 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'MP2 Energy SO component (singlet) = ', Emp2_S
     760           58 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'Scaling factor SO                 = ', mp2_env%scale_S
     761              :          ELSE
     762          392 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'MP2 Coulomb Energy = ', Emp2_Cou/2.0_dp
     763          392 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'MP2 Exchange Energy = ', Emp2_ex
     764          392 :             IF (nspins == 1) THEN
     765              :                ! valid only in the closed shell case
     766          292 :                Emp2_S = Emp2_Cou/2.0_dp
     767          292 :                IF (calc_ex) THEN
     768          292 :                   Emp2_T = Emp2_ex + Emp2_Cou/2.0_dp
     769              :                ELSE
     770              :                   ! unknown if Emp2_ex is not computed
     771            0 :                   Emp2_T = 0.0_dp
     772              :                END IF
     773              :             END IF
     774          392 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'MP2 Energy SO component (singlet) = ', Emp2_S
     775          392 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'MP2 Energy SS component (triplet) = ', Emp2_T
     776          392 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'Scaling factor SO                 = ', mp2_env%scale_S
     777          392 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'Scaling factor SS                 = ', mp2_env%scale_T
     778              :          END IF
     779          450 :          Emp2_S = Emp2_S*mp2_env%scale_S
     780          450 :          Emp2_T = Emp2_T*mp2_env%scale_T
     781          450 :          Emp2 = Emp2_S + Emp2_T
     782          450 :          IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'Second order perturbation energy  =   ', Emp2
     783              :       ELSE
     784          246 :          IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.6)') 'Total RI-RPA Time=', t2 - t1
     785              : 
     786          246 :          update_xc_energy = .TRUE.
     787          246 :          IF (mp2_env%ri_rpa%do_ri_g0w0 .AND. .NOT. mp2_env%ri_g0w0%update_xc_energy) update_xc_energy = .FALSE.
     788           82 :          IF (.NOT. update_xc_energy) Emp2 = 0.0_dp
     789              : 
     790          246 :          IF (unit_nr > 0 .AND. update_xc_energy) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'RI-RPA energy  =   ', Emp2
     791          246 :          IF (unit_nr > 0 .AND. mp2_env%ri_rpa%sigma_param /= sigma_none) THEN
     792            5 :             WRITE (unit_nr, '(T3,A,T56,F25.14)') 'Sigma corr. to RI-RPA energy  =   ', &
     793           10 :                mp2_env%ri_rpa%e_sigma_corr
     794              :          END IF
     795          246 :          IF (mp2_env%ri_rpa%exchange_correction == rpa_exchange_axk) THEN
     796           10 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'RI-RPA-AXK energy=', mp2_env%ri_rpa%ener_exchange
     797          236 :          ELSE IF (mp2_env%ri_rpa%exchange_correction == rpa_exchange_sosex) THEN
     798            2 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'RI-RPA-SOSEX energy=', mp2_env%ri_rpa%ener_exchange
     799              :          END IF
     800          246 :          IF (mp2_env%ri_rpa%do_rse) THEN
     801            9 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'Diagonal singles correction (dRSE) = ', &
     802            6 :                mp2_env%ri_rpa%rse_corr_diag
     803            9 :             IF (unit_nr > 0) WRITE (unit_nr, '(T3,A,T56,F25.14)') 'Full singles correction (RSE) =', &
     804            6 :                mp2_env%ri_rpa%rse_corr
     805            6 :             IF (dft_control%do_admm) CPABORT("RPA RSE not implemented with RI_RPA%ADMM on")
     806              :          END IF
     807              :       END IF
     808          696 :       IF (unit_nr > 0) WRITE (unit_nr, *)
     809              : 
     810              :       ! we have it !!!!
     811          696 :       IF (mp2_env%ri_rpa%exchange_correction /= rpa_exchange_none) THEN
     812           12 :          Emp2 = Emp2 + mp2_env%ri_rpa%ener_exchange
     813              :       END IF
     814          696 :       IF (mp2_env%ri_rpa%do_rse) THEN
     815            6 :          Emp2 = Emp2 + mp2_env%ri_rpa%rse_corr
     816              :       END IF
     817          696 :       IF (mp2_env%ri_rpa%sigma_param /= sigma_none) THEN
     818              :          !WRITE (unit_nr, '(T3,A,T56,F25.14)') 'Sigma corr. to RI-RPA energy  =   ',&
     819           10 :          Emp2 = Emp2 + mp2_env%ri_rpa%e_sigma_corr
     820              :       END IF
     821          696 :       energy%mp2 = Emp2
     822          696 :       energy%total = energy%total + Emp2
     823              : 
     824         1550 :       DO ispin = 1, nspins
     825         1550 :          CALL deallocate_mo_set(mo_set=mos_mp2(ispin))
     826              :       END DO
     827          696 :       DEALLOCATE (mos_mp2)
     828              : 
     829              :       ! if necessary reallocate hfx buffer
     830          696 :       IF (free_hfx_buffer .AND. (.NOT. calc_forces) .AND. &
     831              :           (mp2_env%ri_g0w0%do_ri_Sigma_x .OR. .NOT. mp2_env%ri_rpa_im_time%do_kpoints_from_Gamma)) THEN
     832          120 :          CALL timeset(routineN//"_alloc_hfx", handle2)
     833          240 :          DO irep = 1, n_rep_hf
     834          360 :             DO i_thread = 0, n_threads - 1
     835          120 :                actual_x_data => qs_env%x_data(irep, i_thread + 1)
     836              : 
     837          120 :                do_dynamic_load_balancing = .TRUE.
     838          120 :                IF (n_threads == 1 .OR. actual_x_data%memory_parameter%do_disk_storage) do_dynamic_load_balancing = .FALSE.
     839              : 
     840              :                IF (do_dynamic_load_balancing) THEN
     841            0 :                   my_bin_size = SIZE(actual_x_data%distribution_energy)
     842              :                ELSE
     843          120 :                   my_bin_size = 1
     844              :                END IF
     845              : 
     846          240 :                IF (.NOT. actual_x_data%memory_parameter%do_all_on_the_fly) THEN
     847          120 :                   CALL alloc_containers(actual_x_data%store_ints, my_bin_size)
     848              : 
     849          240 :                   DO bin = 1, my_bin_size
     850          120 :                      maxval_container => actual_x_data%store_ints%maxval_container(bin)
     851          120 :                      integral_containers => actual_x_data%store_ints%integral_containers(:, bin)
     852          120 :                      CALL hfx_init_container(maxval_container, actual_x_data%memory_parameter%actual_memory_usage, .FALSE.)
     853         7920 :                      DO i = 1, 64
     854         7800 :                         CALL hfx_init_container(integral_containers(i), actual_x_data%memory_parameter%actual_memory_usage, .FALSE.)
     855              :                      END DO
     856              :                   END DO
     857              :                END IF
     858              :             END DO
     859              :          END DO
     860          120 :          CALL timestop(handle2)
     861              :       END IF
     862              : 
     863          696 :       CALL hfx_release_basis_types(basis_parameter)
     864              : 
     865              :       ! if required calculate the EXX contribution from the DFT density
     866          696 :       IF (mp2_env%method == ri_rpa_method_gpw .AND. .NOT. calc_forces) THEN
     867              :          do_exx = .FALSE.
     868          194 :          hfx_sections => section_vals_get_subs_vals(input, "DFT%XC%WF_CORRELATION%RI_RPA%HF")
     869          194 :          CALL section_vals_get(hfx_sections, explicit=do_exx)
     870          194 :          IF (do_exx) THEN
     871          132 :             do_gw = mp2_env%ri_rpa%do_ri_g0w0
     872          132 :             do_admm = mp2_env%ri_rpa%do_admm
     873          132 :             reuse_hfx = qs_env%mp2_env%ri_rpa%reuse_hfx
     874          132 :             do_im_time = qs_env%mp2_env%do_im_time
     875              : 
     876              :             CALL calculate_exx(qs_env=qs_env, &
     877              :                                unit_nr=unit_nr, &
     878              :                                hfx_sections=hfx_sections, &
     879              :                                x_data=qs_env%mp2_env%ri_rpa%x_data, &
     880              :                                do_gw=do_gw, &
     881              :                                do_admm=do_admm, &
     882              :                                calc_forces=.FALSE., &
     883              :                                reuse_hfx=reuse_hfx, &
     884              :                                do_im_time=do_im_time, &
     885              :                                E_ex_from_GW=E_ex_from_GW, &
     886              :                                E_admm_from_GW=E_admm_from_GW, &
     887          132 :                                t3=t3)
     888              : 
     889              :          END IF
     890              :       END IF
     891              : 
     892              :       CALL cp_print_key_finished_output(unit_nr, logger, input, &
     893          696 :                                         "DFT%XC%WF_CORRELATION%PRINT")
     894              : 
     895          696 :       CALL timestop(handle)
     896              : 
     897         3480 :    END SUBROUTINE mp2_main
     898              : 
     899              : ! **************************************************************************************************
     900              : !> \brief ...
     901              : !> \param natom ...
     902              : !> \param max_nset ...
     903              : !> \param index_table ...
     904              : !> \param basis_parameter ...
     905              : !> \param kind_of ...
     906              : ! **************************************************************************************************
     907          696 :    PURE SUBROUTINE build_index_table(natom, max_nset, index_table, basis_parameter, kind_of)
     908              :       INTEGER, INTENT(IN)                                :: natom, max_nset
     909              :       INTEGER, DIMENSION(natom, max_nset), INTENT(OUT)   :: index_table
     910              :       TYPE(hfx_basis_type), DIMENSION(:), POINTER        :: basis_parameter
     911              :       INTEGER, DIMENSION(natom), INTENT(IN)              :: kind_of
     912              : 
     913              :       INTEGER                                            :: counter, iatom, ikind, iset, nset
     914              : 
     915         8784 :       index_table = -HUGE(0)
     916              :       counter = 0
     917         2722 :       DO iatom = 1, natom
     918         2026 :          ikind = kind_of(iatom)
     919         2026 :          nset = basis_parameter(ikind)%nset
     920         8540 :          DO iset = 1, nset
     921         5818 :             index_table(iatom, iset) = counter + 1
     922         7844 :             counter = counter + basis_parameter(ikind)%nsgf(iset)
     923              :          END DO
     924              :       END DO
     925              : 
     926          696 :    END SUBROUTINE build_index_table
     927              : 
     928              : ! **************************************************************************************************
     929              : !> \brief ...
     930              : !> \param matrix_s ...
     931              : !> \param matrix_ks ...
     932              : !> \param mos ...
     933              : !> \param matrix_s_kp ...
     934              : !> \param matrix_ks_transl ...
     935              : !> \param kpoints ...
     936              : ! **************************************************************************************************
     937            4 :    PURE SUBROUTINE get_gamma(matrix_s, matrix_ks, mos, matrix_s_kp, matrix_ks_transl, kpoints)
     938              : 
     939              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, matrix_ks
     940              :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     941              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_s_kp, matrix_ks_transl
     942              :       TYPE(kpoint_type), POINTER                         :: kpoints
     943              : 
     944              :       INTEGER                                            :: nspins
     945              : 
     946            4 :       nspins = SIZE(matrix_ks_transl, 1)
     947              : 
     948            4 :       matrix_ks(1:nspins) => matrix_ks_transl(1:nspins, 1)
     949            4 :       matrix_s(1:1) => matrix_s_kp(1:1, 1)
     950            4 :       mos(1:nspins) => kpoints%kp_env(1)%kpoint_env%mos(1:nspins, 1)
     951              : 
     952            4 :    END SUBROUTINE get_gamma
     953              : 
     954              : END MODULE mp2
     955              : 
        

Generated by: LCOV version 2.0-1