LCOV - code coverage report
Current view: top level - src - rpa_im_time_force_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:24d69ee) Lines: 97.3 % 1972 1919
Test Date: 2026-09-03 07:32:15 Functions: 100.0 % 12 12

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines needed for cubic-scaling RPA and SOS-Laplace-MP2 forces
      10              : !> \author Augustin Bussy
      11              : ! **************************************************************************************************
      12              : MODULE rpa_im_time_force_methods
      13              :    USE admm_methods,                    ONLY: admm_projection_derivative
      14              :    USE admm_types,                      ONLY: admm_type,&
      15              :                                               get_admm_env
      16              :    USE ao_util,                         ONLY: exp_radius_very_extended
      17              :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      18              :                                               get_atomic_kind_set
      19              :    USE basis_set_types,                 ONLY: gto_basis_set_p_type,&
      20              :                                               gto_basis_set_type
      21              :    USE bibliography,                    ONLY: Bussy2023,&
      22              :                                               cite_reference
      23              :    USE cell_types,                      ONLY: cell_type,&
      24              :                                               pbc
      25              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      26              :    USE cp_control_types,                ONLY: dft_control_type
      27              :    USE cp_dbcsr_api,                    ONLY: &
      28              :         dbcsr_add, dbcsr_clear, dbcsr_complete_redistribute, dbcsr_copy, dbcsr_create, &
      29              :         dbcsr_distribution_new, dbcsr_distribution_release, dbcsr_distribution_type, &
      30              :         dbcsr_get_block_p, dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, &
      31              :         dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, &
      32              :         dbcsr_p_type, dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, &
      33              :         dbcsr_type_no_symmetry, dbcsr_type_symmetric
      34              :    USE cp_dbcsr_cholesky,               ONLY: cp_dbcsr_cholesky_decompose,&
      35              :                                               cp_dbcsr_cholesky_invert
      36              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_add_on_diag,&
      37              :                                               dbcsr_frobenius_norm
      38              :    USE cp_dbcsr_diag,                   ONLY: cp_dbcsr_power
      39              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      40              :                                               copy_fm_to_dbcsr,&
      41              :                                               cp_dbcsr_dist2d_to_dist,&
      42              :                                               cp_dbcsr_sm_fm_multiply,&
      43              :                                               dbcsr_allocate_matrix_set,&
      44              :                                               dbcsr_deallocate_matrix_set
      45              :    USE cp_eri_mme_interface,            ONLY: cp_eri_mme_update_local_counts
      46              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      47              :                                               cp_fm_struct_release,&
      48              :                                               cp_fm_struct_type
      49              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      50              :                                               cp_fm_release,&
      51              :                                               cp_fm_set_all,&
      52              :                                               cp_fm_to_fm,&
      53              :                                               cp_fm_type
      54              :    USE dbt_api,                         ONLY: &
      55              :         dbt_batched_contract_finalize, dbt_batched_contract_init, dbt_clear, dbt_contract, &
      56              :         dbt_copy, dbt_copy_matrix_to_tensor, dbt_copy_tensor_to_matrix, dbt_create, dbt_destroy, &
      57              :         dbt_filter, dbt_get_info, dbt_mp_environ_pgrid, dbt_pgrid_create, dbt_pgrid_destroy, &
      58              :         dbt_pgrid_type, dbt_scale, dbt_type
      59              :    USE distribution_2d_types,           ONLY: distribution_2d_type
      60              :    USE gaussian_gridlevels,             ONLY: gaussian_gridlevel
      61              :    USE hfx_admm_utils,                  ONLY: tddft_hfx_matrix
      62              :    USE hfx_derivatives,                 ONLY: derivatives_four_center
      63              :    USE hfx_exx,                         ONLY: add_exx_to_rhs
      64              :    USE hfx_ri,                          ONLY: get_2c_der_force,&
      65              :                                               get_force_from_3c_trace,&
      66              :                                               get_idx_to_atom,&
      67              :                                               hfx_ri_update_forces
      68              :    USE hfx_types,                       ONLY: alloc_containers,&
      69              :                                               block_ind_type,&
      70              :                                               dealloc_containers,&
      71              :                                               hfx_compression_type,&
      72              :                                               hfx_type
      73              :    USE input_constants,                 ONLY: do_admm_aux_exch_func_none,&
      74              :                                               do_eri_gpw,&
      75              :                                               do_eri_mme,&
      76              :                                               do_potential_id,&
      77              :                                               ri_rpa_method_gpw
      78              :    USE input_section_types,             ONLY: section_vals_get,&
      79              :                                               section_vals_get_subs_vals,&
      80              :                                               section_vals_type,&
      81              :                                               section_vals_val_get
      82              :    USE iterate_matrix,                  ONLY: matrix_exponential
      83              :    USE kinds,                           ONLY: dp,&
      84              :                                               int_8
      85              :    USE libint_2c_3c,                    ONLY: libint_potential_type
      86              :    USE machine,                         ONLY: m_flush,&
      87              :                                               m_walltime
      88              :    USE mathconstants,                   ONLY: fourpi
      89              :    USE message_passing,                 ONLY: mp_cart_type,&
      90              :                                               mp_para_env_release,&
      91              :                                               mp_para_env_type
      92              :    USE mp2_eri,                         ONLY: integrate_set_2c
      93              :    USE mp2_eri_gpw,                     ONLY: calc_potential_gpw,&
      94              :                                               cleanup_gpw,&
      95              :                                               prepare_gpw,&
      96              :                                               virial_gpw_potential
      97              :    USE mp2_types,                       ONLY: mp2_type
      98              :    USE orbital_pointers,                ONLY: ncoset
      99              :    USE parallel_gemm_api,               ONLY: parallel_gemm
     100              :    USE particle_methods,                ONLY: get_particle_set
     101              :    USE particle_types,                  ONLY: particle_type
     102              :    USE pw_env_types,                    ONLY: pw_env_get,&
     103              :                                               pw_env_type
     104              :    USE pw_methods,                      ONLY: pw_axpy,&
     105              :                                               pw_copy,&
     106              :                                               pw_integral_ab,&
     107              :                                               pw_scale,&
     108              :                                               pw_transfer,&
     109              :                                               pw_zero
     110              :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
     111              :    USE pw_poisson_types,                ONLY: pw_poisson_type
     112              :    USE pw_pool_types,                   ONLY: pw_pool_type
     113              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
     114              :                                               pw_r3d_rs_type
     115              :    USE qs_collocate_density,            ONLY: calculate_rho_elec,&
     116              :                                               collocate_function
     117              :    USE qs_core_matrices,                ONLY: core_matrices,&
     118              :                                               kinetic_energy_matrix
     119              :    USE qs_density_matrices,             ONLY: calculate_whz_matrix
     120              :    USE qs_environment_types,            ONLY: get_qs_env,&
     121              :                                               qs_environment_type,&
     122              :                                               set_qs_env
     123              :    USE qs_force_types,                  ONLY: qs_force_type
     124              :    USE qs_fxc,                          ONLY: qs_fxc_create
     125              :    USE qs_integral_utils,               ONLY: basis_set_list_setup
     126              :    USE qs_integrate_potential,          ONLY: integrate_pgf_product,&
     127              :                                               integrate_v_core_rspace,&
     128              :                                               integrate_v_rspace
     129              :    USE qs_interactions,                 ONLY: init_interaction_radii_orb_basis
     130              :    USE qs_kind_types,                   ONLY: qs_kind_type
     131              :    USE qs_ks_methods,                   ONLY: calc_rho_tot_gspace
     132              :    USE qs_ks_reference,                 ONLY: ks_ref_potential
     133              :    USE qs_ks_types,                     ONLY: set_ks_env
     134              :    USE qs_linres_types,                 ONLY: linres_control_type
     135              :    USE qs_matrix_w,                     ONLY: compute_matrix_w
     136              :    USE qs_mo_types,                     ONLY: get_mo_set,&
     137              :                                               mo_set_type
     138              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type,&
     139              :                                               release_neighbor_list_sets
     140              :    USE qs_overlap,                      ONLY: build_overlap_matrix
     141              :    USE qs_p_env_methods,                ONLY: p_env_create,&
     142              :                                               p_env_psi0_changed
     143              :    USE qs_p_env_types,                  ONLY: p_env_release,&
     144              :                                               qs_p_env_type
     145              :    USE qs_rho_atom_types,               ONLY: rho_atom_type
     146              :    USE qs_rho_types,                    ONLY: qs_rho_create,&
     147              :                                               qs_rho_get,&
     148              :                                               qs_rho_set,&
     149              :                                               qs_rho_type
     150              :    USE qs_tensors,                      ONLY: &
     151              :         build_2c_derivatives, build_2c_integrals, build_2c_neighbor_lists, build_3c_derivatives, &
     152              :         build_3c_neighbor_lists, calc_2c_virial, calc_3c_virial, compress_tensor, &
     153              :         decompress_tensor, get_tensor_occupancy, neighbor_list_3c_destroy
     154              :    USE qs_tensors_types,                ONLY: create_2c_tensor,&
     155              :                                               create_3c_tensor,&
     156              :                                               create_tensor_batches,&
     157              :                                               distribution_3d_create,&
     158              :                                               distribution_3d_type,&
     159              :                                               neighbor_list_3c_type
     160              :    USE realspace_grid_types,            ONLY: map_gaussian_here,&
     161              :                                               realspace_grid_type
     162              :    USE response_solver,                 ONLY: response_equation_new
     163              :    USE rpa_im_time,                     ONLY: compute_mat_dm_global
     164              :    USE rpa_im_time_force_types,         ONLY: im_time_force_type
     165              :    USE rs_pw_interface,                 ONLY: potential_pw2rs
     166              :    USE task_list_types,                 ONLY: task_list_type
     167              :    USE virial_types,                    ONLY: virial_type
     168              : #include "./base/base_uses.f90"
     169              : 
     170              :    IMPLICIT NONE
     171              : 
     172              :    PRIVATE
     173              : 
     174              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rpa_im_time_force_methods'
     175              : 
     176              :    PUBLIC :: init_im_time_forces, calc_laplace_loop_forces, calc_post_loop_forces, &
     177              :              keep_initial_quad, calc_rpa_loop_forces
     178              : 
     179              : CONTAINS
     180              : 
     181              : ! **************************************************************************************************
     182              : !> \brief Initializes and pre-calculates all needed tensors for the forces
     183              : !> \param force_data ...
     184              : !> \param fm_matrix_PQ ...
     185              : !> \param t_3c_M the 3-center M tensor to be used as a template
     186              : !> \param unit_nr ...
     187              : !> \param mp2_env ...
     188              : !> \param qs_env ...
     189              : ! **************************************************************************************************
     190           50 :    SUBROUTINE init_im_time_forces(force_data, fm_matrix_PQ, t_3c_M, unit_nr, mp2_env, qs_env)
     191              : 
     192              :       TYPE(im_time_force_type), INTENT(INOUT)            :: force_data
     193              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_matrix_PQ
     194              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_3c_M
     195              :       INTEGER, INTENT(IN)                                :: unit_nr
     196              :       TYPE(mp2_type)                                     :: mp2_env
     197              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     198              : 
     199              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'init_im_time_forces'
     200              : 
     201              :       INTEGER                                            :: handle, i_mem, i_xyz, ibasis, ispin, &
     202              :                                                             n_dependent, n_mem, n_rep, natom, &
     203              :                                                             nkind, nspins
     204              :       INTEGER(int_8)                                     :: nze, nze_tot
     205           50 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: dist1, dist2, dist_AO_1, dist_AO_2, &
     206           50 :                                                             dist_RI, dummy_end, dummy_start, &
     207          100 :                                                             end_blocks, sizes_AO, sizes_RI, &
     208           50 :                                                             start_blocks
     209              :       INTEGER, DIMENSION(2)                              :: pdims_t2c
     210              :       INTEGER, DIMENSION(3)                              :: nblks_total, pcoord, pdims, pdims_t3c
     211          100 :       INTEGER, DIMENSION(:), POINTER                     :: col_bsize, row_bsize
     212              :       LOGICAL                                            :: do_periodic, use_virial
     213              :       REAL(dp)                                           :: compression_factor, eps_pgf_orb, &
     214              :                                                             eps_pgf_orb_old, memory, occ
     215              :       TYPE(cell_type), POINTER                           :: cell
     216              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     217              :       TYPE(dbcsr_distribution_type)                      :: dbcsr_dist
     218          100 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, rho_ao
     219              :       TYPE(dbcsr_type)                                   :: dbcsr_work, dbcsr_work2, dbcsr_work3
     220          100 :       TYPE(dbcsr_type), DIMENSION(1)                     :: t_2c_int_tmp
     221          350 :       TYPE(dbcsr_type), DIMENSION(1, 3)                  :: t_2c_der_tmp
     222          250 :       TYPE(dbt_pgrid_type)                               :: pgrid_t2c, pgrid_t3c
     223         1000 :       TYPE(dbt_type)                                     :: t_2c_template, t_2c_tmp, t_3c_template
     224           50 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:, :, :)    :: t_3c_der_AO_prv, t_3c_der_RI_prv
     225              :       TYPE(dft_control_type), POINTER                    :: dft_control
     226              :       TYPE(distribution_2d_type), POINTER                :: dist_2d
     227              :       TYPE(distribution_3d_type)                         :: dist_3d, dist_vir
     228              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
     229           50 :          DIMENSION(:), TARGET                            :: basis_set_ao, basis_set_ri_aux
     230              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis, ri_basis
     231              :       TYPE(libint_potential_type)                        :: identity_pot
     232           50 :       TYPE(mp_cart_type)                                 :: mp_comm_t3c, mp_comm_vir
     233              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     234              :       TYPE(neighbor_list_3c_type)                        :: nl_3c
     235              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     236           50 :          POINTER                                         :: nl_2c
     237           50 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     238           50 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     239              :       TYPE(qs_rho_type), POINTER                         :: rho
     240              :       TYPE(section_vals_type), POINTER                   :: qs_section
     241              :       TYPE(virial_type), POINTER                         :: virial
     242              : 
     243           50 :       NULLIFY (dft_control, para_env, particle_set, qs_kind_set, dist_2d, nl_2c, blacs_env, matrix_s, &
     244           50 :                rho, rho_ao, cell, qs_section, orb_basis, ri_basis, virial)
     245              : 
     246           50 :       CALL cite_reference(Bussy2023)
     247              : 
     248           50 :       CALL timeset(routineN, handle)
     249              : 
     250              :       CALL get_qs_env(qs_env, natom=natom, nkind=nkind, dft_control=dft_control, para_env=para_env, &
     251           50 :                       particle_set=particle_set, qs_kind_set=qs_kind_set, cell=cell, virial=virial)
     252           50 :       IF (dft_control%qs_control%gapw) THEN
     253            0 :          CPABORT("Low-scaling RPA/SOS-MP2 forces only available with GPW")
     254              :       END IF
     255              : 
     256           50 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     257              : 
     258           50 :       do_periodic = .FALSE.
     259          128 :       IF (ANY(cell%perd == 1)) do_periodic = .TRUE.
     260           50 :       force_data%do_periodic = do_periodic
     261              : 
     262              :       !Dealing with the 3-center derivatives
     263           50 :       pdims_t3c = 0
     264           50 :       CALL dbt_pgrid_create(para_env, pdims_t3c, pgrid_t3c)
     265              : 
     266              :       !Make sure we use the proper QS EPS_PGF_ORB values
     267           50 :       qs_section => section_vals_get_subs_vals(qs_env%input, "DFT%QS")
     268           50 :       CALL section_vals_val_get(qs_section, "EPS_PGF_ORB", n_rep_val=n_rep)
     269           50 :       IF (n_rep /= 0) THEN
     270            0 :          CALL section_vals_val_get(qs_section, "EPS_PGF_ORB", r_val=eps_pgf_orb)
     271              :       ELSE
     272           50 :          CALL section_vals_val_get(qs_section, "EPS_DEFAULT", r_val=eps_pgf_orb)
     273           50 :          eps_pgf_orb = SQRT(eps_pgf_orb)
     274              :       END IF
     275           50 :       eps_pgf_orb_old = dft_control%qs_control%eps_pgf_orb
     276              : 
     277          200 :       ALLOCATE (sizes_RI(natom), sizes_AO(natom))
     278          400 :       ALLOCATE (basis_set_ri_aux(nkind), basis_set_ao(nkind))
     279           50 :       CALL basis_set_list_setup(basis_set_ri_aux, "RI_AUX", qs_kind_set)
     280           50 :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_RI, basis=basis_set_ri_aux)
     281           50 :       CALL basis_set_list_setup(basis_set_ao, "ORB", qs_kind_set)
     282           50 :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_AO, basis=basis_set_ao)
     283              : 
     284          150 :       DO ibasis = 1, SIZE(basis_set_ao)
     285          100 :          orb_basis => basis_set_ao(ibasis)%gto_basis_set
     286          100 :          CALL init_interaction_radii_orb_basis(orb_basis, eps_pgf_orb)
     287          100 :          ri_basis => basis_set_ri_aux(ibasis)%gto_basis_set
     288          150 :          CALL init_interaction_radii_orb_basis(ri_basis, eps_pgf_orb)
     289              :       END DO
     290              : 
     291              :       CALL create_3c_tensor(t_3c_template, dist_RI, dist_AO_1, dist_AO_2, pgrid_t3c, &
     292           50 :                             sizes_RI, sizes_AO, sizes_AO, map1=[1], map2=[2, 3], name="der (RI AO | AO)")
     293              : 
     294         1550 :       ALLOCATE (t_3c_der_RI_prv(1, 1, 3), t_3c_der_AO_prv(1, 1, 3))
     295          200 :       DO i_xyz = 1, 3
     296          150 :          CALL dbt_create(t_3c_template, t_3c_der_RI_prv(1, 1, i_xyz))
     297          200 :          CALL dbt_create(t_3c_template, t_3c_der_AO_prv(1, 1, i_xyz))
     298              :       END DO
     299              : 
     300           50 :       IF (use_virial) THEN
     301           52 :          ALLOCATE (force_data%t_3c_virial, force_data%t_3c_virial_split)
     302            4 :          CALL dbt_create(t_3c_template, force_data%t_3c_virial)
     303            4 :          CALL dbt_create(t_3c_M, force_data%t_3c_virial_split)
     304              :       END IF
     305           50 :       CALL dbt_destroy(t_3c_template)
     306              : 
     307           50 :       CALL dbt_mp_environ_pgrid(pgrid_t3c, pdims, pcoord)
     308           50 :       CALL mp_comm_t3c%create(pgrid_t3c%mp_comm_2d, 3, pdims)
     309              :       CALL distribution_3d_create(dist_3d, dist_RI, dist_AO_1, dist_AO_2, &
     310           50 :                                   nkind, particle_set, mp_comm_t3c, own_comm=.TRUE.)
     311              : 
     312              :       !In case of virial, we need to store the 3c_nl
     313           50 :       IF (use_virial) THEN
     314            4 :          ALLOCATE (force_data%nl_3c)
     315            4 :          CALL mp_comm_vir%create(pgrid_t3c%mp_comm_2d, 3, pdims)
     316              :          CALL distribution_3d_create(dist_vir, dist_RI, dist_AO_1, dist_AO_2, &
     317            4 :                                      nkind, particle_set, mp_comm_vir, own_comm=.TRUE.)
     318              :          CALL build_3c_neighbor_lists(force_data%nl_3c, basis_set_ri_aux, basis_set_ao, basis_set_ao, &
     319              :                                       dist_vir, mp2_env%ri_metric, "RPA_3c_nl", qs_env, op_pos=1, &
     320            4 :                                       sym_jk=.FALSE., own_dist=.TRUE.)
     321              :       END IF
     322              : 
     323              :       CALL build_3c_neighbor_lists(nl_3c, basis_set_ri_aux, basis_set_ao, basis_set_ao, dist_3d, &
     324              :                                    mp2_env%ri_metric, "RPA_3c_nl", qs_env, op_pos=1, sym_jk=.TRUE., &
     325           50 :                                    own_dist=.TRUE.)
     326           50 :       DEALLOCATE (dist_RI, dist_AO_1, dist_AO_2)
     327              : 
     328              :       !Prepare the resulting 3c tensors in the format of t_3c_M for compatible traces: (RI|AO AO), split blocks
     329           50 :       CALL dbt_get_info(t_3c_M, nblks_total=nblks_total)
     330          250 :       ALLOCATE (force_data%bsizes_RI_split(nblks_total(1)), force_data%bsizes_AO_split(nblks_total(2)))
     331           50 :       CALL dbt_get_info(t_3c_M, blk_size_1=force_data%bsizes_RI_split, blk_size_2=force_data%bsizes_AO_split)
     332          200 :       DO i_xyz = 1, 3
     333          150 :          CALL dbt_create(t_3c_M, force_data%t_3c_der_RI(i_xyz))
     334          200 :          CALL dbt_create(t_3c_M, force_data%t_3c_der_AO(i_xyz))
     335              :       END DO
     336              : 
     337              :       !Keep track of atom index corresponding to split blocks
     338          100 :       ALLOCATE (force_data%idx_to_at_RI(nblks_total(1)))
     339           50 :       CALL get_idx_to_atom(force_data%idx_to_at_RI, force_data%bsizes_RI_split, sizes_RI)
     340              : 
     341          100 :       ALLOCATE (force_data%idx_to_at_AO(nblks_total(2)))
     342           50 :       CALL get_idx_to_atom(force_data%idx_to_at_AO, force_data%bsizes_AO_split, sizes_AO)
     343              : 
     344           50 :       n_mem = mp2_env%ri_rpa_im_time%cut_memory
     345           50 :       CALL create_tensor_batches(sizes_RI, n_mem, dummy_start, dummy_end, start_blocks, end_blocks)
     346           50 :       DEALLOCATE (dummy_start, dummy_end)
     347              : 
     348       212300 :       ALLOCATE (force_data%t_3c_der_AO_comp(n_mem, 3), force_data%t_3c_der_RI_comp(n_mem, 3))
     349         1100 :       ALLOCATE (force_data%t_3c_der_AO_ind(n_mem, 3), force_data%t_3c_der_RI_ind(n_mem, 3))
     350              : 
     351           50 :       memory = 0.0_dp
     352           50 :       nze_tot = 0
     353          150 :       DO i_mem = 1, n_mem
     354              :          CALL build_3c_derivatives(t_3c_der_RI_prv, t_3c_der_AO_prv, mp2_env%ri_rpa_im_time%eps_filter, &
     355              :                                    qs_env, nl_3c, basis_set_ri_aux, basis_set_ao, basis_set_ao, &
     356              :                                    mp2_env%ri_metric, der_eps=mp2_env%ri_rpa_im_time%eps_filter, op_pos=1, &
     357          300 :                                    bounds_i=[start_blocks(i_mem), end_blocks(i_mem)])
     358              : 
     359          450 :          DO i_xyz = 1, 3
     360          300 :             CALL dbt_copy(t_3c_der_RI_prv(1, 1, i_xyz), force_data%t_3c_der_RI(i_xyz), move_data=.TRUE.)
     361          300 :             CALL dbt_filter(force_data%t_3c_der_RI(i_xyz), mp2_env%ri_rpa_im_time%eps_filter)
     362          300 :             CALL get_tensor_occupancy(force_data%t_3c_der_RI(i_xyz), nze, occ)
     363          300 :             nze_tot = nze_tot + nze
     364              : 
     365          300 :             CALL alloc_containers(force_data%t_3c_der_RI_comp(i_mem, i_xyz), 1)
     366              :             CALL compress_tensor(force_data%t_3c_der_RI(i_xyz), force_data%t_3c_der_RI_ind(i_mem, i_xyz)%ind, &
     367          300 :                                  force_data%t_3c_der_RI_comp(i_mem, i_xyz), mp2_env%ri_rpa_im_time%eps_compress, memory)
     368          300 :             CALL dbt_clear(force_data%t_3c_der_RI(i_xyz))
     369              : 
     370          300 :             CALL dbt_copy(t_3c_der_AO_prv(1, 1, i_xyz), force_data%t_3c_der_AO(i_xyz), move_data=.TRUE.)
     371          300 :             CALL dbt_filter(force_data%t_3c_der_AO(i_xyz), mp2_env%ri_rpa_im_time%eps_filter)
     372          300 :             CALL get_tensor_occupancy(force_data%t_3c_der_AO(i_xyz), nze, occ)
     373          300 :             nze_tot = nze_tot + nze
     374              : 
     375          300 :             CALL alloc_containers(force_data%t_3c_der_AO_comp(i_mem, i_xyz), 1)
     376              :             CALL compress_tensor(force_data%t_3c_der_AO(i_xyz), force_data%t_3c_der_AO_ind(i_mem, i_xyz)%ind, &
     377          300 :                                  force_data%t_3c_der_AO_comp(i_mem, i_xyz), mp2_env%ri_rpa_im_time%eps_compress, memory)
     378         1000 :             CALL dbt_clear(force_data%t_3c_der_AO(i_xyz))
     379              :          END DO
     380              :       END DO
     381           50 :       CALL neighbor_list_3c_destroy(nl_3c)
     382          200 :       DO i_xyz = 1, 3
     383          150 :          CALL dbt_destroy(t_3c_der_RI_prv(1, 1, i_xyz))
     384          200 :          CALL dbt_destroy(t_3c_der_AO_prv(1, 1, i_xyz))
     385              :       END DO
     386              : 
     387           50 :       CALL para_env%sum(memory)
     388           50 :       compression_factor = REAL(nze_tot, dp)*1.0E-06*8.0_dp/memory
     389           50 :       IF (unit_nr > 0) THEN
     390              :          WRITE (UNIT=unit_nr, FMT="((T3,A,T66,F11.2,A4))") &
     391           25 :             "MEMORY_INFO| Memory for 3-center derivatives (compressed):", memory, ' MiB'
     392              : 
     393              :          WRITE (UNIT=unit_nr, FMT="((T3,A,T60,F21.2))") &
     394           25 :             "MEMORY_INFO| Compression factor:                  ", compression_factor
     395              :       END IF
     396              : 
     397              :       !Dealing with the 2-center derivatives
     398           50 :       CALL get_qs_env(qs_env, distribution_2d=dist_2d, blacs_env=blacs_env, matrix_s=matrix_s)
     399           50 :       CALL cp_dbcsr_dist2d_to_dist(dist_2d, dbcsr_dist)
     400          150 :       ALLOCATE (row_bsize(SIZE(sizes_RI)))
     401          100 :       ALLOCATE (col_bsize(SIZE(sizes_RI)))
     402          212 :       row_bsize(:) = sizes_RI(:)
     403          212 :       col_bsize(:) = sizes_RI(:)
     404              : 
     405           50 :       pdims_t2c = 0
     406           50 :       CALL dbt_pgrid_create(para_env, pdims_t2c, pgrid_t2c)
     407              :       CALL create_2c_tensor(t_2c_template, dist1, dist2, pgrid_t2c, force_data%bsizes_RI_split, &
     408           50 :                             force_data%bsizes_RI_split, name='(RI| RI)')
     409           50 :       DEALLOCATE (dist1, dist2)
     410              : 
     411           50 :       CALL dbcsr_create(t_2c_int_tmp(1), "(P|Q) RPA", dbcsr_dist, dbcsr_type_symmetric, row_bsize, col_bsize)
     412          200 :       DO i_xyz = 1, 3
     413              :          CALL dbcsr_create(t_2c_der_tmp(1, i_xyz), "(P|Q) RPA der", dbcsr_dist, &
     414          200 :                            dbcsr_type_antisymmetric, row_bsize, col_bsize)
     415              :       END DO
     416              : 
     417           50 :       IF (use_virial) THEN
     418            4 :          ALLOCATE (force_data%RI_virial_pot, force_data%RI_virial_met)
     419              :          CALL dbcsr_create(force_data%RI_virial_pot, "RI_virial", dbcsr_dist, &
     420            4 :                            dbcsr_type_no_symmetry, row_bsize, col_bsize)
     421              :          CALL dbcsr_create(force_data%RI_virial_met, "RI_virial", dbcsr_dist, &
     422            4 :                            dbcsr_type_no_symmetry, row_bsize, col_bsize)
     423              :       END IF
     424              : 
     425              :       ! Main (P|Q) integrals and derivatives
     426              :       ! Integrals are passed as a full matrix => convert to DBCSR
     427           50 :       CALL dbcsr_create(dbcsr_work, template=t_2c_int_tmp(1))
     428           50 :       CALL copy_fm_to_dbcsr(fm_matrix_PQ, dbcsr_work)
     429              : 
     430              :       ! We need the  +/- square root of (P|Q)
     431           50 :       CALL dbcsr_create(dbcsr_work2, template=t_2c_int_tmp(1))
     432           50 :       CALL dbcsr_create(dbcsr_work3, template=t_2c_int_tmp(1))
     433           50 :       CALL dbcsr_copy(dbcsr_work2, dbcsr_work)
     434           50 :       CALL cp_dbcsr_power(dbcsr_work, -0.5_dp, 1.0E-7_dp, n_dependent, para_env, blacs_env) !1.0E-7 ev qunenching thresh
     435              : 
     436              :       ! Transfer to tensor format with split blocks
     437           50 :       CALL dbt_create(dbcsr_work, t_2c_tmp)
     438           50 :       CALL dbt_copy_matrix_to_tensor(dbcsr_work, t_2c_tmp)
     439           50 :       CALL dbt_create(t_2c_template, force_data%t_2c_pot_msqrt)
     440           50 :       CALL dbt_copy(t_2c_tmp, force_data%t_2c_pot_msqrt, move_data=.TRUE.)
     441           50 :       CALL dbt_filter(force_data%t_2c_pot_msqrt, mp2_env%ri_rpa_im_time%eps_filter)
     442              : 
     443           50 :       CALL dbcsr_multiply('N', 'N', 1.0_dp, dbcsr_work2, dbcsr_work, 0.0_dp, dbcsr_work3)
     444           50 :       CALL dbt_copy_matrix_to_tensor(dbcsr_work3, t_2c_tmp)
     445           50 :       CALL dbt_create(t_2c_template, force_data%t_2c_pot_psqrt)
     446           50 :       CALL dbt_copy(t_2c_tmp, force_data%t_2c_pot_psqrt, move_data=.TRUE.)
     447           50 :       CALL dbt_filter(force_data%t_2c_pot_psqrt, mp2_env%ri_rpa_im_time%eps_filter)
     448           50 :       CALL dbt_destroy(t_2c_tmp)
     449           50 :       CALL dbcsr_release(dbcsr_work2)
     450           50 :       CALL dbcsr_release(dbcsr_work3)
     451           50 :       CALL dbcsr_clear(dbcsr_work)
     452              : 
     453              :       ! Deal with the 2c potential derivatives. Only precompute if not in PBCs
     454           50 :       IF (.NOT. do_periodic) THEN
     455              :          CALL build_2c_neighbor_lists(nl_2c, basis_set_ri_aux, basis_set_ri_aux, mp2_env%potential_parameter, &
     456           26 :                                       "RPA_2c_nl_pot", qs_env, sym_ij=.TRUE., dist_2d=dist_2d)
     457              :          CALL build_2c_derivatives(t_2c_der_tmp, mp2_env%ri_rpa_im_time%eps_filter, qs_env, nl_2c, &
     458           26 :                                    basis_set_ri_aux, basis_set_ri_aux, mp2_env%potential_parameter)
     459           26 :          CALL release_neighbor_list_sets(nl_2c)
     460              : 
     461          104 :          DO i_xyz = 1, 3
     462           78 :             CALL dbt_create(t_2c_der_tmp(1, i_xyz), t_2c_tmp)
     463           78 :             CALL dbt_copy_matrix_to_tensor(t_2c_der_tmp(1, i_xyz), t_2c_tmp)
     464           78 :             CALL dbt_create(t_2c_template, force_data%t_2c_der_pot(i_xyz))
     465           78 :             CALL dbt_copy(t_2c_tmp, force_data%t_2c_der_pot(i_xyz), move_data=.TRUE.)
     466           78 :             CALL dbt_filter(force_data%t_2c_der_pot(i_xyz), mp2_env%ri_rpa_im_time%eps_filter)
     467           78 :             CALL dbt_destroy(t_2c_tmp)
     468          104 :             CALL dbcsr_clear(t_2c_der_tmp(1, i_xyz))
     469              :          END DO
     470              : 
     471           26 :          IF (use_virial) THEN
     472              :             CALL build_2c_neighbor_lists(force_data%nl_2c_pot, basis_set_ri_aux, basis_set_ri_aux, &
     473              :                                          mp2_env%potential_parameter, "RPA_2c_nl_pot", qs_env, &
     474            0 :                                          sym_ij=.FALSE., dist_2d=dist_2d)
     475              :          END IF
     476              :       END IF
     477              :       ! Create a G_PQ matrix to collect the terms for the force trace in the periodic case
     478           50 :       CALL dbcsr_create(force_data%G_PQ, "G_PQ", dbcsr_dist, dbcsr_type_no_symmetry, row_bsize, col_bsize)
     479              : 
     480              :       ! we need the RI metric derivatives and the inverse of the integrals
     481              :       CALL build_2c_neighbor_lists(nl_2c, basis_set_ri_aux, basis_set_ri_aux, mp2_env%ri_metric, &
     482           50 :                                    "RPA_2c_nl_metric", qs_env, sym_ij=.TRUE., dist_2d=dist_2d)
     483              :       CALL build_2c_integrals(t_2c_int_tmp, mp2_env%ri_rpa_im_time%eps_filter, qs_env, nl_2c, &
     484           50 :                               basis_set_ri_aux, basis_set_ri_aux, mp2_env%ri_metric)
     485              :       CALL build_2c_derivatives(t_2c_der_tmp, mp2_env%ri_rpa_im_time%eps_filter, qs_env, nl_2c, &
     486           50 :                                 basis_set_ri_aux, basis_set_ri_aux, mp2_env%ri_metric)
     487           50 :       CALL release_neighbor_list_sets(nl_2c)
     488              : 
     489           50 :       IF (use_virial) THEN
     490              :          CALL build_2c_neighbor_lists(force_data%nl_2c_met, basis_set_ri_aux, basis_set_ri_aux, &
     491              :                                       mp2_env%ri_metric, "RPA_2c_nl_metric", qs_env, sym_ij=.FALSE., &
     492            4 :                                       dist_2d=dist_2d)
     493              :       END IF
     494              : 
     495           50 :       CALL dbcsr_copy(dbcsr_work, t_2c_int_tmp(1))
     496           50 :       CALL cp_dbcsr_cholesky_decompose(dbcsr_work, para_env=para_env, blacs_env=blacs_env)
     497           50 :       CALL cp_dbcsr_cholesky_invert(dbcsr_work, para_env=para_env, blacs_env=blacs_env, uplo_to_full=.TRUE.)
     498              : 
     499           50 :       CALL dbt_create(dbcsr_work, t_2c_tmp)
     500           50 :       CALL dbt_copy_matrix_to_tensor(dbcsr_work, t_2c_tmp)
     501           50 :       CALL dbt_create(t_2c_template, force_data%t_2c_inv_metric)
     502           50 :       CALL dbt_copy(t_2c_tmp, force_data%t_2c_inv_metric, move_data=.TRUE.)
     503           50 :       CALL dbt_filter(force_data%t_2c_inv_metric, mp2_env%ri_rpa_im_time%eps_filter)
     504           50 :       CALL dbt_destroy(t_2c_tmp)
     505           50 :       CALL dbcsr_clear(dbcsr_work)
     506           50 :       CALL dbcsr_clear(t_2c_int_tmp(1))
     507              : 
     508          200 :       DO i_xyz = 1, 3
     509          150 :          CALL dbt_create(t_2c_der_tmp(1, i_xyz), t_2c_tmp)
     510          150 :          CALL dbt_copy_matrix_to_tensor(t_2c_der_tmp(1, i_xyz), t_2c_tmp)
     511          150 :          CALL dbt_create(t_2c_template, force_data%t_2c_der_metric(i_xyz))
     512          150 :          CALL dbt_copy(t_2c_tmp, force_data%t_2c_der_metric(i_xyz), move_data=.TRUE.)
     513          150 :          CALL dbt_filter(force_data%t_2c_der_metric(i_xyz), mp2_env%ri_rpa_im_time%eps_filter)
     514          150 :          CALL dbt_destroy(t_2c_tmp)
     515          200 :          CALL dbcsr_clear(t_2c_der_tmp(1, i_xyz))
     516              :       END DO
     517              : 
     518              :       !Pre-calculate matrix K = metric^-1 * V^0.5
     519           50 :       CALL dbt_create(t_2c_template, force_data%t_2c_K)
     520              :       CALL dbt_contract(1.0_dp, force_data%t_2c_inv_metric, force_data%t_2c_pot_psqrt, &
     521              :                         0.0_dp, force_data%t_2c_K, &
     522              :                         contract_1=[2], notcontract_1=[1], &
     523              :                         contract_2=[1], notcontract_2=[2], &
     524           50 :                         map_1=[1], map_2=[2], filter_eps=mp2_env%ri_rpa_im_time%eps_filter)
     525              : 
     526              :       ! Finally, we need the overlap matrix derivative and the inverse of the integrals
     527           50 :       CALL dbt_destroy(t_2c_template)
     528           50 :       CALL dbcsr_release(dbcsr_work)
     529           50 :       CALL dbcsr_release(t_2c_int_tmp(1))
     530          200 :       DO i_xyz = 1, 3
     531          200 :          CALL dbcsr_release(t_2c_der_tmp(1, i_xyz))
     532              :       END DO
     533              : 
     534           50 :       DEALLOCATE (row_bsize, col_bsize)
     535          150 :       ALLOCATE (row_bsize(SIZE(sizes_AO)))
     536          100 :       ALLOCATE (col_bsize(SIZE(sizes_AO)))
     537          212 :       row_bsize(:) = sizes_AO(:)
     538          212 :       col_bsize(:) = sizes_AO(:)
     539              : 
     540              :       CALL create_2c_tensor(t_2c_template, dist1, dist2, pgrid_t2c, force_data%bsizes_AO_split, &
     541           50 :                             force_data%bsizes_AO_split, name='(AO| AO)')
     542           50 :       DEALLOCATE (dist1, dist2)
     543              : 
     544          200 :       DO i_xyz = 1, 3
     545              :          CALL dbcsr_create(t_2c_der_tmp(1, i_xyz), "(P|Q) RPA der", dbcsr_dist, &
     546          200 :                            dbcsr_type_antisymmetric, row_bsize, col_bsize)
     547              :       END DO
     548              : 
     549           50 :       identity_pot%potential_type = do_potential_id
     550              :       CALL build_2c_neighbor_lists(nl_2c, basis_set_ao, basis_set_ao, identity_pot, &
     551           50 :                                    "RPA_2c_nl_metric", qs_env, sym_ij=.TRUE., dist_2d=dist_2d)
     552              :       CALL build_2c_derivatives(t_2c_der_tmp, mp2_env%ri_rpa_im_time%eps_filter, qs_env, nl_2c, &
     553           50 :                                 basis_set_ao, basis_set_ao, identity_pot)
     554           50 :       CALL release_neighbor_list_sets(nl_2c)
     555              : 
     556           50 :       IF (use_virial) THEN
     557              :          CALL build_2c_neighbor_lists(force_data%nl_2c_ovlp, basis_set_ao, basis_set_ao, identity_pot, &
     558            4 :                                       "RPA_2c_nl_metric", qs_env, sym_ij=.FALSE., dist_2d=dist_2d)
     559              :       END IF
     560              : 
     561           50 :       CALL dbcsr_create(force_data%inv_ovlp, template=matrix_s(1)%matrix)
     562           50 :       CALL dbcsr_copy(force_data%inv_ovlp, matrix_s(1)%matrix)
     563           50 :       CALL cp_dbcsr_cholesky_decompose(force_data%inv_ovlp, para_env=para_env, blacs_env=blacs_env)
     564           50 :       CALL cp_dbcsr_cholesky_invert(force_data%inv_ovlp, para_env=para_env, blacs_env=blacs_env, uplo_to_full=.TRUE.)
     565              : 
     566          200 :       DO i_xyz = 1, 3
     567          150 :          CALL dbt_create(t_2c_der_tmp(1, i_xyz), t_2c_tmp)
     568          150 :          CALL dbt_copy_matrix_to_tensor(t_2c_der_tmp(1, i_xyz), t_2c_tmp)
     569          150 :          CALL dbt_create(t_2c_template, force_data%t_2c_der_ovlp(i_xyz))
     570          150 :          CALL dbt_copy(t_2c_tmp, force_data%t_2c_der_ovlp(i_xyz), move_data=.TRUE.)
     571          150 :          CALL dbt_filter(force_data%t_2c_der_ovlp(i_xyz), mp2_env%ri_rpa_im_time%eps_filter)
     572          150 :          CALL dbt_destroy(t_2c_tmp)
     573          200 :          CALL dbcsr_clear(t_2c_der_tmp(1, i_xyz))
     574              :       END DO
     575              : 
     576              :       !Create the rest of the 2-center AO tensors
     577           50 :       nspins = dft_control%nspins
     578          324 :       ALLOCATE (force_data%P_virt(nspins), force_data%P_occ(nspins))
     579          274 :       ALLOCATE (force_data%sum_YP_tau(nspins), force_data%sum_O_tau(nspins))
     580          112 :       DO ispin = 1, nspins
     581           62 :          ALLOCATE (force_data%P_virt(ispin)%matrix, force_data%P_occ(ispin)%matrix)
     582           62 :          ALLOCATE (force_data%sum_YP_tau(ispin)%matrix, force_data%sum_O_tau(ispin)%matrix)
     583           62 :          CALL dbcsr_create(force_data%P_virt(ispin)%matrix, template=matrix_s(1)%matrix)
     584           62 :          CALL dbcsr_create(force_data%P_occ(ispin)%matrix, template=matrix_s(1)%matrix)
     585           62 :          CALL dbcsr_create(force_data%sum_O_tau(ispin)%matrix, template=matrix_s(1)%matrix)
     586           62 :          CALL dbcsr_create(force_data%sum_YP_tau(ispin)%matrix, template=matrix_s(1)%matrix)
     587              : 
     588           62 :          CALL dbcsr_copy(force_data%sum_O_tau(ispin)%matrix, matrix_s(1)%matrix)
     589           62 :          CALL dbcsr_copy(force_data%sum_YP_tau(ispin)%matrix, matrix_s(1)%matrix)
     590              : 
     591           62 :          CALL dbcsr_set(force_data%sum_O_tau(ispin)%matrix, 0.0_dp)
     592          112 :          CALL dbcsr_set(force_data%sum_YP_tau(ispin)%matrix, 0.0_dp)
     593              :       END DO
     594              : 
     595              :       !Populate the density matrices: 1 = P_virt*S +P_occ*S ==> P_virt = S^-1 - P_occ
     596           50 :       CALL get_qs_env(qs_env, rho=rho)
     597           50 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     598           50 :       CALL dbcsr_copy(force_data%P_occ(1)%matrix, rho_ao(1)%matrix)
     599           50 :       IF (nspins == 1) THEN
     600           38 :          CALL dbcsr_scale(force_data%P_occ(1)%matrix, 0.5_dp) !because double occupency
     601              :       ELSE
     602           12 :          CALL dbcsr_copy(force_data%P_occ(2)%matrix, rho_ao(2)%matrix)
     603              :       END IF
     604          112 :       DO ispin = 1, nspins
     605           62 :          CALL dbcsr_copy(force_data%P_virt(ispin)%matrix, force_data%inv_ovlp)
     606          112 :          CALL dbcsr_add(force_data%P_virt(ispin)%matrix, force_data%P_occ(ispin)%matrix, 1.0_dp, -1.0_dp)
     607              :       END DO
     608              : 
     609          150 :       DO ibasis = 1, SIZE(basis_set_ao)
     610          100 :          orb_basis => basis_set_ao(ibasis)%gto_basis_set
     611          100 :          CALL init_interaction_radii_orb_basis(orb_basis, eps_pgf_orb_old)
     612          100 :          ri_basis => basis_set_ri_aux(ibasis)%gto_basis_set
     613          150 :          CALL init_interaction_radii_orb_basis(ri_basis, eps_pgf_orb_old)
     614              :       END DO
     615              : 
     616           50 :       CALL dbt_destroy(t_2c_template)
     617           50 :       CALL dbcsr_release(dbcsr_work)
     618          200 :       DO i_xyz = 1, 3
     619          200 :          CALL dbcsr_release(t_2c_der_tmp(1, i_xyz))
     620              :       END DO
     621           50 :       DEALLOCATE (row_bsize, col_bsize)
     622           50 :       CALL dbt_pgrid_destroy(pgrid_t3c)
     623           50 :       CALL dbt_pgrid_destroy(pgrid_t2c)
     624           50 :       CALL dbcsr_distribution_release(dbcsr_dist)
     625           50 :       CALL timestop(handle)
     626              : 
     627          600 :    END SUBROUTINE init_im_time_forces
     628              : 
     629              : ! **************************************************************************************************
     630              : !> \brief Updates the cubic-scaling SOS-Laplace-MP2 contribution to the forces at each quadrature point
     631              : !> \param force_data ...
     632              : !> \param mat_P_omega ...
     633              : !> \param t_3c_M ...
     634              : !> \param t_3c_O ...
     635              : !> \param t_3c_O_compressed ...
     636              : !> \param t_3c_O_ind ...
     637              : !> \param fm_scaled_dm_occ_tau ...
     638              : !> \param fm_scaled_dm_virt_tau ...
     639              : !> \param fm_mo_coeff_occ ...
     640              : !> \param fm_mo_coeff_virt ...
     641              : !> \param fm_mo_coeff_occ_scaled ...
     642              : !> \param fm_mo_coeff_virt_scaled ...
     643              : !> \param starts_array_mc ...
     644              : !> \param ends_array_mc ...
     645              : !> \param starts_array_mc_block ...
     646              : !> \param ends_array_mc_block ...
     647              : !> \param num_integ_points ...
     648              : !> \param nmo ...
     649              : !> \param Eigenval ...
     650              : !> \param tau_tj ...
     651              : !> \param tau_wj ...
     652              : !> \param cut_memory ...
     653              : !> \param Pspin ...
     654              : !> \param Qspin ...
     655              : !> \param open_shell ...
     656              : !> \param unit_nr ...
     657              : !> \param dbcsr_time ...
     658              : !> \param dbcsr_nflop ...
     659              : !> \param mp2_env ...
     660              : !> \param qs_env ...
     661              : !> \note In open-shell, we need to take Q from one spin, and everything from the other
     662              : ! **************************************************************************************************
     663          130 :    SUBROUTINE calc_laplace_loop_forces(force_data, mat_P_omega, t_3c_M, t_3c_O, t_3c_O_compressed, &
     664           26 :                                        t_3c_O_ind, fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, &
     665           26 :                                        fm_mo_coeff_occ, fm_mo_coeff_virt, fm_mo_coeff_occ_scaled, &
     666           26 :                                        fm_mo_coeff_virt_scaled, starts_array_mc, ends_array_mc, &
     667           26 :                                        starts_array_mc_block, ends_array_mc_block, num_integ_points, &
     668           52 :                                        nmo, Eigenval, tau_tj, tau_wj, cut_memory, Pspin, Qspin, &
     669              :                                        open_shell, unit_nr, dbcsr_time, dbcsr_nflop, mp2_env, qs_env)
     670              : 
     671              :       TYPE(im_time_force_type), INTENT(INOUT)            :: force_data
     672              :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(INOUT) :: mat_P_omega
     673              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_3c_M, t_3c_O
     674              :       TYPE(hfx_compression_type), DIMENSION(:)           :: t_3c_O_compressed
     675              :       TYPE(block_ind_type), DIMENSION(:), INTENT(INOUT)  :: t_3c_O_ind
     676              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_scaled_dm_occ_tau, &
     677              :                                                             fm_scaled_dm_virt_tau
     678              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mo_coeff_occ, fm_mo_coeff_virt
     679              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mo_coeff_occ_scaled, &
     680              :                                                             fm_mo_coeff_virt_scaled
     681              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: starts_array_mc, ends_array_mc, &
     682              :                                                             starts_array_mc_block, &
     683              :                                                             ends_array_mc_block
     684              :       INTEGER, INTENT(IN)                                :: num_integ_points, nmo
     685              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: Eigenval
     686              :       REAL(KIND=dp), DIMENSION(num_integ_points), &
     687              :          INTENT(IN)                                      :: tau_tj
     688              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
     689              :          INTENT(IN)                                      :: tau_wj
     690              :       INTEGER, INTENT(IN)                                :: cut_memory, Pspin, Qspin
     691              :       LOGICAL, INTENT(IN)                                :: open_shell
     692              :       INTEGER, INTENT(IN)                                :: unit_nr
     693              :       REAL(dp), INTENT(INOUT)                            :: dbcsr_time
     694              :       INTEGER(int_8), INTENT(INOUT)                      :: dbcsr_nflop
     695              :       TYPE(mp2_type)                                     :: mp2_env
     696              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     697              : 
     698              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calc_laplace_loop_forces'
     699              : 
     700              :       INTEGER :: dummy_int, handle, handle2, i_mem, i_xyz, ibasis, ispin, j_xyz, jquad, k_xyz, &
     701              :          n_mem_RI, n_rep, natom, nkind, nspins, unit_nr_dbcsr
     702              :       INTEGER(int_8)                                     :: flop, nze, nze_ddint, nze_der_AO, &
     703              :                                                             nze_der_RI, nze_KQK
     704           26 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, batch_blk_end, &
     705           26 :                                                             batch_blk_start, batch_end_RI, &
     706           26 :                                                             batch_start_RI, kind_of, mc_ranges, &
     707           26 :                                                             mc_ranges_RI
     708           26 :       INTEGER, DIMENSION(:, :), POINTER                  :: dummy_ptr
     709              :       LOGICAL                                            :: memory_info, use_virial
     710              :       REAL(dp)                                           :: eps_filter, eps_pgf_orb, &
     711              :                                                             eps_pgf_orb_old, fac, occ, occ_ddint, &
     712              :                                                             occ_der_AO, occ_der_RI, occ_KQK, &
     713              :                                                             omega, pref, t1, t2, tau
     714              :       REAL(dp), DIMENSION(3, 3)                          :: work_virial, work_virial_ovlp
     715           26 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     716              :       TYPE(cell_type), POINTER                           :: cell
     717           26 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     718           26 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_occ, mat_dm_virt
     719              :       TYPE(dbcsr_type)                                   :: dbcsr_work1, dbcsr_work2, dbcsr_work3, &
     720              :                                                             exp_occ, exp_virt, R_occ, R_virt, &
     721              :                                                             virial_ovlp, Y_1, Y_2
     722         1274 :       TYPE(dbt_type) :: t_2c_AO, t_2c_RI, t_2c_RI_2, t_2c_tmp, t_3c_0, t_3c_1, t_3c_3, t_3c_4, &
     723         1274 :          t_3c_5, t_3c_6, t_3c_7, t_3c_8, t_3c_help_1, t_3c_help_2, t_3c_ints, t_3c_sparse, &
     724         1456 :          t_3c_work, t_dm_occ, t_dm_virt, t_KQKT, t_M_occ, t_M_virt, t_Q, t_R_occ, t_R_virt
     725           26 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:)          :: t_P
     726              :       TYPE(dft_control_type), POINTER                    :: dft_control
     727              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
     728           26 :          DIMENSION(:), TARGET                            :: basis_set_ao, basis_set_ri_aux
     729              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis, ri_basis
     730              :       TYPE(libint_potential_type)                        :: identity_pot
     731              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     732           26 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     733           26 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
     734           26 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     735              :       TYPE(section_vals_type), POINTER                   :: qs_section
     736              :       TYPE(virial_type), POINTER                         :: virial
     737              : 
     738           26 :       NULLIFY (matrix_s, dummy_ptr, atomic_kind_set, force, matrix_s, matrix_ks, mat_dm_occ, mat_dm_virt)
     739           26 :       NULLIFY (dft_control, virial, particle_set, cell, para_env, orb_basis, ri_basis, qs_section)
     740           26 :       NULLIFY (qs_kind_set)
     741              : 
     742           26 :       CALL timeset(routineN, handle)
     743              : 
     744              :       CALL get_qs_env(qs_env, matrix_s=matrix_s, natom=natom, atomic_kind_set=atomic_kind_set, &
     745              :                       force=force, matrix_ks=matrix_ks, dft_control=dft_control, virial=virial, &
     746              :                       particle_set=particle_set, cell=cell, para_env=para_env, nkind=nkind, &
     747           26 :                       qs_kind_set=qs_kind_set)
     748           26 :       eps_filter = mp2_env%ri_rpa_im_time%eps_filter
     749           26 :       nspins = dft_control%nspins
     750              : 
     751           26 :       memory_info = mp2_env%ri_rpa_im_time%memory_info
     752           26 :       IF (memory_info) THEN
     753            0 :          unit_nr_dbcsr = unit_nr
     754              :       ELSE
     755           26 :          unit_nr_dbcsr = 0
     756              :       END IF
     757              : 
     758           26 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
     759              : 
     760           26 :       IF (use_virial) virial%pv_calculate = .TRUE.
     761              : 
     762           26 :       IF (use_virial) THEN
     763            2 :          qs_section => section_vals_get_subs_vals(qs_env%input, "DFT%QS")
     764            2 :          CALL section_vals_val_get(qs_section, "EPS_PGF_ORB", n_rep_val=n_rep)
     765            2 :          IF (n_rep /= 0) THEN
     766            0 :             CALL section_vals_val_get(qs_section, "EPS_PGF_ORB", r_val=eps_pgf_orb)
     767              :          ELSE
     768            2 :             CALL section_vals_val_get(qs_section, "EPS_DEFAULT", r_val=eps_pgf_orb)
     769            2 :             eps_pgf_orb = SQRT(eps_pgf_orb)
     770              :          END IF
     771            2 :          eps_pgf_orb_old = dft_control%qs_control%eps_pgf_orb
     772              : 
     773           16 :          ALLOCATE (basis_set_ri_aux(nkind), basis_set_ao(nkind))
     774            2 :          CALL basis_set_list_setup(basis_set_ri_aux, "RI_AUX", qs_kind_set)
     775            2 :          CALL basis_set_list_setup(basis_set_ao, "ORB", qs_kind_set)
     776              : 
     777            8 :          DO ibasis = 1, SIZE(basis_set_ao)
     778            4 :             orb_basis => basis_set_ao(ibasis)%gto_basis_set
     779            4 :             CALL init_interaction_radii_orb_basis(orb_basis, eps_pgf_orb)
     780            4 :             ri_basis => basis_set_ri_aux(ibasis)%gto_basis_set
     781            6 :             CALL init_interaction_radii_orb_basis(ri_basis, eps_pgf_orb)
     782              :          END DO
     783              :       END IF
     784              : 
     785              :       !We follow the general logic of the compute_mat_P_omega routine
     786          268 :       ALLOCATE (t_P(nspins))
     787           26 :       CALL dbt_create(force_data%t_2c_K, t_2c_RI)
     788           26 :       CALL dbt_create(force_data%t_2c_K, t_2c_RI_2)
     789           26 :       CALL dbt_create(force_data%t_2c_der_ovlp(1), t_2c_AO)
     790              : 
     791           26 :       CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of, atom_of_kind=atom_of_kind)
     792              : 
     793              :       ! Always do the batching of the MO on mu and sigma, such that it is consistent between
     794              :       ! the occupied and the virtual quantities
     795           78 :       ALLOCATE (mc_ranges(cut_memory + 1))
     796           78 :       mc_ranges(:cut_memory) = starts_array_mc_block(:)
     797           26 :       mc_ranges(cut_memory + 1) = ends_array_mc_block(cut_memory) + 1
     798              : 
     799              :       ! Also need some batching on the RI, because it loses sparsity at some point
     800           26 :       n_mem_RI = cut_memory
     801              :       CALL create_tensor_batches(force_data%bsizes_RI_split, n_mem_RI, batch_start_RI, batch_end_RI, &
     802           26 :                                  batch_blk_start, batch_blk_end)
     803           78 :       ALLOCATE (mc_ranges_RI(n_mem_RI + 1))
     804           78 :       mc_ranges_RI(1:n_mem_RI) = batch_blk_start(1:n_mem_RI)
     805           26 :       mc_ranges_RI(n_mem_RI + 1) = batch_blk_end(n_mem_RI) + 1
     806           26 :       DEALLOCATE (batch_blk_start, batch_blk_end)
     807              : 
     808              :       !Pre-allocate all required tensors and matrices
     809           60 :       DO ispin = 1, nspins
     810           60 :          CALL dbt_create(t_2c_RI, t_P(ispin))
     811              :       END DO
     812           26 :       CALL dbt_create(t_2c_RI, t_Q)
     813           26 :       CALL dbt_create(t_2c_RI, t_KQKT)
     814           26 :       CALL dbt_create(t_2c_AO, t_dm_occ)
     815           26 :       CALL dbt_create(t_2c_AO, t_dm_virt)
     816              : 
     817              :       !note: t_3c_O and t_3c_M have different mappings (map_1d, map_2d)
     818           26 :       CALL dbt_create(t_3c_O, t_M_occ)
     819           26 :       CALL dbt_create(t_3c_O, t_M_virt)
     820           26 :       CALL dbt_create(t_3c_O, t_3c_0)
     821              : 
     822           26 :       CALL dbt_create(t_3c_O, t_3c_1)
     823           26 :       CALL dbt_create(t_3c_O, t_3c_3)
     824           26 :       CALL dbt_create(t_3c_O, t_3c_4)
     825           26 :       CALL dbt_create(t_3c_O, t_3c_5)
     826           26 :       CALL dbt_create(t_3c_M, t_3c_6)
     827           26 :       CALL dbt_create(t_3c_M, t_3c_7)
     828           26 :       CALL dbt_create(t_3c_M, t_3c_8)
     829           26 :       CALL dbt_create(t_3c_M, t_3c_sparse)
     830           26 :       CALL dbt_create(t_3c_O, t_3c_help_1)
     831           26 :       CALL dbt_create(t_3c_O, t_3c_help_2)
     832           26 :       CALL dbt_create(t_2c_AO, t_R_occ)
     833           26 :       CALL dbt_create(t_2c_AO, t_R_virt)
     834           26 :       CALL dbt_create(t_3c_M, t_3c_ints)
     835           26 :       CALL dbt_create(t_3c_M, t_3c_work)
     836              : 
     837              :       !Pre-define the sparsity of t_3c_4 as a function of the derivatives
     838           26 :       occ_der_AO = 0; nze_der_AO = 0
     839           26 :       occ_der_RI = 0; nze_der_RI = 0
     840          104 :       DO i_xyz = 1, 3
     841          260 :          DO i_mem = 1, cut_memory
     842              :             CALL decompress_tensor(force_data%t_3c_der_RI(i_xyz), force_data%t_3c_der_RI_ind(i_mem, i_xyz)%ind, &
     843          156 :                                    force_data%t_3c_der_RI_comp(i_mem, i_xyz), mp2_env%ri_rpa_im_time%eps_compress)
     844          156 :             CALL get_tensor_occupancy(force_data%t_3c_der_RI(i_xyz), nze, occ)
     845          156 :             occ_der_RI = occ_der_RI + occ
     846          156 :             nze_der_RI = nze_der_RI + nze
     847          156 :             CALL dbt_copy(force_data%t_3c_der_RI(i_xyz), t_3c_sparse, summation=.TRUE., move_data=.TRUE.)
     848              : 
     849              :             CALL decompress_tensor(force_data%t_3c_der_AO(i_xyz), force_data%t_3c_der_AO_ind(i_mem, i_xyz)%ind, &
     850          156 :                                    force_data%t_3c_der_AO_comp(i_mem, i_xyz), mp2_env%ri_rpa_im_time%eps_compress)
     851          156 :             CALL get_tensor_occupancy(force_data%t_3c_der_AO(i_xyz), nze, occ)
     852          156 :             occ_der_AO = occ_der_AO + occ
     853          156 :             nze_der_AO = nze_der_AO + nze
     854          156 :             CALL dbt_copy(force_data%t_3c_der_AO(i_xyz), t_3c_sparse, order=[1, 3, 2], summation=.TRUE.)
     855          546 :             CALL dbt_copy(force_data%t_3c_der_AO(i_xyz), t_3c_sparse, summation=.TRUE., move_data=.TRUE.)
     856              :          END DO
     857              :       END DO
     858           26 :       occ_der_RI = occ_der_RI/3.0_dp
     859           26 :       occ_der_AO = occ_der_AO/3.0_dp
     860           26 :       nze_der_RI = nze_der_RI/3
     861           26 :       nze_der_AO = nze_der_AO/3
     862              : 
     863           26 :       CALL dbcsr_create(R_occ, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     864           26 :       CALL dbcsr_create(R_virt, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     865           26 :       CALL dbcsr_create(dbcsr_work1, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     866           26 :       CALL dbcsr_create(dbcsr_work2, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     867           26 :       CALL dbcsr_create(dbcsr_work3, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     868           26 :       CALL dbcsr_create(exp_occ, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     869           26 :       CALL dbcsr_create(exp_virt, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     870           26 :       IF (use_virial) CALL dbcsr_create(virial_ovlp, template=dbcsr_work1)
     871              : 
     872           26 :       CALL dbt_batched_contract_init(t_3c_0, batch_range_2=mc_ranges, batch_range_3=mc_ranges)
     873           26 :       CALL dbt_batched_contract_init(t_3c_1, batch_range_2=mc_ranges, batch_range_3=mc_ranges)
     874           26 :       CALL dbt_batched_contract_init(t_3c_3, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
     875           26 :       CALL dbt_batched_contract_init(t_M_occ, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
     876           26 :       CALL dbt_batched_contract_init(t_M_virt, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
     877              : 
     878           26 :       CALL dbt_batched_contract_init(t_3c_ints, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
     879           26 :       CALL dbt_batched_contract_init(t_3c_work, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
     880              : 
     881              :       CALL dbt_batched_contract_init(t_3c_4, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
     882           26 :                                      batch_range_3=mc_ranges)
     883              :       CALL dbt_batched_contract_init(t_3c_5, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
     884           26 :                                      batch_range_3=mc_ranges)
     885              :       CALL dbt_batched_contract_init(t_3c_6, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
     886           26 :                                      batch_range_3=mc_ranges)
     887              :       CALL dbt_batched_contract_init(t_3c_7, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
     888           26 :                                      batch_range_3=mc_ranges)
     889              :       CALL dbt_batched_contract_init(t_3c_8, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
     890           26 :                                      batch_range_3=mc_ranges)
     891              :       CALL dbt_batched_contract_init(t_3c_sparse, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
     892           26 :                                      batch_range_3=mc_ranges)
     893              : 
     894           26 :       work_virial = 0.0_dp
     895           26 :       work_virial_ovlp = 0.0_dp
     896          104 :       DO jquad = 1, num_integ_points
     897           78 :          tau = tau_tj(jquad)
     898           78 :          omega = tau_wj(jquad)
     899           78 :          fac = -2.0_dp*omega*mp2_env%scale_S
     900           78 :          IF (open_shell) fac = 0.5_dp*fac
     901           78 :          occ_ddint = 0; nze_ddint = 0
     902              : 
     903           78 :          CALL para_env%sync()
     904           78 :          t1 = m_walltime()
     905              : 
     906              :          !Deal with the force contributions where there is no explicit 3-center quantities, i.e. the
     907              :          !forces due to the metric and potential derivatives
     908          180 :          DO ispin = 1, nspins
     909          102 :             CALL dbt_create(mat_P_omega(jquad, ispin)%matrix, t_2c_tmp)
     910          102 :             CALL dbt_copy_matrix_to_tensor(mat_P_omega(jquad, ispin)%matrix, t_2c_tmp)
     911          102 :             CALL dbt_copy(t_2c_tmp, t_P(ispin), move_data=.TRUE.)
     912          102 :             CALL dbt_filter(t_P(ispin), eps_filter)
     913          180 :             CALL dbt_destroy(t_2c_tmp)
     914              :          END DO
     915              : 
     916              :          !Q = K^T*P*K, open-shell: Q is from one spin, everything else from the other
     917              :          CALL dbt_contract(1.0_dp, t_P(Qspin), force_data%t_2c_K, 0.0_dp, t_2c_RI, &
     918              :                            contract_1=[2], notcontract_1=[1], &
     919              :                            contract_2=[1], notcontract_2=[2], &
     920              :                            map_1=[1], map_2=[2], filter_eps=eps_filter, &
     921           78 :                            flop=flop, unit_nr=unit_nr_dbcsr)
     922           78 :          dbcsr_nflop = dbcsr_nflop + flop
     923              :          CALL dbt_contract(1.0_dp, force_data%t_2c_K, t_2c_RI, 0.0_dp, t_Q, &
     924              :                            contract_1=[1], notcontract_1=[2], &
     925              :                            contract_2=[1], notcontract_2=[2], &
     926              :                            map_1=[1], map_2=[2], filter_eps=eps_filter, &
     927           78 :                            flop=flop, unit_nr=unit_nr_dbcsr)
     928           78 :          dbcsr_nflop = dbcsr_nflop + flop
     929           78 :          CALL dbt_clear(t_2c_RI)
     930              : 
     931              :          CALL perform_2c_ops(force, t_KQKT, force_data, fac, t_Q, t_P(Pspin), t_2c_RI, t_2c_RI_2, &
     932           78 :                              use_virial, atom_of_kind, kind_of, eps_filter, dbcsr_nflop, unit_nr_dbcsr)
     933           78 :          CALL get_tensor_occupancy(t_KQKT, nze_KQK, occ_KQK)
     934              : 
     935              :          !Calculate the pseudo-density matrix in tensor form. There are a few useless arguments for SOS-MP2
     936              :          CALL compute_mat_dm_global(fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, tau_tj, num_integ_points, &
     937              :                                     nmo, fm_mo_coeff_occ(Pspin), fm_mo_coeff_virt(Pspin), &
     938              :                                     fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, mat_dm_occ, mat_dm_virt, &
     939              :                                     matrix_s, Pspin, Eigenval(:, Pspin), 0.0_dp, eps_filter, &
     940              :                                     mp2_env%ri_rpa_im_time%memory_info, unit_nr, &
     941           78 :                                     jquad, .FALSE., .FALSE., qs_env, dummy_int, dummy_ptr, para_env)
     942              : 
     943           78 :          CALL dbt_create(mat_dm_occ(jquad, 1)%matrix, t_2c_tmp)
     944           78 :          CALL dbt_copy_matrix_to_tensor(mat_dm_occ(jquad, 1)%matrix, t_2c_tmp)
     945           78 :          CALL dbt_copy(t_2c_tmp, t_dm_occ, move_data=.TRUE.)
     946           78 :          CALL dbt_filter(t_dm_occ, eps_filter)
     947           78 :          CALL dbt_destroy(t_2c_tmp)
     948              : 
     949           78 :          CALL dbt_create(mat_dm_virt(jquad, 1)%matrix, t_2c_tmp)
     950           78 :          CALL dbt_copy_matrix_to_tensor(mat_dm_virt(jquad, 1)%matrix, t_2c_tmp)
     951           78 :          CALL dbt_copy(t_2c_tmp, t_dm_virt, move_data=.TRUE.)
     952           78 :          CALL dbt_filter(t_dm_virt, eps_filter)
     953           78 :          CALL dbt_destroy(t_2c_tmp)
     954              : 
     955              :          !Deal with the 3-center quantities.
     956              :          CALL perform_3c_ops(force, t_R_occ, t_R_virt, force_data, fac, cut_memory, n_mem_RI, &
     957              :                              t_KQKT, t_dm_occ, t_dm_virt, t_3c_O, t_3c_M, t_M_occ, t_M_virt, t_3c_0, t_3c_1, &
     958              :                              t_3c_3, t_3c_4, t_3c_5, t_3c_6, t_3c_7, t_3c_8, t_3c_sparse, t_3c_help_1, t_3c_help_2, &
     959              :                              t_3c_ints, t_3c_work, starts_array_mc, ends_array_mc, batch_start_RI, &
     960              :                              batch_end_RI, t_3c_O_compressed, t_3c_O_ind, use_virial, &
     961              :                              atom_of_kind, kind_of, eps_filter, occ_ddint, nze_ddint, dbcsr_nflop, &
     962           78 :                              unit_nr_dbcsr, mp2_env)
     963              : 
     964           78 :          CALL timeset(routineN//"_dbcsr", handle2)
     965              :          !We go back to DBCSR matrices from now on
     966              :          !Note: R matrices are in fact symmetric, but use a normal type for convenience
     967           78 :          CALL dbt_create(matrix_s(1)%matrix, t_2c_tmp)
     968           78 :          CALL dbt_copy(t_R_occ, t_2c_tmp, move_data=.TRUE.)
     969           78 :          CALL dbt_copy_tensor_to_matrix(t_2c_tmp, R_occ)
     970              : 
     971           78 :          CALL dbt_copy(t_R_virt, t_2c_tmp, move_data=.TRUE.)
     972           78 :          CALL dbt_copy_tensor_to_matrix(t_2c_tmp, R_virt)
     973              : 
     974              :          !Iteratively calculate the Y1 and Y2 matrices
     975              :          CALL dbcsr_multiply('N', 'N', tau, force_data%P_occ(Pspin)%matrix, &
     976           78 :                              matrix_ks(Pspin)%matrix, 0.0_dp, dbcsr_work1)
     977           78 :          CALL build_Y_matrix(Y_1, dbcsr_work1, force_data%P_occ(Pspin)%matrix, R_virt, eps_filter)
     978           78 :          CALL matrix_exponential(exp_occ, dbcsr_work1, 1.0_dp, 1.0_dp, eps_filter)
     979              : 
     980              :          CALL dbcsr_multiply('N', 'N', -tau, force_data%P_virt(Pspin)%matrix, &
     981           78 :                              matrix_ks(Pspin)%matrix, 0.0_dp, dbcsr_work1)
     982           78 :          CALL build_Y_matrix(Y_2, dbcsr_work1, force_data%P_virt(Pspin)%matrix, R_occ, eps_filter)
     983           78 :          CALL matrix_exponential(exp_virt, dbcsr_work1, 1.0_dp, 1.0_dp, eps_filter)
     984              : 
     985              :          !The force contribution coming from [-S^-1*(e^-tau*P_virt*F)^T*R_occ*S^-1
     986              :          !                                    +tau*S^-1*Y_2^T*F*S^-1] * der_S
     987           78 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, R_occ, force_data%inv_ovlp, 0.0_dp, dbcsr_work1)
     988           78 :          CALL dbcsr_multiply('T', 'N', 1.0_dp, exp_virt, dbcsr_work1, 0.0_dp, dbcsr_work3)
     989           78 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, force_data%inv_ovlp, dbcsr_work3, 0.0_dp, dbcsr_work2)
     990              : 
     991           78 :          CALL dbcsr_multiply('N', 'T', tau, force_data%inv_ovlp, Y_2, 0.0_dp, dbcsr_work3)
     992           78 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, dbcsr_work3, matrix_ks(Pspin)%matrix, 0.0_dp, dbcsr_work1)
     993           78 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, dbcsr_work1, force_data%inv_ovlp, 0.0_dp, dbcsr_work3)
     994              : 
     995           78 :          CALL dbcsr_add(dbcsr_work2, dbcsr_work3, 1.0_dp, -1.0_dp)
     996              : 
     997           78 :          CALL dbt_copy_matrix_to_tensor(dbcsr_work2, t_2c_tmp)
     998           78 :          CALL dbt_copy(t_2c_tmp, t_2c_AO, move_data=.TRUE.)
     999              : 
    1000           78 :          pref = -1.0_dp*fac
    1001              :          CALL get_2c_der_force(force, t_2c_AO, force_data%t_2c_der_ovlp, atom_of_kind, &
    1002           78 :                                kind_of, force_data%idx_to_at_AO, pref, do_ovlp=.TRUE.)
    1003              : 
    1004           78 :          IF (use_virial) CALL dbcsr_add(virial_ovlp, dbcsr_work2, 1.0_dp, pref)
    1005              : 
    1006              :          !The final contribution from Tr[(tau*Y_1*P_occ - tau*Y_2*P_virt) * der_F]
    1007              :          CALL dbcsr_multiply('N', 'N', tau*fac, Y_1, force_data%P_occ(Pspin)%matrix, 1.0_dp, &
    1008           78 :                              force_data%sum_YP_tau(Pspin)%matrix, retain_sparsity=.TRUE.)
    1009              :          CALL dbcsr_multiply('N', 'N', -tau*fac, Y_2, force_data%P_virt(Pspin)%matrix, 1.0_dp, &
    1010           78 :                              force_data%sum_YP_tau(Pspin)%matrix, retain_sparsity=.TRUE.)
    1011              : 
    1012              :          !Build-up the RHS of the response equation.
    1013           78 :          pref = -omega*mp2_env%scale_S
    1014              :          CALL dbcsr_multiply('N', 'N', pref, R_virt, exp_occ, 1.0_dp, &
    1015           78 :                              force_data%sum_O_tau(Pspin)%matrix, retain_sparsity=.TRUE.)
    1016              :          CALL dbcsr_multiply('N', 'N', -pref, R_occ, exp_virt, 1.0_dp, &
    1017           78 :                              force_data%sum_O_tau(Pspin)%matrix, retain_sparsity=.TRUE.)
    1018              :          CALL dbcsr_multiply('N', 'N', pref*tau, matrix_ks(Pspin)%matrix, Y_1, 1.0_dp, &
    1019           78 :                              force_data%sum_O_tau(Pspin)%matrix, retain_sparsity=.TRUE.)
    1020              :          CALL dbcsr_multiply('N', 'N', pref*tau, matrix_ks(Pspin)%matrix, Y_2, 1.0_dp, &
    1021           78 :                              force_data%sum_O_tau(Pspin)%matrix, retain_sparsity=.TRUE.)
    1022              : 
    1023           78 :          CALL timestop(handle2)
    1024              : 
    1025              :          !Print some info
    1026           78 :          CALL para_env%sync()
    1027           78 :          t2 = m_walltime()
    1028           78 :          dbcsr_time = dbcsr_time + t2 - t1
    1029              : 
    1030           78 :          IF (unit_nr > 0) THEN
    1031              :             WRITE (unit_nr, '(/T3,A,1X,I3,A)') &
    1032           39 :                'RPA_LOW_SCALING_INFO| Info for time point', jquad, '    (gradients)'
    1033              :             WRITE (unit_nr, '(T6,A,T56,F25.6)') &
    1034           39 :                'Execution time (s):', t2 - t1
    1035              :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
    1036           39 :                'Occupancy of 3c AO derivs:', REAL(nze_der_AO, dp), '/', occ_der_AO*100, '%'
    1037              :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
    1038           39 :                'Occupancy of 3c RI derivs:', REAL(nze_der_RI, dp), '/', occ_der_RI*100, '%'
    1039              :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
    1040           39 :                'Occupancy of the Docc * Dvirt * 3c-int tensor', REAL(nze_ddint, dp), '/', occ_ddint*100, '%'
    1041              :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
    1042           39 :                'Occupancy of KQK^T 2c-tensor:', REAL(nze_KQK, dp), '/', occ_KQK*100, '%'
    1043           39 :             CALL m_flush(unit_nr)
    1044              :          END IF
    1045              : 
    1046              :          !intermediate clean-up
    1047           78 :          CALL dbcsr_release(Y_1)
    1048           78 :          CALL dbcsr_release(Y_2)
    1049          416 :          CALL dbt_destroy(t_2c_tmp)
    1050              :       END DO !jquad
    1051              : 
    1052           26 :       CALL dbt_batched_contract_finalize(t_3c_0)
    1053           26 :       CALL dbt_batched_contract_finalize(t_3c_1)
    1054           26 :       CALL dbt_batched_contract_finalize(t_3c_3)
    1055           26 :       CALL dbt_batched_contract_finalize(t_M_occ)
    1056           26 :       CALL dbt_batched_contract_finalize(t_M_virt)
    1057              : 
    1058           26 :       CALL dbt_batched_contract_finalize(t_3c_ints)
    1059           26 :       CALL dbt_batched_contract_finalize(t_3c_work)
    1060              : 
    1061           26 :       CALL dbt_batched_contract_finalize(t_3c_4)
    1062           26 :       CALL dbt_batched_contract_finalize(t_3c_5)
    1063           26 :       CALL dbt_batched_contract_finalize(t_3c_6)
    1064           26 :       CALL dbt_batched_contract_finalize(t_3c_7)
    1065           26 :       CALL dbt_batched_contract_finalize(t_3c_8)
    1066           26 :       CALL dbt_batched_contract_finalize(t_3c_sparse)
    1067              : 
    1068              :       !Calculate the 2c and 3c contributions to the virial
    1069           26 :       IF (use_virial) THEN
    1070            2 :          CALL dbt_copy(force_data%t_3c_virial_split, force_data%t_3c_virial, move_data=.TRUE.)
    1071              :          CALL calc_3c_virial(work_virial, force_data%t_3c_virial, 1.0_dp, qs_env, force_data%nl_3c, &
    1072              :                              basis_set_ri_aux, basis_set_ao, basis_set_ao, mp2_env%ri_metric, &
    1073            2 :                              der_eps=mp2_env%ri_rpa_im_time%eps_filter, op_pos=1)
    1074              : 
    1075              :          CALL calc_2c_virial(work_virial, force_data%RI_virial_met, 1.0_dp, qs_env, force_data%nl_2c_met, &
    1076            2 :                              basis_set_ri_aux, basis_set_ri_aux, mp2_env%ri_metric)
    1077            2 :          CALL dbcsr_clear(force_data%RI_virial_met)
    1078              : 
    1079            2 :          IF (.NOT. force_data%do_periodic) THEN
    1080              :             CALL calc_2c_virial(work_virial, force_data%RI_virial_pot, 1.0_dp, qs_env, force_data%nl_2c_pot, &
    1081            0 :                                 basis_set_ri_aux, basis_set_ri_aux, mp2_env%potential_parameter)
    1082            0 :             CALL dbcsr_clear(force_data%RI_virial_pot)
    1083              :          END IF
    1084              : 
    1085            2 :          identity_pot%potential_type = do_potential_id
    1086              :          CALL calc_2c_virial(work_virial_ovlp, virial_ovlp, 1.0_dp, qs_env, force_data%nl_2c_ovlp, &
    1087            2 :                              basis_set_ao, basis_set_ao, identity_pot)
    1088            2 :          CALL dbcsr_release(virial_ovlp)
    1089              : 
    1090            8 :          DO k_xyz = 1, 3
    1091           26 :             DO j_xyz = 1, 3
    1092           78 :                DO i_xyz = 1, 3
    1093              :                   virial%pv_mp2(i_xyz, j_xyz) = virial%pv_mp2(i_xyz, j_xyz) &
    1094           54 :                                                 - work_virial(i_xyz, k_xyz)*cell%hmat(j_xyz, k_xyz)
    1095              :                   virial%pv_overlap(i_xyz, j_xyz) = virial%pv_overlap(i_xyz, j_xyz) &
    1096           54 :                                                     - work_virial_ovlp(i_xyz, k_xyz)*cell%hmat(j_xyz, k_xyz)
    1097              :                   virial%pv_virial(i_xyz, j_xyz) = virial%pv_virial(i_xyz, j_xyz) &
    1098              :                                                    - work_virial(i_xyz, k_xyz)*cell%hmat(j_xyz, k_xyz) &
    1099           72 :                                                    - work_virial_ovlp(i_xyz, k_xyz)*cell%hmat(j_xyz, k_xyz)
    1100              :                END DO
    1101              :             END DO
    1102              :          END DO
    1103              :       END IF
    1104              : 
    1105              :       !Calculate the periodic contributions of (P|Q) to the force and the virial
    1106           26 :       work_virial = 0.0_dp
    1107           26 :       IF (force_data%do_periodic) THEN
    1108           10 :          IF (mp2_env%eri_method == do_eri_gpw) THEN
    1109            6 :             CALL get_2c_gpw_forces(force_data%G_PQ, force, work_virial, use_virial, mp2_env, qs_env)
    1110            4 :          ELSE IF (mp2_env%eri_method == do_eri_mme) THEN
    1111            4 :             CALL get_2c_mme_forces(force_data%G_PQ, force, mp2_env, qs_env)
    1112            4 :             IF (use_virial) CPABORT("Stress tensor not available with MME intrgrals")
    1113              :          ELSE
    1114            0 :             CPABORT("Periodic case not possible with OS integrals")
    1115              :          END IF
    1116           10 :          CALL dbcsr_clear(force_data%G_PQ)
    1117              :       END IF
    1118              : 
    1119           26 :       IF (use_virial) THEN
    1120           26 :          virial%pv_mp2 = virial%pv_mp2 + work_virial
    1121           26 :          virial%pv_virial = virial%pv_virial + work_virial
    1122            2 :          virial%pv_calculate = .FALSE.
    1123              : 
    1124            6 :          DO ibasis = 1, SIZE(basis_set_ao)
    1125            4 :             orb_basis => basis_set_ao(ibasis)%gto_basis_set
    1126            4 :             CALL init_interaction_radii_orb_basis(orb_basis, eps_pgf_orb_old)
    1127            4 :             ri_basis => basis_set_ri_aux(ibasis)%gto_basis_set
    1128            6 :             CALL init_interaction_radii_orb_basis(ri_basis, eps_pgf_orb_old)
    1129              :          END DO
    1130              :       END IF
    1131              : 
    1132              :       !clean-up
    1133           26 :       IF (ASSOCIATED(dummy_ptr)) DEALLOCATE (dummy_ptr)
    1134           60 :       DO ispin = 1, nspins
    1135           60 :          CALL dbt_destroy(t_P(ispin))
    1136              :       END DO
    1137           26 :       CALL dbt_destroy(t_3c_0)
    1138           26 :       CALL dbt_destroy(t_3c_1)
    1139           26 :       CALL dbt_destroy(t_3c_3)
    1140           26 :       CALL dbt_destroy(t_3c_4)
    1141           26 :       CALL dbt_destroy(t_3c_5)
    1142           26 :       CALL dbt_destroy(t_3c_6)
    1143           26 :       CALL dbt_destroy(t_3c_7)
    1144           26 :       CALL dbt_destroy(t_3c_8)
    1145           26 :       CALL dbt_destroy(t_3c_sparse)
    1146           26 :       CALL dbt_destroy(t_3c_help_1)
    1147           26 :       CALL dbt_destroy(t_3c_help_2)
    1148           26 :       CALL dbt_destroy(t_3c_ints)
    1149           26 :       CALL dbt_destroy(t_3c_work)
    1150           26 :       CALL dbt_destroy(t_R_occ)
    1151           26 :       CALL dbt_destroy(t_R_virt)
    1152           26 :       CALL dbt_destroy(t_dm_occ)
    1153           26 :       CALL dbt_destroy(t_dm_virt)
    1154           26 :       CALL dbt_destroy(t_Q)
    1155           26 :       CALL dbt_destroy(t_KQKT)
    1156           26 :       CALL dbt_destroy(t_M_occ)
    1157           26 :       CALL dbt_destroy(t_M_virt)
    1158           26 :       CALL dbcsr_release(R_occ)
    1159           26 :       CALL dbcsr_release(R_virt)
    1160           26 :       CALL dbcsr_release(dbcsr_work1)
    1161           26 :       CALL dbcsr_release(dbcsr_work2)
    1162           26 :       CALL dbcsr_release(dbcsr_work3)
    1163           26 :       CALL dbcsr_release(exp_occ)
    1164           26 :       CALL dbcsr_release(exp_virt)
    1165              : 
    1166           26 :       CALL dbt_destroy(t_2c_RI)
    1167           26 :       CALL dbt_destroy(t_2c_RI_2)
    1168           26 :       CALL dbt_destroy(t_2c_AO)
    1169           26 :       CALL dbcsr_deallocate_matrix_set(mat_dm_occ)
    1170           26 :       CALL dbcsr_deallocate_matrix_set(mat_dm_virt)
    1171              : 
    1172           26 :       CALL timestop(handle)
    1173              : 
    1174          112 :    END SUBROUTINE calc_laplace_loop_forces
    1175              : 
    1176              : ! **************************************************************************************************
    1177              : !> \brief Updates the cubic-scaling RPA contribution to the forces at each quadrature point. This
    1178              : !>        routine is adapted from the corresponding Laplace SOS-MP2 loop force one.
    1179              : !> \param force_data ...
    1180              : !> \param mat_P_omega ...
    1181              : !> \param t_3c_M ...
    1182              : !> \param t_3c_O ...
    1183              : !> \param t_3c_O_compressed ...
    1184              : !> \param t_3c_O_ind ...
    1185              : !> \param fm_scaled_dm_occ_tau ...
    1186              : !> \param fm_scaled_dm_virt_tau ...
    1187              : !> \param fm_mo_coeff_occ ...
    1188              : !> \param fm_mo_coeff_virt ...
    1189              : !> \param fm_mo_coeff_occ_scaled ...
    1190              : !> \param fm_mo_coeff_virt_scaled ...
    1191              : !> \param starts_array_mc ...
    1192              : !> \param ends_array_mc ...
    1193              : !> \param starts_array_mc_block ...
    1194              : !> \param ends_array_mc_block ...
    1195              : !> \param num_integ_points ...
    1196              : !> \param nmo ...
    1197              : !> \param Eigenval ...
    1198              : !> \param e_fermi ...
    1199              : !> \param weights_cos_tf_t_to_w ...
    1200              : !> \param weights_cos_tf_w_to_t ...
    1201              : !> \param tj ...
    1202              : !> \param wj ...
    1203              : !> \param tau_tj ...
    1204              : !> \param cut_memory ...
    1205              : !> \param ispin ...
    1206              : !> \param open_shell ...
    1207              : !> \param unit_nr ...
    1208              : !> \param dbcsr_time ...
    1209              : !> \param dbcsr_nflop ...
    1210              : !> \param mp2_env ...
    1211              : !> \param qs_env ...
    1212              : ! **************************************************************************************************
    1213          180 :    SUBROUTINE calc_rpa_loop_forces(force_data, mat_P_omega, t_3c_M, t_3c_O, t_3c_O_compressed, &
    1214           36 :                                    t_3c_O_ind, fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, &
    1215           36 :                                    fm_mo_coeff_occ, fm_mo_coeff_virt, fm_mo_coeff_occ_scaled, &
    1216           36 :                                    fm_mo_coeff_virt_scaled, starts_array_mc, ends_array_mc, &
    1217           36 :                                    starts_array_mc_block, ends_array_mc_block, num_integ_points, &
    1218           36 :                                    nmo, Eigenval, e_fermi, weights_cos_tf_t_to_w, weights_cos_tf_w_to_t, &
    1219           36 :                                    tj, wj, tau_tj, cut_memory, ispin, open_shell, unit_nr, dbcsr_time, &
    1220              :                                    dbcsr_nflop, mp2_env, qs_env)
    1221              : 
    1222              :       TYPE(im_time_force_type), INTENT(INOUT)            :: force_data
    1223              :       TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(INOUT) :: mat_P_omega
    1224              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_3c_M, t_3c_O
    1225              :       TYPE(hfx_compression_type), DIMENSION(:)           :: t_3c_O_compressed
    1226              :       TYPE(block_ind_type), DIMENSION(:), INTENT(INOUT)  :: t_3c_O_ind
    1227              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_scaled_dm_occ_tau, &
    1228              :                                                             fm_scaled_dm_virt_tau
    1229              :       TYPE(cp_fm_type), DIMENSION(:), INTENT(IN)         :: fm_mo_coeff_occ, fm_mo_coeff_virt
    1230              :       TYPE(cp_fm_type), INTENT(IN)                       :: fm_mo_coeff_occ_scaled, &
    1231              :                                                             fm_mo_coeff_virt_scaled
    1232              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: starts_array_mc, ends_array_mc, &
    1233              :                                                             starts_array_mc_block, &
    1234              :                                                             ends_array_mc_block
    1235              :       INTEGER, INTENT(IN)                                :: num_integ_points, nmo
    1236              :       REAL(KIND=dp), DIMENSION(:, :), INTENT(IN)         :: Eigenval
    1237              :       REAL(KIND=dp), INTENT(IN)                          :: e_fermi
    1238              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :), &
    1239              :          INTENT(IN)                                      :: weights_cos_tf_t_to_w, &
    1240              :                                                             weights_cos_tf_w_to_t
    1241              :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
    1242              :          INTENT(IN)                                      :: tj, wj
    1243              :       REAL(KIND=dp), DIMENSION(num_integ_points), &
    1244              :          INTENT(IN)                                      :: tau_tj
    1245              :       INTEGER, INTENT(IN)                                :: cut_memory, ispin
    1246              :       LOGICAL, INTENT(IN)                                :: open_shell
    1247              :       INTEGER, INTENT(IN)                                :: unit_nr
    1248              :       REAL(dp), INTENT(INOUT)                            :: dbcsr_time
    1249              :       INTEGER(int_8), INTENT(INOUT)                      :: dbcsr_nflop
    1250              :       TYPE(mp2_type)                                     :: mp2_env
    1251              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1252              : 
    1253              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'calc_rpa_loop_forces'
    1254              : 
    1255              :       INTEGER :: dummy_int, handle, handle2, i_mem, i_xyz, ibasis, iquad, j_xyz, jquad, k_xyz, &
    1256              :          n_mem_RI, n_rep, natom, nkind, nspins, unit_nr_dbcsr
    1257              :       INTEGER(int_8)                                     :: flop, nze, nze_ddint, nze_der_AO, &
    1258              :                                                             nze_der_RI, nze_KBK
    1259           36 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, batch_blk_end, &
    1260           36 :                                                             batch_blk_start, batch_end_RI, &
    1261           36 :                                                             batch_start_RI, kind_of, mc_ranges, &
    1262           36 :                                                             mc_ranges_RI
    1263           36 :       INTEGER, DIMENSION(:, :), POINTER                  :: dummy_ptr
    1264              :       LOGICAL                                            :: memory_info, use_virial
    1265              :       REAL(dp) :: eps_filter, eps_pgf_orb, eps_pgf_orb_old, fac, occ, occ_ddint, occ_der_AO, &
    1266              :          occ_der_RI, occ_KBK, omega, pref, spin_fac, t1, t2, tau, weight
    1267              :       REAL(dp), DIMENSION(3, 3)                          :: work_virial, work_virial_ovlp
    1268           36 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1269              :       TYPE(cell_type), POINTER                           :: cell
    1270              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1271           36 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mat_P_tau, matrix_ks, matrix_s
    1272           36 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_dm_occ, mat_dm_virt
    1273              :       TYPE(dbcsr_type)                                   :: dbcsr_work1, dbcsr_work2, dbcsr_work3, &
    1274              :                                                             dbcsr_work_symm, exp_occ, exp_virt, &
    1275              :                                                             R_occ, R_virt, virial_ovlp, Y_1, Y_2
    1276         1764 :       TYPE(dbt_type) :: t_2c_AO, t_2c_RI, t_2c_RI_2, t_2c_tmp, t_3c_0, t_3c_1, t_3c_3, t_3c_4, &
    1277         1764 :          t_3c_5, t_3c_6, t_3c_7, t_3c_8, t_3c_help_1, t_3c_help_2, t_3c_ints, t_3c_sparse, &
    1278         2016 :          t_3c_work, t_dm_occ, t_dm_virt, t_KBKT, t_M_occ, t_M_virt, t_P, t_R_occ, t_R_virt
    1279           36 :       TYPE(dbt_type), ALLOCATABLE, DIMENSION(:)          :: t_B
    1280              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1281              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
    1282           36 :          DIMENSION(:), TARGET                            :: basis_set_ao, basis_set_ri_aux
    1283              :       TYPE(gto_basis_set_type), POINTER                  :: orb_basis, ri_basis
    1284              :       TYPE(libint_potential_type)                        :: identity_pot
    1285              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1286           36 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1287           36 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    1288           36 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1289              :       TYPE(section_vals_type), POINTER                   :: qs_section
    1290              :       TYPE(virial_type), POINTER                         :: virial
    1291              : 
    1292           36 :       NULLIFY (matrix_s, dummy_ptr, atomic_kind_set, force, matrix_s, matrix_ks, mat_dm_occ, mat_dm_virt)
    1293           36 :       NULLIFY (dft_control, virial, particle_set, cell, blacs_env, para_env, orb_basis, ri_basis)
    1294           36 :       NULLIFY (qs_kind_set)
    1295              : 
    1296           36 :       CALL timeset(routineN, handle)
    1297              : 
    1298              :       CALL get_qs_env(qs_env, matrix_s=matrix_s, natom=natom, atomic_kind_set=atomic_kind_set, &
    1299              :                       force=force, matrix_ks=matrix_ks, dft_control=dft_control, virial=virial, &
    1300              :                       particle_set=particle_set, cell=cell, blacs_env=blacs_env, para_env=para_env, &
    1301           36 :                       qs_kind_set=qs_kind_set, nkind=nkind)
    1302           36 :       eps_filter = mp2_env%ri_rpa_im_time%eps_filter
    1303           36 :       nspins = dft_control%nspins
    1304              : 
    1305           36 :       memory_info = mp2_env%ri_rpa_im_time%memory_info
    1306           36 :       IF (memory_info) THEN
    1307            0 :          unit_nr_dbcsr = unit_nr
    1308              :       ELSE
    1309           36 :          unit_nr_dbcsr = 0
    1310              :       END IF
    1311              : 
    1312           36 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
    1313              : 
    1314           36 :       IF (use_virial) virial%pv_calculate = .TRUE.
    1315              : 
    1316           36 :       IF (use_virial) THEN
    1317            2 :          qs_section => section_vals_get_subs_vals(qs_env%input, "DFT%QS")
    1318            2 :          CALL section_vals_val_get(qs_section, "EPS_PGF_ORB", n_rep_val=n_rep)
    1319            2 :          IF (n_rep /= 0) THEN
    1320            0 :             CALL section_vals_val_get(qs_section, "EPS_PGF_ORB", r_val=eps_pgf_orb)
    1321              :          ELSE
    1322            2 :             CALL section_vals_val_get(qs_section, "EPS_DEFAULT", r_val=eps_pgf_orb)
    1323            2 :             eps_pgf_orb = SQRT(eps_pgf_orb)
    1324              :          END IF
    1325            2 :          eps_pgf_orb_old = dft_control%qs_control%eps_pgf_orb
    1326              : 
    1327           16 :          ALLOCATE (basis_set_ri_aux(nkind), basis_set_ao(nkind))
    1328            2 :          CALL basis_set_list_setup(basis_set_ri_aux, "RI_AUX", qs_kind_set)
    1329            2 :          CALL basis_set_list_setup(basis_set_ao, "ORB", qs_kind_set)
    1330              : 
    1331            8 :          DO ibasis = 1, SIZE(basis_set_ao)
    1332            4 :             orb_basis => basis_set_ao(ibasis)%gto_basis_set
    1333            4 :             CALL init_interaction_radii_orb_basis(orb_basis, eps_pgf_orb)
    1334            4 :             ri_basis => basis_set_ri_aux(ibasis)%gto_basis_set
    1335            6 :             CALL init_interaction_radii_orb_basis(ri_basis, eps_pgf_orb)
    1336              :          END DO
    1337              :       END IF
    1338              : 
    1339              :       !We follow the general logic of the compute_mat_P_omega routine
    1340           36 :       CALL dbt_create(force_data%t_2c_K, t_2c_RI)
    1341           36 :       CALL dbt_create(force_data%t_2c_K, t_2c_RI_2)
    1342           36 :       CALL dbt_create(force_data%t_2c_der_ovlp(1), t_2c_AO)
    1343              : 
    1344           36 :       CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of, atom_of_kind=atom_of_kind)
    1345              : 
    1346              :       ! Always do the batching of the MO on mu and sigma, such that it is consistent between
    1347              :       ! the occupied and the virtual quantities
    1348          108 :       ALLOCATE (mc_ranges(cut_memory + 1))
    1349          108 :       mc_ranges(:cut_memory) = starts_array_mc_block(:)
    1350           36 :       mc_ranges(cut_memory + 1) = ends_array_mc_block(cut_memory) + 1
    1351              : 
    1352              :       ! Also need some batching on the RI, because it loses sparsity at some point
    1353           36 :       n_mem_RI = cut_memory
    1354              :       CALL create_tensor_batches(force_data%bsizes_RI_split, n_mem_RI, batch_start_RI, batch_end_RI, &
    1355           36 :                                  batch_blk_start, batch_blk_end)
    1356          108 :       ALLOCATE (mc_ranges_RI(n_mem_RI + 1))
    1357          108 :       mc_ranges_RI(1:n_mem_RI) = batch_blk_start(1:n_mem_RI)
    1358           36 :       mc_ranges_RI(n_mem_RI + 1) = batch_blk_end(n_mem_RI) + 1
    1359           36 :       DEALLOCATE (batch_blk_start, batch_blk_end)
    1360              : 
    1361              :       !Pre-allocate all required tensors and matrices
    1362           36 :       CALL dbt_create(t_2c_RI, t_P)
    1363           36 :       CALL dbt_create(t_2c_RI, t_KBKT)
    1364           36 :       CALL dbt_create(t_2c_AO, t_dm_occ)
    1365           36 :       CALL dbt_create(t_2c_AO, t_dm_virt)
    1366              : 
    1367              :       !note: t_3c_O and t_3c_M have different mappings (map_1d, map_2d)
    1368           36 :       CALL dbt_create(t_3c_O, t_M_occ)
    1369           36 :       CALL dbt_create(t_3c_O, t_M_virt)
    1370           36 :       CALL dbt_create(t_3c_O, t_3c_0)
    1371              : 
    1372           36 :       CALL dbt_create(t_3c_O, t_3c_1)
    1373           36 :       CALL dbt_create(t_3c_O, t_3c_3)
    1374           36 :       CALL dbt_create(t_3c_O, t_3c_4)
    1375           36 :       CALL dbt_create(t_3c_O, t_3c_5)
    1376           36 :       CALL dbt_create(t_3c_M, t_3c_6)
    1377           36 :       CALL dbt_create(t_3c_M, t_3c_7)
    1378           36 :       CALL dbt_create(t_3c_M, t_3c_8)
    1379           36 :       CALL dbt_create(t_3c_M, t_3c_sparse)
    1380           36 :       CALL dbt_create(t_3c_O, t_3c_help_1)
    1381           36 :       CALL dbt_create(t_3c_O, t_3c_help_2)
    1382           36 :       CALL dbt_create(t_2c_AO, t_R_occ)
    1383           36 :       CALL dbt_create(t_2c_AO, t_R_virt)
    1384           36 :       CALL dbt_create(t_3c_M, t_3c_ints)
    1385           36 :       CALL dbt_create(t_3c_M, t_3c_work)
    1386              : 
    1387              :       !Before entring the loop, need to compute the 2c tensors B = (1 + Q(w))^-1 - 1, for each
    1388              :       !frequency grid point, before doing the transformation to the time grid
    1389          416 :       ALLOCATE (t_B(num_integ_points))
    1390          128 :       DO jquad = 1, num_integ_points
    1391          128 :          CALL dbt_create(t_2c_RI, t_B(jquad))
    1392              :       END DO
    1393              : 
    1394          200 :       ALLOCATE (mat_P_tau(num_integ_points))
    1395          128 :       DO jquad = 1, num_integ_points
    1396           92 :          ALLOCATE (mat_P_tau(jquad)%matrix)
    1397          128 :          CALL dbcsr_create(mat_P_tau(jquad)%matrix, template=mat_P_omega(jquad, ispin)%matrix)
    1398              :       END DO
    1399              : 
    1400           36 :       CALL dbcsr_create(dbcsr_work_symm, template=force_data%G_PQ, matrix_type=dbcsr_type_symmetric)
    1401           36 :       CALL dbt_create(dbcsr_work_symm, t_2c_tmp)
    1402              : 
    1403              :       !loop over freqeuncies
    1404          128 :       DO iquad = 1, num_integ_points
    1405           92 :          omega = tj(iquad)
    1406              : 
    1407              :          !calculate (1 + Q(w))^-1 - 1 for the given freq.
    1408              :          !Always take spin alpha (get 2*alpha in closed shell, and alpha+beta in open-shell)
    1409           92 :          CALL dbcsr_copy(dbcsr_work_symm, mat_P_omega(iquad, 1)%matrix)
    1410           92 :          CALL dbt_copy_matrix_to_tensor(dbcsr_work_symm, t_2c_tmp)
    1411           92 :          CALL dbt_copy(t_2c_tmp, t_2c_RI, move_data=.TRUE.)
    1412              : 
    1413              :          CALL dbt_contract(1.0_dp, t_2c_RI, force_data%t_2c_K, 0.0_dp, t_2c_RI_2, &
    1414              :                            contract_1=[2], notcontract_1=[1], &
    1415              :                            contract_2=[1], notcontract_2=[2], &
    1416              :                            map_1=[1], map_2=[2], filter_eps=eps_filter, &
    1417           92 :                            flop=flop, unit_nr=unit_nr_dbcsr)
    1418           92 :          dbcsr_nflop = dbcsr_nflop + flop
    1419              :          CALL dbt_contract(1.0_dp, force_data%t_2c_K, t_2c_RI_2, 0.0_dp, t_2c_RI, &
    1420              :                            contract_1=[1], notcontract_1=[2], &
    1421              :                            contract_2=[1], notcontract_2=[2], &
    1422              :                            map_1=[1], map_2=[2], filter_eps=eps_filter, &
    1423           92 :                            flop=flop, unit_nr=unit_nr_dbcsr)
    1424           92 :          CALL dbt_copy(t_2c_RI, t_2c_tmp, move_data=.TRUE.)
    1425           92 :          CALL dbt_copy_tensor_to_matrix(t_2c_tmp, dbcsr_work_symm)
    1426           92 :          CALL dbcsr_add_on_diag(dbcsr_work_symm, 1.0_dp)
    1427              : 
    1428           92 :          CALL cp_dbcsr_cholesky_decompose(dbcsr_work_symm, para_env=para_env, blacs_env=blacs_env)
    1429           92 :          CALL cp_dbcsr_cholesky_invert(dbcsr_work_symm, para_env=para_env, blacs_env=blacs_env, uplo_to_full=.TRUE.)
    1430              : 
    1431           92 :          CALL dbcsr_add_on_diag(dbcsr_work_symm, -1.0_dp)
    1432              : 
    1433          372 :          DO jquad = 1, num_integ_points
    1434          244 :             tau = tau_tj(jquad)
    1435              : 
    1436              :             !the P matrix to time.
    1437          244 :             weight = weights_cos_tf_w_to_t(jquad, iquad)*COS(tau*omega)
    1438          244 :             IF (open_shell) THEN
    1439           64 :                IF (ispin == 1) THEN
    1440              :                   !mat_P_omega contains the sum of alpha and beta spin => we only want alpha
    1441           32 :                   CALL dbcsr_add(mat_P_tau(jquad)%matrix, mat_P_omega(iquad, 1)%matrix, 1.0_dp, weight)
    1442           32 :                   CALL dbcsr_add(mat_P_tau(jquad)%matrix, mat_P_omega(iquad, 2)%matrix, 1.0_dp, -weight)
    1443              :                ELSE
    1444           32 :                   CALL dbcsr_add(mat_P_tau(jquad)%matrix, mat_P_omega(iquad, 2)%matrix, 1.0_dp, weight)
    1445              :                END IF
    1446              :             ELSE
    1447              :                !factor 0.5 because originam matrix Q is scaled by 2 in RPA (spin)
    1448          180 :                weight = 0.5_dp*weight
    1449          180 :                CALL dbcsr_add(mat_P_tau(jquad)%matrix, mat_P_omega(iquad, 1)%matrix, 1.0_dp, weight)
    1450              :             END IF
    1451              : 
    1452              :             !convert B matrix to time
    1453          244 :             weight = weights_cos_tf_t_to_w(iquad, jquad)*COS(tau*omega)*wj(iquad)
    1454          244 :             CALL dbt_copy_matrix_to_tensor(dbcsr_work_symm, t_2c_tmp)
    1455          244 :             CALL dbt_scale(t_2c_tmp, weight)
    1456          336 :             CALL dbt_copy(t_2c_tmp, t_B(jquad), summation=.TRUE., move_data=.TRUE.)
    1457              :          END DO
    1458              :       END DO
    1459           36 :       CALL dbt_destroy(t_2c_tmp)
    1460           36 :       CALL dbcsr_release(dbcsr_work_symm)
    1461           36 :       CALL dbt_clear(t_2c_RI)
    1462           36 :       CALL dbt_clear(t_2c_RI_2)
    1463              : 
    1464              :       !Pre-define the sparsity of t_3c_4 as a function of the derivatives
    1465           36 :       occ_der_AO = 0; nze_der_AO = 0
    1466           36 :       occ_der_RI = 0; nze_der_RI = 0
    1467          144 :       DO i_xyz = 1, 3
    1468          360 :          DO i_mem = 1, cut_memory
    1469              :             CALL decompress_tensor(force_data%t_3c_der_RI(i_xyz), force_data%t_3c_der_RI_ind(i_mem, i_xyz)%ind, &
    1470          216 :                                    force_data%t_3c_der_RI_comp(i_mem, i_xyz), mp2_env%ri_rpa_im_time%eps_compress)
    1471          216 :             CALL get_tensor_occupancy(force_data%t_3c_der_RI(i_xyz), nze, occ)
    1472          216 :             occ_der_RI = occ_der_RI + occ
    1473          216 :             nze_der_RI = nze_der_RI + nze
    1474          216 :             CALL dbt_copy(force_data%t_3c_der_RI(i_xyz), t_3c_sparse, summation=.TRUE., move_data=.TRUE.)
    1475              : 
    1476              :             CALL decompress_tensor(force_data%t_3c_der_AO(i_xyz), force_data%t_3c_der_AO_ind(i_mem, i_xyz)%ind, &
    1477          216 :                                    force_data%t_3c_der_AO_comp(i_mem, i_xyz), mp2_env%ri_rpa_im_time%eps_compress)
    1478          216 :             CALL get_tensor_occupancy(force_data%t_3c_der_AO(i_xyz), nze, occ)
    1479          216 :             occ_der_AO = occ_der_AO + occ
    1480          216 :             nze_der_AO = nze_der_AO + nze
    1481          216 :             CALL dbt_copy(force_data%t_3c_der_AO(i_xyz), t_3c_sparse, order=[1, 3, 2], summation=.TRUE.)
    1482          756 :             CALL dbt_copy(force_data%t_3c_der_AO(i_xyz), t_3c_sparse, summation=.TRUE., move_data=.TRUE.)
    1483              :          END DO
    1484              :       END DO
    1485           36 :       occ_der_RI = occ_der_RI/3.0_dp
    1486           36 :       occ_der_AO = occ_der_AO/3.0_dp
    1487           36 :       nze_der_RI = nze_der_RI/3
    1488           36 :       nze_der_AO = nze_der_AO/3
    1489              : 
    1490           36 :       CALL dbcsr_create(R_occ, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1491           36 :       CALL dbcsr_create(R_virt, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1492           36 :       CALL dbcsr_create(dbcsr_work_symm, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_symmetric)
    1493           36 :       CALL dbcsr_create(dbcsr_work1, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1494           36 :       CALL dbcsr_create(dbcsr_work2, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1495           36 :       CALL dbcsr_create(dbcsr_work3, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1496           36 :       CALL dbcsr_create(exp_occ, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1497           36 :       CALL dbcsr_create(exp_virt, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1498           36 :       IF (use_virial) CALL dbcsr_create(virial_ovlp, template=dbcsr_work1)
    1499              : 
    1500           36 :       CALL dbt_batched_contract_init(t_3c_0, batch_range_2=mc_ranges, batch_range_3=mc_ranges)
    1501           36 :       CALL dbt_batched_contract_init(t_3c_1, batch_range_2=mc_ranges, batch_range_3=mc_ranges)
    1502           36 :       CALL dbt_batched_contract_init(t_3c_3, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
    1503           36 :       CALL dbt_batched_contract_init(t_M_occ, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
    1504           36 :       CALL dbt_batched_contract_init(t_M_virt, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
    1505              : 
    1506           36 :       CALL dbt_batched_contract_init(t_3c_ints, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
    1507           36 :       CALL dbt_batched_contract_init(t_3c_work, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges)
    1508              : 
    1509              :       CALL dbt_batched_contract_init(t_3c_4, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
    1510           36 :                                      batch_range_3=mc_ranges)
    1511              :       CALL dbt_batched_contract_init(t_3c_5, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
    1512           36 :                                      batch_range_3=mc_ranges)
    1513              :       CALL dbt_batched_contract_init(t_3c_6, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
    1514           36 :                                      batch_range_3=mc_ranges)
    1515              :       CALL dbt_batched_contract_init(t_3c_7, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
    1516           36 :                                      batch_range_3=mc_ranges)
    1517              :       CALL dbt_batched_contract_init(t_3c_8, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
    1518           36 :                                      batch_range_3=mc_ranges)
    1519              :       CALL dbt_batched_contract_init(t_3c_sparse, batch_range_1=mc_ranges_RI, batch_range_2=mc_ranges, &
    1520           36 :                                      batch_range_3=mc_ranges)
    1521              : 
    1522           36 :       fac = 1.0_dp/fourpi*mp2_env%ri_rpa%scale_rpa
    1523           36 :       IF (open_shell) fac = 0.5_dp*fac
    1524              : 
    1525           36 :       work_virial = 0.0_dp
    1526           36 :       work_virial_ovlp = 0.0_dp
    1527          128 :       DO jquad = 1, num_integ_points
    1528           92 :          tau = tau_tj(jquad)
    1529           92 :          occ_ddint = 0; nze_ddint = 0
    1530              : 
    1531           92 :          CALL para_env%sync()
    1532           92 :          t1 = m_walltime()
    1533              : 
    1534              :          !Deal with the force contributions where there is no explicit 3-center quantities, i.e. the
    1535              :          !forces due to the metric and potential derivatives
    1536           92 :          CALL dbt_create(mat_P_tau(jquad)%matrix, t_2c_tmp)
    1537           92 :          CALL dbt_copy_matrix_to_tensor(mat_P_tau(jquad)%matrix, t_2c_tmp)
    1538           92 :          CALL dbt_copy(t_2c_tmp, t_P, move_data=.TRUE.)
    1539           92 :          CALL dbt_filter(t_P, eps_filter)
    1540           92 :          CALL dbt_destroy(t_2c_tmp)
    1541              : 
    1542              :          CALL perform_2c_ops(force, t_KBKT, force_data, fac, t_B(jquad), t_P, t_2c_RI, t_2c_RI_2, &
    1543           92 :                              use_virial, atom_of_kind, kind_of, eps_filter, dbcsr_nflop, unit_nr_dbcsr)
    1544           92 :          CALL get_tensor_occupancy(t_KBKT, nze_KBK, occ_KBK)
    1545              : 
    1546              :          !Calculate the pseudo-density matrix in tensor form. There are a few useless arguments for SOS-MP2
    1547              :          CALL compute_mat_dm_global(fm_scaled_dm_occ_tau, fm_scaled_dm_virt_tau, tau_tj, num_integ_points, &
    1548              :                                     nmo, fm_mo_coeff_occ(ispin), fm_mo_coeff_virt(ispin), &
    1549              :                                     fm_mo_coeff_occ_scaled, fm_mo_coeff_virt_scaled, mat_dm_occ, mat_dm_virt, &
    1550              :                                     matrix_s, ispin, Eigenval(:, ispin), e_fermi, eps_filter, &
    1551              :                                     mp2_env%ri_rpa_im_time%memory_info, unit_nr, &
    1552           92 :                                     jquad, .FALSE., .FALSE., qs_env, dummy_int, dummy_ptr, para_env)
    1553              : 
    1554           92 :          CALL dbt_create(mat_dm_occ(jquad, 1)%matrix, t_2c_tmp)
    1555           92 :          CALL dbt_copy_matrix_to_tensor(mat_dm_occ(jquad, 1)%matrix, t_2c_tmp)
    1556           92 :          CALL dbt_copy(t_2c_tmp, t_dm_occ, move_data=.TRUE.)
    1557           92 :          CALL dbt_filter(t_dm_occ, eps_filter)
    1558           92 :          CALL dbt_destroy(t_2c_tmp)
    1559              : 
    1560           92 :          CALL dbt_create(mat_dm_virt(jquad, 1)%matrix, t_2c_tmp)
    1561           92 :          CALL dbt_copy_matrix_to_tensor(mat_dm_virt(jquad, 1)%matrix, t_2c_tmp)
    1562           92 :          CALL dbt_copy(t_2c_tmp, t_dm_virt, move_data=.TRUE.)
    1563           92 :          CALL dbt_filter(t_dm_virt, eps_filter)
    1564           92 :          CALL dbt_destroy(t_2c_tmp)
    1565              : 
    1566              :          !Deal with the 3-center quantities.
    1567              :          CALL perform_3c_ops(force, t_R_occ, t_R_virt, force_data, fac, cut_memory, n_mem_RI, &
    1568              :                              t_KBKT, t_dm_occ, t_dm_virt, t_3c_O, t_3c_M, t_M_occ, t_M_virt, t_3c_0, t_3c_1, &
    1569              :                              t_3c_3, t_3c_4, t_3c_5, t_3c_6, t_3c_7, t_3c_8, t_3c_sparse, t_3c_help_1, t_3c_help_2, &
    1570              :                              t_3c_ints, t_3c_work, starts_array_mc, ends_array_mc, batch_start_RI, &
    1571              :                              batch_end_RI, t_3c_O_compressed, t_3c_O_ind, use_virial, &
    1572              :                              atom_of_kind, kind_of, eps_filter, occ_ddint, nze_ddint, dbcsr_nflop, &
    1573           92 :                              unit_nr_dbcsr, mp2_env)
    1574              : 
    1575           92 :          CALL timeset(routineN//"_dbcsr", handle2)
    1576              :          !We go back to DBCSR matrices from now on
    1577              :          !Note: R matrices are in fact symmetric, but use a normal type for convenience
    1578           92 :          CALL dbt_create(matrix_s(1)%matrix, t_2c_tmp)
    1579           92 :          CALL dbt_copy(t_R_occ, t_2c_tmp, move_data=.TRUE.)
    1580           92 :          CALL dbt_copy_tensor_to_matrix(t_2c_tmp, R_occ)
    1581              : 
    1582           92 :          CALL dbt_copy(t_R_virt, t_2c_tmp, move_data=.TRUE.)
    1583           92 :          CALL dbt_copy_tensor_to_matrix(t_2c_tmp, R_virt)
    1584              : 
    1585              :          !Iteratively calculate the Y1 and Y2 matrices
    1586           92 :          CALL dbcsr_copy(dbcsr_work_symm, matrix_ks(ispin)%matrix)
    1587           92 :          CALL dbcsr_add(dbcsr_work_symm, matrix_s(1)%matrix, 1.0_dp, -e_fermi)
    1588              :          CALL dbcsr_multiply('N', 'N', tau, force_data%P_occ(ispin)%matrix, &
    1589           92 :                              dbcsr_work_symm, 0.0_dp, dbcsr_work1)
    1590           92 :          CALL build_Y_matrix(Y_1, dbcsr_work1, force_data%P_occ(ispin)%matrix, R_virt, eps_filter)
    1591           92 :          CALL matrix_exponential(exp_occ, dbcsr_work1, 1.0_dp, 1.0_dp, eps_filter)
    1592              : 
    1593              :          CALL dbcsr_multiply('N', 'N', -tau, force_data%P_virt(ispin)%matrix, &
    1594           92 :                              dbcsr_work_symm, 0.0_dp, dbcsr_work1)
    1595           92 :          CALL build_Y_matrix(Y_2, dbcsr_work1, force_data%P_virt(ispin)%matrix, R_occ, eps_filter)
    1596           92 :          CALL matrix_exponential(exp_virt, dbcsr_work1, 1.0_dp, 1.0_dp, eps_filter)
    1597              : 
    1598              :          !The force contribution coming from [-S^-1*(e^-tau*P_virt*F)^T*R_occ*S^-1
    1599              :          !                                    +tau*S^-1*Y_2^T*F*S^-1] * der_S
    1600              :          !as well as -tau*e_fermi*Y_1*P^occ + tau*e_fermi*Y_2*P^virt
    1601           92 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, R_occ, force_data%inv_ovlp, 0.0_dp, dbcsr_work1)
    1602           92 :          CALL dbcsr_multiply('T', 'N', 1.0_dp, exp_virt, dbcsr_work1, 0.0_dp, dbcsr_work3)
    1603           92 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, force_data%inv_ovlp, dbcsr_work3, 0.0_dp, dbcsr_work2)
    1604              : 
    1605           92 :          CALL dbcsr_multiply('N', 'T', tau, force_data%inv_ovlp, Y_2, 0.0_dp, dbcsr_work3)
    1606           92 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, dbcsr_work3, dbcsr_work_symm, 0.0_dp, dbcsr_work1)
    1607           92 :          CALL dbcsr_multiply('N', 'N', -1.0_dp, dbcsr_work1, force_data%inv_ovlp, 1.0_dp, dbcsr_work2)
    1608              : 
    1609           92 :          CALL dbcsr_multiply('N', 'T', tau*e_fermi, force_data%P_occ(ispin)%matrix, Y_1, 1.0_dp, dbcsr_work2)
    1610           92 :          CALL dbcsr_multiply('N', 'T', -tau*e_fermi, force_data%P_virt(ispin)%matrix, Y_2, 1.0_dp, dbcsr_work2)
    1611              : 
    1612           92 :          CALL dbt_copy_matrix_to_tensor(dbcsr_work2, t_2c_tmp)
    1613           92 :          CALL dbt_copy(t_2c_tmp, t_2c_AO, move_data=.TRUE.)
    1614              : 
    1615           92 :          pref = -1.0_dp*fac
    1616              :          CALL get_2c_der_force(force, t_2c_AO, force_data%t_2c_der_ovlp, atom_of_kind, &
    1617           92 :                                kind_of, force_data%idx_to_at_AO, pref, do_ovlp=.TRUE.)
    1618              : 
    1619           92 :          IF (use_virial) CALL dbcsr_add(virial_ovlp, dbcsr_work2, 1.0_dp, pref)
    1620              : 
    1621              :          !The final contribution from Tr[(tau*Y_1*P_occ - tau*Y_2*P_virt) * der_F]
    1622              :          CALL dbcsr_multiply('N', 'N', fac*tau, Y_1, force_data%P_occ(ispin)%matrix, 1.0_dp, &
    1623           92 :                              force_data%sum_YP_tau(ispin)%matrix, retain_sparsity=.TRUE.)
    1624              :          CALL dbcsr_multiply('N', 'N', -fac*tau, Y_2, force_data%P_virt(ispin)%matrix, 1.0_dp, &
    1625           92 :                              force_data%sum_YP_tau(ispin)%matrix, retain_sparsity=.TRUE.)
    1626              : 
    1627           92 :          spin_fac = 0.5_dp*fac
    1628           92 :          IF (open_shell) spin_fac = 2.0_dp*spin_fac
    1629              :          !Build-up the RHS of the response equation.
    1630              :          CALL dbcsr_multiply('N', 'N', 1.0_dp*spin_fac, R_virt, exp_occ, 1.0_dp, &
    1631           92 :                              force_data%sum_O_tau(ispin)%matrix, retain_sparsity=.TRUE.)
    1632              :          CALL dbcsr_multiply('N', 'N', -1.0_dp*spin_fac, R_occ, exp_virt, 1.0_dp, &
    1633           92 :                              force_data%sum_O_tau(ispin)%matrix, retain_sparsity=.TRUE.)
    1634              :          CALL dbcsr_multiply('N', 'N', tau*spin_fac, dbcsr_work_symm, Y_1, 1.0_dp, &
    1635           92 :                              force_data%sum_O_tau(ispin)%matrix, retain_sparsity=.TRUE.)
    1636              :          CALL dbcsr_multiply('N', 'N', tau*spin_fac, dbcsr_work_symm, Y_2, 1.0_dp, &
    1637           92 :                              force_data%sum_O_tau(ispin)%matrix, retain_sparsity=.TRUE.)
    1638              : 
    1639           92 :          CALL timestop(handle2)
    1640              : 
    1641              :          !Print some info
    1642           92 :          CALL para_env%sync()
    1643           92 :          t2 = m_walltime()
    1644           92 :          dbcsr_time = dbcsr_time + t2 - t1
    1645              : 
    1646           92 :          IF (unit_nr > 0) THEN
    1647              :             WRITE (unit_nr, '(/T3,A,1X,I3,A)') &
    1648           46 :                'RPA_LOW_SCALING_INFO| Info for time point', jquad, '    (gradients)'
    1649              :             WRITE (unit_nr, '(T6,A,T56,F25.6)') &
    1650           46 :                'Time:', t2 - t1
    1651              :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
    1652           46 :                'Occupancy of 3c AO derivs:', REAL(nze_der_AO, dp), '/', occ_der_AO*100, '%'
    1653              :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
    1654           46 :                'Occupancy of 3c RI derivs:', REAL(nze_der_RI, dp), '/', occ_der_RI*100, '%'
    1655              :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
    1656           46 :                'Occupancy of the Docc * Dvirt * 3c-int tensor', REAL(nze_ddint, dp), '/', occ_ddint*100, '%'
    1657              :             WRITE (unit_nr, '(T6,A,T63,ES7.1,1X,A1,1X,F7.3,A1)') &
    1658           46 :                'Occupancy of KBK^T 2c-tensor:', REAL(nze_KBK, dp), '/', occ_KBK*100, '%'
    1659           46 :             CALL m_flush(unit_nr)
    1660              :          END IF
    1661              : 
    1662              :          !intermediate clean-up
    1663           92 :          CALL dbcsr_release(Y_1)
    1664           92 :          CALL dbcsr_release(Y_2)
    1665          496 :          CALL dbt_destroy(t_2c_tmp)
    1666              : 
    1667              :       END DO !jquad
    1668              : 
    1669           36 :       CALL dbt_batched_contract_finalize(t_3c_0)
    1670           36 :       CALL dbt_batched_contract_finalize(t_3c_1)
    1671           36 :       CALL dbt_batched_contract_finalize(t_3c_3)
    1672           36 :       CALL dbt_batched_contract_finalize(t_M_occ)
    1673           36 :       CALL dbt_batched_contract_finalize(t_M_virt)
    1674              : 
    1675           36 :       CALL dbt_batched_contract_finalize(t_3c_ints)
    1676           36 :       CALL dbt_batched_contract_finalize(t_3c_work)
    1677              : 
    1678           36 :       CALL dbt_batched_contract_finalize(t_3c_4)
    1679           36 :       CALL dbt_batched_contract_finalize(t_3c_5)
    1680           36 :       CALL dbt_batched_contract_finalize(t_3c_6)
    1681           36 :       CALL dbt_batched_contract_finalize(t_3c_7)
    1682           36 :       CALL dbt_batched_contract_finalize(t_3c_8)
    1683           36 :       CALL dbt_batched_contract_finalize(t_3c_sparse)
    1684              : 
    1685              :       !Calculate the 2c and 3c contributions to the virial
    1686           36 :       IF (use_virial) THEN
    1687            2 :          CALL dbt_copy(force_data%t_3c_virial_split, force_data%t_3c_virial, move_data=.TRUE.)
    1688              :          CALL calc_3c_virial(work_virial, force_data%t_3c_virial, 1.0_dp, qs_env, force_data%nl_3c, &
    1689              :                              basis_set_ri_aux, basis_set_ao, basis_set_ao, mp2_env%ri_metric, &
    1690            2 :                              der_eps=mp2_env%ri_rpa_im_time%eps_filter, op_pos=1)
    1691              : 
    1692              :          CALL calc_2c_virial(work_virial, force_data%RI_virial_met, 1.0_dp, qs_env, force_data%nl_2c_met, &
    1693            2 :                              basis_set_ri_aux, basis_set_ri_aux, mp2_env%ri_metric)
    1694            2 :          CALL dbcsr_clear(force_data%RI_virial_met)
    1695              : 
    1696            2 :          IF (.NOT. force_data%do_periodic) THEN
    1697              :             CALL calc_2c_virial(work_virial, force_data%RI_virial_pot, 1.0_dp, qs_env, force_data%nl_2c_pot, &
    1698            0 :                                 basis_set_ri_aux, basis_set_ri_aux, mp2_env%potential_parameter)
    1699            0 :             CALL dbcsr_clear(force_data%RI_virial_pot)
    1700              :          END IF
    1701              : 
    1702            2 :          identity_pot%potential_type = do_potential_id
    1703              :          CALL calc_2c_virial(work_virial_ovlp, virial_ovlp, 1.0_dp, qs_env, force_data%nl_2c_ovlp, &
    1704            2 :                              basis_set_ao, basis_set_ao, identity_pot)
    1705            2 :          CALL dbcsr_release(virial_ovlp)
    1706              : 
    1707            8 :          DO k_xyz = 1, 3
    1708           26 :             DO j_xyz = 1, 3
    1709           78 :                DO i_xyz = 1, 3
    1710              :                   virial%pv_mp2(i_xyz, j_xyz) = virial%pv_mp2(i_xyz, j_xyz) &
    1711           54 :                                                 - work_virial(i_xyz, k_xyz)*cell%hmat(j_xyz, k_xyz)
    1712              :                   virial%pv_overlap(i_xyz, j_xyz) = virial%pv_overlap(i_xyz, j_xyz) &
    1713           54 :                                                     - work_virial_ovlp(i_xyz, k_xyz)*cell%hmat(j_xyz, k_xyz)
    1714              :                   virial%pv_virial(i_xyz, j_xyz) = virial%pv_virial(i_xyz, j_xyz) &
    1715              :                                                    - work_virial(i_xyz, k_xyz)*cell%hmat(j_xyz, k_xyz) &
    1716           72 :                                                    - work_virial_ovlp(i_xyz, k_xyz)*cell%hmat(j_xyz, k_xyz)
    1717              :                END DO
    1718              :             END DO
    1719              :          END DO
    1720              :       END IF
    1721              : 
    1722              :       !Calculate the periodic contributions of (P|Q) to the force and the virial
    1723           36 :       work_virial = 0.0_dp
    1724           36 :       IF (force_data%do_periodic) THEN
    1725           18 :          IF (mp2_env%eri_method == do_eri_gpw) THEN
    1726            6 :             CALL get_2c_gpw_forces(force_data%G_PQ, force, work_virial, use_virial, mp2_env, qs_env)
    1727           12 :          ELSE IF (mp2_env%eri_method == do_eri_mme) THEN
    1728           12 :             CALL get_2c_mme_forces(force_data%G_PQ, force, mp2_env, qs_env)
    1729           12 :             IF (use_virial) CPABORT("Stress tensor not available with MME intrgrals")
    1730              :          ELSE
    1731            0 :             CPABORT("Periodic case not possible with OS integrals")
    1732              :          END IF
    1733           18 :          CALL dbcsr_clear(force_data%G_PQ)
    1734              :       END IF
    1735              : 
    1736           36 :       IF (use_virial) THEN
    1737           26 :          virial%pv_mp2 = virial%pv_mp2 + work_virial
    1738           26 :          virial%pv_virial = virial%pv_virial + work_virial
    1739            2 :          virial%pv_calculate = .FALSE.
    1740              : 
    1741            6 :          DO ibasis = 1, SIZE(basis_set_ao)
    1742            4 :             orb_basis => basis_set_ao(ibasis)%gto_basis_set
    1743            4 :             CALL init_interaction_radii_orb_basis(orb_basis, eps_pgf_orb_old)
    1744            4 :             ri_basis => basis_set_ri_aux(ibasis)%gto_basis_set
    1745            6 :             CALL init_interaction_radii_orb_basis(ri_basis, eps_pgf_orb_old)
    1746              :          END DO
    1747              :       END IF
    1748              : 
    1749              :       !clean-up
    1750           36 :       IF (ASSOCIATED(dummy_ptr)) DEALLOCATE (dummy_ptr)
    1751          128 :       DO jquad = 1, num_integ_points
    1752          128 :          CALL dbt_destroy(t_B(jquad))
    1753              :       END DO
    1754           36 :       CALL dbt_destroy(t_P)
    1755           36 :       CALL dbt_destroy(t_3c_0)
    1756           36 :       CALL dbt_destroy(t_3c_1)
    1757           36 :       CALL dbt_destroy(t_3c_3)
    1758           36 :       CALL dbt_destroy(t_3c_4)
    1759           36 :       CALL dbt_destroy(t_3c_5)
    1760           36 :       CALL dbt_destroy(t_3c_6)
    1761           36 :       CALL dbt_destroy(t_3c_7)
    1762           36 :       CALL dbt_destroy(t_3c_8)
    1763           36 :       CALL dbt_destroy(t_3c_sparse)
    1764           36 :       CALL dbt_destroy(t_3c_help_1)
    1765           36 :       CALL dbt_destroy(t_3c_help_2)
    1766           36 :       CALL dbt_destroy(t_3c_ints)
    1767           36 :       CALL dbt_destroy(t_3c_work)
    1768           36 :       CALL dbt_destroy(t_R_occ)
    1769           36 :       CALL dbt_destroy(t_R_virt)
    1770           36 :       CALL dbt_destroy(t_dm_occ)
    1771           36 :       CALL dbt_destroy(t_dm_virt)
    1772           36 :       CALL dbt_destroy(t_KBKT)
    1773           36 :       CALL dbt_destroy(t_M_occ)
    1774           36 :       CALL dbt_destroy(t_M_virt)
    1775           36 :       CALL dbcsr_release(R_occ)
    1776           36 :       CALL dbcsr_release(R_virt)
    1777           36 :       CALL dbcsr_release(dbcsr_work_symm)
    1778           36 :       CALL dbcsr_release(dbcsr_work1)
    1779           36 :       CALL dbcsr_release(dbcsr_work2)
    1780           36 :       CALL dbcsr_release(dbcsr_work3)
    1781           36 :       CALL dbcsr_release(exp_occ)
    1782           36 :       CALL dbcsr_release(exp_virt)
    1783              : 
    1784           36 :       CALL dbt_destroy(t_2c_RI)
    1785           36 :       CALL dbt_destroy(t_2c_RI_2)
    1786           36 :       CALL dbt_destroy(t_2c_AO)
    1787           36 :       CALL dbcsr_deallocate_matrix_set(mat_dm_occ)
    1788           36 :       CALL dbcsr_deallocate_matrix_set(mat_dm_virt)
    1789           36 :       CALL dbcsr_deallocate_matrix_set(mat_P_tau)
    1790              : 
    1791           36 :       CALL timestop(handle)
    1792              : 
    1793          200 :    END SUBROUTINE calc_rpa_loop_forces
    1794              : 
    1795              : ! **************************************************************************************************
    1796              : !> \brief This subroutines performs the 2c tensor operations that are common accros low-scaling RPA
    1797              : !>        and SOS-MP2, including forces and virial
    1798              : !> \param force ...
    1799              : !> \param t_KBKT returns the 2c tensor product of K*B*K^T
    1800              : !> \param force_data ...
    1801              : !> \param fac ...
    1802              : !> \param t_B depending on RPA or SOS-MP2, t_B contains (1 + Q)^-1 - 1 or simply Q, respectively
    1803              : !> \param t_P ...
    1804              : !> \param t_2c_RI ...
    1805              : !> \param t_2c_RI_2 ...
    1806              : !> \param use_virial ...
    1807              : !> \param atom_of_kind ...
    1808              : !> \param kind_of ...
    1809              : !> \param eps_filter ...
    1810              : !> \param dbcsr_nflop ...
    1811              : !> \param unit_nr_dbcsr ...
    1812              : ! **************************************************************************************************
    1813          170 :    SUBROUTINE perform_2c_ops(force, t_KBKT, force_data, fac, t_B, t_P, t_2c_RI, t_2c_RI_2, use_virial, &
    1814          170 :                              atom_of_kind, kind_of, eps_filter, dbcsr_nflop, unit_nr_dbcsr)
    1815              : 
    1816              :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    1817              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_KBKT
    1818              :       TYPE(im_time_force_type), INTENT(INOUT)            :: force_data
    1819              :       REAL(dp), INTENT(IN)                               :: fac
    1820              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_B, t_P, t_2c_RI, t_2c_RI_2
    1821              :       LOGICAL, INTENT(IN)                                :: use_virial
    1822              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: atom_of_kind, kind_of
    1823              :       REAL(dp), INTENT(IN)                               :: eps_filter
    1824              :       INTEGER(int_8), INTENT(INOUT)                      :: dbcsr_nflop
    1825              :       INTEGER, INTENT(IN)                                :: unit_nr_dbcsr
    1826              : 
    1827              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'perform_2c_ops'
    1828              : 
    1829              :       INTEGER                                            :: handle
    1830              :       INTEGER(int_8)                                     :: flop
    1831              :       REAL(dp)                                           :: pref
    1832         2890 :       TYPE(dbt_type)                                     :: t_2c_tmp, t_2c_virial
    1833              : 
    1834          170 :       CALL timeset(routineN, handle)
    1835              : 
    1836          170 :       IF (use_virial) CALL dbt_create(force_data%RI_virial_pot, t_2c_virial)
    1837              : 
    1838              :       !P^T*K*B + P*K*B^T (note we calculate and save K*B*K^T for later, and P=P^T)
    1839              :       CALL dbt_contract(1.0_dp, force_data%t_2c_K, t_B, 0.0_dp, t_2c_RI, &
    1840              :                         contract_1=[2], notcontract_1=[1], &
    1841              :                         contract_2=[1], notcontract_2=[2], &
    1842              :                         map_1=[1], map_2=[2], filter_eps=eps_filter, &
    1843          170 :                         flop=flop, unit_nr=unit_nr_dbcsr)
    1844          170 :       dbcsr_nflop = dbcsr_nflop + flop
    1845              : 
    1846              :       CALL dbt_contract(1.0_dp, t_2c_RI, force_data%t_2c_K, 0.0_dp, t_KBKT, &
    1847              :                         contract_1=[2], notcontract_1=[1], &
    1848              :                         contract_2=[2], notcontract_2=[1], &
    1849              :                         map_1=[1], map_2=[2], filter_eps=eps_filter, &
    1850          170 :                         flop=flop, unit_nr=unit_nr_dbcsr)
    1851          170 :       dbcsr_nflop = dbcsr_nflop + flop
    1852              : 
    1853              :       CALL dbt_contract(2.0_dp, t_P, t_2c_RI, 0.0_dp, t_2c_RI_2, & !t_2c_RI_2 holds P^T*K*B
    1854              :                         contract_1=[2], notcontract_1=[1], &
    1855              :                         contract_2=[1], notcontract_2=[2], &
    1856              :                         map_1=[1], map_2=[2], filter_eps=eps_filter, &
    1857          170 :                         flop=flop, unit_nr=unit_nr_dbcsr)
    1858          170 :       dbcsr_nflop = dbcsr_nflop + flop
    1859          170 :       CALL dbt_clear(t_2c_RI)
    1860              :       !t_2c_RI_2 currently holds 2*P^T*K*B = P^T*K*B + P*K*B^T (because of symmetry)
    1861              : 
    1862              :       !For the metric contribution, we need S^-1*(P^T*K*B + P*K*B^T)*K^T
    1863              :       CALL dbt_contract(1.0_dp, force_data%t_2c_inv_metric, t_2c_RI_2, 0.0_dp, t_2c_RI, &
    1864              :                         contract_1=[2], notcontract_1=[1], &
    1865              :                         contract_2=[1], notcontract_2=[2], &
    1866              :                         map_1=[1], map_2=[2], filter_eps=eps_filter, &
    1867          170 :                         flop=flop, unit_nr=unit_nr_dbcsr)
    1868          170 :       dbcsr_nflop = dbcsr_nflop + flop
    1869              : 
    1870              :       CALL dbt_contract(1.0_dp, t_2c_RI, force_data%t_2c_K, 0.0_dp, t_2c_RI_2, &
    1871              :                         contract_1=[2], notcontract_1=[1], &
    1872              :                         contract_2=[2], notcontract_2=[1], &
    1873              :                         map_1=[1], map_2=[2], filter_eps=eps_filter, &
    1874          170 :                         flop=flop, unit_nr=unit_nr_dbcsr)
    1875          170 :       dbcsr_nflop = dbcsr_nflop + flop
    1876              : 
    1877              :       !Here we do the trace for the force
    1878          170 :       pref = -1.0_dp*fac
    1879              :       CALL get_2c_der_force(force, t_2c_RI_2, force_data%t_2c_der_metric, atom_of_kind, &
    1880          170 :                             kind_of, force_data%idx_to_at_RI, pref, do_mp2=.TRUE.)
    1881          170 :       IF (use_virial) THEN
    1882           12 :          CALL dbt_copy(t_2c_RI_2, t_2c_virial)
    1883           12 :          CALL dbt_scale(t_2c_virial, pref)
    1884           12 :          CALL dbt_copy_tensor_to_matrix(t_2c_virial, force_data%RI_virial_met, summation=.TRUE.)
    1885           12 :          CALL dbt_clear(t_2c_virial)
    1886              :       END IF
    1887              : 
    1888              :       !For the potential contribution, we need S^-1*(P^T*K*B + P*K*B^T)*V^-0.5
    1889              :       !some of it is still in t_2c_RI: ( S^-1*(P^T*K*B + P*K*B^T) )
    1890              :       CALL dbt_contract(1.0_dp, t_2c_RI, force_data%t_2c_pot_msqrt, 0.0_dp, t_2c_RI_2, &
    1891              :                         contract_1=[2], notcontract_1=[1], &
    1892              :                         contract_2=[1], notcontract_2=[2], &
    1893              :                         map_1=[1], map_2=[2], filter_eps=eps_filter, &
    1894          170 :                         flop=flop, unit_nr=unit_nr_dbcsr)
    1895          170 :       dbcsr_nflop = dbcsr_nflop + flop
    1896              : 
    1897              :       !Here we do the trace for the force. In the periodic case, we store the matrix in G_PQ for later
    1898          170 :       pref = 0.5_dp*fac
    1899          170 :       IF (force_data%do_periodic) THEN
    1900           76 :          CALL dbt_scale(t_2c_RI_2, pref)
    1901           76 :          CALL dbt_create(force_data%G_PQ, t_2c_tmp)
    1902           76 :          CALL dbt_copy(t_2c_RI_2, t_2c_tmp, move_data=.TRUE.)
    1903           76 :          CALL dbt_copy_tensor_to_matrix(t_2c_tmp, force_data%G_PQ, summation=.TRUE.)
    1904           76 :          CALL dbt_destroy(t_2c_tmp)
    1905              :       ELSE
    1906              :          CALL get_2c_der_force(force, t_2c_RI_2, force_data%t_2c_der_pot, atom_of_kind, &
    1907           94 :                                kind_of, force_data%idx_to_at_RI, pref, do_mp2=.TRUE.)
    1908              : 
    1909           94 :          IF (use_virial) THEN
    1910            0 :             CALL dbt_copy(t_2c_RI_2, t_2c_virial)
    1911            0 :             CALL dbt_scale(t_2c_virial, pref)
    1912            0 :             CALL dbt_copy_tensor_to_matrix(t_2c_virial, force_data%RI_virial_pot, summation=.TRUE.)
    1913            0 :             CALL dbt_clear(t_2c_virial)
    1914              :          END IF
    1915              :       END IF
    1916              : 
    1917          170 :       CALL dbt_clear(t_2c_RI)
    1918          170 :       CALL dbt_clear(t_2c_RI_2)
    1919              : 
    1920          170 :       IF (use_virial) CALL dbt_destroy(t_2c_virial)
    1921              : 
    1922          170 :       CALL timestop(handle)
    1923              : 
    1924          170 :    END SUBROUTINE perform_2c_ops
    1925              : 
    1926              : ! **************************************************************************************************
    1927              : !> \brief This subroutines performs the 3c tensor operations that are common accros low-scaling RPA
    1928              : !>        and SOS-MP2, including forces and virial
    1929              : !> \param force ...
    1930              : !> \param t_R_occ ...
    1931              : !> \param t_R_virt ...
    1932              : !> \param force_data ...
    1933              : !> \param fac ...
    1934              : !> \param cut_memory ...
    1935              : !> \param n_mem_RI ...
    1936              : !> \param t_KBKT ...
    1937              : !> \param t_dm_occ ...
    1938              : !> \param t_dm_virt ...
    1939              : !> \param t_3c_O ...
    1940              : !> \param t_3c_M ...
    1941              : !> \param t_M_occ ...
    1942              : !> \param t_M_virt ...
    1943              : !> \param t_3c_0 ...
    1944              : !> \param t_3c_1 ...
    1945              : !> \param t_3c_3 ...
    1946              : !> \param t_3c_4 ...
    1947              : !> \param t_3c_5 ...
    1948              : !> \param t_3c_6 ...
    1949              : !> \param t_3c_7 ...
    1950              : !> \param t_3c_8 ...
    1951              : !> \param t_3c_sparse ...
    1952              : !> \param t_3c_help_1 ...
    1953              : !> \param t_3c_help_2 ...
    1954              : !> \param t_3c_ints ...
    1955              : !> \param t_3c_work ...
    1956              : !> \param starts_array_mc ...
    1957              : !> \param ends_array_mc ...
    1958              : !> \param batch_start_RI ...
    1959              : !> \param batch_end_RI ...
    1960              : !> \param t_3c_O_compressed ...
    1961              : !> \param t_3c_O_ind ...
    1962              : !> \param use_virial ...
    1963              : !> \param atom_of_kind ...
    1964              : !> \param kind_of ...
    1965              : !> \param eps_filter ...
    1966              : !> \param occ_ddint ...
    1967              : !> \param nze_ddint ...
    1968              : !> \param dbcsr_nflop ...
    1969              : !> \param unit_nr_dbcsr ...
    1970              : !> \param mp2_env ...
    1971              : ! **************************************************************************************************
    1972          170 :    SUBROUTINE perform_3c_ops(force, t_R_occ, t_R_virt, force_data, fac, cut_memory, n_mem_RI, &
    1973              :                              t_KBKT, t_dm_occ, t_dm_virt, t_3c_O, t_3c_M, t_M_occ, t_M_virt, t_3c_0, t_3c_1, &
    1974              :                              t_3c_3, t_3c_4, t_3c_5, t_3c_6, t_3c_7, t_3c_8, t_3c_sparse, t_3c_help_1, t_3c_help_2, &
    1975          170 :                              t_3c_ints, t_3c_work, starts_array_mc, ends_array_mc, batch_start_RI, &
    1976          170 :                              batch_end_RI, t_3c_O_compressed, t_3c_O_ind, use_virial, &
    1977          170 :                              atom_of_kind, kind_of, eps_filter, occ_ddint, nze_ddint, dbcsr_nflop, &
    1978              :                              unit_nr_dbcsr, mp2_env)
    1979              : 
    1980              :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    1981              :       TYPE(dbt_type), INTENT(INOUT)                      :: t_R_occ, t_R_virt
    1982              :       TYPE(im_time_force_type), INTENT(INOUT)            :: force_data
    1983              :       REAL(dp), INTENT(IN)                               :: fac
    1984              :       INTEGER, INTENT(IN)                                :: cut_memory, n_mem_RI
    1985              :       TYPE(dbt_type), INTENT(INOUT) :: t_KBKT, t_dm_occ, t_dm_virt, t_3c_O, t_3c_M, t_M_occ, &
    1986              :          t_M_virt, t_3c_0, t_3c_1, t_3c_3, t_3c_4, t_3c_5, t_3c_6, t_3c_7, t_3c_8, t_3c_sparse, &
    1987              :          t_3c_help_1, t_3c_help_2, t_3c_ints, t_3c_work
    1988              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: starts_array_mc, ends_array_mc, &
    1989              :                                                             batch_start_RI, batch_end_RI
    1990              :       TYPE(hfx_compression_type), DIMENSION(:)           :: t_3c_O_compressed
    1991              :       TYPE(block_ind_type), DIMENSION(:), INTENT(INOUT)  :: t_3c_O_ind
    1992              :       LOGICAL, INTENT(IN)                                :: use_virial
    1993              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: atom_of_kind, kind_of
    1994              :       REAL(dp), INTENT(IN)                               :: eps_filter
    1995              :       REAL(dp), INTENT(INOUT)                            :: occ_ddint
    1996              :       INTEGER(int_8), INTENT(INOUT)                      :: nze_ddint, dbcsr_nflop
    1997              :       INTEGER, INTENT(IN)                                :: unit_nr_dbcsr
    1998              :       TYPE(mp2_type)                                     :: mp2_env
    1999              : 
    2000              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'perform_3c_ops'
    2001              : 
    2002              :       INTEGER                                            :: dummy_int, handle, handle2, i_mem, &
    2003              :                                                             i_xyz, j_mem, k_mem
    2004              :       INTEGER(int_8)                                     :: flop, nze
    2005              :       INTEGER, DIMENSION(2, 1)                           :: ibounds, jbounds, kbounds
    2006              :       INTEGER, DIMENSION(2, 2)                           :: bounds_2c
    2007              :       INTEGER, DIMENSION(2, 3)                           :: bounds_cpy
    2008              :       INTEGER, DIMENSION(3)                              :: bounds_3c
    2009              :       REAL(dp)                                           :: memory, occ, pref
    2010          170 :       TYPE(block_ind_type), ALLOCATABLE, DIMENSION(:, :) :: blk_indices
    2011              :       TYPE(hfx_compression_type), ALLOCATABLE, &
    2012          170 :          DIMENSION(:, :)                                 :: store_3c
    2013              : 
    2014          170 :       CALL timeset(routineN, handle)
    2015              : 
    2016          170 :       CALL dbt_get_info(t_3c_M, nfull_total=bounds_3c)
    2017              : 
    2018              :       !Pre-compute and compress KBK^T * (pq|R)
    2019       360910 :       ALLOCATE (store_3c(n_mem_RI, cut_memory))
    2020         1700 :       ALLOCATE (blk_indices(n_mem_RI, cut_memory))
    2021          170 :       memory = 0.0_dp
    2022          170 :       CALL timeset(routineN//"_pre_3c", handle2)
    2023              :       !temporarily build the full int 3c tensor
    2024          170 :       CALL dbt_copy(t_3c_O, t_3c_0)
    2025          510 :       DO i_mem = 1, cut_memory
    2026              :          CALL decompress_tensor(t_3c_O, t_3c_O_ind(i_mem)%ind, t_3c_O_compressed(i_mem), &
    2027          340 :                                 mp2_env%ri_rpa_im_time%eps_compress)
    2028          340 :          CALL dbt_copy(t_3c_O, t_3c_ints)
    2029          340 :          CALL dbt_copy(t_3c_O, t_3c_0, move_data=.TRUE., summation=.TRUE.)
    2030              : 
    2031         1190 :          DO k_mem = 1, n_mem_RI
    2032         2040 :             kbounds(:, 1) = [batch_start_RI(k_mem), batch_end_RI(k_mem)]
    2033              : 
    2034          680 :             CALL alloc_containers(store_3c(k_mem, i_mem), 1)
    2035              : 
    2036              :             !contract with KBK^T over the RI index and store
    2037          680 :             CALL dbt_batched_contract_init(t_KBKT)
    2038              :             CALL dbt_contract(1.0_dp, t_KBKT, t_3c_ints, 0.0_dp, t_3c_work, &
    2039              :                               contract_1=[2], notcontract_1=[1], &
    2040              :                               contract_2=[1], notcontract_2=[2, 3], &
    2041              :                               map_1=[1], map_2=[2, 3], filter_eps=eps_filter, &
    2042          680 :                               bounds_2=kbounds, flop=flop, unit_nr=unit_nr_dbcsr)
    2043          680 :             CALL dbt_batched_contract_finalize(t_KBKT)
    2044          680 :             dbcsr_nflop = dbcsr_nflop + flop
    2045              : 
    2046          680 :             CALL dbt_copy(t_3c_work, t_3c_M, move_data=.TRUE.)
    2047              :             CALL compress_tensor(t_3c_M, blk_indices(k_mem, i_mem)%ind, store_3c(k_mem, i_mem), &
    2048         1020 :                                  mp2_env%ri_rpa_im_time%eps_compress, memory)
    2049              :          END DO
    2050              :       END DO !i_mem
    2051          170 :       CALL dbt_clear(t_3c_M)
    2052          170 :       CALL dbt_copy(t_3c_M, t_3c_ints)
    2053          170 :       CALL timestop(handle2)
    2054              : 
    2055          170 :       CALL dbt_batched_contract_init(t_R_occ)
    2056          170 :       CALL dbt_batched_contract_init(t_R_virt)
    2057          510 :       DO i_mem = 1, cut_memory
    2058         1020 :          ibounds(:, 1) = [starts_array_mc(i_mem), ends_array_mc(i_mem)]
    2059              : 
    2060              :          !Compute the matrices M (integrals in t_3c_0)
    2061          340 :          CALL timeset(routineN//"_3c_M", handle2)
    2062          340 :          CALL dbt_batched_contract_init(t_dm_occ)
    2063              :          CALL dbt_contract(1.0_dp, t_3c_0, t_dm_occ, 0.0_dp, t_3c_1, &
    2064              :                            contract_1=[3], notcontract_1=[1, 2], &
    2065              :                            contract_2=[1], notcontract_2=[2], &
    2066              :                            map_1=[1, 2], map_2=[3], filter_eps=eps_filter, &
    2067          340 :                            bounds_3=ibounds, flop=flop, unit_nr=unit_nr_dbcsr)
    2068          340 :          dbcsr_nflop = dbcsr_nflop + flop
    2069          340 :          CALL dbt_batched_contract_finalize(t_dm_occ)
    2070          340 :          CALL dbt_copy(t_3c_1, t_M_occ, order=[1, 3, 2], move_data=.TRUE.)
    2071              : 
    2072          340 :          CALL dbt_batched_contract_init(t_dm_virt)
    2073              :          CALL dbt_contract(1.0_dp, t_3c_0, t_dm_virt, 0.0_dp, t_3c_1, &
    2074              :                            contract_1=[3], notcontract_1=[1, 2], &
    2075              :                            contract_2=[1], notcontract_2=[2], &
    2076              :                            map_1=[1, 2], map_2=[3], filter_eps=eps_filter, &
    2077          340 :                            bounds_3=ibounds, flop=flop, unit_nr=unit_nr_dbcsr)
    2078          340 :          dbcsr_nflop = dbcsr_nflop + flop
    2079          340 :          CALL dbt_batched_contract_finalize(t_dm_virt)
    2080          340 :          CALL dbt_copy(t_3c_1, t_M_virt, order=[1, 3, 2], move_data=.TRUE.)
    2081          340 :          CALL timestop(handle2)
    2082              : 
    2083              :          !Compute the R matrices
    2084          340 :          CALL timeset(routineN//"_3c_R", handle2)
    2085         1020 :          DO k_mem = 1, n_mem_RI
    2086              :             CALL decompress_tensor(t_3c_M, blk_indices(k_mem, i_mem)%ind, store_3c(k_mem, i_mem), &
    2087          680 :                                    mp2_env%ri_rpa_im_time%eps_compress)
    2088          680 :             CALL dbt_copy(t_3c_M, t_3c_3, move_data=.TRUE.)
    2089              : 
    2090              :             CALL dbt_contract(1.0_dp, t_M_occ, t_3c_3, 1.0_dp, t_R_occ, &
    2091              :                               contract_1=[1, 2], notcontract_1=[3], &
    2092              :                               contract_2=[1, 2], notcontract_2=[3], &
    2093              :                               map_1=[1], map_2=[2], filter_eps=eps_filter, &
    2094          680 :                               flop=flop, unit_nr=unit_nr_dbcsr)
    2095          680 :             dbcsr_nflop = dbcsr_nflop + flop
    2096              : 
    2097              :             CALL dbt_contract(1.0_dp, t_M_virt, t_3c_3, 1.0_dp, t_R_virt, &
    2098              :                               contract_1=[1, 2], notcontract_1=[3], &
    2099              :                               contract_2=[1, 2], notcontract_2=[3], &
    2100              :                               map_1=[1], map_2=[2], filter_eps=eps_filter, &
    2101          680 :                               flop=flop, unit_nr=unit_nr_dbcsr)
    2102         1020 :             dbcsr_nflop = dbcsr_nflop + flop
    2103              :          END DO
    2104          340 :          CALL dbt_copy(t_3c_M, t_3c_3)
    2105          340 :          CALL dbt_copy(t_3c_M, t_M_virt)
    2106          340 :          CALL timestop(handle2)
    2107              : 
    2108          340 :          CALL dbt_copy(t_M_occ, t_3c_4, move_data=.TRUE.)
    2109              : 
    2110          340 :          IF (cut_memory > 0) CALL dbt_batched_contract_init(t_KBKT)
    2111         1020 :          DO j_mem = 1, cut_memory
    2112         2040 :             jbounds(:, 1) = [starts_array_mc(j_mem), ends_array_mc(j_mem)]
    2113              : 
    2114         2040 :             bounds_cpy(:, 1) = [1, bounds_3c(1)]
    2115         2040 :             bounds_cpy(:, 2) = [starts_array_mc(i_mem), ends_array_mc(i_mem)]
    2116         2040 :             bounds_cpy(:, 3) = [starts_array_mc(j_mem), ends_array_mc(j_mem)]
    2117          680 :             CALL dbt_copy(t_3c_sparse, t_3c_7, bounds=bounds_cpy)
    2118              : 
    2119          680 :             CALL dbt_batched_contract_init(t_dm_virt)
    2120         2040 :             DO k_mem = 1, n_mem_RI
    2121         4080 :                bounds_2c(:, 1) = [batch_start_RI(k_mem), batch_end_RI(k_mem)]
    2122         4080 :                bounds_2c(:, 2) = [starts_array_mc(i_mem), ends_array_mc(i_mem)]
    2123              : 
    2124         1360 :                CALL timeset(routineN//"_3c_dm", handle2)
    2125              : 
    2126              :                !Calculate (mu nu| P) * D_occ * D_virt
    2127              :                !Note: technically need M_occ*D_virt + M_virt*D_occ, but it is equivalent to 2*M_occ*D_virt
    2128              :                CALL dbt_contract(2.0_dp, t_3c_4, t_dm_virt, 0.0_dp, t_3c_5, &
    2129              :                                  contract_1=[3], notcontract_1=[1, 2], &
    2130              :                                  contract_2=[1], notcontract_2=[2], &
    2131              :                                  map_1=[1, 2], map_2=[3], filter_eps=eps_filter, &
    2132         1360 :                                  bounds_2=bounds_2c, bounds_3=jbounds, flop=flop, unit_nr=unit_nr_dbcsr)
    2133         1360 :                dbcsr_nflop = dbcsr_nflop + flop
    2134              : 
    2135         1360 :                CALL get_tensor_occupancy(t_3c_5, nze, occ)
    2136         1360 :                nze_ddint = nze_ddint + nze
    2137         1360 :                occ_ddint = occ_ddint + occ
    2138              : 
    2139              :                ! Skip the expensive KBK^T contraction when the intermediate block is empty
    2140         1360 :                IF (nze == 0) THEN
    2141            0 :                   CALL dbt_clear(t_3c_5)
    2142            0 :                   CYCLE
    2143              :                END IF
    2144              : 
    2145         1360 :                CALL dbt_copy(t_3c_5, t_3c_6, move_data=.TRUE.)
    2146         1360 :                CALL timestop(handle2)
    2147              : 
    2148              :                !Calculate the contraction of the above with K*B*K^T
    2149         1360 :                CALL timeset(routineN//"_3c_KBK", handle2)
    2150              :                CALL dbt_contract(1.0_dp, t_KBKT, t_3c_6, 0.0_dp, t_3c_7, &
    2151              :                                  contract_1=[2], notcontract_1=[1], &
    2152              :                                  contract_2=[1], notcontract_2=[2, 3], &
    2153              :                                  map_1=[1], map_2=[2, 3], &
    2154         1360 :                                  retain_sparsity=.TRUE., flop=flop, unit_nr=unit_nr_dbcsr)
    2155         1360 :                dbcsr_nflop = dbcsr_nflop + flop
    2156         1360 :                CALL timestop(handle2)
    2157         6120 :                CALL dbt_copy(t_3c_7, t_3c_8, summation=.TRUE.)
    2158              : 
    2159              :             END DO !k_mem
    2160         1020 :             CALL dbt_batched_contract_finalize(t_dm_virt)
    2161              :          END DO !j_mem
    2162          340 :          IF (cut_memory > 0) CALL dbt_batched_contract_finalize(t_KBKT)
    2163              : 
    2164          340 :          CALL dbt_copy(t_3c_8, t_3c_help_1, move_data=.TRUE.)
    2165              : 
    2166          340 :          pref = 1.0_dp*fac
    2167         1020 :          DO k_mem = 1, cut_memory
    2168         2720 :             DO i_xyz = 1, 3
    2169         2040 :                CALL dbt_clear(force_data%t_3c_der_RI(i_xyz))
    2170              :                CALL decompress_tensor(force_data%t_3c_der_RI(i_xyz), force_data%t_3c_der_RI_ind(k_mem, i_xyz)%ind, &
    2171         2720 :                                       force_data%t_3c_der_RI_comp(k_mem, i_xyz), mp2_env%ri_rpa_im_time%eps_compress)
    2172              :             END DO
    2173              :             CALL get_force_from_3c_trace(force, t_3c_help_1, force_data%t_3c_der_RI, atom_of_kind, kind_of, &
    2174         1020 :                                          force_data%idx_to_at_RI, pref, do_mp2=.TRUE., deriv_dim=1)
    2175              :          END DO
    2176              : 
    2177          340 :          IF (use_virial) THEN
    2178           24 :             CALL dbt_copy(t_3c_help_1, t_3c_help_2)
    2179           24 :             CALL dbt_scale(t_3c_help_2, pref)
    2180           24 :             CALL dbt_copy(t_3c_help_2, force_data%t_3c_virial_split, summation=.TRUE., move_data=.TRUE.)
    2181              :          END IF
    2182              : 
    2183          340 :          CALL dbt_copy(t_3c_help_1, t_3c_help_2)
    2184          340 :          CALL dbt_copy(t_3c_help_1, t_3c_help_2, order=[1, 3, 2], move_data=.TRUE., summation=.TRUE.)
    2185         1020 :          DO k_mem = 1, cut_memory
    2186         2720 :             DO i_xyz = 1, 3
    2187         2040 :                CALL dbt_clear(force_data%t_3c_der_AO(i_xyz))
    2188              :                CALL decompress_tensor(force_data%t_3c_der_AO(i_xyz), force_data%t_3c_der_AO_ind(k_mem, i_xyz)%ind, &
    2189         2720 :                                       force_data%t_3c_der_AO_comp(k_mem, i_xyz), mp2_env%ri_rpa_im_time%eps_compress)
    2190              :             END DO
    2191              :             CALL get_force_from_3c_trace(force, t_3c_help_2, force_data%t_3c_der_AO, atom_of_kind, kind_of, &
    2192         1020 :                                          force_data%idx_to_at_AO, pref, do_mp2=.TRUE., deriv_dim=3)
    2193              :          END DO
    2194              : 
    2195         1190 :          CALL dbt_clear(t_3c_help_2)
    2196              :       END DO !i_mem
    2197          170 :       CALL dbt_batched_contract_finalize(t_R_occ)
    2198          170 :       CALL dbt_batched_contract_finalize(t_R_virt)
    2199              : 
    2200          510 :       DO k_mem = 1, n_mem_RI
    2201         1190 :          DO i_mem = 1, cut_memory
    2202         1020 :             CALL dealloc_containers(store_3c(k_mem, i_mem), dummy_int)
    2203              :          END DO
    2204              :       END DO
    2205          850 :       DEALLOCATE (store_3c, blk_indices)
    2206              : 
    2207          170 :       CALL timestop(handle)
    2208              : 
    2209          340 :    END SUBROUTINE perform_3c_ops
    2210              : 
    2211              : ! **************************************************************************************************
    2212              : !> \brief All the forces that can be calculated after the loop on the Laplace quaradture, using
    2213              : !>        terms collected during the said loop. This inludes the z-vector equation and its reponse
    2214              : !>        forces, as well as the force coming from the trace with the derivative of the KS matrix
    2215              : !> \param force_data ...
    2216              : !> \param unit_nr ...
    2217              : !> \param qs_env ...
    2218              : ! **************************************************************************************************
    2219           50 :    SUBROUTINE calc_post_loop_forces(force_data, unit_nr, qs_env)
    2220              : 
    2221              :       TYPE(im_time_force_type), INTENT(INOUT)            :: force_data
    2222              :       INTEGER, INTENT(IN)                                :: unit_nr
    2223              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2224              : 
    2225              :       CHARACTER(len=*), PARAMETER :: routineN = 'calc_post_loop_forces'
    2226              : 
    2227              :       INTEGER                                            :: handle, ispin, nao, nao_aux, nocc, nspins
    2228              :       LOGICAL                                            :: do_exx
    2229              :       REAL(dp)                                           :: focc
    2230              :       TYPE(admm_type), POINTER                           :: admm_env
    2231              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    2232           50 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: cpmos, mo_occ
    2233              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    2234           50 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: dbcsr_p_work, matrix_p_mp2, &
    2235           50 :                                                             matrix_p_mp2_admm, matrix_s, &
    2236           50 :                                                             matrix_s_aux, work_admm, YP_admm
    2237              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2238              :       TYPE(linres_control_type), POINTER                 :: linres_control
    2239           50 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    2240              :       TYPE(qs_p_env_type), POINTER                       :: p_env
    2241              :       TYPE(section_vals_type), POINTER                   :: hfx_section, lr_section
    2242              : 
    2243           50 :       NULLIFY (linres_control, p_env, dft_control, matrix_s, mos, mo_coeff, fm_struct, lr_section, &
    2244           50 :                dbcsr_p_work, YP_admm, matrix_p_mp2, admm_env, work_admm, matrix_s_aux, matrix_p_mp2_admm)
    2245              : 
    2246           50 :       CALL timeset(routineN, handle)
    2247              : 
    2248           50 :       CALL get_qs_env(qs_env, dft_control=dft_control, matrix_s=matrix_s, mos=mos)
    2249           50 :       nspins = dft_control%nspins
    2250              : 
    2251              :       ! Setting up for the z-vector equation
    2252              : 
    2253              :       ! Initialize linres_control
    2254           50 :       lr_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%WF_CORRELATION%LOW_SCALING%CPHF")
    2255              : 
    2256           50 :       ALLOCATE (linres_control)
    2257           50 :       CALL section_vals_val_get(lr_section, "MAX_ITER", i_val=linres_control%max_iter)
    2258           50 :       CALL section_vals_val_get(lr_section, "EPS_CONV", r_val=linres_control%eps)
    2259           50 :       CALL section_vals_val_get(lr_section, "PRECONDITIONER", i_val=linres_control%preconditioner_type)
    2260           50 :       CALL section_vals_val_get(lr_section, "ENERGY_GAP", r_val=linres_control%energy_gap)
    2261              : 
    2262           50 :       linres_control%do_kernel = .TRUE.
    2263           50 :       linres_control%lr_triplet = .FALSE.
    2264           50 :       linres_control%converged = .FALSE.
    2265           50 :       linres_control%eps_filter = qs_env%mp2_env%ri_rpa_im_time%eps_filter
    2266              : 
    2267           50 :       CALL set_qs_env(qs_env, linres_control=linres_control)
    2268              : 
    2269           50 :       IF (unit_nr > 0) THEN
    2270           25 :          WRITE (unit_nr, *)
    2271           25 :          WRITE (unit_nr, '(T3,A)') 'MP2_CPHF| Iterative solution of Z-Vector equations'
    2272           25 :          WRITE (unit_nr, '(T3,A,T45,ES8.1)') 'MP2_CPHF| Convergence threshold:', linres_control%eps
    2273           25 :          WRITE (unit_nr, '(T3,A,T45,I8)') 'MP2_CPHF| Maximum number of iterations: ', linres_control%max_iter
    2274              :       END IF
    2275              : 
    2276          350 :       ALLOCATE (p_env)
    2277           50 :       CALL p_env_create(p_env, qs_env, orthogonal_orbitals=.TRUE., linres_control=linres_control)
    2278           50 :       CALL p_env_psi0_changed(p_env, qs_env)
    2279              : 
    2280              :       ! Matrix allocation
    2281           50 :       CALL dbcsr_allocate_matrix_set(p_env%p1, nspins)
    2282           50 :       CALL dbcsr_allocate_matrix_set(p_env%w1, nspins)
    2283           50 :       CALL dbcsr_allocate_matrix_set(dbcsr_p_work, nspins)
    2284          112 :       DO ispin = 1, nspins
    2285           62 :          ALLOCATE (p_env%p1(ispin)%matrix, p_env%w1(ispin)%matrix, dbcsr_p_work(ispin)%matrix)
    2286           62 :          CALL dbcsr_create(matrix=p_env%p1(ispin)%matrix, template=matrix_s(1)%matrix)
    2287           62 :          CALL dbcsr_create(matrix=p_env%w1(ispin)%matrix, template=matrix_s(1)%matrix)
    2288           62 :          CALL dbcsr_create(matrix=dbcsr_p_work(ispin)%matrix, template=matrix_s(1)%matrix)
    2289           62 :          CALL dbcsr_copy(p_env%p1(ispin)%matrix, matrix_s(1)%matrix)
    2290           62 :          CALL dbcsr_copy(p_env%w1(ispin)%matrix, matrix_s(1)%matrix)
    2291           62 :          CALL dbcsr_copy(dbcsr_p_work(ispin)%matrix, matrix_s(1)%matrix)
    2292           62 :          CALL dbcsr_set(p_env%p1(ispin)%matrix, 0.0_dp)
    2293           62 :          CALL dbcsr_set(p_env%w1(ispin)%matrix, 0.0_dp)
    2294          112 :          CALL dbcsr_set(dbcsr_p_work(ispin)%matrix, 0.0_dp)
    2295              :       END DO
    2296              : 
    2297           50 :       IF (dft_control%do_admm) THEN
    2298           16 :          CALL get_admm_env(qs_env%admm_env, matrix_s_aux_fit=matrix_s_aux)
    2299           16 :          CALL dbcsr_allocate_matrix_set(p_env%p1_admm, nspins)
    2300           16 :          CALL dbcsr_allocate_matrix_set(work_admm, nspins)
    2301           36 :          DO ispin = 1, nspins
    2302           20 :             ALLOCATE (p_env%p1_admm(ispin)%matrix, work_admm(ispin)%matrix)
    2303           20 :             CALL dbcsr_create(p_env%p1_admm(ispin)%matrix, template=matrix_s_aux(1)%matrix)
    2304           20 :             CALL dbcsr_copy(p_env%p1_admm(ispin)%matrix, matrix_s_aux(1)%matrix)
    2305           20 :             CALL dbcsr_set(p_env%p1_admm(ispin)%matrix, 0.0_dp)
    2306           20 :             CALL dbcsr_create(work_admm(ispin)%matrix, template=matrix_s_aux(1)%matrix)
    2307           20 :             CALL dbcsr_copy(work_admm(ispin)%matrix, matrix_s_aux(1)%matrix)
    2308           36 :             CALL dbcsr_set(work_admm(ispin)%matrix, 0.0_dp)
    2309              :          END DO
    2310              :       END IF
    2311              : 
    2312              :       ! Preparing the RHS of the z-vector equation
    2313           50 :       CALL prepare_for_response(force_data, qs_env)
    2314          324 :       ALLOCATE (cpmos(nspins), mo_occ(nspins))
    2315          112 :       DO ispin = 1, nspins
    2316           62 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nao=nao, homo=nocc)
    2317           62 :          NULLIFY (fm_struct)
    2318              :          CALL cp_fm_struct_create(fm_struct, ncol_global=nocc, &
    2319           62 :                                   template_fmstruct=mo_coeff%matrix_struct)
    2320           62 :          CALL cp_fm_create(cpmos(ispin), fm_struct)
    2321           62 :          CALL cp_fm_set_all(cpmos(ispin), 0.0_dp)
    2322           62 :          CALL cp_fm_create(mo_occ(ispin), fm_struct)
    2323           62 :          CALL cp_fm_to_fm(mo_coeff, mo_occ(ispin), nocc)
    2324          174 :          CALL cp_fm_struct_release(fm_struct)
    2325              :       END DO
    2326              : 
    2327              :       ! in case of EXX, need to add the HF Hamiltonian to the RHS of the Z-vector equation
    2328              :       ! Strategy: we take the ks_matrix, remove the current xc contribution, and then add the RPA HF one
    2329           50 :       do_exx = .FALSE.
    2330           50 :       IF (qs_env%mp2_env%method == ri_rpa_method_gpw) THEN
    2331           28 :          hfx_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%WF_CORRELATION%RI_RPA%HF")
    2332           28 :          CALL section_vals_get(hfx_section, explicit=do_exx)
    2333              :       END IF
    2334              : 
    2335           50 :       IF (do_exx) THEN
    2336              :          CALL add_exx_to_rhs(rhs=force_data%sum_O_tau, &
    2337              :                              qs_env=qs_env, &
    2338              :                              ext_hfx_section=hfx_section, &
    2339              :                              x_data=qs_env%mp2_env%ri_rpa%x_data, &
    2340              :                              recalc_integrals=.FALSE., &
    2341              :                              do_admm=qs_env%mp2_env%ri_rpa%do_admm, &
    2342              :                              do_exx=do_exx, &
    2343           18 :                              reuse_hfx=qs_env%mp2_env%ri_rpa%reuse_hfx)
    2344              :       END IF
    2345              : 
    2346           50 :       focc = 2.0_dp
    2347           50 :       IF (nspins == 1) focc = 4.0_dp
    2348          112 :       DO ispin = 1, nspins
    2349           62 :          CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, homo=nocc)
    2350              :          CALL cp_dbcsr_sm_fm_multiply(force_data%sum_O_tau(ispin)%matrix, mo_occ(ispin), &
    2351              :                                       cpmos(ispin), nocc, &
    2352          112 :                                       alpha=focc, beta=0.0_dp)
    2353              :       END DO
    2354              : 
    2355              :       ! The z-vector equation and associated forces
    2356           50 :       CALL response_equation_new(qs_env, p_env, cpmos, unit_nr)
    2357              : 
    2358              :       ! Save the mp2 density matrix
    2359           50 :       CALL get_qs_env(qs_env, matrix_p_mp2=matrix_p_mp2)
    2360           50 :       IF (ASSOCIATED(matrix_p_mp2)) CALL dbcsr_deallocate_matrix_set(matrix_p_mp2)
    2361          112 :       DO ispin = 1, nspins
    2362           62 :          CALL dbcsr_copy(dbcsr_p_work(ispin)%matrix, p_env%p1(ispin)%matrix)
    2363          112 :          CALL dbcsr_add(dbcsr_p_work(ispin)%matrix, force_data%sum_YP_tau(ispin)%matrix, 1.0_dp, 1.0_dp)
    2364              :       END DO
    2365           50 :       CALL set_ks_env(qs_env%ks_env, matrix_p_mp2=dbcsr_p_work)
    2366              : 
    2367           50 :       IF (dft_control%do_admm) THEN
    2368           16 :          CALL dbcsr_allocate_matrix_set(YP_admm, nspins)
    2369           16 :          CALL get_qs_env(qs_env, matrix_p_mp2_admm=matrix_p_mp2_admm, admm_env=admm_env)
    2370           16 :          nao = admm_env%nao_orb
    2371           16 :          nao_aux = admm_env%nao_aux_fit
    2372           16 :          IF (ASSOCIATED(matrix_p_mp2_admm)) CALL dbcsr_deallocate_matrix_set(matrix_p_mp2_admm)
    2373           36 :          DO ispin = 1, nspins
    2374              : 
    2375              :             !sum_YP_tau in the auxiliary basis
    2376           20 :             CALL copy_dbcsr_to_fm(force_data%sum_YP_tau(ispin)%matrix, admm_env%work_orb_orb)
    2377              :             CALL parallel_gemm('N', 'N', nao_aux, nao, nao, 1.0_dp, admm_env%A, admm_env%work_orb_orb, &
    2378           20 :                                0.0_dp, admm_env%work_aux_orb)
    2379              :             CALL parallel_gemm('N', 'T', nao_aux, nao_aux, nao, 1.0_dp, admm_env%work_aux_orb, admm_env%A, &
    2380           20 :                                0.0_dp, admm_env%work_aux_aux)
    2381           20 :             CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, work_admm(ispin)%matrix, keep_sparsity=.TRUE.)
    2382              : 
    2383              :             !save the admm representation od sum_YP_tau
    2384           20 :             ALLOCATE (YP_admm(ispin)%matrix)
    2385           20 :             CALL dbcsr_create(YP_admm(ispin)%matrix, template=work_admm(ispin)%matrix)
    2386           20 :             CALL dbcsr_copy(YP_admm(ispin)%matrix, work_admm(ispin)%matrix)
    2387              : 
    2388           36 :             CALL dbcsr_add(work_admm(ispin)%matrix, p_env%p1_admm(ispin)%matrix, 1.0_dp, 1.0_dp)
    2389              : 
    2390              :          END DO
    2391           16 :          CALL set_ks_env(qs_env%ks_env, matrix_p_mp2_admm=work_admm)
    2392              :       END IF
    2393              : 
    2394              :       !Calculate the response force and the force from the trace with F
    2395           50 :       CALL update_im_time_forces(p_env, force_data%sum_O_tau, force_data%sum_YP_tau, YP_admm, qs_env)
    2396              : 
    2397              :       !clean-up
    2398           50 :       IF (dft_control%do_admm) CALL dbcsr_deallocate_matrix_set(YP_admm)
    2399              : 
    2400           50 :       CALL cp_fm_release(cpmos)
    2401           50 :       CALL cp_fm_release(mo_occ)
    2402           50 :       CALL p_env_release(p_env)
    2403           50 :       DEALLOCATE (p_env)
    2404              : 
    2405           50 :       CALL timestop(handle)
    2406              : 
    2407          100 :    END SUBROUTINE calc_post_loop_forces
    2408              : 
    2409              : ! **************************************************************************************************
    2410              : !> \brief Prepares the RHS of the z-vector equation. Apply the xc and HFX kernel on the previously
    2411              : !>        stored sum_YP_tau density, and add it to the final force_data%sum_O_tau quantity
    2412              : !> \param force_data ...
    2413              : !> \param qs_env ...
    2414              : ! **************************************************************************************************
    2415           50 :    SUBROUTINE prepare_for_response(force_data, qs_env)
    2416              : 
    2417              :       TYPE(im_time_force_type), INTENT(INOUT)            :: force_data
    2418              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2419              : 
    2420              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'prepare_for_response'
    2421              : 
    2422              :       INTEGER                                            :: handle, ispin, nao, nao_aux, nspins
    2423              :       LOGICAL                                            :: do_hfx, do_tau, do_tau_admm
    2424              :       REAL(dp)                                           :: ehartree
    2425              :       TYPE(admm_type), POINTER                           :: admm_env
    2426           50 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: dbcsr_p_work, ker_tau_admm, matrix_s, &
    2427           50 :                                                             matrix_s_aux, work_admm
    2428              :       TYPE(dbcsr_type)                                   :: dbcsr_work
    2429              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2430              :       TYPE(pw_c1d_gs_type)                               :: rhoz_tot_gspace, zv_hartree_gspace
    2431           50 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rhoz_g
    2432              :       TYPE(pw_env_type), POINTER                         :: pw_env
    2433              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
    2434              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2435              :       TYPE(pw_r3d_rs_type)                               :: zv_hartree_rspace
    2436           50 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rhoz_r, tauz_r, v_xc, v_xc_tau
    2437              :       TYPE(qs_rho_type), POINTER                         :: rho, rho_aux_fit, rhoz
    2438           50 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho0_atom_set, rho1_atom_set
    2439              :       TYPE(section_vals_type), POINTER                   :: hfx_section, xc_section
    2440              :       TYPE(task_list_type), POINTER                      :: task_list_aux_fit
    2441              : 
    2442           50 :       NULLIFY (pw_env, rhoz_r, rhoz_g, tauz_r, v_xc, v_xc_tau, &
    2443           50 :                poisson_env, auxbas_pw_pool, dft_control, admm_env, xc_section, rho, rho_aux_fit, &
    2444           50 :                task_list_aux_fit, ker_tau_admm, work_admm, dbcsr_p_work, matrix_s, hfx_section)
    2445           50 :       NULLIFY (rho0_atom_set, rho1_atom_set)
    2446              : 
    2447           50 :       CALL timeset(routineN, handle)
    2448              : 
    2449           50 :       CALL get_qs_env(qs_env, dft_control=dft_control, pw_env=pw_env, rho=rho, matrix_s=matrix_s)
    2450           50 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, poisson_env=poisson_env)
    2451           50 :       nspins = dft_control%nspins
    2452              : 
    2453           50 :       CALL dbcsr_allocate_matrix_set(dbcsr_p_work, nspins)
    2454          112 :       DO ispin = 1, nspins
    2455           62 :          ALLOCATE (dbcsr_p_work(ispin)%matrix)
    2456           62 :          CALL dbcsr_create(matrix=dbcsr_p_work(ispin)%matrix, template=matrix_s(1)%matrix)
    2457           62 :          CALL dbcsr_copy(dbcsr_p_work(ispin)%matrix, matrix_s(1)%matrix)
    2458          112 :          CALL dbcsr_set(dbcsr_p_work(ispin)%matrix, 0.0_dp)
    2459              :       END DO
    2460              : 
    2461              :       !Apply the kernel on the density saved in force_data%sum_YP_tau
    2462          374 :       ALLOCATE (rhoz_r(nspins), rhoz_g(nspins))
    2463          112 :       DO ispin = 1, nspins
    2464           62 :          CALL auxbas_pw_pool%create_pw(rhoz_r(ispin))
    2465          112 :          CALL auxbas_pw_pool%create_pw(rhoz_g(ispin))
    2466              :       END DO
    2467           50 :       CALL auxbas_pw_pool%create_pw(rhoz_tot_gspace)
    2468           50 :       CALL auxbas_pw_pool%create_pw(zv_hartree_rspace)
    2469           50 :       CALL auxbas_pw_pool%create_pw(zv_hartree_gspace)
    2470              : 
    2471           50 :       CALL pw_zero(rhoz_tot_gspace)
    2472          112 :       DO ispin = 1, nspins
    2473              :          CALL calculate_rho_elec(ks_env=qs_env%ks_env, matrix_p=force_data%sum_YP_tau(ispin)%matrix, &
    2474           62 :                                  rho=rhoz_r(ispin), rho_gspace=rhoz_g(ispin))
    2475          112 :          CALL pw_axpy(rhoz_g(ispin), rhoz_tot_gspace)
    2476              :       END DO
    2477              : 
    2478              :       CALL pw_poisson_solve(poisson_env, rhoz_tot_gspace, ehartree, &
    2479           50 :                             zv_hartree_gspace)
    2480              : 
    2481           50 :       CALL pw_transfer(zv_hartree_gspace, zv_hartree_rspace)
    2482           50 :       CALL pw_scale(zv_hartree_rspace, zv_hartree_rspace%pw_grid%dvol)
    2483              : 
    2484           50 :       CALL qs_rho_get(rho, tau_r_valid=do_tau)
    2485           50 :       IF (do_tau) THEN
    2486              :          BLOCK
    2487              :             TYPE(pw_c1d_gs_type) :: tauz_g
    2488           24 :             ALLOCATE (tauz_r(nspins))
    2489            8 :             CALL auxbas_pw_pool%create_pw(tauz_g)
    2490           16 :             DO ispin = 1, nspins
    2491            8 :                CALL auxbas_pw_pool%create_pw(tauz_r(ispin))
    2492              : 
    2493              :                CALL calculate_rho_elec(ks_env=qs_env%ks_env, matrix_p=force_data%sum_YP_tau(ispin)%matrix, &
    2494           16 :                                        rho=tauz_r(ispin), rho_gspace=tauz_g, compute_tau=.TRUE.)
    2495              :             END DO
    2496           16 :             CALL auxbas_pw_pool%give_back_pw(tauz_g)
    2497              :          END BLOCK
    2498              :       END IF
    2499              : 
    2500           50 :       IF (dft_control%do_admm) THEN
    2501           16 :          CALL get_qs_env(qs_env, admm_env=admm_env)
    2502           16 :          xc_section => admm_env%xc_section_primary
    2503              :       ELSE
    2504           34 :          xc_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC")
    2505              :       END IF
    2506              : 
    2507              :       !Primary XC kernel
    2508           50 :       ALLOCATE (rhoz)
    2509           50 :       CALL qs_rho_create(rhoz)
    2510           50 :       IF (ASSOCIATED(rhoz_r)) THEN
    2511           50 :          CALL qs_rho_set(rhoz, rho_r=rhoz_r, rho_r_valid=.TRUE.)
    2512              :       END IF
    2513           50 :       IF (ASSOCIATED(rhoz_g)) THEN
    2514           50 :          CALL qs_rho_set(rhoz, rho_g=rhoz_g, rho_g_valid=.TRUE.)
    2515              :       END IF
    2516           50 :       IF (ASSOCIATED(tauz_r)) THEN
    2517            8 :          CALL qs_rho_set(rhoz, tau_r=tauz_r, tau_r_valid=.TRUE.)
    2518              :       END IF
    2519              :       !
    2520              :       CALL qs_fxc_create(qs_env, rho, rhoz, rho0_atom_set, xc_section, .FALSE., &
    2521           50 :                          v_xc, v_xc_tau, rho1_atom_set)
    2522              :       !
    2523           50 :       DEALLOCATE (rhoz)
    2524              : 
    2525          112 :       DO ispin = 1, nspins
    2526           62 :          CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
    2527           62 :          CALL pw_axpy(zv_hartree_rspace, v_xc(ispin))
    2528              :          CALL integrate_v_rspace(qs_env=qs_env, &
    2529              :                                  v_rspace=v_xc(ispin), &
    2530              :                                  hmat=dbcsr_p_work(ispin), &
    2531           62 :                                  calculate_forces=.FALSE.)
    2532              : 
    2533          112 :          CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
    2534              :       END DO
    2535           50 :       CALL auxbas_pw_pool%give_back_pw(rhoz_tot_gspace)
    2536           50 :       CALL auxbas_pw_pool%give_back_pw(zv_hartree_rspace)
    2537           50 :       CALL auxbas_pw_pool%give_back_pw(zv_hartree_gspace)
    2538           50 :       DEALLOCATE (v_xc)
    2539              : 
    2540           50 :       IF (do_tau) THEN
    2541           16 :          DO ispin = 1, nspins
    2542            8 :             CALL pw_scale(v_xc_tau(ispin), v_xc_tau(ispin)%pw_grid%dvol)
    2543              :             CALL integrate_v_rspace(qs_env=qs_env, &
    2544              :                                     v_rspace=v_xc_tau(ispin), &
    2545              :                                     hmat=dbcsr_p_work(ispin), &
    2546              :                                     compute_tau=.TRUE., &
    2547            8 :                                     calculate_forces=.FALSE.)
    2548           16 :             CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
    2549              :          END DO
    2550            8 :          DEALLOCATE (v_xc_tau)
    2551              :       END IF
    2552              : 
    2553              :       !Auxiliary xc kernel (admm)
    2554           50 :       IF (dft_control%do_admm) THEN
    2555           16 :          CALL get_qs_env(qs_env, admm_env=admm_env)
    2556              :          CALL get_admm_env(admm_env, matrix_s_aux_fit=matrix_s_aux, &
    2557           16 :                            task_list_aux_fit=task_list_aux_fit, rho_aux_fit=rho_aux_fit)
    2558              : 
    2559           16 :          CALL qs_rho_get(rho_aux_fit, tau_r_valid=do_tau_admm)
    2560              : 
    2561           16 :          CALL dbcsr_allocate_matrix_set(work_admm, nspins)
    2562           16 :          CALL dbcsr_allocate_matrix_set(ker_tau_admm, nspins)
    2563           36 :          DO ispin = 1, nspins
    2564           20 :             ALLOCATE (work_admm(ispin)%matrix, ker_tau_admm(ispin)%matrix)
    2565           20 :             CALL dbcsr_create(work_admm(ispin)%matrix, template=matrix_s_aux(1)%matrix)
    2566           20 :             CALL dbcsr_copy(work_admm(ispin)%matrix, matrix_s_aux(1)%matrix)
    2567           20 :             CALL dbcsr_set(work_admm(ispin)%matrix, 0.0_dp)
    2568           20 :             CALL dbcsr_create(ker_tau_admm(ispin)%matrix, template=matrix_s_aux(1)%matrix)
    2569           20 :             CALL dbcsr_copy(ker_tau_admm(ispin)%matrix, matrix_s_aux(1)%matrix)
    2570           36 :             CALL dbcsr_set(ker_tau_admm(ispin)%matrix, 0.0_dp)
    2571              :          END DO
    2572              : 
    2573              :          !get the density in the auxuliary density
    2574           16 :          CPASSERT(ASSOCIATED(admm_env%work_orb_orb))
    2575           16 :          CPASSERT(ASSOCIATED(admm_env%work_aux_orb))
    2576           16 :          CPASSERT(ASSOCIATED(admm_env%work_aux_aux))
    2577           16 :          nao = admm_env%nao_orb
    2578           16 :          nao_aux = admm_env%nao_aux_fit
    2579           36 :          DO ispin = 1, nspins
    2580           20 :             CALL copy_dbcsr_to_fm(force_data%sum_YP_tau(ispin)%matrix, admm_env%work_orb_orb)
    2581              :             CALL parallel_gemm('N', 'N', nao_aux, nao, nao, 1.0_dp, admm_env%A, admm_env%work_orb_orb, &
    2582           20 :                                0.0_dp, admm_env%work_aux_orb)
    2583              :             CALL parallel_gemm('N', 'T', nao_aux, nao_aux, nao, 1.0_dp, admm_env%work_aux_orb, admm_env%A, &
    2584           20 :                                0.0_dp, admm_env%work_aux_aux)
    2585           36 :             CALL copy_fm_to_dbcsr(admm_env%work_aux_aux, ker_tau_admm(ispin)%matrix, keep_sparsity=.TRUE.)
    2586              :          END DO
    2587              : 
    2588           16 :          IF (.NOT. qs_env%admm_env%aux_exch_func == do_admm_aux_exch_func_none) THEN
    2589           36 :             DO ispin = 1, nspins
    2590           20 :                CALL pw_zero(rhoz_r(ispin))
    2591           20 :                CALL pw_zero(rhoz_g(ispin))
    2592              :                CALL calculate_rho_elec(ks_env=qs_env%ks_env, matrix_p=ker_tau_admm(ispin)%matrix, &
    2593              :                                        rho=rhoz_r(ispin), rho_gspace=rhoz_g(ispin), &
    2594           36 :                                        basis_type="AUX_FIT", task_list_external=task_list_aux_fit)
    2595              :             END DO
    2596              : 
    2597           16 :             IF (do_tau_admm) THEN
    2598              :                BLOCK
    2599              :                   TYPE(pw_c1d_gs_type) :: tauz_g
    2600            0 :                   CALL auxbas_pw_pool%create_pw(tauz_g)
    2601            0 :                   DO ispin = 1, nspins
    2602            0 :                      CALL pw_zero(tauz_r(ispin))
    2603              :                      CALL calculate_rho_elec(ks_env=qs_env%ks_env, matrix_p=ker_tau_admm(ispin)%matrix, &
    2604              :                                              rho=tauz_r(ispin), rho_gspace=tauz_g, &
    2605              :                                              basis_type="AUX_FIT", task_list_external=task_list_aux_fit, &
    2606            0 :                                              compute_tau=.TRUE.)
    2607              :                   END DO
    2608            0 :                   CALL auxbas_pw_pool%give_back_pw(tauz_g)
    2609              :                END BLOCK
    2610              :             END IF
    2611              : 
    2612           16 :             xc_section => admm_env%xc_section_aux
    2613           16 :             ALLOCATE (rhoz)
    2614           16 :             CALL qs_rho_create(rhoz)
    2615           16 :             IF (ASSOCIATED(rhoz_r)) THEN
    2616           16 :                CALL qs_rho_set(rhoz, rho_r=rhoz_r, rho_r_valid=.TRUE.)
    2617              :             END IF
    2618           16 :             IF (ASSOCIATED(rhoz_g)) THEN
    2619           16 :                CALL qs_rho_set(rhoz, rho_g=rhoz_g, rho_g_valid=.TRUE.)
    2620              :             END IF
    2621           16 :             IF (ASSOCIATED(tauz_r)) THEN
    2622            0 :                CALL qs_rho_set(rhoz, tau_r=tauz_r, tau_r_valid=.TRUE.)
    2623              :             END IF
    2624              :             !
    2625              :             CALL qs_fxc_create(qs_env, rho_aux_fit, rhoz, rho0_atom_set, xc_section, .FALSE., &
    2626           16 :                                v_xc, v_xc_tau, rho1_atom_set)
    2627              :             !
    2628           16 :             DEALLOCATE (rhoz)
    2629              : 
    2630           36 :             DO ispin = 1, nspins
    2631           20 :                CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
    2632              :                CALL integrate_v_rspace(qs_env=qs_env, &
    2633              :                                        v_rspace=v_xc(ispin), &
    2634              :                                        hmat=work_admm(ispin), &
    2635              :                                        calculate_forces=.FALSE., &
    2636              :                                        basis_type="AUX_FIT", &
    2637           20 :                                        task_list_external=task_list_aux_fit)
    2638           36 :                CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
    2639              :             END DO
    2640           16 :             DEALLOCATE (v_xc)
    2641              : 
    2642           16 :             IF (do_tau_admm) THEN
    2643            0 :                DO ispin = 1, nspins
    2644            0 :                   CALL pw_scale(v_xc_tau(ispin), v_xc_tau(ispin)%pw_grid%dvol)
    2645              :                   CALL integrate_v_rspace(qs_env=qs_env, &
    2646              :                                           v_rspace=v_xc_tau(ispin), &
    2647              :                                           hmat=work_admm(ispin), &
    2648              :                                           calculate_forces=.FALSE., &
    2649              :                                           basis_type="AUX_FIT", &
    2650              :                                           task_list_external=task_list_aux_fit, &
    2651            0 :                                           compute_tau=.TRUE.)
    2652            0 :                   CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
    2653              :                END DO
    2654            0 :                DEALLOCATE (v_xc_tau)
    2655              :             END IF
    2656              :          END IF !admm
    2657              :       END IF
    2658              : 
    2659          112 :       DO ispin = 1, nspins
    2660           62 :          CALL auxbas_pw_pool%give_back_pw(rhoz_r(ispin))
    2661          112 :          CALL auxbas_pw_pool%give_back_pw(rhoz_g(ispin))
    2662              :       END DO
    2663           50 :       DEALLOCATE (rhoz_r, rhoz_g)
    2664              : 
    2665           50 :       IF (do_tau) THEN
    2666           16 :          DO ispin = 1, nspins
    2667           16 :             CALL auxbas_pw_pool%give_back_pw(tauz_r(ispin))
    2668              :          END DO
    2669            8 :          DEALLOCATE (tauz_r)
    2670              :       END IF
    2671              : 
    2672              :       !HFX kernel
    2673           50 :       hfx_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%HF")
    2674           50 :       CALL section_vals_get(hfx_section, explicit=do_hfx)
    2675           50 :       IF (do_hfx) THEN
    2676           32 :          IF (dft_control%do_admm) THEN
    2677           16 :             CALL tddft_hfx_matrix(work_admm, ker_tau_admm, qs_env, .FALSE., .FALSE.)
    2678              : 
    2679              :             !Going back to primary basis
    2680           16 :             CALL dbcsr_create(dbcsr_work, template=dbcsr_p_work(1)%matrix)
    2681           16 :             CALL dbcsr_copy(dbcsr_work, dbcsr_p_work(1)%matrix)
    2682           16 :             CALL dbcsr_set(dbcsr_work, 0.0_dp)
    2683           36 :             DO ispin = 1, nspins
    2684           20 :                CALL copy_dbcsr_to_fm(work_admm(ispin)%matrix, admm_env%work_aux_aux)
    2685              :                CALL parallel_gemm('N', 'N', nao_aux, nao, nao_aux, 1.0_dp, admm_env%work_aux_aux, admm_env%A, &
    2686           20 :                                   0.0_dp, admm_env%work_aux_orb)
    2687              :                CALL parallel_gemm('T', 'N', nao, nao, nao_aux, 1.0_dp, admm_env%A, admm_env%work_aux_orb, &
    2688           20 :                                   0.0_dp, admm_env%work_orb_orb)
    2689           20 :                CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, dbcsr_work, keep_sparsity=.TRUE.)
    2690           36 :                CALL dbcsr_add(dbcsr_p_work(ispin)%matrix, dbcsr_work, 1.0_dp, 1.0_dp)
    2691              :             END DO
    2692           16 :             CALL dbcsr_release(dbcsr_work)
    2693           16 :             CALL dbcsr_deallocate_matrix_set(ker_tau_admm)
    2694              :          ELSE
    2695           16 :             CALL tddft_hfx_matrix(dbcsr_p_work, force_data%sum_YP_tau, qs_env, .FALSE., .FALSE.)
    2696              :          END IF
    2697              :       END IF
    2698              : 
    2699          112 :       DO ispin = 1, nspins
    2700          112 :          CALL dbcsr_add(force_data%sum_O_tau(ispin)%matrix, dbcsr_p_work(ispin)%matrix, 1.0_dp, 1.0_dp)
    2701              :       END DO
    2702              : 
    2703           50 :       CALL dbcsr_deallocate_matrix_set(dbcsr_p_work)
    2704           50 :       CALL dbcsr_deallocate_matrix_set(work_admm)
    2705              : 
    2706           50 :       CALL timestop(handle)
    2707              : 
    2708          250 :    END SUBROUTINE prepare_for_response
    2709              : 
    2710              : ! **************************************************************************************************
    2711              : !> \brief Calculate the force and virial due to the (P|Q) GPW integral derivatives
    2712              : !> \param G_PQ ...
    2713              : !> \param force ...
    2714              : !> \param h_stress ...
    2715              : !> \param use_virial ...
    2716              : !> \param mp2_env ...
    2717              : !> \param qs_env ...
    2718              : ! **************************************************************************************************
    2719           12 :    SUBROUTINE get_2c_gpw_forces(G_PQ, force, h_stress, use_virial, mp2_env, qs_env)
    2720              : 
    2721              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: G_PQ
    2722              :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    2723              :       REAL(dp), DIMENSION(3, 3), INTENT(INOUT)           :: h_stress
    2724              :       LOGICAL, INTENT(IN)                                :: use_virial
    2725              :       TYPE(mp2_type), INTENT(INOUT)                      :: mp2_env
    2726              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2727              : 
    2728              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'get_2c_gpw_forces'
    2729              : 
    2730              :       INTEGER :: atom_a, color, handle, i, i_RI, i_xyz, iatom, igrid_level, ikind, ipgf, iset, j, &
    2731              :          j_RI, jatom, lb_RI, n_RI, natom, ncoa, ncoms, nkind, nproc, nseta, o1, offset, pdims(2), &
    2732              :          sgfa, ub_RI
    2733           24 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, iproc_map, kind_of, &
    2734           12 :                                                             sizes_RI
    2735           24 :       INTEGER, DIMENSION(:), POINTER                     :: col_dist, la_max, la_min, npgfa, nsgfa, &
    2736           12 :                                                             row_dist
    2737           12 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, pgrid
    2738              :       LOGICAL                                            :: found, one_proc_group
    2739              :       REAL(dp)                                           :: cutoff_old, radius, relative_cutoff_old
    2740           12 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: e_cutoff_old, wf_vector
    2741              :       REAL(dp), DIMENSION(3)                             :: force_a, force_b, ra
    2742              :       REAL(dp), DIMENSION(3, 3)                          :: my_virial_a, my_virial_b
    2743           12 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: h_tmp, I_ab, pab, pblock, sphi_a, zeta
    2744           12 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2745              :       TYPE(cell_type), POINTER                           :: cell
    2746              :       TYPE(dbcsr_distribution_type)                      :: dbcsr_dist
    2747              :       TYPE(dbcsr_type)                                   :: tmp_G_PQ
    2748              :       TYPE(dft_control_type), POINTER                    :: dft_control
    2749              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
    2750           12 :          DIMENSION(:), TARGET                            :: basis_set_ri_aux
    2751              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a
    2752           12 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    2753              :       TYPE(mp_para_env_type), POINTER                    :: para_env, para_env_ext
    2754              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    2755           12 :          POINTER                                         :: sab_orb
    2756           12 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2757           48 :       TYPE(pw_c1d_gs_type)                               :: dvg(3), pot_g, rho_g, rho_g_copy
    2758              :       TYPE(pw_env_type), POINTER                         :: pw_env_ext
    2759              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
    2760              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    2761              :       TYPE(pw_r3d_rs_type)                               :: psi_L, rho_r
    2762           12 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2763           12 :       TYPE(realspace_grid_type), DIMENSION(:), POINTER   :: rs_v
    2764              :       TYPE(task_list_type), POINTER                      :: task_list_ext
    2765              : 
    2766           12 :       NULLIFY (sab_orb, task_list_ext, particle_set, qs_kind_set, dft_control, pw_env_ext, auxbas_pw_pool, &
    2767           12 :                poisson_env, atomic_kind_set, para_env, cell, rs_v, mos, basis_set_a)
    2768              : 
    2769           12 :       CALL timeset(routineN, handle)
    2770              : 
    2771              :       CALL get_qs_env(qs_env, dft_control=dft_control, para_env=para_env, sab_orb=sab_orb, &
    2772              :                       natom=natom, nkind=nkind, qs_kind_set=qs_kind_set, particle_set=particle_set, &
    2773           12 :                       mos=mos, cell=cell, atomic_kind_set=atomic_kind_set)
    2774              : 
    2775              :       !The idea is to use GPW to compute the integrals and derivatives. Because the potential needs
    2776              :       !to be calculated for each phi_j (column) of all AO pairs, and because that is expensive, we want
    2777              :       !to minimize the amount of time we do that. Therefore, we work with a special distribution, where
    2778              :       !each column of the resulting DBCSR matrix is mapped to a sub-communicator.
    2779              : 
    2780              :       !Try to get the optimal pdims (we want a grid that is flat: many cols, few rows)
    2781           12 :       IF (para_env%num_pe <= natom) THEN
    2782              :          pdims(1) = 1
    2783              :          pdims(2) = para_env%num_pe
    2784              :       ELSE
    2785            0 :          DO i = natom, 1, -1
    2786            0 :             IF (MODULO(para_env%num_pe, i) == 0) THEN
    2787            0 :                pdims(1) = para_env%num_pe/i
    2788            0 :                pdims(2) = i
    2789            0 :                EXIT
    2790              :             END IF
    2791              :          END DO
    2792              :       END IF
    2793              : 
    2794           48 :       ALLOCATE (row_dist(natom), col_dist(natom))
    2795           48 :       DO iatom = 1, natom
    2796           48 :          row_dist(iatom) = MODULO(iatom, pdims(1))
    2797              :       END DO
    2798           48 :       DO jatom = 1, natom
    2799           48 :          col_dist(jatom) = MODULO(jatom, pdims(2))
    2800              :       END DO
    2801              : 
    2802           48 :       ALLOCATE (pgrid(0:pdims(1) - 1, 0:pdims(2) - 1))
    2803           12 :       nproc = 0
    2804           24 :       DO i = 0, pdims(1) - 1
    2805           48 :          DO j = 0, pdims(2) - 1
    2806           24 :             pgrid(i, j) = nproc
    2807           36 :             nproc = nproc + 1
    2808              :          END DO
    2809              :       END DO
    2810              : 
    2811           12 :       CALL dbcsr_distribution_new(dbcsr_dist, group=para_env%get_handle(), pgrid=pgrid, row_dist=row_dist, col_dist=col_dist)
    2812              : 
    2813              :       !The temporary DBCSR integrals and derivatives matrices in this flat distribution
    2814           12 :       CALL dbcsr_create(tmp_G_PQ, template=G_PQ, matrix_type=dbcsr_type_no_symmetry, dist=dbcsr_dist)
    2815           12 :       CALL dbcsr_complete_redistribute(G_PQ, tmp_G_PQ)
    2816              : 
    2817           84 :       ALLOCATE (basis_set_ri_aux(nkind), sizes_RI(natom))
    2818           12 :       CALL basis_set_list_setup(basis_set_ri_aux, "RI_AUX", qs_kind_set)
    2819           12 :       CALL get_particle_set(particle_set, qs_kind_set, nsgf=sizes_RI, basis=basis_set_ri_aux)
    2820           48 :       n_RI = SUM(sizes_RI)
    2821              : 
    2822           12 :       one_proc_group = mp2_env%mp2_num_proc == 1
    2823           12 :       ALLOCATE (para_env_ext)
    2824           12 :       IF (one_proc_group) THEN
    2825              :          !one subgroup per proc
    2826            4 :          CALL para_env_ext%from_split(para_env, para_env%mepos)
    2827              :       ELSE
    2828              :          !Split the communicator accross the columns of the matrix
    2829            8 :          ncoms = MIN(pdims(2), para_env%num_pe/mp2_env%mp2_num_proc)
    2830           16 :          DO i = 0, pdims(1) - 1
    2831           32 :             DO j = 0, pdims(2) - 1
    2832           24 :                IF (pgrid(i, j) == para_env%mepos) color = MODULO(j + 1, ncoms)
    2833              :             END DO
    2834              :          END DO
    2835            8 :          CALL para_env_ext%from_split(para_env, color)
    2836              :       END IF
    2837              : 
    2838              :       !sab_orb and task_list_ext are essentially dummies
    2839              :       CALL prepare_gpw(qs_env, dft_control, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_ext, pw_env_ext, &
    2840           12 :                        auxbas_pw_pool, poisson_env, task_list_ext, rho_r, rho_g, pot_g, psi_L, sab_orb)
    2841              : 
    2842           12 :       IF (use_virial) THEN
    2843            4 :          CALL auxbas_pw_pool%create_pw(rho_g_copy)
    2844           16 :          DO i_xyz = 1, 3
    2845           16 :             CALL auxbas_pw_pool%create_pw(dvg(i_xyz))
    2846              :          END DO
    2847              :       END IF
    2848              : 
    2849           36 :       ALLOCATE (wf_vector(n_RI))
    2850              : 
    2851           12 :       CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of, atom_of_kind=atom_of_kind)
    2852              : 
    2853           36 :       ALLOCATE (iproc_map(natom))
    2854              : 
    2855              :       !Loop over the atomic blocks
    2856           48 :       DO jatom = 1, natom
    2857              : 
    2858              :          !Only calculate if on the correct sub-communicator/proc
    2859           36 :          IF (one_proc_group) THEN
    2860           12 :             iproc_map = 0
    2861           48 :             DO iatom = 1, natom
    2862           48 :                IF (pgrid(row_dist(iatom), col_dist(jatom)) == para_env%mepos) iproc_map(iatom) = 1
    2863              :             END DO
    2864           30 :             IF (.NOT. ANY(iproc_map == 1)) CYCLE
    2865              :          ELSE
    2866           24 :             IF (.NOT. MODULO(col_dist(jatom) + 1, ncoms) == color) CYCLE
    2867              :          END IF
    2868              : 
    2869           60 :          lb_RI = SUM(sizes_RI(1:jatom - 1))
    2870           30 :          ub_RI = lb_RI + sizes_RI(jatom)
    2871          872 :          DO j_RI = lb_RI + 1, ub_RI
    2872              : 
    2873          830 :             wf_vector = 0.0_dp
    2874          830 :             wf_vector(j_RI) = 1.0_dp
    2875              : 
    2876              :             CALL collocate_function(wf_vector, psi_L, rho_g, atomic_kind_set, qs_kind_set, cell, &
    2877              :                                     particle_set, pw_env_ext, dft_control%qs_control%eps_rho_rspace, &
    2878          830 :                                     basis_type="RI_AUX")
    2879              : 
    2880          830 :             IF (use_virial) THEN
    2881          166 :                CALL calc_potential_gpw(rho_r, rho_g, poisson_env, pot_g, mp2_env%potential_parameter, dvg)
    2882              : 
    2883          166 :                wf_vector = 0.0_dp
    2884          664 :                DO iatom = 1, natom
    2885              :                   !only compute if i,j atom pair on correct proc
    2886          498 :                   IF (one_proc_group) THEN
    2887          498 :                      IF (.NOT. iproc_map(iatom) == 1) CYCLE
    2888              :                   END IF
    2889              : 
    2890          498 :                   CALL dbcsr_get_block_p(tmp_G_PQ, iatom, jatom, pblock, found)
    2891          498 :                   IF (.NOT. found) CYCLE
    2892              : 
    2893          996 :                   i_RI = SUM(sizes_RI(1:iatom - 1))
    2894        14940 :                   wf_vector(i_RI + 1:i_RI + sizes_RI(iatom)) = pblock(:, j_RI - lb_RI)
    2895              :                END DO
    2896              : 
    2897          166 :                CALL pw_copy(rho_g, rho_g_copy)
    2898              :                CALL collocate_function(wf_vector, psi_L, rho_g, atomic_kind_set, qs_kind_set, cell, &
    2899              :                                        particle_set, pw_env_ext, dft_control%qs_control%eps_rho_rspace, &
    2900          166 :                                        basis_type="RI_AUX")
    2901              : 
    2902              :                CALL calc_potential_gpw(psi_L, rho_g, poisson_env, pot_g, mp2_env%potential_parameter, &
    2903          166 :                                        no_transfer=.TRUE.)
    2904              :                CALL virial_gpw_potential(rho_g_copy, pot_g, rho_g, dvg, h_stress, &
    2905          166 :                                          mp2_env%potential_parameter, para_env_ext)
    2906              :             ELSE
    2907          664 :                CALL calc_potential_gpw(rho_r, rho_g, poisson_env, pot_g, mp2_env%potential_parameter)
    2908              :             END IF
    2909              : 
    2910          830 :             NULLIFY (rs_v)
    2911          830 :             CALL pw_env_get(pw_env_ext, rs_grids=rs_v)
    2912          830 :             CALL potential_pw2rs(rs_v, rho_r, pw_env_ext)
    2913              : 
    2914         3356 :             DO iatom = 1, natom
    2915              : 
    2916              :                !only compute if i,j atom pair on correct proc
    2917         2490 :                IF (one_proc_group) THEN
    2918          498 :                   IF (.NOT. iproc_map(iatom) == 1) CYCLE
    2919              :                END IF
    2920              : 
    2921         2490 :                force_a(:) = 0.0_dp
    2922         2490 :                force_b(:) = 0.0_dp
    2923         2490 :                IF (use_virial) THEN
    2924          498 :                   my_virial_a = 0.0_dp
    2925          498 :                   my_virial_b = 0.0_dp
    2926              :                END IF
    2927              : 
    2928         2490 :                ikind = kind_of(iatom)
    2929         2490 :                atom_a = atom_of_kind(iatom)
    2930              : 
    2931         2490 :                basis_set_a => basis_set_ri_aux(ikind)%gto_basis_set
    2932         2490 :                first_sgfa => basis_set_a%first_sgf
    2933         2490 :                la_max => basis_set_a%lmax
    2934         2490 :                la_min => basis_set_a%lmin
    2935         2490 :                nseta = basis_set_a%nset
    2936         2490 :                nsgfa => basis_set_a%nsgf_set
    2937         2490 :                sphi_a => basis_set_a%sphi
    2938         2490 :                zeta => basis_set_a%zet
    2939         2490 :                npgfa => basis_set_a%npgf
    2940              : 
    2941         2490 :                ra(:) = pbc(particle_set(iatom)%r, cell)
    2942              : 
    2943         2490 :                CALL dbcsr_get_block_p(tmp_G_PQ, iatom, jatom, pblock, found)
    2944         2490 :                IF (.NOT. found) CYCLE
    2945              : 
    2946              :                offset = 0
    2947        15936 :                DO iset = 1, nseta
    2948        14442 :                   ncoa = npgfa(iset)*ncoset(la_max(iset))
    2949        14442 :                   sgfa = first_sgfa(1, iset)
    2950              : 
    2951       131472 :                   ALLOCATE (h_tmp(ncoa, 1)); h_tmp = 0.0_dp
    2952        99102 :                   ALLOCATE (I_ab(nsgfa(iset), 1)); I_ab = 0.0_dp
    2953       117030 :                   ALLOCATE (pab(ncoa, 1)); pab = 0.0_dp
    2954              : 
    2955        97110 :                   I_ab(1:nsgfa(iset), 1) = 2.0_dp*pblock(offset + 1:offset + nsgfa(iset), j_RI - lb_RI)
    2956              :                   CALL dgemm("N", "N", ncoa, 1, nsgfa(iset), 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
    2957        14442 :                              I_ab(1, 1), nsgfa(iset), 0.0_dp, pab(1, 1), ncoa)
    2958              : 
    2959        28884 :                   igrid_level = gaussian_gridlevel(pw_env_ext%gridlevel_info, MINVAL(zeta(:, iset)))
    2960              : 
    2961              :                   ! The last three parameters are used to check whether a given function is within the own range.
    2962              :                   ! Here, it is always the case, so let's enforce it because mod(0, 1)==0
    2963        14442 :                   IF (map_gaussian_here(rs_v(igrid_level), cell%h_inv, ra, 0, 1, 0)) THEN
    2964        28884 :                      DO ipgf = 1, npgfa(iset)
    2965        14442 :                         o1 = (ipgf - 1)*ncoset(la_max(iset))
    2966        14442 :                         igrid_level = gaussian_gridlevel(pw_env_ext%gridlevel_info, zeta(ipgf, iset))
    2967              : 
    2968              :                         radius = exp_radius_very_extended(la_min=la_min(iset), la_max=la_max(iset), &
    2969              :                                                           lb_min=0, lb_max=0, ra=ra, rb=ra, rp=ra, &
    2970              :                                                           zetp=zeta(ipgf, iset), &
    2971              :                                                           eps=dft_control%qs_control%eps_gvg_rspace, &
    2972        14442 :                                                           prefactor=1.0_dp, cutoff=1.0_dp)
    2973              : 
    2974              :                         CALL integrate_pgf_product( &
    2975              :                            la_max=la_max(iset), zeta=zeta(ipgf, iset), la_min=la_min(iset), &
    2976              :                            lb_max=0, zetb=0.0_dp, lb_min=0, &
    2977              :                            ra=ra, rab=[0.0_dp, 0.0_dp, 0.0_dp], &
    2978              :                            rsgrid=rs_v(igrid_level), &
    2979              :                            hab=h_tmp, pab=pab, &
    2980              :                            o1=o1, &
    2981              :                            o2=0, &
    2982              :                            radius=radius, &
    2983              :                            calculate_forces=.TRUE., &
    2984              :                            force_a=force_a, force_b=force_b, &
    2985        28884 :                            use_virial=use_virial, my_virial_a=my_virial_a, my_virial_b=my_virial_b)
    2986              : 
    2987              :                      END DO
    2988              : 
    2989              :                   END IF
    2990              : 
    2991        14442 :                   offset = offset + nsgfa(iset)
    2992        15936 :                   DEALLOCATE (pab, h_tmp, I_ab)
    2993              :                END DO !iset
    2994              : 
    2995         5976 :                force(ikind)%mp2_non_sep(:, atom_a) = force(ikind)%mp2_non_sep(:, atom_a) + force_a + force_b
    2996        10790 :                IF (use_virial) h_stress = h_stress + my_virial_a + my_virial_b
    2997              : 
    2998              :             END DO !iatom
    2999              :          END DO !j_RI
    3000              :       END DO !jatom
    3001              : 
    3002           12 :       IF (use_virial) THEN
    3003            4 :          CALL auxbas_pw_pool%give_back_pw(rho_g_copy)
    3004           16 :          DO i_xyz = 1, 3
    3005           16 :             CALL auxbas_pw_pool%give_back_pw(dvg(i_xyz))
    3006              :          END DO
    3007              :       END IF
    3008              : 
    3009              :       CALL cleanup_gpw(qs_env, e_cutoff_old, cutoff_old, relative_cutoff_old, para_env_ext, pw_env_ext, &
    3010           12 :                        task_list_ext, auxbas_pw_pool, rho_r, rho_g, pot_g, psi_L)
    3011              : 
    3012           12 :       CALL dbcsr_release(tmp_G_PQ)
    3013           12 :       CALL dbcsr_distribution_release(dbcsr_dist)
    3014           12 :       DEALLOCATE (col_dist, row_dist, pgrid)
    3015              : 
    3016           12 :       CALL mp_para_env_release(para_env_ext)
    3017              : 
    3018           12 :       CALL timestop(handle)
    3019              : 
    3020           36 :    END SUBROUTINE get_2c_gpw_forces
    3021              : 
    3022              : ! **************************************************************************************************
    3023              : !> \brief Calculate the forces due to the (P|Q) MME integral derivatives
    3024              : !> \param G_PQ ...
    3025              : !> \param force ...
    3026              : !> \param mp2_env ...
    3027              : !> \param qs_env ...
    3028              : ! **************************************************************************************************
    3029           16 :    SUBROUTINE get_2c_mme_forces(G_PQ, force, mp2_env, qs_env)
    3030              : 
    3031              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: G_PQ
    3032              :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    3033              :       TYPE(mp2_type), INTENT(INOUT)                      :: mp2_env
    3034              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3035              : 
    3036              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'get_2c_mme_forces'
    3037              : 
    3038              :       INTEGER :: atom_a, atom_b, G_count, handle, i_xyz, iatom, ikind, iset, jatom, jkind, jset, &
    3039              :          natom, nkind, nseta, nsetb, offset_hab_a, offset_hab_b, R_count, sgfa, sgfb
    3040           16 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: atom_of_kind, kind_of
    3041           16 :       INTEGER, DIMENSION(:), POINTER                     :: la_max, la_min, lb_max, lb_min, npgfa, &
    3042           16 :                                                             npgfb, nsgfa, nsgfb
    3043           16 :       INTEGER, DIMENSION(:, :), POINTER                  :: first_sgfa, first_sgfb
    3044              :       LOGICAL                                            :: found
    3045              :       REAL(dp)                                           :: new_force, pref
    3046           16 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: hab
    3047           16 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: hdab
    3048           16 :       REAL(dp), DIMENSION(:, :), POINTER                 :: pblock
    3049              :       REAL(KIND=dp), DIMENSION(3)                        :: ra, rb
    3050           16 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: sphi_a, sphi_b, zeta, zetb
    3051           16 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    3052              :       TYPE(cell_type), POINTER                           :: cell
    3053              :       TYPE(dbcsr_iterator_type)                          :: iter
    3054              :       TYPE(gto_basis_set_p_type), ALLOCATABLE, &
    3055           16 :          DIMENSION(:), TARGET                            :: basis_set_ri_aux
    3056              :       TYPE(gto_basis_set_type), POINTER                  :: basis_set_a, basis_set_b
    3057              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3058           16 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    3059           16 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    3060              : 
    3061           16 :       NULLIFY (qs_kind_set, basis_set_a, basis_set_b, pblock, particle_set, &
    3062           16 :                cell, la_max, la_min, lb_min, npgfa, lb_max, npgfb, nsgfa, &
    3063           16 :                nsgfb, first_sgfa, first_sgfb, sphi_a, sphi_b, zeta, zetb, &
    3064           16 :                atomic_kind_set, para_env)
    3065              : 
    3066           16 :       CALL timeset(routineN, handle)
    3067              : 
    3068              :       CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, nkind=nkind, particle_set=particle_set, &
    3069           16 :                       cell=cell, atomic_kind_set=atomic_kind_set, natom=natom, para_env=para_env)
    3070              : 
    3071           16 :       CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of, atom_of_kind=atom_of_kind)
    3072              : 
    3073           80 :       ALLOCATE (basis_set_ri_aux(nkind))
    3074           16 :       CALL basis_set_list_setup(basis_set_ri_aux, "RI_AUX", qs_kind_set)
    3075              : 
    3076           16 :       G_count = 0; R_count = 0
    3077              : 
    3078           16 :       CALL dbcsr_iterator_start(iter, G_PQ)
    3079          116 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    3080              : 
    3081          100 :          CALL dbcsr_iterator_next_block(iter, row=iatom, column=jatom)
    3082          100 :          CALL dbcsr_get_block_p(G_PQ, iatom, jatom, pblock, found)
    3083          100 :          IF (.NOT. found) CYCLE
    3084          100 :          IF (iatom > jatom) CYCLE
    3085           64 :          pref = 2.0_dp
    3086           64 :          IF (iatom == jatom) pref = 1.0_dp
    3087              : 
    3088           64 :          ikind = kind_of(iatom)
    3089           64 :          jkind = kind_of(jatom)
    3090              : 
    3091           64 :          atom_a = atom_of_kind(iatom)
    3092           64 :          atom_b = atom_of_kind(jatom)
    3093              : 
    3094           64 :          basis_set_a => basis_set_ri_aux(ikind)%gto_basis_set
    3095           64 :          first_sgfa => basis_set_a%first_sgf
    3096           64 :          la_max => basis_set_a%lmax
    3097           64 :          la_min => basis_set_a%lmin
    3098           64 :          nseta = basis_set_a%nset
    3099           64 :          nsgfa => basis_set_a%nsgf_set
    3100           64 :          sphi_a => basis_set_a%sphi
    3101           64 :          zeta => basis_set_a%zet
    3102           64 :          npgfa => basis_set_a%npgf
    3103              : 
    3104           64 :          basis_set_b => basis_set_ri_aux(jkind)%gto_basis_set
    3105           64 :          first_sgfb => basis_set_b%first_sgf
    3106           64 :          lb_max => basis_set_b%lmax
    3107           64 :          lb_min => basis_set_b%lmin
    3108           64 :          nsetb = basis_set_b%nset
    3109           64 :          nsgfb => basis_set_b%nsgf_set
    3110           64 :          sphi_b => basis_set_b%sphi
    3111           64 :          zetb => basis_set_b%zet
    3112           64 :          npgfb => basis_set_b%npgf
    3113              : 
    3114           64 :          ra(:) = pbc(particle_set(iatom)%r, cell)
    3115           64 :          rb(:) = pbc(particle_set(jatom)%r, cell)
    3116              : 
    3117          256 :          ALLOCATE (hab(basis_set_a%nsgf, basis_set_b%nsgf))
    3118          256 :          ALLOCATE (hdab(3, basis_set_a%nsgf, basis_set_b%nsgf))
    3119           64 :          hab(:, :) = 0.0_dp
    3120           64 :          hdab(:, :, :) = 0.0_dp
    3121              : 
    3122           64 :          offset_hab_a = 0
    3123          756 :          DO iset = 1, nseta
    3124          692 :             sgfa = first_sgfa(1, iset)
    3125              : 
    3126          692 :             offset_hab_b = 0
    3127         6340 :             DO jset = 1, nsetb
    3128         5648 :                sgfb = first_sgfb(1, jset)
    3129              : 
    3130              :                CALL integrate_set_2c(mp2_env%eri_mme_param%par, mp2_env%potential_parameter, la_min(iset), &
    3131              :                                      la_max(iset), lb_min(jset), lb_max(jset), npgfa(iset), npgfb(jset), &
    3132              :                                      zeta(:, iset), zetb(:, jset), ra, rb, hab, nsgfa(iset), nsgfb(jset), &
    3133              :                                      offset_hab_a, offset_hab_b, 0, 0, sphi_a, sphi_b, sgfa, sgfb, &
    3134              :                                      nsgfa(iset), nsgfb(jset), do_eri_mme, hdab=hdab, &
    3135         5648 :                                      G_count=G_count, R_count=R_count)
    3136              : 
    3137         6340 :                offset_hab_b = offset_hab_b + nsgfb(jset)
    3138              :             END DO
    3139          756 :             offset_hab_a = offset_hab_a + nsgfa(iset)
    3140              :          END DO
    3141              : 
    3142          256 :          DO i_xyz = 1, 3
    3143       143832 :             new_force = pref*SUM(pblock(:, :)*hdab(i_xyz, :, :))
    3144          192 :             force(ikind)%mp2_non_sep(i_xyz, atom_a) = force(ikind)%mp2_non_sep(i_xyz, atom_a) + new_force
    3145          256 :             force(jkind)%mp2_non_sep(i_xyz, atom_b) = force(jkind)%mp2_non_sep(i_xyz, atom_b) - new_force
    3146              :          END DO
    3147              : 
    3148          216 :          DEALLOCATE (hab, hdab)
    3149              :       END DO
    3150           16 :       CALL dbcsr_iterator_stop(iter)
    3151              : 
    3152           16 :       CALL cp_eri_mme_update_local_counts(mp2_env%eri_mme_param, para_env, G_count_2c=G_count, R_count_2c=R_count)
    3153              : 
    3154           16 :       CALL timestop(handle)
    3155              : 
    3156           48 :    END SUBROUTINE get_2c_mme_forces
    3157              : 
    3158              : ! **************************************************************************************************
    3159              : !> \brief This routines gather all the force updates due to the response density and the trace with F
    3160              : !>        Also update the forces due to the SCF density for XC and exact exchange
    3161              : !> \param p_env the p_env coming from the response calculation
    3162              : !> \param matrix_hz the matrix going into the RHS of the response equation
    3163              : !> \param matrix_p_F the density matrix with which we evaluate Trace[P*F]
    3164              : !> \param matrix_p_F_admm ...
    3165              : !> \param qs_env ...
    3166              : !> \note very much inspired from the response_force routine in response_solver.F, especially for virial
    3167              : ! **************************************************************************************************
    3168           50 :    SUBROUTINE update_im_time_forces(p_env, matrix_hz, matrix_p_F, matrix_p_F_admm, qs_env)
    3169              : 
    3170              :       TYPE(qs_p_env_type), POINTER                       :: p_env
    3171              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_hz, matrix_p_F, matrix_p_F_admm
    3172              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3173              : 
    3174              :       CHARACTER(len=*), PARAMETER :: routineN = 'update_im_time_forces'
    3175              : 
    3176              :       INTEGER                                            :: handle, i, idens, ispin, n_rep_hf, nao, &
    3177              :                                                             nao_aux, nder, nimages, nocc, nspins
    3178              :       LOGICAL                                            :: do_exx, do_hfx, do_tau, do_tau_admm, &
    3179              :                                                             use_virial
    3180              :       REAL(dp)                                           :: dummy_real1, dummy_real2, ehartree, exc, &
    3181              :                                                             focc
    3182              :       REAL(dp), DIMENSION(3, 3)                          :: h_stress, pv_loc
    3183              :       TYPE(admm_type), POINTER                           :: admm_env
    3184           50 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    3185           50 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: current_density, current_density_admm, &
    3186           50 :          current_mat_h, matrix_p_mp2, matrix_p_mp2_admm, matrix_s, matrix_s_aux_fit, matrix_w, &
    3187           50 :          rho_ao, rho_ao_aux, scrm, scrm_admm
    3188           50 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: dbcsr_work_h, dbcsr_work_p, mpa2
    3189              :       TYPE(dbcsr_type)                                   :: dbcsr_work
    3190              :       TYPE(dft_control_type), POINTER                    :: dft_control
    3191           50 :       TYPE(hfx_type), DIMENSION(:, :), POINTER           :: x_data
    3192           50 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    3193              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3194              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
    3195           50 :          POINTER                                         :: sab_orb, sac_ae, sac_ppl, sap_ppnl
    3196           50 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    3197              :       TYPE(pw_c1d_gs_type)                               :: rho_tot_gspace, rhoz_tot_gspace, &
    3198              :                                                             zv_hartree_gspace
    3199           50 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rhoz_g
    3200              :       TYPE(pw_env_type), POINTER                         :: pw_env
    3201              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
    3202              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    3203              :       TYPE(pw_r3d_rs_type)                               :: vh_rspace, vhxc_rspace, zv_hartree_rspace
    3204           50 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rhoz_r, tauz_r, v_xc, v_xc_tau, &
    3205           50 :                                                             vadmm_rspace, vtau_rspace, vxc_rspace
    3206           50 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
    3207           50 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    3208              :       TYPE(qs_rho_type), POINTER                         :: rho, rho_aux_fit, rhoz
    3209           50 :       TYPE(rho_atom_type), DIMENSION(:), POINTER         :: rho0_atom_set, rho1_atom_set
    3210              :       TYPE(section_vals_type), POINTER                   :: hfx_section, xc_section
    3211              :       TYPE(task_list_type), POINTER                      :: task_list_aux_fit
    3212              :       TYPE(virial_type), POINTER                         :: virial
    3213              : 
    3214           50 :       NULLIFY (scrm, rho, dft_control, matrix_p_mp2, matrix_s, &
    3215           50 :                matrix_p_mp2_admm, admm_env, sab_orb, dbcsr_work_p, &
    3216           50 :                dbcsr_work_h, sac_ae, sac_ppl, sap_ppnl, force, virial, &
    3217           50 :                qs_kind_set, atomic_kind_set, particle_set, pw_env, poisson_env, &
    3218           50 :                auxbas_pw_pool, task_list_aux_fit, matrix_s_aux_fit, scrm_admm, &
    3219           50 :                rho_aux_fit, rho_ao_aux, x_data, hfx_section, xc_section, &
    3220           50 :                para_env, rhoz_g, rhoz_r, tauz_r, v_xc, v_xc_tau, vxc_rspace, &
    3221           50 :                vtau_rspace, vadmm_rspace, rho_ao, matrix_w)
    3222           50 :       NULLIFY (rho0_atom_set, rho1_atom_set)
    3223              : 
    3224           50 :       CALL timeset(routineN, handle)
    3225              : 
    3226              :       CALL get_qs_env(qs_env, rho=rho, dft_control=dft_control, matrix_s=matrix_s, admm_env=admm_env, &
    3227              :                       sab_orb=sab_orb, sac_ae=sac_ae, sac_ppl=sac_ppl, sap_ppnl=sap_ppnl, force=force, &
    3228              :                       virial=virial, particle_set=particle_set, qs_kind_set=qs_kind_set, &
    3229           50 :                       atomic_kind_set=atomic_kind_set, x_data=x_data, para_env=para_env)
    3230           50 :       nspins = dft_control%nspins
    3231              : 
    3232           50 :       use_virial = virial%pv_availability .AND. (.NOT. virial%pv_numer)
    3233           50 :       IF (use_virial) virial%pv_calculate = .TRUE.
    3234              : 
    3235              :       !Whether we replace the force/energy of SCF XC with HF in RPA
    3236           50 :       do_exx = .FALSE.
    3237           50 :       IF (qs_env%mp2_env%method == ri_rpa_method_gpw) THEN
    3238           28 :          hfx_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC%WF_CORRELATION%RI_RPA%HF")
    3239           28 :          CALL section_vals_get(hfx_section, explicit=do_exx)
    3240              :       END IF
    3241              : 
    3242              :       !Get the mp2 density matrix which is p_env%p1 + matrix_p_F
    3243           50 :       CALL get_qs_env(qs_env, matrix_p_mp2=matrix_p_mp2, matrix_p_mp2_admm=matrix_p_mp2_admm)
    3244              : 
    3245              :       !The kinetic term (only response density)
    3246           50 :       NULLIFY (scrm)
    3247           50 :       mpa2(1:nspins, 1:1) => matrix_p_mp2(1:nspins)
    3248              :       CALL kinetic_energy_matrix(qs_env, matrix_t=scrm, matrix_p=mpa2, &
    3249              :                                  matrix_name="KINETIC ENERGY MATRIX", &
    3250              :                                  basis_type="ORB", &
    3251           50 :                                  sab_orb=sab_orb, calculate_forces=.TRUE.)
    3252           50 :       CALL dbcsr_deallocate_matrix_set(scrm)
    3253              : 
    3254              :       !The pseudo-potential terms (only reponse density)
    3255           50 :       CALL dbcsr_allocate_matrix_set(scrm, nspins)
    3256          112 :       DO ispin = 1, nspins
    3257           62 :          ALLOCATE (scrm(ispin)%matrix)
    3258           62 :          CALL dbcsr_create(scrm(ispin)%matrix, template=matrix_s(1)%matrix)
    3259           62 :          CALL dbcsr_copy(scrm(ispin)%matrix, matrix_s(1)%matrix)
    3260          112 :          CALL dbcsr_set(scrm(ispin)%matrix, 0.0_dp)
    3261              :       END DO
    3262              : 
    3263           50 :       nder = 1
    3264           50 :       nimages = 1
    3265          424 :       ALLOCATE (dbcsr_work_p(nspins, 1), dbcsr_work_h(nspins, 1))
    3266          112 :       DO ispin = 1, nspins
    3267           62 :          dbcsr_work_p(ispin, 1)%matrix => matrix_p_mp2(ispin)%matrix
    3268          112 :          dbcsr_work_h(ispin, 1)%matrix => scrm(ispin)%matrix
    3269              :       END DO
    3270              : 
    3271           50 :       CALL core_matrices(qs_env, dbcsr_work_h, dbcsr_work_p, .TRUE., nder)
    3272              : 
    3273           50 :       DEALLOCATE (dbcsr_work_p, dbcsr_work_h)
    3274              : 
    3275           50 :       IF (use_virial) THEN
    3276            4 :          h_stress = 0.0_dp
    3277           52 :          virial%pv_xc = 0.0_dp
    3278            4 :          NULLIFY (vxc_rspace, vtau_rspace, vadmm_rspace)
    3279              :          CALL ks_ref_potential(qs_env, vh_rspace, vxc_rspace, vtau_rspace, vadmm_rspace, &
    3280            4 :                                dummy_real1, dummy_real2, h_stress)
    3281           52 :          virial%pv_ehartree = virial%pv_ehartree + h_stress/REAL(para_env%num_pe, dp)
    3282           52 :          virial%pv_virial = virial%pv_virial + h_stress/REAL(para_env%num_pe, dp)
    3283            4 :          IF (.NOT. do_exx) THEN
    3284              :             !if RPA EXX, then do not consider XC virial (replaced by RPA%HF virial)
    3285           52 :             virial%pv_exc = virial%pv_exc - virial%pv_xc
    3286           52 :             virial%pv_virial = virial%pv_virial - virial%pv_xc
    3287              :          END IF
    3288              :       ELSE
    3289           46 :          CALL ks_ref_potential(qs_env, vh_rspace, vxc_rspace, vtau_rspace, vadmm_rspace, dummy_real1, dummy_real2)
    3290              :       END IF
    3291           50 :       do_tau = ASSOCIATED(vtau_rspace)
    3292              : 
    3293              :       !Core forces from the SCF
    3294           50 :       CALL integrate_v_core_rspace(vh_rspace, qs_env)
    3295              : 
    3296              :       !The Hartree-xc potential term, P*dVHxc (mp2 + SCF density x deriv of the SCF potential)
    3297              :       !Get the total density
    3298           50 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
    3299          112 :       DO ispin = 1, nspins
    3300          112 :          CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, 1.0_dp)
    3301              :       END DO
    3302              : 
    3303           50 :       CALL get_qs_env(qs_env, pw_env=pw_env)
    3304              :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
    3305           50 :                       poisson_env=poisson_env)
    3306           50 :       CALL auxbas_pw_pool%create_pw(vhxc_rspace)
    3307              : 
    3308           98 :       IF (use_virial) pv_loc = virial%pv_virial
    3309              : 
    3310           50 :       IF (do_exx) THEN
    3311              :          !Only want response XC contribution, but SCF+response Hartree contribution
    3312           44 :          DO ispin = 1, nspins
    3313              :             !Hartree
    3314           26 :             CALL pw_transfer(vh_rspace, vhxc_rspace)
    3315              :             CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
    3316              :                                     hmat=scrm(ispin), pmat=rho_ao(ispin), &
    3317           26 :                                     qs_env=qs_env, calculate_forces=.TRUE.)
    3318              :             !XC
    3319           26 :             CALL pw_transfer(vxc_rspace(ispin), vhxc_rspace)
    3320              :             CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
    3321              :                                     hmat=scrm(ispin), pmat=matrix_p_mp2(ispin), &
    3322           26 :                                     qs_env=qs_env, calculate_forces=.TRUE.)
    3323           44 :             IF (do_tau) THEN
    3324              :                CALL integrate_v_rspace(v_rspace=vtau_rspace(ispin), &
    3325              :                                        hmat=scrm(ispin), pmat=matrix_p_mp2(ispin), &
    3326            0 :                                        qs_env=qs_env, calculate_forces=.TRUE., compute_tau=.TRUE.)
    3327              :             END IF
    3328              :          END DO
    3329              :       ELSE
    3330           68 :          DO ispin = 1, nspins
    3331           36 :             CALL pw_transfer(vh_rspace, vhxc_rspace)
    3332           36 :             CALL pw_axpy(vxc_rspace(ispin), vhxc_rspace)
    3333              :             CALL integrate_v_rspace(v_rspace=vhxc_rspace, &
    3334              :                                     hmat=scrm(ispin), pmat=rho_ao(ispin), &
    3335           36 :                                     qs_env=qs_env, calculate_forces=.TRUE.)
    3336           68 :             IF (do_tau) THEN
    3337              :                CALL integrate_v_rspace(v_rspace=vtau_rspace(ispin), &
    3338              :                                        hmat=scrm(ispin), pmat=rho_ao(ispin), &
    3339            8 :                                        qs_env=qs_env, calculate_forces=.TRUE., compute_tau=.TRUE.)
    3340              :             END IF
    3341              :          END DO
    3342              :       END IF
    3343           50 :       CALL auxbas_pw_pool%give_back_pw(vhxc_rspace)
    3344              : 
    3345           98 :       IF (use_virial) virial%pv_ehartree = virial%pv_ehartree + (virial%pv_virial - pv_loc)
    3346              : 
    3347              :       !The admm projection contribution (mp2 + SCF densities). If EXX, then only mp2 density
    3348           50 :       IF (dft_control%do_admm) THEN
    3349              :          CALL get_admm_env(admm_env, task_list_aux_fit=task_list_aux_fit, rho_aux_fit=rho_aux_fit, &
    3350           16 :                            matrix_s_aux_fit=matrix_s_aux_fit)
    3351           16 :          CALL qs_rho_get(rho_aux_fit, rho_ao=rho_ao_aux)
    3352           16 :          CALL dbcsr_allocate_matrix_set(scrm_admm, nspins)
    3353           36 :          DO ispin = 1, nspins
    3354           20 :             ALLOCATE (scrm_admm(ispin)%matrix)
    3355           20 :             CALL dbcsr_create(scrm_admm(ispin)%matrix, template=matrix_s_aux_fit(1)%matrix)
    3356           20 :             CALL dbcsr_copy(scrm_admm(ispin)%matrix, matrix_s_aux_fit(1)%matrix)
    3357           36 :             CALL dbcsr_set(scrm_admm(ispin)%matrix, 0.0_dp)
    3358              :          END DO
    3359              : 
    3360           64 :          IF (use_virial) pv_loc = virial%pv_virial
    3361           16 :          IF (.NOT. qs_env%admm_env%aux_exch_func == do_admm_aux_exch_func_none) THEN
    3362           36 :             DO ispin = 1, nspins
    3363           36 :                IF (do_exx) THEN
    3364              :                   CALL integrate_v_rspace(v_rspace=vadmm_rspace(ispin), &
    3365              :                                           hmat=scrm_admm(ispin), pmat=matrix_p_mp2_admm(ispin), &
    3366              :                                           qs_env=qs_env, calculate_forces=.TRUE., &
    3367            8 :                                           basis_type="AUX_FIT", task_list_external=task_list_aux_fit)
    3368              :                ELSE
    3369           12 :                   CALL dbcsr_add(rho_ao_aux(ispin)%matrix, matrix_p_mp2_admm(ispin)%matrix, 1.0_dp, 1.0_dp)
    3370              :                   CALL integrate_v_rspace(v_rspace=vadmm_rspace(ispin), &
    3371              :                                           hmat=scrm_admm(ispin), pmat=rho_ao_aux(ispin), &
    3372              :                                           qs_env=qs_env, calculate_forces=.TRUE., &
    3373           12 :                                           basis_type="AUX_FIT", task_list_external=task_list_aux_fit)
    3374           12 :                   CALL dbcsr_add(rho_ao_aux(ispin)%matrix, matrix_p_mp2_admm(ispin)%matrix, 1.0_dp, -1.0_dp)
    3375              :                END IF
    3376              :             END DO
    3377              :          END IF
    3378           64 :          IF (use_virial) virial%pv_ehartree = virial%pv_ehartree + (virial%pv_virial - pv_loc)
    3379              : 
    3380           16 :          CALL tddft_hfx_matrix(scrm_admm, rho_ao_aux, qs_env, .FALSE., .FALSE.)
    3381              : 
    3382           16 :          IF (do_exx) THEN
    3383            4 :             CALL admm_projection_derivative(qs_env, scrm_admm, matrix_p_mp2)
    3384              :          ELSE
    3385           12 :             CALL admm_projection_derivative(qs_env, scrm_admm, rho_ao)
    3386              :          END IF
    3387              :       END IF
    3388              : 
    3389              :       !The exact-exchange term (mp2 + SCF densities)
    3390           50 :       xc_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC")
    3391           50 :       hfx_section => section_vals_get_subs_vals(xc_section, "HF")
    3392           50 :       CALL section_vals_get(hfx_section, explicit=do_hfx)
    3393              : 
    3394           50 :       IF (do_hfx) THEN
    3395           32 :          CALL section_vals_get(hfx_section, n_repetition=n_rep_hf)
    3396           32 :          CPASSERT(n_rep_hf == 1)
    3397           80 :          IF (use_virial) virial%pv_fock_4c = 0.0_dp
    3398              : 
    3399              :          !In case of EXX, only want to response HFX forces, as the SCF will change according to RI_RPA%HF
    3400           32 :          IF (do_exx) THEN
    3401            8 :             IF (dft_control%do_admm) THEN
    3402            4 :                CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit)
    3403            4 :                CALL qs_rho_get(rho_aux_fit, rho_ao=rho_ao_aux, rho_ao_kp=dbcsr_work_p)
    3404            4 :                IF (x_data(1, 1)%do_hfx_ri) THEN
    3405              : 
    3406              :                   CALL hfx_ri_update_forces(qs_env, x_data(1, 1)%ri_data, nspins, &
    3407              :                                             x_data(1, 1)%general_parameter%fraction, &
    3408              :                                             rho_ao=dbcsr_work_p, rho_ao_resp=matrix_p_mp2_admm, &
    3409            0 :                                             use_virial=use_virial, resp_only=.TRUE.)
    3410              :                ELSE
    3411              :                   CALL derivatives_four_center(qs_env, dbcsr_work_p, matrix_p_mp2_admm, hfx_section, para_env, &
    3412            4 :                                                1, use_virial, resp_only=.TRUE.)
    3413              :                END IF
    3414              :             ELSE
    3415            8 :                DO ispin = 1, nspins
    3416            8 :                   CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, -1.0_dp)
    3417              :                END DO
    3418            4 :                CALL qs_rho_get(rho, rho_ao_kp=dbcsr_work_p)
    3419            4 :                IF (x_data(1, 1)%do_hfx_ri) THEN
    3420              : 
    3421              :                   CALL hfx_ri_update_forces(qs_env, x_data(1, 1)%ri_data, nspins, &
    3422              :                                             x_data(1, 1)%general_parameter%fraction, &
    3423              :                                             rho_ao=dbcsr_work_p, rho_ao_resp=matrix_p_mp2, &
    3424            0 :                                             use_virial=use_virial, resp_only=.TRUE.)
    3425              :                ELSE
    3426              :                   CALL derivatives_four_center(qs_env, dbcsr_work_p, matrix_p_mp2, hfx_section, para_env, &
    3427            4 :                                                1, use_virial, resp_only=.TRUE.)
    3428              :                END IF
    3429            8 :                DO ispin = 1, nspins
    3430            8 :                   CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, 1.0_dp)
    3431              :                END DO
    3432              :             END IF !admm
    3433              : 
    3434              :          ELSE !No Exx
    3435           24 :             IF (dft_control%do_admm) THEN
    3436           12 :                CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit)
    3437           12 :                CALL qs_rho_get(rho_aux_fit, rho_ao=rho_ao_aux, rho_ao_kp=dbcsr_work_p)
    3438           24 :                DO ispin = 1, nspins
    3439           24 :                   CALL dbcsr_add(rho_ao_aux(ispin)%matrix, matrix_p_mp2_admm(ispin)%matrix, 1.0_dp, 1.0_dp)
    3440              :                END DO
    3441           12 :                IF (x_data(1, 1)%do_hfx_ri) THEN
    3442              : 
    3443              :                   CALL hfx_ri_update_forces(qs_env, x_data(1, 1)%ri_data, nspins, &
    3444              :                                             x_data(1, 1)%general_parameter%fraction, &
    3445              :                                             rho_ao=dbcsr_work_p, rho_ao_resp=matrix_p_mp2_admm, &
    3446            0 :                                             use_virial=use_virial, resp_only=.FALSE.)
    3447              :                ELSE
    3448              :                   CALL derivatives_four_center(qs_env, dbcsr_work_p, matrix_p_mp2_admm, hfx_section, para_env, &
    3449           12 :                                                1, use_virial, resp_only=.FALSE.)
    3450              :                END IF
    3451           24 :                DO ispin = 1, nspins
    3452           24 :                   CALL dbcsr_add(rho_ao_aux(ispin)%matrix, matrix_p_mp2_admm(ispin)%matrix, 1.0_dp, -1.0_dp)
    3453              :                END DO
    3454              :             ELSE
    3455           12 :                CALL qs_rho_get(rho, rho_ao_kp=dbcsr_work_p)
    3456           12 :                IF (x_data(1, 1)%do_hfx_ri) THEN
    3457              : 
    3458              :                   CALL hfx_ri_update_forces(qs_env, x_data(1, 1)%ri_data, nspins, &
    3459              :                                             x_data(1, 1)%general_parameter%fraction, &
    3460              :                                             rho_ao=dbcsr_work_p, rho_ao_resp=matrix_p_mp2, &
    3461            0 :                                             use_virial=use_virial, resp_only=.FALSE.)
    3462              :                ELSE
    3463              :                   CALL derivatives_four_center(qs_env, dbcsr_work_p, matrix_p_mp2, hfx_section, para_env, &
    3464           12 :                                                1, use_virial, resp_only=.FALSE.)
    3465              :                END IF
    3466              :             END IF
    3467              :          END IF !do_exx
    3468              : 
    3469           32 :          IF (use_virial) THEN
    3470           52 :             virial%pv_exx = virial%pv_exx - virial%pv_fock_4c
    3471           52 :             virial%pv_virial = virial%pv_virial - virial%pv_fock_4c
    3472              :          END IF
    3473              :       END IF
    3474              : 
    3475              :       !retrieve the SCF density
    3476           50 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
    3477          112 :       DO ispin = 1, nspins
    3478          112 :          CALL dbcsr_add(rho_ao(ispin)%matrix, matrix_p_mp2(ispin)%matrix, 1.0_dp, -1.0_dp)
    3479              :       END DO
    3480              : 
    3481              :       !From here, we need to do everything twice. Once for the response density, and once for the
    3482              :       !density that is used for the trace Tr[P*F]. The reason is that the former is needed for the
    3483              :       !eventual overlap contribution from matrix_wz
    3484              :       !Only with the mp2 density
    3485              : 
    3486          436 :       ALLOCATE (current_density(nspins), current_mat_h(nspins), current_density_admm(nspins))
    3487          150 :       DO idens = 1, 2
    3488          224 :          DO ispin = 1, nspins
    3489          224 :             IF (idens == 1) THEN
    3490           62 :                current_density(ispin)%matrix => matrix_p_F(ispin)%matrix
    3491           62 :                current_mat_h(ispin)%matrix => scrm(ispin)%matrix
    3492           62 :                IF (dft_control%do_admm) current_density_admm(ispin)%matrix => matrix_p_F_admm(ispin)%matrix
    3493              :             ELSE
    3494           62 :                current_density(ispin)%matrix => p_env%p1(ispin)%matrix
    3495           62 :                current_mat_h(ispin)%matrix => matrix_hz(ispin)%matrix
    3496           62 :                IF (dft_control%do_admm) current_density_admm(ispin)%matrix => p_env%p1_admm(ispin)%matrix
    3497              :             END IF
    3498              :          END DO
    3499              : 
    3500              :          !The core-denstiy derivative
    3501          748 :          ALLOCATE (rhoz_r(nspins), rhoz_g(nspins))
    3502          224 :          DO ispin = 1, nspins
    3503          124 :             CALL auxbas_pw_pool%create_pw(rhoz_r(ispin))
    3504          224 :             CALL auxbas_pw_pool%create_pw(rhoz_g(ispin))
    3505              :          END DO
    3506          100 :          CALL auxbas_pw_pool%create_pw(rhoz_tot_gspace)
    3507          100 :          CALL auxbas_pw_pool%create_pw(zv_hartree_rspace)
    3508          100 :          CALL auxbas_pw_pool%create_pw(zv_hartree_gspace)
    3509              : 
    3510          100 :          CALL pw_zero(rhoz_tot_gspace)
    3511          224 :          DO ispin = 1, nspins
    3512              :             CALL calculate_rho_elec(ks_env=qs_env%ks_env, matrix_p=current_density(ispin)%matrix, &
    3513          124 :                                     rho=rhoz_r(ispin), rho_gspace=rhoz_g(ispin))
    3514          224 :             CALL pw_axpy(rhoz_g(ispin), rhoz_tot_gspace)
    3515              :          END DO
    3516              : 
    3517          100 :          IF (use_virial) THEN
    3518              : 
    3519            8 :             CALL get_qs_env(qs_env, rho=rho)
    3520            8 :             CALL auxbas_pw_pool%create_pw(rho_tot_gspace)
    3521              : 
    3522            8 :             CALL calc_rho_tot_gspace(rho_tot_gspace, qs_env, rho)
    3523              : 
    3524            8 :             h_stress(:, :) = 0.0_dp
    3525              :             CALL pw_poisson_solve(poisson_env, &
    3526              :                                   density=rhoz_tot_gspace, &
    3527              :                                   ehartree=ehartree, &
    3528              :                                   vhartree=zv_hartree_gspace, &
    3529              :                                   h_stress=h_stress, &
    3530            8 :                                   aux_density=rho_tot_gspace)
    3531              : 
    3532            8 :             CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
    3533              : 
    3534              :             !Green contribution
    3535          104 :             virial%pv_ehartree = virial%pv_ehartree + 2.0_dp*h_stress/REAL(para_env%num_pe, dp)
    3536          104 :             virial%pv_virial = virial%pv_virial + 2.0_dp*h_stress/REAL(para_env%num_pe, dp)
    3537              : 
    3538              :          ELSE
    3539              :             CALL pw_poisson_solve(poisson_env, rhoz_tot_gspace, ehartree, &
    3540           92 :                                   zv_hartree_gspace)
    3541              :          END IF
    3542              : 
    3543          100 :          CALL pw_transfer(zv_hartree_gspace, zv_hartree_rspace)
    3544          100 :          CALL pw_scale(zv_hartree_rspace, zv_hartree_rspace%pw_grid%dvol)
    3545          100 :          CALL integrate_v_core_rspace(zv_hartree_rspace, qs_env)
    3546              : 
    3547          100 :          IF (do_tau) THEN
    3548              :             BLOCK
    3549              :                TYPE(pw_c1d_gs_type) :: tauz_g
    3550           16 :                CALL auxbas_pw_pool%create_pw(tauz_g)
    3551           48 :                ALLOCATE (tauz_r(nspins))
    3552           32 :                DO ispin = 1, nspins
    3553           16 :                   CALL auxbas_pw_pool%create_pw(tauz_r(ispin))
    3554              : 
    3555              :                   CALL calculate_rho_elec(ks_env=qs_env%ks_env, matrix_p=current_density(ispin)%matrix, &
    3556           32 :                                           rho=tauz_r(ispin), rho_gspace=tauz_g, compute_tau=.TRUE.)
    3557              :                END DO
    3558           16 :                CALL auxbas_pw_pool%give_back_pw(tauz_g)
    3559              :             END BLOCK
    3560              :          END IF
    3561              : 
    3562              :          !Volume contribution to the virial
    3563          100 :          IF (use_virial) THEN
    3564              :             !Volume contribution
    3565              :             exc = 0.0_dp
    3566           16 :             DO ispin = 1, nspins
    3567              :                exc = exc + pw_integral_ab(rhoz_r(ispin), vxc_rspace(ispin))/ &
    3568           16 :                      vxc_rspace(ispin)%pw_grid%dvol
    3569              :             END DO
    3570            8 :             IF (ASSOCIATED(vtau_rspace)) THEN
    3571            0 :                DO ispin = 1, nspins
    3572              :                   exc = exc + pw_integral_ab(tauz_r(ispin), vtau_rspace(ispin))/ &
    3573            0 :                         vtau_rspace(ispin)%pw_grid%dvol
    3574              :                END DO
    3575              :             END IF
    3576           32 :             DO i = 1, 3
    3577           24 :                virial%pv_ehartree(i, i) = virial%pv_ehartree(i, i) - 4.0_dp*ehartree/REAL(para_env%num_pe, dp)
    3578           24 :                virial%pv_exc(i, i) = virial%pv_exc(i, i) - exc/REAL(para_env%num_pe, dp)
    3579              :                virial%pv_virial(i, i) = virial%pv_virial(i, i) - 4.0_dp*ehartree/REAL(para_env%num_pe, dp) &
    3580           32 :                                         - exc/REAL(para_env%num_pe, dp)
    3581              :             END DO
    3582              :          END IF
    3583              : 
    3584              :          !The xc-kernel term.
    3585          100 :          IF (dft_control%do_admm) THEN
    3586           32 :             CALL get_qs_env(qs_env, admm_env=admm_env)
    3587           32 :             xc_section => admm_env%xc_section_primary
    3588              :          ELSE
    3589           68 :             xc_section => section_vals_get_subs_vals(qs_env%input, "DFT%XC")
    3590              :          END IF
    3591              : 
    3592          196 :          IF (use_virial) virial%pv_xc = 0.0_dp
    3593              : 
    3594          100 :          ALLOCATE (rhoz)
    3595          100 :          CALL qs_rho_create(rhoz)
    3596          100 :          IF (ASSOCIATED(rhoz_r)) THEN
    3597          100 :             CALL qs_rho_set(rhoz, rho_r=rhoz_r, rho_r_valid=.TRUE.)
    3598              :          END IF
    3599          100 :          IF (ASSOCIATED(rhoz_g)) THEN
    3600          100 :             CALL qs_rho_set(rhoz, rho_g=rhoz_g, rho_g_valid=.TRUE.)
    3601              :          END IF
    3602          100 :          IF (ASSOCIATED(tauz_r)) THEN
    3603           16 :             CALL qs_rho_set(rhoz, tau_r=tauz_r, tau_r_valid=.TRUE.)
    3604              :          END IF
    3605              :          !
    3606              :          CALL qs_fxc_create(qs_env, rho, rhoz, rho0_atom_set, xc_section, .FALSE., &
    3607              :                             v_xc, v_xc_tau, rho1_atom_set, &
    3608          100 :                             compute_virial=use_virial, virial_xc=virial%pv_xc)
    3609              :          !
    3610          100 :          DEALLOCATE (rhoz)
    3611              : 
    3612          100 :          IF (use_virial) THEN
    3613          104 :             virial%pv_exc = virial%pv_exc + virial%pv_xc
    3614          104 :             virial%pv_virial = virial%pv_virial + virial%pv_xc
    3615              : 
    3616          104 :             pv_loc = virial%pv_virial
    3617              :          END IF
    3618              : 
    3619          100 :          CALL qs_rho_get(rho, rho_ao_kp=dbcsr_work_p)
    3620          224 :          DO ispin = 1, nspins
    3621          124 :             CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
    3622          124 :             CALL pw_axpy(zv_hartree_rspace, v_xc(ispin))
    3623              :             CALL integrate_v_rspace(qs_env=qs_env, &
    3624              :                                     v_rspace=v_xc(ispin), &
    3625              :                                     hmat=current_mat_h(ispin), &
    3626              :                                     pmat=dbcsr_work_p(ispin, 1), &
    3627          124 :                                     calculate_forces=.TRUE.)
    3628          224 :             CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
    3629              :          END DO
    3630          100 :          CALL auxbas_pw_pool%give_back_pw(rhoz_tot_gspace)
    3631          100 :          CALL auxbas_pw_pool%give_back_pw(zv_hartree_rspace)
    3632          100 :          CALL auxbas_pw_pool%give_back_pw(zv_hartree_gspace)
    3633          100 :          DEALLOCATE (v_xc)
    3634              : 
    3635          100 :          IF (do_tau) THEN
    3636           32 :             DO ispin = 1, nspins
    3637           16 :                CALL pw_scale(v_xc_tau(ispin), v_xc_tau(ispin)%pw_grid%dvol)
    3638              :                CALL integrate_v_rspace(qs_env=qs_env, &
    3639              :                                        v_rspace=v_xc_tau(ispin), &
    3640              :                                        hmat=current_mat_h(ispin), &
    3641              :                                        pmat=dbcsr_work_p(ispin, 1), &
    3642              :                                        compute_tau=.TRUE., &
    3643           16 :                                        calculate_forces=.TRUE.)
    3644           32 :                CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
    3645              :             END DO
    3646           16 :             DEALLOCATE (v_xc_tau)
    3647              :          END IF
    3648              : 
    3649          196 :          IF (use_virial) virial%pv_ehartree = virial%pv_ehartree + (virial%pv_virial - pv_loc)
    3650              : 
    3651          100 :          IF (do_hfx) THEN
    3652           64 :             IF (dft_control%do_admm) THEN
    3653           72 :                DO ispin = 1, nspins
    3654           72 :                   CALL dbcsr_set(scrm_admm(ispin)%matrix, 0.0_dp)
    3655              :                END DO
    3656           32 :                CALL qs_rho_get(rho_aux_fit, tau_r_valid=do_tau_admm)
    3657              : 
    3658           32 :                IF (.NOT. admm_env%aux_exch_func == do_admm_aux_exch_func_none) THEN
    3659           32 :                   CALL get_admm_env(admm_env, rho_aux_fit=rho_aux_fit)
    3660           72 :                   DO ispin = 1, nspins
    3661           40 :                      CALL pw_zero(rhoz_r(ispin))
    3662           40 :                      CALL pw_zero(rhoz_g(ispin))
    3663              :                      CALL calculate_rho_elec(ks_env=qs_env%ks_env, matrix_p=current_density_admm(ispin)%matrix, &
    3664              :                                              rho=rhoz_r(ispin), rho_gspace=rhoz_g(ispin), &
    3665           72 :                                              basis_type="AUX_FIT", task_list_external=task_list_aux_fit)
    3666              :                   END DO
    3667              : 
    3668           32 :                   IF (do_tau_admm) THEN
    3669              :                      BLOCK
    3670              :                         TYPE(pw_c1d_gs_type) :: tauz_g
    3671            0 :                         CALL auxbas_pw_pool%create_pw(tauz_g)
    3672            0 :                         DO ispin = 1, nspins
    3673            0 :                            CALL pw_zero(tauz_r(ispin))
    3674              :                            CALL calculate_rho_elec(ks_env=qs_env%ks_env, matrix_p=current_density(ispin)%matrix, &
    3675              :                                                    rho=tauz_r(ispin), rho_gspace=tauz_g, &
    3676              :                                                    basis_type="AUX_FIT", task_list_external=task_list_aux_fit, &
    3677            0 :                                                    compute_tau=.TRUE.)
    3678              :                         END DO
    3679            0 :                         CALL auxbas_pw_pool%give_back_pw(tauz_g)
    3680              :                      END BLOCK
    3681              :                   END IF
    3682              : 
    3683              :                   !Volume contribution to the virial
    3684           32 :                   IF (use_virial) THEN
    3685              :                      exc = 0.0_dp
    3686           16 :                      DO ispin = 1, nspins
    3687              :                         exc = exc + pw_integral_ab(rhoz_r(ispin), vadmm_rspace(ispin))/ &
    3688           16 :                               vadmm_rspace(ispin)%pw_grid%dvol
    3689              :                      END DO
    3690           32 :                      DO i = 1, 3
    3691           24 :                         virial%pv_exc(i, i) = virial%pv_exc(i, i) - exc/REAL(para_env%num_pe, dp)
    3692           32 :                         virial%pv_virial(i, i) = virial%pv_virial(i, i) - exc/REAL(para_env%num_pe, dp)
    3693              :                      END DO
    3694              : 
    3695          104 :                      virial%pv_xc = 0.0_dp
    3696              :                   END IF
    3697              : 
    3698           32 :                   xc_section => admm_env%xc_section_aux
    3699           32 :                   ALLOCATE (rhoz)
    3700           32 :                   CALL qs_rho_create(rhoz)
    3701           32 :                   IF (ASSOCIATED(rhoz_r)) THEN
    3702           32 :                      CALL qs_rho_set(rhoz, rho_r=rhoz_r, rho_r_valid=.TRUE.)
    3703              :                   END IF
    3704           32 :                   IF (ASSOCIATED(rhoz_g)) THEN
    3705           32 :                      CALL qs_rho_set(rhoz, rho_g=rhoz_g, rho_g_valid=.TRUE.)
    3706              :                   END IF
    3707           32 :                   IF (ASSOCIATED(tauz_r)) THEN
    3708            0 :                      CALL qs_rho_set(rhoz, tau_r=tauz_r, tau_r_valid=.TRUE.)
    3709              :                   END IF
    3710              :                   !
    3711              :                   CALL qs_fxc_create(qs_env, rho_aux_fit, rhoz, rho0_atom_set, xc_section, .FALSE., &
    3712              :                                      v_xc, v_xc_tau, rho1_atom_set, &
    3713           32 :                                      compute_virial=use_virial, virial_xc=virial%pv_xc)
    3714              :                   !
    3715           32 :                   DEALLOCATE (rhoz)
    3716              : 
    3717           32 :                   IF (use_virial) THEN
    3718          104 :                      virial%pv_exc = virial%pv_exc + virial%pv_xc
    3719          104 :                      virial%pv_virial = virial%pv_virial + virial%pv_xc
    3720              : 
    3721          104 :                      pv_loc = virial%pv_virial
    3722              :                   END IF
    3723              : 
    3724           32 :                   CALL qs_rho_get(rho_aux_fit, rho_ao_kp=dbcsr_work_p)
    3725           72 :                   DO ispin = 1, nspins
    3726           40 :                      CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
    3727              :                      CALL integrate_v_rspace(qs_env=qs_env, &
    3728              :                                              v_rspace=v_xc(ispin), &
    3729              :                                              hmat=scrm_admm(ispin), &
    3730              :                                              pmat=dbcsr_work_p(ispin, 1), &
    3731              :                                              calculate_forces=.TRUE., &
    3732              :                                              basis_type="AUX_FIT", &
    3733           40 :                                              task_list_external=task_list_aux_fit)
    3734           72 :                      CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
    3735              :                   END DO
    3736           32 :                   DEALLOCATE (v_xc)
    3737              : 
    3738           32 :                   IF (do_tau_admm) THEN
    3739            0 :                      DO ispin = 1, nspins
    3740            0 :                         CALL pw_scale(v_xc_tau(ispin), v_xc_tau(ispin)%pw_grid%dvol)
    3741              :                         CALL integrate_v_rspace(qs_env=qs_env, &
    3742              :                                                 v_rspace=v_xc_tau(ispin), &
    3743              :                                                 hmat=scrm_admm(ispin), &
    3744              :                                                 pmat=dbcsr_work_p(ispin, 1), &
    3745              :                                                 calculate_forces=.TRUE., &
    3746              :                                                 basis_type="AUX_FIT", &
    3747              :                                                 task_list_external=task_list_aux_fit, &
    3748            0 :                                                 compute_tau=.TRUE.)
    3749            0 :                         CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
    3750              :                      END DO
    3751            0 :                      DEALLOCATE (v_xc_tau)
    3752              :                   END IF
    3753              : 
    3754          128 :                   IF (use_virial) virial%pv_ehartree = virial%pv_ehartree + (virial%pv_virial - pv_loc)
    3755              :                END IF
    3756              : 
    3757           32 :                CALL tddft_hfx_matrix(scrm_admm, current_density_admm, qs_env, .FALSE., .FALSE.)
    3758              : 
    3759           32 :                CALL qs_rho_get(rho, rho_ao_kp=dbcsr_work_p)
    3760           32 :                CALL admm_projection_derivative(qs_env, scrm_admm, dbcsr_work_p(:, 1))
    3761              : 
    3762              :                !If response density, need to get matrix_hz contribution
    3763           32 :                CALL dbcsr_create(dbcsr_work, template=matrix_s(1)%matrix)
    3764           32 :                IF (idens == 2) THEN
    3765           16 :                   nao = admm_env%nao_orb
    3766           16 :                   nao_aux = admm_env%nao_aux_fit
    3767           36 :                   DO ispin = 1, nspins
    3768           20 :                      CALL dbcsr_copy(dbcsr_work, matrix_hz(ispin)%matrix)
    3769           20 :                      CALL dbcsr_set(dbcsr_work, 0.0_dp)
    3770              : 
    3771              :                      CALL cp_dbcsr_sm_fm_multiply(scrm_admm(ispin)%matrix, admm_env%A, &
    3772           20 :                                                   admm_env%work_aux_orb, nao)
    3773              :                      CALL parallel_gemm('T', 'N', nao, nao, nao_aux, &
    3774              :                                         1.0_dp, admm_env%A, admm_env%work_aux_orb, 0.0_dp, &
    3775           20 :                                         admm_env%work_orb_orb)
    3776           20 :                      CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, dbcsr_work, keep_sparsity=.TRUE.)
    3777           36 :                      CALL dbcsr_add(matrix_hz(ispin)%matrix, dbcsr_work, 1.0_dp, 1.0_dp)
    3778              :                   END DO
    3779              :                END IF
    3780              : 
    3781           32 :                CALL dbcsr_release(dbcsr_work)
    3782              :             ELSE !no admm
    3783              : 
    3784              :                !Need the contribution to matrix_hz as well
    3785           32 :                IF (idens == 2) THEN
    3786           16 :                   CALL tddft_hfx_matrix(matrix_hz, current_density, qs_env, .FALSE., .FALSE.)
    3787              :                END IF
    3788              :             END IF !admm
    3789              :          END IF !do_hfx
    3790              : 
    3791          224 :          DO ispin = 1, nspins
    3792          124 :             CALL auxbas_pw_pool%give_back_pw(rhoz_r(ispin))
    3793          224 :             CALL auxbas_pw_pool%give_back_pw(rhoz_g(ispin))
    3794              :          END DO
    3795          100 :          DEALLOCATE (rhoz_r, rhoz_g)
    3796              : 
    3797          250 :          IF (do_tau) THEN
    3798           32 :             DO ispin = 1, nspins
    3799           32 :                CALL auxbas_pw_pool%give_back_pw(tauz_r(ispin))
    3800              :             END DO
    3801           16 :             DEALLOCATE (tauz_r)
    3802              :          END IF
    3803              :       END DO !idens
    3804           50 :       CALL dbcsr_deallocate_matrix_set(scrm_admm)
    3805              : 
    3806           50 :       DEALLOCATE (current_density, current_mat_h, current_density_admm)
    3807           50 :       CALL dbcsr_deallocate_matrix_set(scrm)
    3808              : 
    3809              :       !The energy weighted and overlap term. ONLY with the response density
    3810           50 :       focc = 2.0_dp
    3811           50 :       IF (nspins == 2) focc = 1.0_dp
    3812           50 :       CALL get_qs_env(qs_env, mos=mos)
    3813          112 :       DO ispin = 1, nspins
    3814           62 :          CALL get_mo_set(mo_set=mos(ispin), homo=nocc)
    3815              :          CALL calculate_whz_matrix(mos(ispin)%mo_coeff, matrix_hz(ispin)%matrix, &
    3816          112 :                                    p_env%w1(ispin)%matrix, focc, nocc)
    3817              :       END DO
    3818           50 :       IF (nspins == 2) CALL dbcsr_add(p_env%w1(1)%matrix, p_env%w1(2)%matrix, 1.0_dp, 1.0_dp)
    3819              : 
    3820              :       !Add to it the SCF W matrix, except if EXX (because taken care of by HF response)
    3821           50 :       IF (.NOT. do_exx) THEN
    3822           32 :          CALL compute_matrix_w(qs_env, calc_forces=.TRUE.)
    3823           32 :          CALL get_qs_env(qs_env, matrix_w=matrix_w)
    3824           32 :          CALL dbcsr_add(p_env%w1(1)%matrix, matrix_w(1)%matrix, 1.0_dp, 1.0_dp)
    3825           32 :          IF (nspins == 2) CALL dbcsr_add(p_env%w1(1)%matrix, matrix_w(2)%matrix, 1.0_dp, 1.0_dp)
    3826              :       END IF
    3827              : 
    3828           50 :       NULLIFY (scrm)
    3829              :       CALL build_overlap_matrix(qs_env%ks_env, matrix_s=scrm, &
    3830              :                                 matrix_name="OVERLAP MATRIX", &
    3831              :                                 basis_type_a="ORB", basis_type_b="ORB", &
    3832              :                                 sab_nl=sab_orb, calculate_forces=.TRUE., &
    3833           50 :                                 matrix_p=p_env%w1(1)%matrix)
    3834              : 
    3835           50 :       IF (.NOT. do_exx) THEN
    3836           32 :          CALL dbcsr_add(p_env%w1(1)%matrix, matrix_w(1)%matrix, 1.0_dp, -1.0_dp)
    3837           32 :          IF (nspins == 2) CALL dbcsr_add(p_env%w1(1)%matrix, matrix_w(2)%matrix, 1.0_dp, -1.0_dp)
    3838           68 :          DO ispin = 1, nspins
    3839           68 :             CALL dbcsr_set(matrix_w(ispin)%matrix, 0.0_dp)
    3840              :          END DO
    3841              :       END IF
    3842              : 
    3843           50 :       IF (nspins == 2) CALL dbcsr_add(p_env%w1(1)%matrix, p_env%w1(2)%matrix, 1.0_dp, -1.0_dp)
    3844           50 :       CALL dbcsr_deallocate_matrix_set(scrm)
    3845              : 
    3846           50 :       IF (use_virial) virial%pv_calculate = .FALSE.
    3847              : 
    3848              :       !clean-up
    3849           50 :       CALL auxbas_pw_pool%give_back_pw(vh_rspace)
    3850              : 
    3851          112 :       DO ispin = 1, nspins
    3852           62 :          CALL auxbas_pw_pool%give_back_pw(vxc_rspace(ispin))
    3853           62 :          IF (ASSOCIATED(vtau_rspace)) THEN
    3854            8 :             CALL auxbas_pw_pool%give_back_pw(vtau_rspace(ispin))
    3855              :          END IF
    3856          112 :          IF (ASSOCIATED(vadmm_rspace)) THEN
    3857           20 :             CALL auxbas_pw_pool%give_back_pw(vadmm_rspace(ispin))
    3858              :          END IF
    3859              :       END DO
    3860           50 :       DEALLOCATE (vxc_rspace)
    3861           50 :       IF (ASSOCIATED(vtau_rspace)) DEALLOCATE (vtau_rspace)
    3862           50 :       IF (ASSOCIATED(vadmm_rspace)) DEALLOCATE (vadmm_rspace)
    3863              : 
    3864           50 :       CALL timestop(handle)
    3865              : 
    3866          100 :    END SUBROUTINE update_im_time_forces
    3867              : 
    3868              : ! **************************************************************************************************
    3869              : !> \brief Iteratively builds the matrix Y = sum_k Y_k until convergence, where
    3870              : !>        Y_k = 1/k*2^n (A/2^n) Y_k-1 + 1/k!*2^n * PR(n) * (A/2^n)^(k-1)
    3871              : !>        n is chosen such that the norm of A is < 1 (and e^A converges fast)
    3872              : !>        PR(n) =  e^(A/2^n)*PR(n-1) + PR(n-1)*e^(A/2^n), PR(0) = P*R^T
    3873              : !> \param Y ...
    3874              : !> \param A ...
    3875              : !> \param P ...
    3876              : !> \param R ...
    3877              : !> \param filter_eps ...
    3878              : ! **************************************************************************************************
    3879          340 :    SUBROUTINE build_Y_matrix(Y, A, P, R, filter_eps)
    3880              : 
    3881              :       TYPE(dbcsr_type), INTENT(OUT)                      :: Y
    3882              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: A, P, R
    3883              :       REAL(dp), INTENT(IN)                               :: filter_eps
    3884              : 
    3885              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'build_Y_matrix'
    3886              : 
    3887              :       INTEGER                                            :: handle, k, n
    3888              :       REAL(dp)                                           :: norm_scalar, threshold
    3889              :       TYPE(dbcsr_type)                                   :: A2n, exp_A2n, PRn, work, work2, Yk
    3890              : 
    3891          340 :       CALL timeset(routineN, handle)
    3892              : 
    3893          340 :       threshold = 1.0E-16_dp
    3894              : 
    3895              :       !Find n such that norm(A) < 1 and we insure convergence of the exponential
    3896          340 :       norm_scalar = dbcsr_frobenius_norm(A)
    3897              : 
    3898              :       !checked: result invariant with value of n
    3899          340 :       n = 1
    3900          466 :       DO
    3901          806 :          IF ((norm_scalar/2.0_dp**n) < 1.0_dp) EXIT
    3902          466 :          n = n + 1
    3903              :       END DO
    3904              : 
    3905              :       !Calculate PR(n) recursively
    3906          340 :       CALL dbcsr_create(PRn, template=A, matrix_type=dbcsr_type_no_symmetry)
    3907          340 :       CALL dbcsr_create(work, template=A, matrix_type=dbcsr_type_no_symmetry)
    3908          340 :       CALL dbcsr_multiply('N', 'N', 1.0_dp, P, R, 0.0_dp, work, filter_eps=filter_eps)
    3909          340 :       CALL dbcsr_create(exp_A2n, template=A, matrix_type=dbcsr_type_no_symmetry)
    3910              : 
    3911         1146 :       DO k = 1, n
    3912          806 :          CALL matrix_exponential(exp_A2n, A, 1.0_dp, 0.5_dp**k, threshold)
    3913          806 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, exp_A2n, work, 0.0_dp, PRn, filter_eps=filter_eps)
    3914          806 :          CALL dbcsr_multiply('N', 'N', 1.0_dp, work, exp_A2n, 1.0_dp, PRn, filter_eps=filter_eps)
    3915         1146 :          CALL dbcsr_copy(work, PRn)
    3916              :       END DO
    3917          340 :       CALL dbcsr_release(exp_A2n)
    3918              : 
    3919              :       !Calculate Y iteratively, until convergence
    3920          340 :       CALL dbcsr_create(A2n, template=A, matrix_type=dbcsr_type_no_symmetry)
    3921          340 :       CALL dbcsr_copy(A2n, A)
    3922          340 :       CALL dbcsr_scale(A2n, 0.5_dp**n)
    3923          340 :       CALL dbcsr_create(Y, template=A, matrix_type=dbcsr_type_no_symmetry)
    3924          340 :       CALL dbcsr_create(Yk, template=A, matrix_type=dbcsr_type_no_symmetry)
    3925          340 :       CALL dbcsr_create(work2, template=A, matrix_type=dbcsr_type_no_symmetry)
    3926              : 
    3927              :       !k=1
    3928          340 :       CALL dbcsr_scale(PRn, 0.5_dp**n)
    3929          340 :       CALL dbcsr_copy(work, PRn)
    3930          340 :       CALL dbcsr_copy(work2, PRn)
    3931          340 :       CALL dbcsr_add(Y, PRn, 1.0_dp, 1.0_dp)
    3932              : 
    3933          340 :       k = 1
    3934         1908 :       DO
    3935         2248 :          k = k + 1
    3936         2248 :          CALL dbcsr_multiply('N', 'N', 1.0_dp/REAL(k, dp), A2n, work, 0.0_dp, Yk, filter_eps=filter_eps)
    3937         2248 :          CALL dbcsr_multiply('N', 'N', 1.0_dp/REAL(k, dp), work2, A2n, 0.0_dp, PRn, filter_eps=filter_eps)
    3938              : 
    3939         2248 :          CALL dbcsr_add(Yk, PRn, 1.0_dp, 1.0_dp)
    3940         2248 :          CALL dbcsr_add(Y, Yk, 1.0_dp, 1.0_dp)
    3941              : 
    3942         2248 :          IF (dbcsr_frobenius_norm(Yk) < threshold) EXIT
    3943         1908 :          CALL dbcsr_copy(work, Yk)
    3944         1908 :          CALL dbcsr_copy(work2, PRn)
    3945              :       END DO
    3946              : 
    3947          340 :       CALL dbcsr_release(work)
    3948          340 :       CALL dbcsr_release(work2)
    3949          340 :       CALL dbcsr_release(PRn)
    3950          340 :       CALL dbcsr_release(A2n)
    3951          340 :       CALL dbcsr_release(Yk)
    3952              : 
    3953          340 :       CALL timestop(handle)
    3954              : 
    3955          340 :    END SUBROUTINE build_Y_matrix
    3956              : 
    3957              : ! **************************************************************************************************
    3958              : !> \brief Overwrites the "optimal" Laplace quadrature with that of the first step
    3959              : !> \param tj ...
    3960              : !> \param wj ...
    3961              : !> \param tau_tj ...
    3962              : !> \param tau_wj ...
    3963              : !> \param weights_cos_tf_t_to_w ...
    3964              : !> \param weights_cos_tf_w_to_t ...
    3965              : !> \param do_laplace ...
    3966              : !> \param do_im_time ...
    3967              : !> \param num_integ_points ...
    3968              : !> \param unit_nr ...
    3969              : !> \param qs_env ...
    3970              : ! **************************************************************************************************
    3971          214 :    SUBROUTINE keep_initial_quad(tj, wj, tau_tj, tau_wj, weights_cos_tf_t_to_w, weights_cos_tf_w_to_t, &
    3972              :                                 do_laplace, do_im_time, num_integ_points, unit_nr, qs_env)
    3973              : 
    3974              :       REAL(dp), ALLOCATABLE, DIMENSION(:), INTENT(INOUT) :: tj, wj, tau_tj, tau_wj
    3975              :       REAL(dp), ALLOCATABLE, DIMENSION(:, :), &
    3976              :          INTENT(INOUT)                                   :: weights_cos_tf_t_to_w, &
    3977              :                                                             weights_cos_tf_w_to_t
    3978              :       LOGICAL, INTENT(IN)                                :: do_laplace, do_im_time
    3979              :       INTEGER, INTENT(IN)                                :: num_integ_points, unit_nr
    3980              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3981              : 
    3982              :       INTEGER                                            :: jquad
    3983              : 
    3984          214 :       IF (do_laplace .OR. do_im_time) THEN
    3985          172 :          IF (.NOT. ASSOCIATED(qs_env%mp2_env%ri_rpa_im_time%tau_tj)) THEN
    3986          408 :             ALLOCATE (qs_env%mp2_env%ri_rpa_im_time%tau_tj(num_integ_points))
    3987          272 :             ALLOCATE (qs_env%mp2_env%ri_rpa_im_time%tau_wj(num_integ_points))
    3988         1138 :             qs_env%mp2_env%ri_rpa_im_time%tau_tj(:) = tau_tj(:)
    3989         1138 :             qs_env%mp2_env%ri_rpa_im_time%tau_wj(:) = tau_wj(:)
    3990              :          ELSE
    3991              :             !If weights already stored, we overwrite the new ones
    3992          152 :             tau_tj(:) = qs_env%mp2_env%ri_rpa_im_time%tau_tj(:)
    3993          152 :             tau_wj(:) = qs_env%mp2_env%ri_rpa_im_time%tau_wj(:)
    3994              :          END IF
    3995              :       END IF
    3996          214 :       IF (.NOT. do_laplace) THEN
    3997          150 :          IF (.NOT. ASSOCIATED(qs_env%mp2_env%ri_rpa_im_time%tj)) THEN
    3998          366 :             ALLOCATE (qs_env%mp2_env%ri_rpa_im_time%tj(num_integ_points))
    3999          244 :             ALLOCATE (qs_env%mp2_env%ri_rpa_im_time%wj(num_integ_points))
    4000         1104 :             qs_env%mp2_env%ri_rpa_im_time%tj(:) = tj(:)
    4001         1104 :             qs_env%mp2_env%ri_rpa_im_time%wj(:) = wj(:)
    4002          122 :             IF (do_im_time) THEN
    4003          368 :                ALLOCATE (qs_env%mp2_env%ri_rpa_im_time%weights_cos_tf_t_to_w(num_integ_points, num_integ_points))
    4004          276 :                ALLOCATE (qs_env%mp2_env%ri_rpa_im_time%weights_cos_tf_w_to_t(num_integ_points, num_integ_points))
    4005        13984 :                qs_env%mp2_env%ri_rpa_im_time%weights_cos_tf_t_to_w(:, :) = weights_cos_tf_t_to_w(:, :)
    4006        13984 :                qs_env%mp2_env%ri_rpa_im_time%weights_cos_tf_w_to_t(:, :) = weights_cos_tf_w_to_t(:, :)
    4007              :             END IF
    4008              :          ELSE
    4009          120 :             tj(:) = qs_env%mp2_env%ri_rpa_im_time%tj(:)
    4010          120 :             wj(:) = qs_env%mp2_env%ri_rpa_im_time%wj(:)
    4011           28 :             IF (do_im_time) THEN
    4012          184 :                weights_cos_tf_t_to_w(:, :) = qs_env%mp2_env%ri_rpa_im_time%weights_cos_tf_t_to_w(:, :)
    4013          184 :                weights_cos_tf_w_to_t(:, :) = qs_env%mp2_env%ri_rpa_im_time%weights_cos_tf_w_to_t(:, :)
    4014              :             END IF
    4015              :          END IF
    4016              :       END IF
    4017          214 :       IF (unit_nr > 0) THEN
    4018              :          !Printing order same as in mp2_grids.F for consistency
    4019          107 :          IF (ASSOCIATED(qs_env%mp2_env%ri_rpa_im_time%tj) .AND. (.NOT. do_laplace)) THEN
    4020              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
    4021           75 :                "MINIMAX_INFO| Number of integration points:", num_integ_points
    4022              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T54,A,T72,A)") &
    4023           75 :                "MINIMAX_INFO| Minimax params (freq grid, scaled):", "Weights", "Abscissas"
    4024          612 :             DO jquad = 1, num_integ_points
    4025          612 :                WRITE (UNIT=unit_nr, FMT="(T41,F20.10,F20.10)") wj(jquad), tj(jquad)
    4026              :             END DO
    4027           75 :             CALL m_flush(unit_nr)
    4028              :          END IF
    4029          107 :          IF (ASSOCIATED(qs_env%mp2_env%ri_rpa_im_time%tau_tj)) THEN
    4030              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T75,i6)") &
    4031           86 :                "MINIMAX_INFO| Number of integration points:", num_integ_points
    4032              :             WRITE (UNIT=unit_nr, FMT="(T3,A,T54,A,T72,A)") &
    4033           86 :                "MINIMAX_INFO| Minimax params (time grid, scaled):", "Weights", "Abscissas"
    4034          645 :             DO jquad = 1, num_integ_points
    4035          645 :                WRITE (UNIT=unit_nr, FMT="(T41,F20.10,F20.10)") tau_wj(jquad), tau_tj(jquad)
    4036              :             END DO
    4037           86 :             CALL m_flush(unit_nr)
    4038              :          END IF
    4039              :       END IF
    4040              : 
    4041          214 :    END SUBROUTINE keep_initial_quad
    4042              : 
    4043              : END MODULE rpa_im_time_force_methods
        

Generated by: LCOV version 2.0-1