LCOV - code coverage report
Current view: top level - src - bse_iterative.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:4dc10b3) Lines: 0 554 0.0 %
Date: 2024-11-21 06:45:46 Functions: 0 17 0.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 Iterative routines for GW + Bethe-Salpeter for computing electronic excitations
      10             : !> \par History
      11             : !>      04.2017 created [Jan Wilhelm]
      12             : !>      11.2023 Davidson solver implemented [Maximilian Graml]
      13             : ! **************************************************************************************************
      14             : MODULE bse_iterative
      15             :    USE cp_fm_types,                     ONLY: cp_fm_get_info,&
      16             :                                               cp_fm_type
      17             :    USE group_dist_types,                ONLY: get_group_dist,&
      18             :                                               group_dist_d1_type
      19             :    USE input_constants,                 ONLY: bse_singlet,&
      20             :                                               bse_triplet
      21             :    USE kinds,                           ONLY: dp
      22             :    USE message_passing,                 ONLY: mp_para_env_type,&
      23             :                                               mp_request_type
      24             :    USE mp2_types,                       ONLY: integ_mat_buffer_type,&
      25             :                                               mp2_type
      26             :    USE physcon,                         ONLY: evolt
      27             :    USE rpa_communication,               ONLY: communicate_buffer
      28             : #include "./base/base_uses.f90"
      29             : 
      30             :    IMPLICIT NONE
      31             : 
      32             :    PRIVATE
      33             : 
      34             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'bse_iterative'
      35             : 
      36             :    PUBLIC :: fill_local_3c_arrays, do_subspace_iterations
      37             : 
      38             : CONTAINS
      39             : 
      40             : ! **************************************************************************************************
      41             : !> \brief ...
      42             : !> \param B_bar_ijQ_bse_local ...
      43             : !> \param B_abQ_bse_local ...
      44             : !> \param B_bar_iaQ_bse_local ...
      45             : !> \param B_iaQ_bse_local ...
      46             : !> \param homo ...
      47             : !> \param virtual ...
      48             : !> \param bse_spin_config ...
      49             : !> \param unit_nr ...
      50             : !> \param Eigenval ...
      51             : !> \param para_env ...
      52             : !> \param mp2_env ...
      53             : ! **************************************************************************************************
      54           0 :    SUBROUTINE do_subspace_iterations(B_bar_ijQ_bse_local, B_abQ_bse_local, B_bar_iaQ_bse_local, &
      55             :                                      B_iaQ_bse_local, homo, virtual, bse_spin_config, unit_nr, &
      56           0 :                                      Eigenval, para_env, mp2_env)
      57             : 
      58             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: B_bar_ijQ_bse_local, B_abQ_bse_local, &
      59             :                                                             B_bar_iaQ_bse_local, B_iaQ_bse_local
      60             :       INTEGER                                            :: homo, virtual, bse_spin_config, unit_nr
      61             :       REAL(KIND=dp), DIMENSION(:)                        :: Eigenval
      62             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
      63             :       TYPE(mp2_type)                                     :: mp2_env
      64             : 
      65             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'do_subspace_iterations'
      66             : 
      67             :       CHARACTER(LEN=10)                                  :: bse_davidson_abort_cond_string, &
      68             :                                                             success_abort_string
      69             :       INTEGER :: bse_davidson_abort_cond, davidson_converged, fac_max_z_space, handle, i_iter, &
      70             :          j_print, local_RI_size, num_add_start_z_space, num_davidson_iter, num_en_unconverged, &
      71             :          num_exact_en_unconverged, num_exc_en, num_max_z_space, num_new_t, num_res_unconverged, &
      72             :          num_Z_vectors, num_Z_vectors_init
      73             :       LOGICAL                                            :: bse_full_diag_debug
      74             :       REAL(kind=dp)                                      :: eps_exc_en, eps_res, max_en_diff, &
      75             :                                                             max_res_norm, z_space_energy_cutoff
      76           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: En_diffs, En_diffs_exact, Full_exc_spectrum, &
      77           0 :          Res_norms, Subspace_full_eigenval, Subspace_new_eigenval, Subspace_prev_eigenval
      78           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: AZ_reshaped, M_ia_tmp, M_ji_tmp, RI_vector, &
      79           0 :          Subspace_new_eigenvec, Subspace_residuals_reshaped, Z_vectors_reshaped
      80           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: AZ, BZ, Subspace_add_dir, &
      81           0 :                                                             Subspace_ritzvec, W_vectors, Z_vectors
      82             : 
      83           0 :       CALL timeset(routineN, handle)
      84             : 
      85             :       !MG to del
      86             :       !Debug flag for exact diagonalization (only using lapack!!!)
      87           0 :       bse_full_diag_debug = .TRUE.
      88           0 :       num_en_unconverged = -1
      89           0 :       num_res_unconverged = -1
      90           0 :       num_exact_en_unconverged = -1
      91             : 
      92           0 :       bse_davidson_abort_cond = mp2_env%bse%davidson_abort_cond
      93           0 :       num_exc_en = mp2_env%bse%num_exc_en
      94           0 :       num_add_start_z_space = mp2_env%bse%num_add_start_z_space
      95           0 :       fac_max_z_space = mp2_env%bse%fac_max_z_space
      96           0 :       num_new_t = mp2_env%bse%num_new_t
      97           0 :       num_davidson_iter = mp2_env%bse%num_davidson_iter
      98           0 :       eps_res = mp2_env%bse%eps_res
      99           0 :       eps_exc_en = mp2_env%bse%eps_exc_en
     100           0 :       z_space_energy_cutoff = mp2_env%bse%z_space_energy_cutoff
     101             : 
     102           0 :       num_Z_vectors_init = num_exc_en + num_add_start_z_space
     103             : 
     104           0 :       IF (unit_nr > 0) THEN
     105           0 :          WRITE (unit_nr, *) "bse_spin_config", bse_spin_config
     106           0 :          WRITE (unit_nr, *) "num_exc_en", num_exc_en
     107           0 :          WRITE (unit_nr, *) "num_add_start_z_space", num_add_start_z_space
     108           0 :          WRITE (unit_nr, *) "num_Z_vectors_init", num_Z_vectors_init
     109           0 :          WRITE (unit_nr, *) "fac_max_z_space", fac_max_z_space
     110           0 :          WRITE (unit_nr, *) "num_new_t", num_new_t
     111           0 :          WRITE (unit_nr, *) "eps_res", eps_res
     112           0 :          WRITE (unit_nr, *) "num_davidson_iter", num_davidson_iter
     113           0 :          WRITE (unit_nr, *) "eps_exc_en", eps_exc_en
     114           0 :          WRITE (unit_nr, *) "bse_davidson_abort_cond", bse_davidson_abort_cond
     115           0 :          WRITE (unit_nr, *) "z_space_energy_cutoff", z_space_energy_cutoff
     116           0 :          WRITE (unit_nr, *) "Printing B_bar_iaQ_bse_local of shape", SHAPE(B_bar_iaQ_bse_local)
     117             :       END IF
     118             : 
     119           0 :       local_RI_size = SIZE(B_iaQ_bse_local, 3)
     120             : 
     121           0 :       num_Z_vectors = num_Z_vectors_init
     122           0 :       num_max_z_space = num_Z_vectors_init*fac_max_z_space
     123             : 
     124             :       !Check input parameters and correct them if necessary
     125           0 :       IF (num_new_t > num_Z_vectors_init) THEN
     126           0 :          num_new_t = num_Z_vectors_init
     127           0 :          IF (unit_nr > 0) THEN
     128             :             CALL cp_warn(__LOCATION__, "Number of added directions has to be smaller/equals than "// &
     129           0 :                          "initial dimension. Corrected num_new_t accordingly.")
     130             :          END IF
     131             :       END IF
     132           0 :       IF (unit_nr > 0) THEN
     133           0 :          WRITE (unit_nr, *) "Between BSE correction Warnings"
     134             :       END IF
     135             :       !If initial number is too big, already the first iteration causes trouble in LAPACK diagonal. (DORGQR)
     136           0 :       IF (2*num_Z_vectors_init > homo*virtual) THEN
     137             :          CALL cp_abort(__LOCATION__, "Initial dimension was too large and could not be corrected. "// &
     138           0 :                        "Choose another num_exc_en and num_add_start_z_space or adapt your basis set.")
     139             :       END IF
     140           0 :       IF (num_max_z_space .GE. homo*virtual) THEN
     141           0 :          fac_max_z_space = homo*virtual/num_Z_vectors_init
     142           0 :          num_max_z_space = num_Z_vectors_init*fac_max_z_space
     143             : 
     144           0 :          IF (fac_max_z_space == 0) THEN
     145             :             CALL cp_abort(__LOCATION__, "Maximal dimension was too large and could not be corrected. "// &
     146           0 :                           "Choose another fac_max_z_space and num_Z_vectors_init or adapt your basis set.")
     147             :          ELSE
     148           0 :             IF (unit_nr > 0) THEN
     149             :                CALL cp_warn(__LOCATION__, "Maximal dimension of Z space has to be smaller than homo*virtual. "// &
     150           0 :                             "Corrected fac_max_z_space accordingly.")
     151             :             END IF
     152             :          END IF
     153             :       END IF
     154             : 
     155           0 :       DO i_iter = 1, num_davidson_iter
     156           0 :          IF (unit_nr > 0) THEN
     157           0 :             WRITE (unit_nr, *) "Allocating Z_vec,AZ,BZ with dimensions (homo,virt,num_Z)", homo, virtual, num_Z_vectors
     158           0 :             WRITE (unit_nr, *) 'ProcNr', para_env%mepos, 'you really enter here for i_iter', i_iter
     159             :          END IF
     160           0 :          ALLOCATE (Z_vectors(homo, virtual, num_Z_vectors))
     161           0 :          Z_vectors = 0.0_dp
     162             : 
     163             :          !Dellocation procedures are a bit intricate, W_/Z_vectors and eigenvalues are needed for the next iteration,
     164             :          !  therefore we have to deallocate them separately from the other quantities
     165           0 :          IF (i_iter == 1) THEN
     166           0 :             CALL initial_guess_Z_vectors(Z_vectors, Eigenval, num_Z_vectors, homo, virtual)
     167           0 :             ALLOCATE (Subspace_prev_eigenval(num_exc_en))
     168           0 :             Subspace_prev_eigenval = 0.0_dp
     169             :          ELSE
     170           0 :             Z_vectors(:, :, :) = W_vectors(:, :, :)
     171           0 :             DEALLOCATE (W_vectors)
     172             :          END IF
     173           0 :          IF (unit_nr > 0) THEN
     174           0 :             WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "Allocated/rewritten Z arrays"
     175             :          END IF
     176             : 
     177             :          CALL create_bse_work_arrays(AZ, Z_vectors_reshaped, AZ_reshaped, BZ, M_ia_tmp, M_ji_tmp, &
     178             :                                      RI_vector, Subspace_new_eigenval, Subspace_full_eigenval, Subspace_new_eigenvec, &
     179             :                                      Subspace_residuals_reshaped, Subspace_ritzvec, Subspace_add_dir, W_vectors, &
     180           0 :                                      homo, virtual, num_Z_vectors, local_RI_size, num_new_t)
     181           0 :          IF (unit_nr > 0) THEN
     182           0 :             WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "Allocated Work arrays"
     183             :          END IF
     184             : 
     185             :          CALL compute_AZ(AZ, Z_vectors, B_iaQ_bse_local, B_bar_ijQ_bse_local, B_abQ_bse_local, &
     186             :                          M_ia_tmp, RI_vector, Eigenval, homo, virtual, num_Z_vectors, local_RI_size, &
     187             :                          para_env, bse_spin_config, z_space_energy_cutoff, i_iter, bse_full_diag_debug, &
     188           0 :                          Full_exc_spectrum, unit_nr)
     189             : 
     190             :          !MG: functionality of BZ not checked (issue with fm_mat_Q_static_bse_gemm in rpa_util needs to be checked!)
     191             :          !CALL compute_BZ(BZ, Z_vectors, B_iaQ_bse_local, B_bar_iaQ_bse_local, &
     192             :          !                M_ji_tmp, homo, virtual, num_Z_vectors, local_RI_size, &
     193             :          !                para_env)
     194             : 
     195           0 :          IF (unit_nr > 0) THEN
     196           0 :             WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "Computed AZ"
     197             :          END IF
     198             : 
     199             :          !MG to check: Reshaping correct?
     200           0 :          AZ_reshaped(:, :) = RESHAPE(AZ, (/homo*virtual, num_Z_vectors/))
     201           0 :          Z_vectors_reshaped(:, :) = RESHAPE(Z_vectors, (/homo*virtual, num_Z_vectors/))
     202             : 
     203             :          ! Diagonalize M and extract smallest eigenvalues/corresponding eigenvector
     204             :          CALL compute_diagonalize_ZAZ(AZ_reshaped, Z_vectors_reshaped, num_Z_vectors, Subspace_new_eigenval, &
     205           0 :                                       Subspace_new_eigenvec, num_new_t, Subspace_full_eigenval, para_env, unit_nr)
     206           0 :          IF (unit_nr > 0) THEN
     207           0 :             WRITE (unit_nr, *) "Eigenval (eV) in iter=", i_iter, " is:", Subspace_new_eigenval(:6)*evolt
     208             :          END IF
     209             : 
     210             :          ! Threshold in energies
     211             :          CALL check_en_convergence(Subspace_full_eigenval, Subspace_prev_eigenval, eps_exc_en, num_en_unconverged, &
     212           0 :                                    num_exc_en, max_en_diff, En_diffs)
     213           0 :          IF (unit_nr > 0) THEN
     214           0 :             WRITE (unit_nr, *) "Largest change of desired exc ens =", max_en_diff
     215             :          END IF
     216             :          ! Compute residuals
     217             :          CALL compute_residuals(AZ_reshaped, Z_vectors_reshaped, Subspace_new_eigenval, Subspace_new_eigenvec, &
     218           0 :                                 Subspace_residuals_reshaped, homo, virtual, num_new_t, num_Z_vectors, Subspace_ritzvec)
     219             : 
     220             :          !Abort, if residuals are small enough w.r.t threshold
     221             :          CALL check_res_convergence(Subspace_residuals_reshaped, num_new_t, eps_res, num_res_unconverged, &
     222           0 :                                     i_iter, max_res_norm, unit_nr, Res_norms)
     223             : 
     224           0 :          davidson_converged = -1
     225           0 :          IF (num_res_unconverged == 0 .AND. bse_davidson_abort_cond /= 0) THEN
     226           0 :             davidson_converged = 1
     227           0 :             success_abort_string = "RESIDUALS"
     228           0 :          ELSE IF (num_en_unconverged == 0 .AND. (bse_davidson_abort_cond /= 1)) THEN
     229           0 :             davidson_converged = 1
     230           0 :             success_abort_string = "ENERGIES"
     231           0 :          ELSE IF (i_iter == num_davidson_iter) THEN
     232           0 :             davidson_converged = -100
     233           0 :             success_abort_string = "-----"
     234             :          ELSE
     235             :             davidson_converged = -1
     236             :          END IF
     237             : 
     238           0 :          IF (bse_davidson_abort_cond == 0) THEN
     239           0 :             bse_davidson_abort_cond_string = "ENERGY"
     240           0 :          ELSE IF (bse_davidson_abort_cond == 1) THEN
     241           0 :             bse_davidson_abort_cond_string = "RESIDUAL"
     242             :          ELSE
     243           0 :             bse_davidson_abort_cond_string = "EITHER"
     244             :          END IF
     245             : 
     246           0 :          IF (davidson_converged == 1) THEN
     247             :             CALL postprocess_bse(Subspace_full_eigenval, num_new_t, eps_res, num_res_unconverged, &
     248             :                                  bse_spin_config, unit_nr, num_exc_en, num_Z_vectors_init, &
     249             :                                  num_davidson_iter, i_iter, num_Z_vectors, num_max_z_space, max_res_norm, &
     250             :                                  max_en_diff, num_en_unconverged, bse_davidson_abort_cond_string, &
     251           0 :                                  eps_exc_en, success_abort_string, z_space_energy_cutoff)
     252             : 
     253             :             !Deallocate matrices, which are otherwise not cleared due to exiting the loop
     254           0 :             DEALLOCATE (AZ, BZ, &
     255           0 :                         Z_vectors, M_ia_tmp, M_ji_tmp, RI_vector, Subspace_prev_eigenval, &
     256           0 :                         Subspace_new_eigenval, Subspace_new_eigenvec, Subspace_residuals_reshaped, &
     257           0 :                         Subspace_add_dir, AZ_reshaped, Z_vectors_reshaped, Subspace_ritzvec, Subspace_full_eigenval)
     258             : 
     259           0 :             EXIT
     260           0 :          ELSE IF (davidson_converged < -1) THEN
     261             :             CALL print_davidson_parameter(i_iter, num_davidson_iter, num_Z_vectors, num_res_unconverged, max_res_norm, &
     262             :                                           eps_res, num_en_unconverged, max_en_diff, eps_exc_en, num_exc_en, &
     263             :                                           num_Z_vectors_init, num_max_z_space, num_new_t, unit_nr, &
     264           0 :                                           success_abort_string, bse_davidson_abort_cond_string, z_space_energy_cutoff)
     265             : 
     266             :             CALL cp_abort(__LOCATION__, "BSE/TDA-Davidson did not converge using "// &
     267           0 :                           bse_davidson_abort_cond_string//" threshold condition!")
     268             :          END IF
     269             : 
     270             :          ! Calculate and add next orthonormal vector and update num_Z_vectors
     271             :          CALL compute_new_directions(homo, virtual, Subspace_residuals_reshaped, Subspace_new_eigenval, Eigenval, &
     272           0 :                                      num_new_t, Subspace_add_dir)
     273             : 
     274             :          !If exact-diag: compute difference to exact eigenvalues
     275             :          IF (bse_full_diag_debug) THEN
     276           0 :             ALLOCATE (En_diffs_exact(num_exc_en))
     277           0 :             num_exact_en_unconverged = 0
     278           0 :             DO j_print = 1, num_exc_en
     279           0 :                En_diffs_exact(j_print) = ABS(Subspace_full_eigenval(j_print) - Full_exc_spectrum(j_print))
     280           0 :                IF (En_diffs_exact(j_print) > eps_exc_en) num_exact_en_unconverged = num_exact_en_unconverged + 1
     281             :             END DO
     282             :          END IF
     283             : 
     284             :          !Check dimensions and orthonormalize vector system, depending on dimensionality
     285             :          CALL check_Z_space_dimension(W_vectors, Z_vectors, Subspace_add_dir, Subspace_ritzvec, &
     286           0 :                                       num_Z_vectors, num_new_t, num_max_z_space, homo, virtual, i_iter, unit_nr)
     287             : 
     288             :          !Copy eigenvalues for threshold
     289           0 :          Subspace_prev_eigenval(:) = Subspace_full_eigenval(:num_exc_en)
     290             : 
     291           0 :          DEALLOCATE (AZ, & !BZ,
     292           0 :                      Z_vectors, M_ia_tmp, M_ji_tmp, RI_vector, &
     293           0 :                      Subspace_new_eigenval, Subspace_new_eigenvec, Subspace_residuals_reshaped, &
     294           0 :                      Subspace_add_dir, AZ_reshaped, Z_vectors_reshaped, Subspace_ritzvec, Subspace_full_eigenval, &
     295           0 :                      Res_norms, En_diffs)
     296             : 
     297             :          IF (bse_full_diag_debug) THEN
     298           0 :             DEALLOCATE (En_diffs_exact)
     299             :          END IF
     300             : 
     301             :          !Orthonorm:
     302           0 :          CALL orthonormalize_W(W_vectors, num_Z_vectors, homo, virtual)
     303             : 
     304             :       END DO
     305             : 
     306           0 :       CALL timestop(handle)
     307             : 
     308           0 :    END SUBROUTINE
     309             : 
     310             : ! **************************************************************************************************
     311             : !> \brief ...
     312             : !> \param W_vectors ...
     313             : !> \param Z_vectors ...
     314             : !> \param Subspace_add_dir ...
     315             : !> \param Subspace_ritzvec ...
     316             : !> \param num_Z_vectors ...
     317             : !> \param num_new_t ...
     318             : !> \param num_max_z_space ...
     319             : !> \param homo ...
     320             : !> \param virtual ...
     321             : !> \param i_iter ...
     322             : !> \param unit_nr ...
     323             : ! **************************************************************************************************
     324           0 :    SUBROUTINE check_Z_space_dimension(W_vectors, Z_vectors, Subspace_add_dir, Subspace_ritzvec, &
     325             :                                       num_Z_vectors, num_new_t, num_max_z_space, homo, virtual, i_iter, unit_nr)
     326             : 
     327             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: W_vectors, Z_vectors, Subspace_add_dir, &
     328             :                                                             Subspace_ritzvec
     329             :       INTEGER                                            :: num_Z_vectors, num_new_t, &
     330             :                                                             num_max_z_space, homo, virtual, &
     331             :                                                             i_iter, unit_nr
     332             : 
     333             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'check_Z_space_dimension'
     334             : 
     335             :       INTEGER                                            :: handle
     336             : 
     337           0 :       CALL timeset(routineN, handle)
     338             : 
     339           0 :       IF (num_Z_vectors + num_new_t .LE. num_max_z_space) THEN
     340           0 :          W_vectors(:, :, :num_Z_vectors) = Z_vectors(:, :, :)
     341           0 :          W_vectors(:, :, num_Z_vectors + 1:) = Subspace_add_dir
     342           0 :          num_Z_vectors = num_Z_vectors + num_new_t
     343             :       ELSE
     344           0 :          IF (unit_nr > 0) THEN
     345           0 :             WRITE (unit_nr, *) "Resetting dimension in i_iter=", i_iter
     346             :          END IF
     347           0 :          DEALLOCATE (W_vectors)
     348           0 :          ALLOCATE (W_vectors(homo, virtual, 2*num_new_t))
     349           0 :          W_vectors(:, :, :num_new_t) = Subspace_ritzvec(:, :, :)
     350           0 :          W_vectors(:, :, num_new_t + 1:) = Subspace_add_dir
     351           0 :          num_Z_vectors = 2*num_new_t
     352             :       END IF
     353             : 
     354           0 :       CALL timestop(handle)
     355             : 
     356           0 :    END SUBROUTINE
     357             : 
     358             : ! **************************************************************************************************
     359             : !> \brief ...
     360             : !> \param AZ ...
     361             : !> \param Z_vectors_reshaped ...
     362             : !> \param AZ_reshaped ...
     363             : !> \param BZ ...
     364             : !> \param M_ia_tmp ...
     365             : !> \param M_ji_tmp ...
     366             : !> \param RI_vector ...
     367             : !> \param Subspace_new_eigenval ...
     368             : !> \param Subspace_full_eigenval ...
     369             : !> \param Subspace_new_eigenvec ...
     370             : !> \param Subspace_residuals_reshaped ...
     371             : !> \param Subspace_ritzvec ...
     372             : !> \param Subspace_add_dir ...
     373             : !> \param W_vectors ...
     374             : !> \param homo ...
     375             : !> \param virtual ...
     376             : !> \param num_Z_vectors ...
     377             : !> \param local_RI_size ...
     378             : !> \param num_new_t ...
     379             : ! **************************************************************************************************
     380           0 :    SUBROUTINE create_bse_work_arrays(AZ, Z_vectors_reshaped, AZ_reshaped, BZ, M_ia_tmp, M_ji_tmp, &
     381             :                                      RI_vector, Subspace_new_eigenval, Subspace_full_eigenval, Subspace_new_eigenvec, &
     382             :                                      Subspace_residuals_reshaped, Subspace_ritzvec, Subspace_add_dir, W_vectors, &
     383             :                                      homo, virtual, num_Z_vectors, local_RI_size, num_new_t)
     384             : 
     385             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: AZ
     386             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Z_vectors_reshaped, AZ_reshaped
     387             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: BZ
     388             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: M_ia_tmp, M_ji_tmp, RI_vector
     389             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Subspace_new_eigenval, &
     390             :                                                             Subspace_full_eigenval
     391             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Subspace_new_eigenvec, &
     392             :                                                             Subspace_residuals_reshaped
     393             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: Subspace_ritzvec, Subspace_add_dir, &
     394             :                                                             W_vectors
     395             :       INTEGER                                            :: homo, virtual, num_Z_vectors, &
     396             :                                                             local_RI_size, num_new_t
     397             : 
     398             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'create_bse_work_arrays'
     399             : 
     400             :       INTEGER                                            :: handle
     401             : 
     402           0 :       CALL timeset(routineN, handle)
     403             : 
     404           0 :       ALLOCATE (AZ(homo, virtual, num_Z_vectors))
     405           0 :       AZ = 0.0_dp
     406             : 
     407           0 :       ALLOCATE (Z_vectors_reshaped(homo*virtual, num_Z_vectors))
     408           0 :       Z_vectors_reshaped = 0.0_dp
     409             : 
     410           0 :       ALLOCATE (AZ_reshaped(homo*virtual, num_Z_vectors))
     411           0 :       AZ_reshaped = 0.0_dp
     412             : 
     413           0 :       ALLOCATE (BZ(homo, virtual, num_Z_vectors))
     414           0 :       BZ = 0.0_dp
     415             : 
     416           0 :       ALLOCATE (M_ia_tmp(homo, virtual))
     417           0 :       M_ia_tmp = 0.0_dp
     418             : 
     419           0 :       ALLOCATE (M_ji_tmp(homo, homo))
     420           0 :       M_ji_tmp = 0.0_dp
     421             : 
     422           0 :       ALLOCATE (RI_vector(local_RI_size, num_Z_vectors))
     423           0 :       RI_vector = 0.0_dp
     424             : 
     425           0 :       ALLOCATE (Subspace_new_eigenval(num_new_t))
     426           0 :       Subspace_new_eigenval = 0.0_dp
     427             : 
     428           0 :       ALLOCATE (Subspace_full_eigenval(num_Z_vectors))
     429           0 :       Subspace_full_eigenval = 0.0_dp
     430             : 
     431           0 :       ALLOCATE (Subspace_new_eigenvec(num_Z_vectors, num_new_t))
     432           0 :       Subspace_new_eigenvec = 0.0_dp
     433             : 
     434           0 :       ALLOCATE (subspace_residuals_reshaped(homo*virtual, num_new_t))
     435           0 :       subspace_residuals_reshaped = 0.0_dp
     436             : 
     437           0 :       ALLOCATE (Subspace_ritzvec(homo, virtual, num_new_t))
     438           0 :       Subspace_ritzvec = 0.0_dp
     439             : 
     440           0 :       ALLOCATE (Subspace_add_dir(homo, virtual, num_new_t))
     441           0 :       Subspace_add_dir = 0.0_dp
     442             : 
     443           0 :       ALLOCATE (W_vectors(homo, virtual, num_Z_vectors + num_new_t))
     444           0 :       W_vectors = 0.0_dp
     445             : 
     446           0 :       CALL timestop(handle)
     447             : 
     448           0 :    END SUBROUTINE
     449             : 
     450             : ! **************************************************************************************************
     451             : !> \brief ...
     452             : !> \param Subspace_full_eigenval ...
     453             : !> \param num_new_t ...
     454             : !> \param eps_res ...
     455             : !> \param num_res_unconverged ...
     456             : !> \param bse_spin_config ...
     457             : !> \param unit_nr ...
     458             : !> \param num_exc_en ...
     459             : !> \param num_Z_vectors_init ...
     460             : !> \param num_davidson_iter ...
     461             : !> \param i_iter ...
     462             : !> \param num_Z_vectors ...
     463             : !> \param num_max_z_space ...
     464             : !> \param max_res_norm ...
     465             : !> \param max_en_diff ...
     466             : !> \param num_en_unconverged ...
     467             : !> \param bse_davidson_abort_cond_string ...
     468             : !> \param eps_exc_en ...
     469             : !> \param success_abort_string ...
     470             : !> \param z_space_energy_cutoff ...
     471             : ! **************************************************************************************************
     472           0 :    SUBROUTINE postprocess_bse(Subspace_full_eigenval, num_new_t, eps_res, num_res_unconverged, &
     473             :                               bse_spin_config, unit_nr, num_exc_en, num_Z_vectors_init, &
     474             :                               num_davidson_iter, i_iter, num_Z_vectors, num_max_z_space, max_res_norm, &
     475             :                               max_en_diff, num_en_unconverged, bse_davidson_abort_cond_string, &
     476             :                               eps_exc_en, success_abort_string, z_space_energy_cutoff)
     477             : 
     478             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Subspace_full_eigenval
     479             :       INTEGER                                            :: num_new_t
     480             :       REAL(KIND=dp)                                      :: eps_res
     481             :       INTEGER :: num_res_unconverged, bse_spin_config, unit_nr, num_exc_en, num_Z_vectors_init, &
     482             :          num_davidson_iter, i_iter, num_Z_vectors, num_max_z_space
     483             :       REAL(KIND=dp)                                      :: max_res_norm, max_en_diff
     484             :       INTEGER                                            :: num_en_unconverged
     485             :       CHARACTER(LEN=10)                                  :: bse_davidson_abort_cond_string
     486             :       REAL(KIND=dp)                                      :: eps_exc_en
     487             :       CHARACTER(LEN=10)                                  :: success_abort_string
     488             :       REAL(KIND=dp)                                      :: z_space_energy_cutoff
     489             : 
     490             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'postprocess_bse'
     491             : 
     492             :       CHARACTER(LEN=10)                                  :: multiplet
     493             :       INTEGER                                            :: handle, i
     494             :       REAL(KIND=dp)                                      :: alpha
     495             : 
     496           0 :       CALL timeset(routineN, handle)
     497             : 
     498             :       !Prepare variables for printing
     499           0 :       SELECT CASE (bse_spin_config)
     500             :       CASE (bse_singlet)
     501           0 :          alpha = 2.0_dp
     502           0 :          multiplet = "Singlet"
     503             :       CASE (bse_triplet)
     504           0 :          alpha = 0.0_dp
     505           0 :          multiplet = "Triplet"
     506             :       END SELECT
     507             : 
     508           0 :       IF (unit_nr > 0) THEN
     509           0 :          WRITE (unit_nr, *) ' '
     510           0 :          WRITE (unit_nr, '(T3,A)') '******************************************************************************'
     511           0 :          WRITE (unit_nr, '(T3,A)') '**                                                                          **'
     512           0 :          WRITE (unit_nr, '(T3,A)') '**                        BSE-TDA EXCITONIC ENERGIES                        **'
     513           0 :          WRITE (unit_nr, '(T3,A)') '**                                                                          **'
     514           0 :          WRITE (unit_nr, '(T3,A)') '******************************************************************************'
     515           0 :          WRITE (unit_nr, '(T3,A)') ' '
     516           0 :          WRITE (unit_nr, '(T3,A)') ' '
     517           0 :          WRITE (unit_nr, '(T3,A)') ' The excitation energies are calculated by iteratively diagonalizing: '
     518           0 :          WRITE (unit_nr, '(T3,A)') ' '
     519           0 :          WRITE (unit_nr, '(T3,A)') '    A_iajb   =  (E_a-E_i) delta_ij delta_ab   +  alpha * v_iajb   -  W_ijab   '
     520           0 :          WRITE (unit_nr, '(T3,A)') ' '
     521             :          WRITE (unit_nr, '(T3,A48,A7,A12,F3.1)') &
     522           0 :             ' The spin-dependent factor for the requested ', multiplet, " is alpha = ", alpha
     523           0 :          WRITE (unit_nr, '(T3,A)') ' '
     524             :          WRITE (unit_nr, '(T3,A16,T50,A22)') &
     525           0 :             ' Excitonic level', 'Excitation energy (eV)'
     526             :          !prints actual energies values
     527           0 :          DO i = 1, num_exc_en
     528           0 :             WRITE (unit_nr, '(T3,I16,T50,F22.3)') i, Subspace_full_eigenval(i)*evolt
     529             :          END DO
     530             : 
     531           0 :          WRITE (unit_nr, '(T3,A)') ' '
     532             : 
     533             :          !prints parameters of Davidson algorithm
     534             :          CALL print_davidson_parameter(i_iter, num_davidson_iter, num_Z_vectors, num_res_unconverged, max_res_norm, &
     535             :                                        eps_res, num_en_unconverged, max_en_diff, eps_exc_en, num_exc_en, &
     536             :                                        num_Z_vectors_init, num_max_z_space, num_new_t, unit_nr, &
     537           0 :                                        success_abort_string, bse_davidson_abort_cond_string, z_space_energy_cutoff)
     538             : 
     539             :          !Insert warning if energies are not converged (could probably be the case if one uses residual threshold)
     540           0 :          IF (num_en_unconverged > 0) THEN
     541           0 :             WRITE (unit_nr, '(T3,A)') '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
     542           0 :             WRITE (unit_nr, '(T3,A2,T79,A2)') '!!', "!!"
     543           0 :             WRITE (unit_nr, '(T3,A2,T8,A65,T79,A2)') '!!', "THERE ARE UNCONVERGED ENERGIES PRINTED OUT, SOMETHING WENT WRONG!", "!!"
     544           0 :             WRITE (unit_nr, '(T3,A2,T79,A2)') '!!', "!!"
     545           0 :             WRITE (unit_nr, '(T3,A)') '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'
     546             :          END IF
     547             :       END IF
     548             : 
     549           0 :       CALL timestop(handle)
     550             : 
     551           0 :    END SUBROUTINE
     552             : 
     553             : ! **************************************************************************************************
     554             : !> \brief ...
     555             : !> \param i_iter ...
     556             : !> \param num_davidson_iter ...
     557             : !> \param num_Z_vectors ...
     558             : !> \param num_res_unconverged ...
     559             : !> \param max_res_norm ...
     560             : !> \param eps_res ...
     561             : !> \param num_en_unconverged ...
     562             : !> \param max_en_diff ...
     563             : !> \param eps_exc_en ...
     564             : !> \param num_exc_en ...
     565             : !> \param num_Z_vectors_init ...
     566             : !> \param num_max_z_space ...
     567             : !> \param num_new_t ...
     568             : !> \param unit_nr ...
     569             : !> \param success_abort_string ...
     570             : !> \param bse_davidson_abort_cond_string ...
     571             : !> \param z_space_energy_cutoff ...
     572             : ! **************************************************************************************************
     573           0 :    SUBROUTINE print_davidson_parameter(i_iter, num_davidson_iter, num_Z_vectors, num_res_unconverged, max_res_norm, &
     574             :                                        eps_res, num_en_unconverged, max_en_diff, eps_exc_en, num_exc_en, &
     575             :                                        num_Z_vectors_init, num_max_z_space, num_new_t, unit_nr, &
     576             :                                        success_abort_string, bse_davidson_abort_cond_string, z_space_energy_cutoff)
     577             : 
     578             :       INTEGER                                            :: i_iter, num_davidson_iter, &
     579             :                                                             num_Z_vectors, num_res_unconverged
     580             :       REAL(KIND=dp)                                      :: max_res_norm, eps_res
     581             :       INTEGER                                            :: num_en_unconverged
     582             :       REAL(KIND=dp)                                      :: max_en_diff, eps_exc_en
     583             :       INTEGER                                            :: num_exc_en, num_Z_vectors_init, &
     584             :                                                             num_max_z_space, num_new_t, unit_nr
     585             :       CHARACTER(LEN=10)                                  :: success_abort_string, &
     586             :                                                             bse_davidson_abort_cond_string
     587             :       REAL(KIND=dp)                                      :: z_space_energy_cutoff
     588             : 
     589             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'print_davidson_parameter'
     590             : 
     591             :       INTEGER                                            :: handle
     592             : 
     593           0 :       CALL timeset(routineN, handle)
     594             : 
     595           0 :       WRITE (unit_nr, '(T3,A)') '******************************************************************************'
     596             :       WRITE (unit_nr, '(T3,A2,T15,A49,T79,A2)') &
     597           0 :          '**', "Parameters of the BSE-Davidson solver:", "**"
     598             :       WRITE (unit_nr, '(T3,A2,T79,A2)') &
     599           0 :          '**', "**"
     600             :       WRITE (unit_nr, '(T3,A2,T79,A2)') &
     601           0 :          '**', "**"
     602             :       WRITE (unit_nr, '(T3,A2,T10,A16,I5,A12,I5,A8,T79,A2)') &
     603           0 :          '**', "Converged after ", i_iter, " of maximal ", num_davidson_iter, " cycles,", "**"
     604             :       WRITE (unit_nr, '(T3,A2,T20,A11,A9,A7,A8,A20,T79,A2)') &
     605           0 :          '**', "because of ", success_abort_string, " using ", &
     606           0 :          bse_davidson_abort_cond_string, " threshold condition", "**"
     607             :       WRITE (unit_nr, '(T3,A2,T79,A2)') &
     608           0 :          '**', "**"
     609             :       WRITE (unit_nr, '(T3,A2,T10,A32,T65,I11,T79,A2)') &
     610           0 :          '**', "The Z space has at the end dim. ", num_Z_vectors, "**"
     611             :       WRITE (unit_nr, '(T3,A2,T10,A45,T65,I11,T79,A2)') &
     612           0 :          '**', "Number of unconverged residuals in subspace: ", num_res_unconverged, "**"
     613             :       WRITE (unit_nr, '(T3,A2,T10,A35,T65,E11.4,T79,A2)') &
     614           0 :          '**', "largest unconverged residual (eV): ", max_res_norm*evolt, "**"
     615             :       WRITE (unit_nr, '(T3,A2,T10,A45,T65,E11.4,T79,A2)') &
     616           0 :          '**', "threshold for convergence of residuals (eV): ", eps_res*evolt, "**"
     617             :       WRITE (unit_nr, '(T3,A2,T10,A45,T65,I11,T79,A2)') &
     618           0 :          '**', "Number of desired, but unconverged energies: ", num_en_unconverged, "**"
     619             :       WRITE (unit_nr, '(T3,A2,T10,A44,T65,E11.4,T79,A2)') &
     620           0 :          '**', "largest unconverged energy difference (eV): ", max_en_diff*evolt, "**"
     621             :       WRITE (unit_nr, '(T3,A2,T10,A44,T65,E11.4,T79,A2)') &
     622           0 :          '**', "threshold for convergence of energies (eV): ", eps_exc_en*evolt, "**"
     623             :       WRITE (unit_nr, '(T3,A2,T10,A40,T65,I11,T79,A2)') &
     624           0 :          '**', "number of computed excitation energies: ", num_exc_en, "**"
     625             : 
     626           0 :       IF (z_space_energy_cutoff > 0) THEN
     627             :          WRITE (unit_nr, '(T3,A2,T10,A37,T65,E11.4,T79,A2)') &
     628           0 :             '**', "cutoff for excitation energies (eV): ", z_space_energy_cutoff*evolt, "**"
     629             :       END IF
     630             : 
     631             :       WRITE (unit_nr, '(T3,A2,T10,A36,T65,I11,T79,A2)') &
     632           0 :          '**', "number of Z space at the beginning: ", num_Z_vectors_init, "**"
     633             :       WRITE (unit_nr, '(T3,A2,T10,A30,T65,I11,T79,A2)') &
     634           0 :          '**', "maximal dimension of Z space: ", num_max_z_space, "**"
     635             :       WRITE (unit_nr, '(T3,A2,T10,A31,T65,I11,T79,A2)') &
     636           0 :          '**', "added directions per iteration: ", num_new_t, "**"
     637             :       WRITE (unit_nr, '(T3,A2,T79,A2)') &
     638           0 :          '**', "**"
     639             :       WRITE (unit_nr, '(T3,A2,T79,A2)') &
     640           0 :          '**', "**"
     641           0 :       WRITE (unit_nr, '(T3,A)') '******************************************************************************'
     642           0 :       WRITE (unit_nr, '(T3,A)') ' '
     643             : 
     644           0 :       CALL timestop(handle)
     645             : 
     646           0 :    END SUBROUTINE
     647             : 
     648             : ! **************************************************************************************************
     649             : !> \brief ...
     650             : !> \param Subspace_full_eigenval ...
     651             : !> \param Subspace_prev_eigenval ...
     652             : !> \param eps_exc_en ...
     653             : !> \param num_en_unconverged ...
     654             : !> \param num_exc_en ...
     655             : !> \param max_en_diff ...
     656             : !> \param En_diffs ...
     657             : ! **************************************************************************************************
     658           0 :    SUBROUTINE check_en_convergence(Subspace_full_eigenval, Subspace_prev_eigenval, eps_exc_en, num_en_unconverged, &
     659             :                                    num_exc_en, max_en_diff, En_diffs)
     660             : 
     661             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Subspace_full_eigenval, &
     662             :                                                             Subspace_prev_eigenval
     663             :       REAL(KIND=dp)                                      :: eps_exc_en
     664             :       INTEGER                                            :: num_en_unconverged, num_exc_en
     665             :       REAL(KIND=dp)                                      :: max_en_diff
     666             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: En_diffs
     667             : 
     668             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'check_en_convergence'
     669             : 
     670             :       INTEGER                                            :: handle, mu_l
     671             : 
     672           0 :       CALL timeset(routineN, handle)
     673             : 
     674           0 :       num_en_unconverged = 0
     675           0 :       ALLOCATE (En_diffs(num_exc_en))
     676           0 :       DO mu_l = 1, num_exc_en
     677           0 :          En_diffs(mu_l) = ABS(Subspace_full_eigenval(mu_l) - Subspace_prev_eigenval(mu_l))
     678           0 :          IF (En_diffs(mu_l) > eps_exc_en) num_en_unconverged = num_en_unconverged + 1
     679             :       END DO
     680           0 :       max_en_diff = MAXVAL(En_diffs)
     681             : 
     682           0 :       CALL timestop(handle)
     683             : 
     684           0 :    END SUBROUTINE
     685             : 
     686             : ! **************************************************************************************************
     687             : !> \brief ...
     688             : !> \param Subspace_residuals_reshaped ...
     689             : !> \param num_new_t ...
     690             : !> \param eps_res ...
     691             : !> \param num_res_unconverged ...
     692             : !> \param i_iter ...
     693             : !> \param max_res_norm ...
     694             : !> \param unit_nr ...
     695             : !> \param Res_norms ...
     696             : ! **************************************************************************************************
     697           0 :    SUBROUTINE check_res_convergence(Subspace_residuals_reshaped, num_new_t, eps_res, num_res_unconverged, &
     698             :                                     i_iter, max_res_norm, unit_nr, Res_norms)
     699             : 
     700             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Subspace_residuals_reshaped
     701             :       INTEGER                                            :: num_new_t
     702             :       REAL(KIND=dp)                                      :: eps_res
     703             :       INTEGER                                            :: num_res_unconverged, i_iter
     704             :       REAL(KIND=dp)                                      :: max_res_norm
     705             :       INTEGER                                            :: unit_nr
     706             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Res_norms
     707             : 
     708             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'check_res_convergence'
     709             : 
     710             :       INTEGER                                            :: handle, mu_l
     711             : 
     712           0 :       CALL timeset(routineN, handle)
     713             : 
     714           0 :       num_res_unconverged = 0
     715           0 :       ALLOCATE (Res_norms(num_new_t))
     716           0 :       DO mu_l = 1, num_new_t
     717           0 :          Res_norms(mu_l) = NORM2(Subspace_residuals_reshaped(:, mu_l))
     718           0 :          IF (Res_norms(mu_l) > eps_res) THEN
     719           0 :             num_res_unconverged = num_res_unconverged + 1
     720           0 :             IF (unit_nr > 0) THEN
     721           0 :                WRITE (unit_nr, *) "Unconverged res in i_iter=", i_iter, "is:", Res_norms(mu_l)
     722             :             END IF
     723             :          END IF
     724             :       END DO
     725           0 :       max_res_norm = MAXVAL(Res_norms)
     726           0 :       IF (unit_nr > 0) THEN
     727           0 :          WRITE (unit_nr, *) "Maximal unconverged res (of ", num_res_unconverged, &
     728           0 :             " unconverged res in this step) in i_iter=", i_iter, "is:", max_res_norm
     729             :       END IF
     730             : 
     731           0 :       CALL timestop(handle)
     732             : 
     733           0 :    END SUBROUTINE
     734             : 
     735             : ! **************************************************************************************************
     736             : !> \brief ...
     737             : !> \param W_vectors ...
     738             : !> \param num_Z_vectors ...
     739             : !> \param homo ...
     740             : !> \param virtual ...
     741             : ! **************************************************************************************************
     742           0 :    SUBROUTINE orthonormalize_W(W_vectors, num_Z_vectors, homo, virtual)
     743             : 
     744             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: W_vectors
     745             :       INTEGER                                            :: num_Z_vectors, homo, virtual
     746             : 
     747             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'orthonormalize_W'
     748             : 
     749             :       INTEGER                                            :: handle, info_dor, info_orth, LWORK_dor, &
     750             :                                                             LWORK_W
     751           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Tau_W, WORK_W, WORK_W_dor
     752             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: W_vectors_reshaped
     753             : 
     754           0 :       CALL timeset(routineN, handle)
     755             : 
     756           0 :       ALLOCATE (W_vectors_reshaped(homo*virtual, num_Z_vectors))
     757           0 :       W_vectors_reshaped(:, :) = RESHAPE(W_vectors, (/homo*virtual, num_Z_vectors/))
     758             : 
     759           0 :       ALLOCATE (Tau_W(MIN(homo*virtual, num_Z_vectors)))
     760           0 :       Tau_W = 0.0_dp
     761             : 
     762           0 :       ALLOCATE (WORK_W(1))
     763           0 :       WORK_W = 0.0_dp
     764             : 
     765           0 :       ALLOCATE (WORK_W_dor(1))
     766           0 :       WORK_W_dor = 0.0_dp
     767             : 
     768           0 :       CALL DGEQRF(homo*virtual, num_Z_vectors, W_vectors_reshaped, homo*virtual, Tau_W, WORK_W, -1, info_orth)
     769           0 :       LWORK_W = INT(WORK_W(1))
     770           0 :       DEALLOCATE (WORK_W)
     771           0 :       ALLOCATE (WORK_W(LWORK_W))
     772           0 :       WORK_W = 0.0_dp
     773           0 :       CALL DGEQRF(homo*virtual, num_Z_vectors, W_vectors_reshaped, homo*virtual, Tau_W, WORK_W, LWORK_W, info_orth)
     774           0 :       IF (info_orth /= 0) THEN
     775           0 :          CPABORT("QR Decomp Step 1 doesnt work")
     776             :       END IF
     777             :       CALL DORGQR(homo*virtual, num_Z_vectors, MIN(homo*virtual, num_Z_vectors), W_vectors_reshaped, homo*virtual, &
     778           0 :                   Tau_W, WORK_W_dor, -1, info_dor)
     779           0 :       LWORK_dor = INT(WORK_W_dor(1))
     780           0 :       DEALLOCATE (WORK_W_dor)
     781           0 :       ALLOCATE (WORK_W_dor(LWORK_dor))
     782           0 :       WORK_W_dor = 0.0_dp
     783             :       CALL DORGQR(homo*virtual, num_Z_vectors, MIN(homo*virtual, num_Z_vectors), W_vectors_reshaped, homo*virtual, &
     784           0 :                   Tau_W, WORK_W_dor, LWORK_dor, info_dor)
     785           0 :       IF (info_orth /= 0) THEN
     786           0 :          CPABORT("QR Decomp Step 2 doesnt work")
     787             :       END IF
     788             : 
     789           0 :       W_vectors(:, :, :) = RESHAPE(W_vectors_reshaped, (/homo, virtual, num_Z_vectors/))
     790             : 
     791           0 :       DEALLOCATE (WORK_W, WORK_W_dor, Tau_W, W_vectors_reshaped)
     792             : 
     793           0 :       CALL timestop(handle)
     794             : 
     795           0 :    END SUBROUTINE
     796             : 
     797             : ! **************************************************************************************************
     798             : !> \brief ...
     799             : !> \param homo ...
     800             : !> \param virtual ...
     801             : !> \param Subspace_residuals_reshaped ...
     802             : !> \param Subspace_new_eigenval ...
     803             : !> \param Eigenval ...
     804             : !> \param num_new_t ...
     805             : !> \param Subspace_add_dir ...
     806             : ! **************************************************************************************************
     807           0 :    SUBROUTINE compute_new_directions(homo, virtual, Subspace_residuals_reshaped, Subspace_new_eigenval, Eigenval, &
     808             :                                      num_new_t, Subspace_add_dir)
     809             : 
     810             :       INTEGER                                            :: homo, virtual
     811             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Subspace_residuals_reshaped
     812             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Subspace_new_eigenval
     813             :       REAL(KIND=dp), DIMENSION(:)                        :: Eigenval
     814             :       INTEGER                                            :: num_new_t
     815             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: Subspace_add_dir
     816             : 
     817             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_new_directions'
     818             : 
     819             :       INTEGER                                            :: a_virt, handle, i_occ, mu_subspace, &
     820             :                                                             prec_neg
     821             :       REAL(KIND=dp)                                      :: prec_scalar
     822             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Subspace_add_dir_reshaped
     823             : 
     824           0 :       CALL timeset(routineN, handle)
     825             : 
     826           0 :       ALLOCATE (Subspace_add_dir_reshaped(homo*virtual, num_new_t))
     827             : 
     828           0 :       prec_neg = 0
     829           0 :       DO mu_subspace = 1, num_new_t
     830           0 :          DO i_occ = 1, homo
     831           0 :             DO a_virt = 1, virtual
     832             :                !MG to check: Indexorder and range of indices
     833           0 :                prec_scalar = -1/(Subspace_new_eigenval(mu_subspace) - (Eigenval(a_virt + homo) - Eigenval(i_occ)))
     834             :                IF (prec_scalar < 0) THEN
     835           0 :                   prec_neg = prec_neg + 1
     836             :                   !prec_scalar = - prec_scalar
     837             :                END IF
     838             :                Subspace_add_dir_reshaped((i_occ - 1)*virtual + a_virt, mu_subspace) = prec_scalar* &
     839           0 :                                                               Subspace_residuals_reshaped((i_occ - 1)*virtual + a_virt, mu_subspace)
     840             :             END DO
     841             :          END DO
     842             :       END DO
     843             : 
     844           0 :       Subspace_add_dir(:, :, :) = RESHAPE(Subspace_add_dir_reshaped, (/homo, virtual, num_new_t/))
     845             : 
     846           0 :       DEALLOCATE (Subspace_add_dir_reshaped)
     847           0 :       CALL timestop(handle)
     848             : 
     849           0 :    END SUBROUTINE
     850             : 
     851             : ! **************************************************************************************************
     852             : !> \brief ...
     853             : !> \param AZ_reshaped ...
     854             : !> \param Z_vectors_reshaped ...
     855             : !> \param Subspace_new_eigenval ...
     856             : !> \param Subspace_new_eigenvec ...
     857             : !> \param Subspace_residuals_reshaped ...
     858             : !> \param homo ...
     859             : !> \param virtual ...
     860             : !> \param num_new_t ...
     861             : !> \param num_Z_vectors ...
     862             : !> \param Subspace_ritzvec ...
     863             : ! **************************************************************************************************
     864           0 :    SUBROUTINE compute_residuals(AZ_reshaped, Z_vectors_reshaped, Subspace_new_eigenval, Subspace_new_eigenvec, &
     865             :                                 Subspace_residuals_reshaped, homo, virtual, num_new_t, num_Z_vectors, Subspace_ritzvec)
     866             : 
     867             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: AZ_reshaped, Z_vectors_reshaped
     868             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Subspace_new_eigenval
     869             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Subspace_new_eigenvec, &
     870             :                                                             Subspace_residuals_reshaped
     871             :       INTEGER                                            :: homo, virtual, num_new_t, num_Z_vectors
     872             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: Subspace_ritzvec
     873             : 
     874             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_residuals'
     875             : 
     876             :       INTEGER                                            :: handle, mu_subspace
     877           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Subspace_res_A, Subspace_res_ev
     878             : 
     879           0 :       CALL timeset(routineN, handle)
     880             : 
     881           0 :       ALLOCATE (Subspace_res_ev(homo*virtual, num_new_t))
     882           0 :       Subspace_res_ev = 0.0_dp
     883             : 
     884           0 :       ALLOCATE (Subspace_res_A(homo*virtual, num_new_t))
     885           0 :       Subspace_res_A = 0.0_dp
     886             : 
     887             :       !Compute all residuals in one loop, iterating over number of new/added t per iteration
     888           0 :       DO mu_subspace = 1, num_new_t
     889             : 
     890             :          CALL DGEMM("N", "N", homo*virtual, 1, num_Z_vectors, 1.0_dp, Z_vectors_reshaped, homo*virtual, &
     891           0 :                     Subspace_new_eigenvec(:, mu_subspace), num_Z_vectors, 0.0_dp, Subspace_res_ev(:, mu_subspace), homo*virtual)
     892             : 
     893             :          CALL DGEMM("N", "N", homo*virtual, 1, num_Z_vectors, 1.0_dp, AZ_reshaped, homo*virtual, &
     894           0 :                     Subspace_new_eigenvec(:, mu_subspace), num_Z_vectors, 0.0_dp, Subspace_res_A(:, mu_subspace), homo*virtual)
     895             : 
     896             :          Subspace_residuals_reshaped(:, mu_subspace) = Subspace_new_eigenval(mu_subspace)*Subspace_res_ev(:, mu_subspace) &
     897           0 :                                                        - Subspace_res_A(:, mu_subspace)
     898             : 
     899             :       END DO
     900           0 :       Subspace_ritzvec(:, :, :) = RESHAPE(Subspace_res_ev, (/homo, virtual, num_new_t/))
     901           0 :       DEALLOCATE (Subspace_res_ev, Subspace_res_A)
     902             : 
     903           0 :       CALL timestop(handle)
     904             : 
     905           0 :    END SUBROUTINE
     906             : 
     907             : ! **************************************************************************************************
     908             : !> \brief ...
     909             : !> \param AZ_reshaped ...
     910             : !> \param Z_vectors_reshaped ...
     911             : !> \param num_Z_vectors ...
     912             : !> \param Subspace_new_eigenval ...
     913             : !> \param Subspace_new_eigenvec ...
     914             : !> \param num_new_t ...
     915             : !> \param Subspace_full_eigenval ...
     916             : !> \param para_env ...
     917             : !> \param unit_nr ...
     918             : ! **************************************************************************************************
     919           0 :    SUBROUTINE compute_diagonalize_ZAZ(AZ_reshaped, Z_vectors_reshaped, num_Z_vectors, Subspace_new_eigenval, &
     920             :                                       Subspace_new_eigenvec, num_new_t, Subspace_full_eigenval, para_env, unit_nr)
     921             : 
     922             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: AZ_reshaped, Z_vectors_reshaped
     923             :       INTEGER, INTENT(in)                                :: num_Z_vectors
     924             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Subspace_new_eigenval
     925             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: Subspace_new_eigenvec
     926             :       INTEGER, INTENT(in)                                :: num_new_t
     927             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Subspace_full_eigenval
     928             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
     929             :       INTEGER, INTENT(in)                                :: unit_nr
     930             : 
     931             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_diagonalize_ZAZ'
     932             : 
     933             :       INTEGER                                            :: handle, i_Z_vector, j_Z_vector, LWORK, &
     934             :                                                             ZAZ_diag_info
     935           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: WORK
     936           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: ZAZ
     937             : 
     938           0 :       CALL timeset(routineN, handle)
     939             : 
     940           0 :       ALLOCATE (ZAZ(num_Z_vectors, num_Z_vectors))
     941           0 :       ZAZ(:, :) = 0.0_dp
     942             : 
     943             :       !Flatten AZ and Z matrices of a certain j_Z_vector w.r.t. occ and virt indices
     944             :       !Multiply for each j_Z_vec and write into matrix of dim (num_Z_vec, num_Z_vec)
     945           0 :       DO i_Z_vector = 1, num_Z_vectors
     946           0 :          DO j_Z_vector = 1, num_Z_vectors
     947           0 :             ZAZ(j_Z_vector, i_Z_vector) = DOT_PRODUCT(Z_vectors_reshaped(:, j_Z_vector), AZ_reshaped(:, i_Z_vector))
     948             :          END DO
     949             :       END DO
     950           0 :       IF (unit_nr > 0) THEN
     951           0 :          WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "Before Diag"
     952             :       END IF
     953             : 
     954             :       !MG to do: Check for symmetry of ZAZ!
     955           0 :       ALLOCATE (WORK(1))
     956           0 :       WORK = 0.0_dp
     957           0 :       CALL DSYEV("V", "U", num_Z_vectors, ZAZ, num_Z_vectors, Subspace_full_eigenval, WORK, -1, ZAZ_diag_info)
     958           0 :       LWORK = INT(WORK(1))
     959           0 :       DEALLOCATE (WORK)
     960           0 :       ALLOCATE (WORK(LWORK))
     961           0 :       WORK = 0.0_dp
     962             :       !MG to check: Usage of symmetric routine okay? (Correct LWORK?)
     963           0 :       CALL DSYEV("V", "U", num_Z_vectors, ZAZ, num_Z_vectors, Subspace_full_eigenval, WORK, LWORK, ZAZ_diag_info)
     964             : 
     965           0 :       IF (ZAZ_diag_info /= 0) THEN
     966           0 :          CPABORT("ZAZ could not be diagonalized successfully.")
     967             :       END IF
     968             : 
     969           0 :       IF (unit_nr > 0) THEN
     970           0 :          WRITE (unit_nr, *) 'ProcNr', para_env%mepos, "After Diag"
     971             :       END IF
     972             : 
     973           0 :       Subspace_new_eigenval(1:num_new_t) = Subspace_full_eigenval(1:num_new_t)
     974           0 :       Subspace_new_eigenvec(:, 1:num_new_t) = ZAZ(:, 1:num_new_t)
     975           0 :       DEALLOCATE (WORK)
     976           0 :       DEALLOCATE (ZAZ)
     977             : 
     978           0 :       CALL timestop(handle)
     979             : 
     980           0 :    END SUBROUTINE
     981             : 
     982             : ! **************************************************************************************************
     983             : !> \brief ...
     984             : !> \param BZ ...
     985             : !> \param Z_vectors ...
     986             : !> \param B_iaQ_bse_local ...
     987             : !> \param B_bar_iaQ_bse_local ...
     988             : !> \param M_ji_tmp ...
     989             : !> \param homo ...
     990             : !> \param virtual ...
     991             : !> \param num_Z_vectors ...
     992             : !> \param local_RI_size ...
     993             : !> \param para_env ...
     994             : ! **************************************************************************************************
     995           0 :    SUBROUTINE compute_BZ(BZ, Z_vectors, B_iaQ_bse_local, B_bar_iaQ_bse_local, &
     996           0 :                          M_ji_tmp, homo, virtual, num_Z_vectors, local_RI_size, para_env)
     997             : 
     998             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: BZ, Z_vectors, B_iaQ_bse_local, &
     999             :                                                             B_bar_iaQ_bse_local
    1000             :       REAL(KIND=dp), DIMENSION(:, :)                     :: M_ji_tmp
    1001             :       INTEGER                                            :: homo, virtual, num_Z_vectors, &
    1002             :                                                             local_RI_size
    1003             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
    1004             : 
    1005             :       INTEGER                                            :: i_Z_vector, LLL
    1006             : 
    1007           0 :       BZ(:, :, :) = 0.0_dp
    1008             : 
    1009             :       !CALL compute_v_ia_jb_part(BZ, Z_vectors, B_iaQ_bse_local, RI_vector, local_RI_size, &
    1010             :       !                          num_Z_vectors, homo, virtual)
    1011             : 
    1012           0 :       DO i_Z_vector = 1, num_Z_vectors
    1013             : 
    1014           0 :          DO LLL = 1, local_RI_size
    1015             : 
    1016             :             ! M_ji^P = sum_b Z_jb*B_bi^P
    1017             :             CALL DGEMM("N", "T", homo, homo, virtual, 1.0_dp, Z_vectors(:, :, i_Z_vector), homo, &
    1018           0 :                        B_iaQ_bse_local(:, :, LLL), homo, 0.0_dp, M_ji_tmp, homo)
    1019             :             ! (BZ)_ia = sum_jP M_ij^P*B^bar_ja^P
    1020             :             CALL DGEMM("T", "N", homo, virtual, homo, 1.0_dp, M_ji_tmp, homo, &
    1021           0 :                        B_bar_iaQ_bse_local, homo, 1.0_dp, BZ(:, :, i_Z_vector), homo)
    1022             : 
    1023             :          END DO
    1024             : 
    1025             :       END DO
    1026             : 
    1027             :       ! we make the sum to sum over all RI basis functions
    1028           0 :       CALL para_env%sum(BZ)
    1029             : 
    1030           0 :    END SUBROUTINE
    1031             : 
    1032             : ! **************************************************************************************************
    1033             : !> \brief ...
    1034             : !> \param AZ ...
    1035             : !> \param Z_vectors ...
    1036             : !> \param B_iaQ_bse_local ...
    1037             : !> \param B_bar_ijQ_bse_local ...
    1038             : !> \param B_abQ_bse_local ...
    1039             : !> \param M_ia_tmp ...
    1040             : !> \param RI_vector ...
    1041             : !> \param Eigenval ...
    1042             : !> \param homo ...
    1043             : !> \param virtual ...
    1044             : !> \param num_Z_vectors ...
    1045             : !> \param local_RI_size ...
    1046             : !> \param para_env ...
    1047             : !> \param bse_spin_config ...
    1048             : !> \param z_space_energy_cutoff ...
    1049             : !> \param i_iter ...
    1050             : !> \param bse_full_diag_debug ...
    1051             : !> \param Full_exc_spectrum ...
    1052             : !> \param unit_nr ...
    1053             : ! **************************************************************************************************
    1054           0 :    SUBROUTINE compute_AZ(AZ, Z_vectors, B_iaQ_bse_local, B_bar_ijQ_bse_local, B_abQ_bse_local, M_ia_tmp, &
    1055           0 :                          RI_vector, Eigenval, homo, virtual, num_Z_vectors, local_RI_size, &
    1056             :                          para_env, bse_spin_config, z_space_energy_cutoff, i_iter, bse_full_diag_debug, &
    1057             :                          Full_exc_spectrum, unit_nr)
    1058             : 
    1059             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: AZ, Z_vectors, B_iaQ_bse_local, &
    1060             :                                                             B_bar_ijQ_bse_local, B_abQ_bse_local
    1061             :       REAL(KIND=dp), DIMENSION(:, :)                     :: M_ia_tmp, RI_vector
    1062             :       REAL(KIND=dp), DIMENSION(:)                        :: Eigenval
    1063             :       INTEGER                                            :: homo, virtual, num_Z_vectors, &
    1064             :                                                             local_RI_size
    1065             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
    1066             :       INTEGER                                            :: bse_spin_config
    1067             :       REAL(KIND=dp)                                      :: z_space_energy_cutoff
    1068             :       INTEGER                                            :: i_iter
    1069             :       LOGICAL                                            :: bse_full_diag_debug
    1070             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: Full_exc_spectrum
    1071             :       INTEGER                                            :: unit_nr
    1072             : 
    1073             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'compute_AZ'
    1074             : 
    1075             :       INTEGER                                            :: a, a_virt, b, diag_info, handle, i, &
    1076             :                                                             i_occ, i_Z_vector, j, LLL, LWORK, m, n
    1077             :       REAL(KIND=dp)                                      :: eigen_diff
    1078           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: WORK
    1079           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: A_full_reshaped
    1080           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :)  :: A_full, v_iajb, W_ijab
    1081             : 
    1082           0 :       CALL timeset(routineN, handle)
    1083           0 :       AZ(:, :, :) = 0.0_dp
    1084             : 
    1085           0 :       IF (i_iter == 1 .AND. bse_full_diag_debug) THEN
    1086           0 :          ALLOCATE (W_ijab(homo, homo, virtual, virtual))
    1087           0 :          ALLOCATE (A_full(homo, virtual, homo, virtual))
    1088           0 :          ALLOCATE (A_full_reshaped(homo*virtual, homo*virtual))
    1089           0 :          ALLOCATE (Full_exc_spectrum(homo*virtual))
    1090           0 :          W_ijab = 0.0_dp
    1091           0 :          A_full = 0.0_dp
    1092           0 :          A_full_reshaped = 0.0_dp
    1093           0 :          Full_exc_spectrum = 0.0_dp
    1094             :       END IF
    1095             : 
    1096             :       CALL compute_v_ia_jb_part(AZ, Z_vectors, B_iaQ_bse_local, RI_vector, local_RI_size, &
    1097             :                                 num_Z_vectors, homo, virtual, bse_spin_config, v_iajb, bse_full_diag_debug, i_iter, &
    1098           0 :                                 para_env)
    1099             : 
    1100           0 :       DO i_Z_vector = 1, num_Z_vectors
    1101             : 
    1102           0 :          DO LLL = 1, local_RI_size
    1103             : 
    1104             :             ! M_ja^P = sum_b Z_jb*B_ba^P
    1105             :             CALL DGEMM("N", "N", homo, virtual, virtual, 1.0_dp, Z_vectors(:, :, i_Z_vector), homo, &
    1106           0 :                        B_abQ_bse_local(:, :, LLL), virtual, 0.0_dp, M_ia_tmp, homo)
    1107             : 
    1108             :             ! (AZ)_ia = sum_jP B_bar_ij^P*M_ja^P
    1109             :             CALL DGEMM("N", "N", homo, virtual, homo, -1.0_dp, B_bar_ijQ_bse_local(:, :, LLL), homo, &
    1110           0 :                        M_ia_tmp, homo, 1.0_dp, AZ(:, :, i_Z_vector), homo)
    1111             : 
    1112             :          END DO
    1113             :       END DO
    1114             : 
    1115           0 :       IF (i_iter == 1 .AND. bse_full_diag_debug) THEN
    1116           0 :          W_ijab = 0.0_dp
    1117             :          !Create screened 4c integrals for check
    1118           0 :          DO LLL = 1, local_RI_size
    1119           0 :             DO i = 1, homo
    1120           0 :                DO j = 1, homo
    1121           0 :                   DO a = 1, virtual
    1122           0 :                      DO b = 1, virtual
    1123           0 :                         W_ijab(i, j, a, b) = W_ijab(i, j, a, b) + B_bar_ijQ_bse_local(i, j, LLL)*B_abQ_bse_local(a, b, LLL)
    1124             :                      END DO
    1125             :                   END DO
    1126             :                END DO
    1127             :             END DO
    1128             :          END DO
    1129             :          ! we make the mp_sum to sum over all RI basis functions
    1130           0 :          CALL para_env%sum(W_ijab)
    1131             :       END IF
    1132             : 
    1133             :       ! we make the mp_sum to sum over all RI basis functions
    1134           0 :       CALL para_env%sum(AZ)
    1135             : 
    1136             :       ! add (e_a-e_i)*Z_ia
    1137           0 :       DO i_occ = 1, homo
    1138           0 :          DO a_virt = 1, virtual
    1139             : 
    1140           0 :             eigen_diff = Eigenval(a_virt + homo) - Eigenval(i_occ)
    1141           0 :             IF (unit_nr > 0 .AND. i_iter == 1) THEN
    1142           0 :                WRITE (unit_nr, *) "Ediff at (i_occ,a_virt)=", i_occ, a_virt, " is: ", eigen_diff
    1143             :             END IF
    1144             : 
    1145           0 :             AZ(i_occ, a_virt, :) = AZ(i_occ, a_virt, :) + Z_vectors(i_occ, a_virt, :)*eigen_diff
    1146             : 
    1147             :          END DO
    1148             :       END DO
    1149             : 
    1150             :       !cut off contributions, which are too high in the excitation spectrum
    1151           0 :       IF (z_space_energy_cutoff > 0) THEN
    1152           0 :          DO i_occ = 1, homo
    1153           0 :             DO a_virt = 1, virtual
    1154             : 
    1155           0 :                IF (Eigenval(a_virt + homo) > z_space_energy_cutoff .OR. -Eigenval(i_occ) > z_space_energy_cutoff) THEN
    1156           0 :                   AZ(i_occ, a_virt, :) = 0
    1157             :                END IF
    1158             : 
    1159             :             END DO
    1160             :          END DO
    1161             :       END IF
    1162             : 
    1163             :       !Debugging purposes: full diagonalization of A
    1164           0 :       IF (i_iter == 1 .AND. bse_full_diag_debug) THEN
    1165           0 :          n = 0
    1166           0 :          DO i = 1, homo
    1167           0 :             DO a = 1, virtual
    1168           0 :                n = n + 1
    1169           0 :                m = 0
    1170           0 :                DO j = 1, homo
    1171           0 :                   DO b = 1, virtual
    1172           0 :                      m = m + 1
    1173           0 :                      IF (a == b .AND. i == j) THEN
    1174           0 :                         eigen_diff = Eigenval(a + homo) - Eigenval(i)
    1175             :                      ELSE
    1176           0 :                         eigen_diff = 0
    1177             :                      END IF
    1178           0 :                      A_full_reshaped(n, m) = eigen_diff + 2*v_iajb(i, a, j, b) - W_ijab(i, j, a, b)
    1179           0 :                      A_full(i, a, j, b) = eigen_diff + 2*v_iajb(i, a, j, b) - W_ijab(i, j, a, b)
    1180             :                   END DO
    1181             :                END DO
    1182             :             END DO
    1183             :          END DO
    1184             : 
    1185             :          !MG to do: Check for symmetry of ZAZ!
    1186           0 :          ALLOCATE (WORK(1))
    1187           0 :          WORK = 0.0_dp
    1188           0 :          CALL DSYEV("N", "U", homo*virtual, A_full_reshaped, homo*virtual, Full_exc_spectrum, WORK, -1, diag_info)
    1189           0 :          LWORK = INT(WORK(1))
    1190           0 :          DEALLOCATE (WORK)
    1191           0 :          ALLOCATE (WORK(LWORK))
    1192           0 :          WORK = 0.0_dp
    1193             :          !MG to check: Usage of symmetric routine okay? (Correct LWORK?)
    1194           0 :          CALL DSYEV("N", "U", homo*virtual, A_full_reshaped, homo*virtual, Full_exc_spectrum, WORK, LWORK, diag_info)
    1195             : 
    1196           0 :          DEALLOCATE (WORK)
    1197             : 
    1198           0 :          DEALLOCATE (W_ijab, v_iajb, A_full, A_full_reshaped)
    1199             :       END IF
    1200             : 
    1201           0 :       CALL timestop(handle)
    1202             : 
    1203           0 :    END SUBROUTINE
    1204             : 
    1205             : ! **************************************************************************************************
    1206             : !> \brief ...
    1207             : !> \param AZ ...
    1208             : !> \param Z_vectors ...
    1209             : !> \param B_iaQ_bse_local ...
    1210             : !> \param RI_vector ...
    1211             : !> \param local_RI_size ...
    1212             : !> \param num_Z_vectors ...
    1213             : !> \param homo ...
    1214             : !> \param virtual ...
    1215             : !> \param bse_spin_config ...
    1216             : !> \param v_iajb ...
    1217             : !> \param bse_full_diag_debug ...
    1218             : !> \param i_iter ...
    1219             : !> \param para_env ...
    1220             : ! **************************************************************************************************
    1221           0 :    SUBROUTINE compute_v_ia_jb_part(AZ, Z_vectors, B_iaQ_bse_local, RI_vector, local_RI_size, &
    1222             :                                    num_Z_vectors, homo, virtual, bse_spin_config, v_iajb, bse_full_diag_debug, i_iter, &
    1223             :                                    para_env)
    1224             : 
    1225             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: AZ, Z_vectors, B_iaQ_bse_local
    1226             :       REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT)      :: RI_vector
    1227             :       INTEGER, INTENT(IN)                                :: local_RI_size, num_Z_vectors, homo, &
    1228             :                                                             virtual, bse_spin_config
    1229             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :)  :: v_iajb
    1230             :       LOGICAL                                            :: bse_full_diag_debug
    1231             :       INTEGER, INTENT(IN)                                :: i_iter
    1232             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
    1233             : 
    1234             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_v_ia_jb_part'
    1235             : 
    1236             :       INTEGER                                            :: a, a_virt, b, handle, i, i_occ, &
    1237             :                                                             i_Z_vector, j, LLL
    1238             :       REAL(KIND=dp)                                      :: alpha
    1239             : 
    1240             : !debugging:
    1241             : 
    1242           0 :       CALL timeset(routineN, handle)
    1243             : 
    1244             :       !Determines factor of exchange term, depending on requested spin configuration (cf. input_constants.F)
    1245           0 :       SELECT CASE (bse_spin_config)
    1246             :       CASE (bse_singlet)
    1247           0 :          alpha = 2.0_dp
    1248             :       CASE (bse_triplet)
    1249           0 :          alpha = 0.0_dp
    1250             :       END SELECT
    1251             : 
    1252           0 :       RI_vector = 0.0_dp
    1253             : 
    1254             :       ! v_P = sum_jb B_jb^P Z_jb
    1255           0 :       DO LLL = 1, local_RI_size
    1256           0 :          DO i_Z_vector = 1, num_Z_vectors
    1257           0 :             DO i_occ = 1, homo
    1258           0 :                DO a_virt = 1, virtual
    1259             : 
    1260             :                   RI_vector(LLL, i_Z_vector) = RI_vector(LLL, i_Z_vector) + &
    1261             :                                                Z_vectors(i_occ, a_virt, i_Z_vector)* &
    1262           0 :                                                B_iaQ_bse_local(i_occ, a_virt, LLL)
    1263             : 
    1264             :                END DO
    1265             :             END DO
    1266             :          END DO
    1267             :       END DO
    1268             : 
    1269             :       ! AZ = sum_P B_ia^P*v_P + ...
    1270           0 :       DO LLL = 1, local_RI_size
    1271           0 :          DO i_Z_vector = 1, num_Z_vectors
    1272           0 :             DO i_occ = 1, homo
    1273           0 :                DO a_virt = 1, virtual
    1274             :                   !MG to check: Minus sign at v oder W? Factor for triplet/singlet
    1275             :                   AZ(i_occ, a_virt, i_Z_vector) = AZ(i_occ, a_virt, i_Z_vector) + &
    1276             :                                                   alpha*RI_vector(LLL, i_Z_vector)* &
    1277           0 :                                                   B_iaQ_bse_local(i_occ, a_virt, LLL)
    1278             : 
    1279             :                END DO
    1280             :             END DO
    1281             :          END DO
    1282             :       END DO
    1283           0 :       IF (i_iter == 1 .AND. bse_full_diag_debug) THEN
    1284           0 :          ALLOCATE (v_iajb(homo, virtual, homo, virtual))
    1285           0 :          v_iajb = 0.0_dp
    1286             :          !Create unscreened 4c integrals for check
    1287           0 :          DO LLL = 1, local_RI_size
    1288           0 :             DO i = 1, homo
    1289           0 :                DO j = 1, homo
    1290           0 :                   DO a = 1, virtual
    1291           0 :                      DO b = 1, virtual
    1292           0 :                         v_iajb(i, a, j, b) = v_iajb(i, a, j, b) + B_iaQ_bse_local(i, a, LLL)*B_iaQ_bse_local(j, b, LLL)
    1293             :                      END DO
    1294             :                   END DO
    1295             :                END DO
    1296             :             END DO
    1297             :          END DO
    1298             :          ! we make the mp_sum to sum over all RI basis functions
    1299           0 :          CALL para_env%sum(v_iajb)
    1300             :       END IF
    1301             : 
    1302           0 :       CALL timestop(handle)
    1303             : 
    1304           0 :    END SUBROUTINE
    1305             : 
    1306             : ! **************************************************************************************************
    1307             : !> \brief ...Eigenval
    1308             : !> \param Z_vectors ...
    1309             : !> \param Eigenval ...
    1310             : !> \param num_Z_vectors ...
    1311             : !> \param homo ...
    1312             : !> \param virtual ...
    1313             : ! **************************************************************************************************
    1314           0 :    SUBROUTINE initial_guess_Z_vectors(Z_vectors, Eigenval, num_Z_vectors, homo, virtual)
    1315             : 
    1316             :       REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT)   :: Z_vectors
    1317             :       REAL(KIND=dp), DIMENSION(:), INTENT(IN)            :: Eigenval
    1318             :       INTEGER, INTENT(IN)                                :: num_Z_vectors, homo, virtual
    1319             : 
    1320             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'initial_guess_Z_vectors'
    1321             : 
    1322             :       INTEGER                                            :: a_virt, handle, i_occ, i_Z_vector, &
    1323             :                                                             min_loc(2)
    1324           0 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: eigen_diff_ia
    1325             : 
    1326           0 :       CALL timeset(routineN, handle)
    1327             : 
    1328           0 :       ALLOCATE (eigen_diff_ia(homo, virtual))
    1329             : 
    1330           0 :       DO i_occ = 1, homo
    1331           0 :          DO a_virt = 1, virtual
    1332           0 :             eigen_diff_ia(i_occ, a_virt) = Eigenval(a_virt + homo) - Eigenval(i_occ)
    1333             :          END DO
    1334             :       END DO
    1335             : 
    1336           0 :       DO i_Z_vector = 1, num_Z_vectors
    1337             : 
    1338           0 :          min_loc = MINLOC(eigen_diff_ia)
    1339             : 
    1340           0 :          Z_vectors(min_loc(1), min_loc(2), i_Z_vector) = 1.0_dp
    1341             : 
    1342           0 :          eigen_diff_ia(min_loc(1), min_loc(2)) = 1.0E20_dp
    1343             : 
    1344             :       END DO
    1345             : 
    1346           0 :       DEALLOCATE (eigen_diff_ia)
    1347             : 
    1348           0 :       CALL timestop(handle)
    1349             : 
    1350           0 :    END SUBROUTINE
    1351             : 
    1352             :    ! **************************************************************************************************
    1353             : !> \brief ...
    1354             : !> \param fm_mat_S_ab_bse ...
    1355             : !> \param fm_mat_S ...
    1356             : !> \param fm_mat_S_bar_ia_bse ...
    1357             : !> \param fm_mat_S_bar_ij_bse ...
    1358             : !> \param B_bar_ijQ_bse_local ...
    1359             : !> \param B_abQ_bse_local ...
    1360             : !> \param B_bar_iaQ_bse_local ...
    1361             : !> \param B_iaQ_bse_local ...
    1362             : !> \param dimen_RI ...
    1363             : !> \param homo ...
    1364             : !> \param virtual ...
    1365             : !> \param gd_array ...
    1366             : !> \param color_sub ...
    1367             : !> \param para_env ...
    1368             : ! **************************************************************************************************
    1369           0 :    SUBROUTINE fill_local_3c_arrays(fm_mat_S_ab_bse, fm_mat_S, &
    1370             :                                    fm_mat_S_bar_ia_bse, fm_mat_S_bar_ij_bse, &
    1371             :                                    B_bar_ijQ_bse_local, B_abQ_bse_local, B_bar_iaQ_bse_local, &
    1372             :                                    B_iaQ_bse_local, dimen_RI, homo, virtual, &
    1373             :                                    gd_array, color_sub, para_env)
    1374             : 
    1375             :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mat_S_ab_bse, fm_mat_S, &
    1376             :                                                             fm_mat_S_bar_ia_bse, &
    1377             :                                                             fm_mat_S_bar_ij_bse
    1378             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    1379             :          INTENT(OUT)                                     :: B_bar_ijQ_bse_local, B_abQ_bse_local, &
    1380             :                                                             B_bar_iaQ_bse_local, B_iaQ_bse_local
    1381             :       INTEGER, INTENT(IN)                                :: dimen_RI, homo, virtual
    1382             :       TYPE(group_dist_d1_type), INTENT(IN)               :: gd_array
    1383             :       INTEGER, INTENT(IN)                                :: color_sub
    1384             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
    1385             : 
    1386             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'fill_local_3c_arrays'
    1387             : 
    1388             :       INTEGER                                            :: handle
    1389             : 
    1390           0 :       CALL timeset(routineN, handle)
    1391             : 
    1392           0 :       CALL allocate_and_fill_local_array(B_iaQ_bse_local, fm_mat_S, gd_array, color_sub, homo, virtual, dimen_RI, para_env)
    1393             : 
    1394             :       CALL allocate_and_fill_local_array(B_bar_iaQ_bse_local, fm_mat_S_bar_ia_bse, gd_array, color_sub, homo, virtual, &
    1395           0 :                                          dimen_RI, para_env)
    1396             : 
    1397             :       CALL allocate_and_fill_local_array(B_bar_ijQ_bse_local, fm_mat_S_bar_ij_bse, gd_array, color_sub, homo, homo, &
    1398           0 :                                          dimen_RI, para_env)
    1399             : 
    1400             :       CALL allocate_and_fill_local_array(B_abQ_bse_local, fm_mat_S_ab_bse, gd_array, color_sub, virtual, virtual, &
    1401           0 :                                          dimen_RI, para_env)
    1402             : 
    1403           0 :       CALL timestop(handle)
    1404             : 
    1405           0 :    END SUBROUTINE
    1406             : 
    1407             : ! **************************************************************************************************
    1408             : !> \brief ...
    1409             : !> \param B_local ...
    1410             : !> \param fm_mat_S ...
    1411             : !> \param gd_array ...
    1412             : !> \param color_sub ...
    1413             : !> \param small_size ...
    1414             : !> \param big_size ...
    1415             : !> \param dimen_RI ...
    1416             : !> \param para_env ...
    1417             : ! **************************************************************************************************
    1418           0 :    SUBROUTINE allocate_and_fill_local_array(B_local, fm_mat_S, gd_array, &
    1419             :                                             color_sub, small_size, big_size, dimen_RI, para_env)
    1420             : 
    1421             :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :), &
    1422             :          INTENT(OUT)                                     :: B_local
    1423             :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mat_S
    1424             :       TYPE(group_dist_d1_type), INTENT(IN)               :: gd_array
    1425             :       INTEGER, INTENT(IN)                                :: color_sub, small_size, big_size, dimen_RI
    1426             :       TYPE(mp_para_env_type), INTENT(IN)                 :: para_env
    1427             : 
    1428             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'allocate_and_fill_local_array'
    1429             : 
    1430             :       INTEGER :: combi_index, end_RI, handle, handle1, i_comm, i_entry, iiB, imepos, jjB, &
    1431             :          level_big_size, level_small_size, ncol_local, nrow_local, num_comm_cycles, RI_index, &
    1432             :          size_RI, start_RI
    1433           0 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: entry_counter, mepos_from_RI_index, &
    1434           0 :                                                             num_entries_rec, num_entries_send
    1435           0 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
    1436             :       REAL(KIND=dp)                                      :: matrix_el
    1437             :       TYPE(integ_mat_buffer_type), ALLOCATABLE, &
    1438           0 :          DIMENSION(:)                                    :: buffer_rec, buffer_send
    1439           0 :       TYPE(mp_request_type), DIMENSION(:, :), POINTER    :: req_array
    1440             : 
    1441           0 :       CALL timeset(routineN, handle)
    1442             : 
    1443           0 :       ALLOCATE (mepos_from_RI_index(dimen_RI))
    1444           0 :       mepos_from_RI_index = 0
    1445             : 
    1446           0 :       DO imepos = 0, para_env%num_pe - 1
    1447             : 
    1448           0 :          CALL get_group_dist(gd_array, pos=imepos, starts=start_RI, ends=end_RI)
    1449             : 
    1450           0 :          mepos_from_RI_index(start_RI:end_RI) = imepos
    1451             : 
    1452             :       END DO
    1453             : 
    1454             :       ! color_sub is automatically the number of the process since every subgroup has only one MPI rank
    1455           0 :       CALL get_group_dist(gd_array, color_sub, start_RI, end_RI, size_RI)
    1456             : 
    1457           0 :       ALLOCATE (B_local(small_size, big_size, 1:size_RI))
    1458             : 
    1459           0 :       ALLOCATE (num_entries_send(0:para_env%num_pe - 1))
    1460           0 :       ALLOCATE (num_entries_rec(0:para_env%num_pe - 1))
    1461             : 
    1462           0 :       ALLOCATE (req_array(1:para_env%num_pe, 4))
    1463             : 
    1464           0 :       ALLOCATE (entry_counter(0:para_env%num_pe - 1))
    1465             : 
    1466             :       CALL cp_fm_get_info(matrix=fm_mat_S, &
    1467             :                           nrow_local=nrow_local, &
    1468             :                           ncol_local=ncol_local, &
    1469             :                           row_indices=row_indices, &
    1470           0 :                           col_indices=col_indices)
    1471             : 
    1472           0 :       num_comm_cycles = 10
    1473             : 
    1474             :       ! communicate not all due to huge memory overhead, since for every number in fm_mat_S, we store
    1475             :       ! three additional ones (RI index, first MO index, second MO index!!)
    1476           0 :       DO i_comm = 0, num_comm_cycles - 1
    1477             : 
    1478           0 :          num_entries_send = 0
    1479           0 :          num_entries_rec = 0
    1480             : 
    1481             :          ! loop over RI index to get the number of sent entries
    1482           0 :          DO jjB = 1, nrow_local
    1483             : 
    1484           0 :             RI_index = row_indices(jjB)
    1485             : 
    1486           0 :             IF (MODULO(RI_index, num_comm_cycles) /= i_comm) CYCLE
    1487             : 
    1488           0 :             imepos = mepos_from_RI_index(RI_index)
    1489             : 
    1490           0 :             num_entries_send(imepos) = num_entries_send(imepos) + ncol_local
    1491             : 
    1492             :          END DO
    1493             : 
    1494           0 :          CALL para_env%alltoall(num_entries_send, num_entries_rec, 1)
    1495             : 
    1496           0 :          ALLOCATE (buffer_rec(0:para_env%num_pe - 1))
    1497           0 :          ALLOCATE (buffer_send(0:para_env%num_pe - 1))
    1498             : 
    1499             :          ! allocate data message and corresponding indices
    1500           0 :          DO imepos = 0, para_env%num_pe - 1
    1501             : 
    1502           0 :             ALLOCATE (buffer_rec(imepos)%msg(num_entries_rec(imepos)))
    1503           0 :             buffer_rec(imepos)%msg = 0.0_dp
    1504             : 
    1505           0 :             ALLOCATE (buffer_send(imepos)%msg(num_entries_send(imepos)))
    1506           0 :             buffer_send(imepos)%msg = 0.0_dp
    1507             : 
    1508           0 :             ALLOCATE (buffer_rec(imepos)%indx(num_entries_rec(imepos), 3))
    1509           0 :             buffer_rec(imepos)%indx = 0
    1510             : 
    1511           0 :             ALLOCATE (buffer_send(imepos)%indx(num_entries_send(imepos), 3))
    1512           0 :             buffer_send(imepos)%indx = 0
    1513             : 
    1514             :          END DO
    1515             : 
    1516           0 :          entry_counter(:) = 0
    1517             : 
    1518             :          ! loop over RI index for filling the send-buffer
    1519           0 :          DO jjB = 1, nrow_local
    1520             : 
    1521           0 :             RI_index = row_indices(jjB)
    1522             : 
    1523           0 :             IF (MODULO(RI_index, num_comm_cycles) /= i_comm) CYCLE
    1524             : 
    1525           0 :             imepos = mepos_from_RI_index(RI_index)
    1526             : 
    1527           0 :             DO iiB = 1, ncol_local
    1528             : 
    1529           0 :                combi_index = col_indices(iiB)
    1530           0 :                level_small_size = MAX(1, combi_index - 1)/MAX(big_size, 2) + 1
    1531           0 :                level_big_size = combi_index - (level_small_size - 1)*big_size
    1532             : 
    1533           0 :                entry_counter(imepos) = entry_counter(imepos) + 1
    1534             : 
    1535           0 :                buffer_send(imepos)%msg(entry_counter(imepos)) = fm_mat_S%local_data(jjB, iiB)
    1536             : 
    1537           0 :                buffer_send(imepos)%indx(entry_counter(imepos), 1) = RI_index
    1538           0 :                buffer_send(imepos)%indx(entry_counter(imepos), 2) = level_small_size
    1539           0 :                buffer_send(imepos)%indx(entry_counter(imepos), 3) = level_big_size
    1540             : 
    1541             :             END DO
    1542             : 
    1543             :          END DO
    1544             : 
    1545           0 :          CALL timeset("BSE_comm_data", handle1)
    1546             : 
    1547           0 :          CALL communicate_buffer(para_env, num_entries_rec, num_entries_send, buffer_rec, buffer_send, req_array)
    1548             : 
    1549           0 :          CALL timestop(handle1)
    1550             : 
    1551             :          ! fill B_local
    1552           0 :          DO imepos = 0, para_env%num_pe - 1
    1553             : 
    1554           0 :             DO i_entry = 1, num_entries_rec(imepos)
    1555             : 
    1556           0 :                RI_index = buffer_rec(imepos)%indx(i_entry, 1) - start_RI + 1
    1557           0 :                level_small_size = buffer_rec(imepos)%indx(i_entry, 2)
    1558           0 :                level_big_size = buffer_rec(imepos)%indx(i_entry, 3)
    1559             : 
    1560           0 :                matrix_el = buffer_rec(imepos)%msg(i_entry)
    1561             : 
    1562           0 :                B_local(level_small_size, level_big_size, RI_index) = matrix_el
    1563             : 
    1564             :             END DO
    1565             : 
    1566             :          END DO
    1567             : 
    1568           0 :          DO imepos = 0, para_env%num_pe - 1
    1569           0 :             DEALLOCATE (buffer_send(imepos)%msg)
    1570           0 :             DEALLOCATE (buffer_send(imepos)%indx)
    1571           0 :             DEALLOCATE (buffer_rec(imepos)%msg)
    1572           0 :             DEALLOCATE (buffer_rec(imepos)%indx)
    1573             :          END DO
    1574             : 
    1575           0 :          DEALLOCATE (buffer_rec, buffer_send)
    1576             : 
    1577             :       END DO
    1578             : 
    1579           0 :       DEALLOCATE (num_entries_send, num_entries_rec)
    1580             : 
    1581           0 :       DEALLOCATE (mepos_from_RI_index)
    1582             : 
    1583           0 :       DEALLOCATE (entry_counter, req_array)
    1584             : 
    1585           0 :       CALL timestop(handle)
    1586             : 
    1587           0 :    END SUBROUTINE
    1588             : 
    1589             : END MODULE bse_iterative

Generated by: LCOV version 1.15