LCOV - code coverage report
Current view: top level - src - ec_orth_solver.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:32ddf85) Lines: 482 514 93.8 %
Date: 2025-05-17 08:08:58 Functions: 9 9 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief AO-based conjugate-gradient response solver routines
      10             : !>
      11             : !>
      12             : !> \date 09.2019
      13             : !> \author Fabian Belleflamme
      14             : ! **************************************************************************************************
      15             : MODULE ec_orth_solver
      16             :    USE admm_types,                      ONLY: admm_type,&
      17             :                                               get_admm_env
      18             :    USE cp_control_types,                ONLY: dft_control_type
      19             :    USE cp_dbcsr_api,                    ONLY: &
      20             :         dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_desymmetrize, dbcsr_filter, dbcsr_finalize, &
      21             :         dbcsr_get_info, dbcsr_multiply, dbcsr_p_type, dbcsr_release, dbcsr_scale, dbcsr_set, &
      22             :         dbcsr_transposed, dbcsr_type, dbcsr_type_no_symmetry
      23             :    USE cp_dbcsr_contrib,                ONLY: dbcsr_add_on_diag,&
      24             :                                               dbcsr_checksum,&
      25             :                                               dbcsr_dot
      26             :    USE cp_dbcsr_operations,             ONLY: dbcsr_allocate_matrix_set,&
      27             :                                               dbcsr_deallocate_matrix_set
      28             :    USE cp_external_control,             ONLY: external_control
      29             :    USE ec_methods,                      ONLY: create_kernel
      30             :    USE input_constants,                 ONLY: do_admm_aux_exch_func_none,&
      31             :                                               kg_tnadd_embed,&
      32             :                                               kg_tnadd_embed_ri,&
      33             :                                               ls_s_sqrt_ns,&
      34             :                                               ls_s_sqrt_proot,&
      35             :                                               precond_mlp
      36             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      37             :                                               section_vals_type,&
      38             :                                               section_vals_val_get
      39             :    USE iterate_matrix,                  ONLY: matrix_sqrt_Newton_Schulz,&
      40             :                                               matrix_sqrt_proot
      41             :    USE kg_correction,                   ONLY: kg_ekin_subset
      42             :    USE kinds,                           ONLY: dp
      43             :    USE machine,                         ONLY: m_flush,&
      44             :                                               m_walltime
      45             :    USE mathlib,                         ONLY: abnormal_value
      46             :    USE message_passing,                 ONLY: mp_para_env_type
      47             :    USE pw_env_types,                    ONLY: pw_env_get,&
      48             :                                               pw_env_type
      49             :    USE pw_methods,                      ONLY: pw_axpy,&
      50             :                                               pw_scale,&
      51             :                                               pw_transfer,&
      52             :                                               pw_zero
      53             :    USE pw_poisson_methods,              ONLY: pw_poisson_solve
      54             :    USE pw_poisson_types,                ONLY: pw_poisson_type
      55             :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
      56             :                                               pw_pool_type
      57             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      58             :                                               pw_r3d_rs_type
      59             :    USE qs_environment_types,            ONLY: get_qs_env,&
      60             :                                               qs_environment_type
      61             :    USE qs_integrate_potential,          ONLY: integrate_v_rspace
      62             :    USE qs_kpp1_env_types,               ONLY: qs_kpp1_env_type
      63             :    USE qs_linres_kernel,                ONLY: apply_hfx,&
      64             :                                               apply_xc_admm
      65             :    USE qs_linres_types,                 ONLY: linres_control_type
      66             :    USE qs_p_env_methods,                ONLY: p_env_check_i_alloc,&
      67             :                                               p_env_finish_kpp1,&
      68             :                                               p_env_update_rho
      69             :    USE qs_p_env_types,                  ONLY: qs_p_env_type
      70             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      71             :                                               qs_rho_type
      72             :    USE xc,                              ONLY: xc_prep_2nd_deriv
      73             : #include "./base/base_uses.f90"
      74             : 
      75             :    IMPLICIT NONE
      76             : 
      77             :    PRIVATE
      78             : 
      79             :    ! Global parameters
      80             : 
      81             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'ec_orth_solver'
      82             : 
      83             :    ! Public subroutines
      84             : 
      85             :    PUBLIC :: ec_response_ao
      86             : 
      87             : CONTAINS
      88             : 
      89             : ! **************************************************************************************************
      90             : !> \brief      Preconditioning of the AO-based CG linear response solver
      91             : !>             M * z_0 = r_0
      92             : !>             M(X) = [F,B], with B = [X,P]
      93             : !>             for M we need F and P in ortho basis
      94             : !>             Returns z_0, the preconditioned residual in orthonormal basis
      95             : !>
      96             : !>             All matrices are in orthonormal Lowdin basis
      97             : !>
      98             : !> \param qs_env ...
      99             : !> \param matrix_ks Ground-state Kohn-Sham matrix
     100             : !> \param matrix_p  Ground-state Density matrix
     101             : !> \param matrix_rhs Unpreconditioned residual of linear response CG
     102             : !> \param matrix_cg_z Preconditioned residual
     103             : !> \param eps_filter ...
     104             : !> \param iounit ...
     105             : !>
     106             : !> \date    01.2020
     107             : !> \author  Fabian Belleflamme
     108             : ! **************************************************************************************************
     109         572 :    SUBROUTINE preconditioner(qs_env, matrix_ks, matrix_p, matrix_rhs, &
     110             :                              matrix_cg_z, eps_filter, iounit)
     111             : 
     112             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     113             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
     114             :          POINTER                                         :: matrix_ks, matrix_p, matrix_rhs
     115             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     116             :          POINTER                                         :: matrix_cg_z
     117             :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
     118             :       INTEGER, INTENT(IN)                                :: iounit
     119             : 
     120             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'preconditioner'
     121             : 
     122             :       INTEGER                                            :: handle, i, ispin, max_iter, nao, nspins
     123             :       LOGICAL                                            :: converged
     124             :       REAL(KIND=dp)                                      :: norm_res, t1, t2
     125         572 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: alpha, beta, new_norm, norm_cA, norm_rr
     126         572 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_Ax, matrix_b, matrix_cg, &
     127         572 :                                                             matrix_res
     128             :       TYPE(dft_control_type), POINTER                    :: dft_control
     129             :       TYPE(linres_control_type), POINTER                 :: linres_control
     130             : 
     131         572 :       CALL timeset(routineN, handle)
     132             : 
     133         572 :       CPASSERT(ASSOCIATED(qs_env))
     134         572 :       CPASSERT(ASSOCIATED(matrix_ks))
     135         572 :       CPASSERT(ASSOCIATED(matrix_p))
     136         572 :       CPASSERT(ASSOCIATED(matrix_rhs))
     137         572 :       CPASSERT(ASSOCIATED(matrix_cg_z))
     138             : 
     139         572 :       NULLIFY (dft_control, linres_control)
     140             : 
     141         572 :       t1 = m_walltime()
     142             : 
     143             :       CALL get_qs_env(qs_env=qs_env, &
     144             :                       dft_control=dft_control, &
     145         572 :                       linres_control=linres_control)
     146         572 :       nspins = dft_control%nspins
     147         572 :       CALL dbcsr_get_info(matrix_ks(1)%matrix, nfullrows_total=nao)
     148             : 
     149        4004 :       ALLOCATE (alpha(nspins), beta(nspins), new_norm(nspins), norm_cA(nspins), norm_rr(nspins))
     150             : 
     151             :       !----------------------------------------
     152             :       ! Create non-symmetric matrices: Ax, B, cg, res
     153             :       !----------------------------------------
     154             : 
     155         572 :       NULLIFY (matrix_Ax, matrix_b, matrix_cg, matrix_res)
     156         572 :       CALL dbcsr_allocate_matrix_set(matrix_Ax, nspins)
     157         572 :       CALL dbcsr_allocate_matrix_set(matrix_b, nspins)
     158         572 :       CALL dbcsr_allocate_matrix_set(matrix_cg, nspins)
     159         572 :       CALL dbcsr_allocate_matrix_set(matrix_res, nspins)
     160             : 
     161        1144 :       DO ispin = 1, nspins
     162         572 :          ALLOCATE (matrix_Ax(ispin)%matrix)
     163         572 :          ALLOCATE (matrix_b(ispin)%matrix)
     164         572 :          ALLOCATE (matrix_cg(ispin)%matrix)
     165         572 :          ALLOCATE (matrix_res(ispin)%matrix)
     166             :          CALL dbcsr_create(matrix_Ax(ispin)%matrix, name="linop MATRIX", &
     167             :                            template=matrix_ks(1)%matrix, &
     168         572 :                            matrix_type=dbcsr_type_no_symmetry)
     169             :          CALL dbcsr_create(matrix_b(ispin)%matrix, name="MATRIX B", &
     170             :                            template=matrix_ks(1)%matrix, &
     171         572 :                            matrix_type=dbcsr_type_no_symmetry)
     172             :          CALL dbcsr_create(matrix_cg(ispin)%matrix, name="TRIAL MATRIX", &
     173             :                            template=matrix_ks(1)%matrix, &
     174         572 :                            matrix_type=dbcsr_type_no_symmetry)
     175             :          CALL dbcsr_create(matrix_res(ispin)%matrix, name="RESIDUE", &
     176             :                            template=matrix_ks(1)%matrix, &
     177        1144 :                            matrix_type=dbcsr_type_no_symmetry)
     178             :       END DO
     179             : 
     180             :       !----------------------------------------
     181             :       ! Get righ-hand-side operators
     182             :       !----------------------------------------
     183             : 
     184             :       ! Initial guess z_0
     185        1144 :       DO ispin = 1, nspins
     186         572 :          CALL dbcsr_copy(matrix_cg_z(ispin)%matrix, matrix_rhs(ispin)%matrix)
     187             : 
     188             :          ! r_0 = b
     189        1144 :          CALL dbcsr_copy(matrix_res(ispin)%matrix, matrix_rhs(ispin)%matrix)
     190             :       END DO
     191             : 
     192             :       ! Projector on trial matrix
     193             :       ! Projector does not need to be applied here,
     194             :       ! as matrix_rhs already had this done before entering preconditioner
     195             :       !CALL projector(qs_env, matrix_p, matrix_cg_z, eps_filter)
     196             : 
     197             :       ! Mz_0
     198         572 :       CALL hessian_op1(matrix_ks, matrix_p, matrix_cg_z, matrix_b, matrix_Ax, eps_filter)
     199             : 
     200             :       ! r_0 = b - Ax_0
     201        1144 :       DO ispin = 1, nspins
     202        1144 :          CALL dbcsr_add(matrix_res(ispin)%matrix, matrix_Ax(ispin)%matrix, 1.0_dp, -1.0_dp)
     203             :       END DO
     204             : 
     205             :       ! Matrix projector T
     206         572 :       CALL projector(qs_env, matrix_p, matrix_res, eps_filter)
     207             : 
     208        1144 :       DO ispin = 1, nspins
     209             :          ! cg = p_0 = z_0
     210        1144 :          CALL dbcsr_copy(matrix_cg(ispin)%matrix, matrix_res(ispin)%matrix)
     211             :       END DO
     212             : 
     213             :       ! header
     214         572 :       IF (iounit > 0) THEN
     215         286 :          WRITE (iounit, "(/,T10,A)") "Preconditioning of search direction"
     216             :          WRITE (iounit, "(/,T10,A,T25,A,T42,A,T62,A,/,T10,A)") &
     217         286 :             "Iteration", "Stepsize", "Convergence", "Time", &
     218         572 :             REPEAT("-", 58)
     219             :       END IF
     220             : 
     221        1144 :       alpha(:) = 0.0_dp
     222         572 :       max_iter = 200
     223         572 :       converged = .FALSE.
     224         572 :       norm_res = 0.0_dp
     225             : 
     226             :       ! start iteration
     227        3062 :       iteration: DO i = 1, max_iter
     228             : 
     229             :          ! Hessian Ax = [F,B] is updated preconditioner
     230        3062 :          CALL hessian_op1(matrix_ks, matrix_p, matrix_cg, matrix_b, matrix_Ax, eps_filter)
     231             : 
     232             :          ! Matrix projector
     233        3062 :          CALL projector(qs_env, matrix_p, matrix_Ax, eps_filter)
     234             : 
     235        6124 :          DO ispin = 1, nspins
     236             : 
     237             :             ! Tr(r_0 * r_0)
     238        3062 :             CALL dbcsr_dot(matrix_res(ispin)%matrix, matrix_res(ispin)%matrix, norm_rr(ispin))
     239        3062 :             IF (abnormal_value(norm_rr(ispin))) &
     240           0 :                CPABORT("Preconditioner: Tr[r_j*r_j] is an abnormal value (NaN/Inf)")
     241             : 
     242        3062 :             IF (norm_rr(ispin) .LT. 0.0_dp) CPABORT("norm_rr < 0")
     243        3062 :             norm_res = MAX(norm_res, ABS(norm_rr(ispin)/REAL(nao, dp)))
     244             : 
     245             :             ! norm_cA = tr(Ap_j * p_j)
     246        3062 :             CALL dbcsr_dot(matrix_cg(ispin)%matrix, matrix_Ax(ispin)%matrix, norm_cA(ispin))
     247             : 
     248             :             ! Determine step-size
     249        3062 :             IF (norm_cA(ispin) .LT. linres_control%eps) THEN
     250          30 :                alpha(ispin) = 1.0_dp
     251             :             ELSE
     252        3032 :                alpha(ispin) = norm_rr(ispin)/norm_cA(ispin)
     253             :             END IF
     254             : 
     255             :             ! x_j+1 = x_j + alpha*p_j
     256             :             ! save contribution of this iteration
     257        3062 :             CALL dbcsr_add(matrix_cg_z(ispin)%matrix, matrix_cg(ispin)%matrix, 1.0_dp, alpha(ispin))
     258             : 
     259             :             ! r_j+1 = r_j - alpha * Ap_j
     260        6124 :             CALL dbcsr_add(matrix_res(ispin)%matrix, matrix_Ax(ispin)%matrix, 1.0_dp, -alpha(ispin))
     261             : 
     262             :          END DO
     263             : 
     264        3062 :          norm_res = 0.0_dp
     265             : 
     266        6124 :          DO ispin = 1, nspins
     267             :             ! Tr[r_j+1*z_j+1]
     268        3062 :             CALL dbcsr_dot(matrix_res(ispin)%matrix, matrix_res(ispin)%matrix, new_norm(ispin))
     269        3062 :             IF (new_norm(ispin) .LT. 0.0_dp) CPABORT("tr(r_j+1*z_j+1) < 0")
     270        3062 :             IF (abnormal_value(new_norm(ispin))) &
     271           0 :                CPABORT("Preconditioner: Tr[r_j+1*z_j+1] is an abnormal value (NaN/Inf)")
     272        3062 :             norm_res = MAX(norm_res, new_norm(ispin)/REAL(nao, dp))
     273             : 
     274             :             IF (norm_rr(ispin) .LT. linres_control%eps*0.001_dp &
     275        3062 :                 .OR. new_norm(ispin) .LT. linres_control%eps*0.001_dp) THEN
     276          36 :                beta(ispin) = 0.0_dp
     277          36 :                converged = .TRUE.
     278             :             ELSE
     279        3026 :                beta(ispin) = new_norm(ispin)/norm_rr(ispin)
     280             :             END IF
     281             : 
     282             :             ! update new search vector (matrix cg)
     283             :             ! cg_j+1 = z_j+1 + beta*cg_j
     284        3062 :             CALL dbcsr_add(matrix_cg(ispin)%matrix, matrix_res(ispin)%matrix, beta(ispin), 1.0_dp)
     285        3062 :             CALL dbcsr_filter(matrix_cg(ispin)%matrix, eps_filter)
     286             : 
     287        6124 :             norm_rr(ispin) = new_norm(ispin)
     288             :          END DO
     289             : 
     290             :          ! Convergence criteria
     291        3062 :          IF (norm_res .LT. linres_control%eps) THEN
     292         572 :             converged = .TRUE.
     293             :          END IF
     294             : 
     295        3062 :          t2 = m_walltime()
     296             :          IF (i .EQ. 1 .OR. MOD(i, 1) .EQ. 0 .OR. converged) THEN
     297        3062 :             IF (iounit > 0) THEN
     298             :                WRITE (iounit, "(T10,I5,T25,1E8.2,T33,F25.14,T58,F8.2)") &
     299        4593 :                   i, MAXVAL(alpha), norm_res, t2 - t1
     300             :                ! Convergence in scientific notation
     301             :                !WRITE (iounit, "(T10,I5,T25,1E8.2,T42,1E14.8,T58,F8.2)") &
     302             :                !   i, MAXVAL(alpha), norm_res, t2 - t1
     303        1531 :                CALL m_flush(iounit)
     304             :             END IF
     305             :          END IF
     306        3062 :          IF (converged) THEN
     307         572 :             IF (iounit > 0) THEN
     308         286 :                WRITE (iounit, "(/,T10,A,I4,A,/)") "The precon solver converged in ", i, " iterations."
     309         286 :                CALL m_flush(iounit)
     310             :             END IF
     311             :             EXIT iteration
     312             :          END IF
     313             : 
     314             :          ! Max number of iteration reached
     315        2490 :          IF (i == max_iter) THEN
     316           0 :             IF (iounit > 0) THEN
     317             :                WRITE (iounit, "(/,T10,A/)") &
     318           0 :                   "The precon solver didnt converge! Maximum number of iterations reached."
     319           0 :                CALL m_flush(iounit)
     320             :             END IF
     321             :             converged = .FALSE.
     322             :          END IF
     323             : 
     324             :       END DO iteration
     325             : 
     326             :       ! Matrix projector
     327         572 :       CALL projector(qs_env, matrix_p, matrix_cg_z, eps_filter)
     328             : 
     329             :       ! Release matrices
     330         572 :       CALL dbcsr_deallocate_matrix_set(matrix_Ax)
     331         572 :       CALL dbcsr_deallocate_matrix_set(matrix_b)
     332         572 :       CALL dbcsr_deallocate_matrix_set(matrix_res)
     333         572 :       CALL dbcsr_deallocate_matrix_set(matrix_cg)
     334             : 
     335         572 :       DEALLOCATE (alpha, beta, new_norm, norm_cA, norm_rr)
     336             : 
     337         572 :       CALL timestop(handle)
     338             : 
     339        1144 :    END SUBROUTINE preconditioner
     340             : 
     341             : ! **************************************************************************************************
     342             : !> \brief AO-based conjugate gradient linear response solver.
     343             : !>        In goes the right hand side B of the equation AZ=B, and the linear transformation of the
     344             : !>        Hessian matrix A on trial matrices is iteratively solved. Result are
     345             : !>        the response density matrix_pz, and the energy-weighted response density matrix_wz.
     346             : !>
     347             : !> \param qs_env ...
     348             : !> \param p_env ...
     349             : !> \param matrix_hz Right hand-side of linear response equation
     350             : !> \param matrix_pz Response density
     351             : !> \param matrix_wz Energy-weighted response density matrix
     352             : !> \param iounit ...
     353             : !> \param should_stop ...
     354             : !>
     355             : !> \date    01.2020
     356             : !> \author  Fabian Belleflamme
     357             : ! **************************************************************************************************
     358         132 :    SUBROUTINE ec_response_ao(qs_env, p_env, matrix_hz, matrix_pz, matrix_wz, iounit, should_stop)
     359             : 
     360             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     361             :       TYPE(qs_p_env_type), POINTER                       :: p_env
     362             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
     363             :          POINTER                                         :: matrix_hz
     364             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     365             :          POINTER                                         :: matrix_pz, matrix_wz
     366             :       INTEGER, INTENT(IN)                                :: iounit
     367             :       LOGICAL, INTENT(OUT)                               :: should_stop
     368             : 
     369             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ec_response_ao'
     370             : 
     371             :       INTEGER                                            :: handle, i, ispin, max_iter_lanczos, nao, &
     372             :                                                             nspins, s_sqrt_method, s_sqrt_order
     373             :       LOGICAL                                            :: restart
     374             :       REAL(KIND=dp)                                      :: eps_filter, eps_lanczos, focc, &
     375             :                                                             min_shift, norm_res, old_conv, shift, &
     376             :                                                             t1, t2
     377         132 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: alpha, beta, new_norm, norm_cA, norm_rr, &
     378         132 :                                                             tr_rz00
     379         132 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ksmat, matrix_Ax, matrix_cg, matrix_cg_z, &
     380         132 :          matrix_ks, matrix_nsc, matrix_p, matrix_res, matrix_s, matrix_z, matrix_z0, rho_ao
     381             :       TYPE(dbcsr_type)                                   :: matrix_s_sqrt, matrix_s_sqrt_inv, &
     382             :                                                             matrix_tmp
     383             :       TYPE(dft_control_type), POINTER                    :: dft_control
     384             :       TYPE(linres_control_type), POINTER                 :: linres_control
     385             :       TYPE(qs_rho_type), POINTER                         :: rho
     386             :       TYPE(section_vals_type), POINTER                   :: solver_section
     387             : 
     388         132 :       CALL timeset(routineN, handle)
     389             : 
     390         132 :       CPASSERT(ASSOCIATED(qs_env))
     391         132 :       CPASSERT(ASSOCIATED(matrix_hz))
     392         132 :       CPASSERT(ASSOCIATED(matrix_pz))
     393         132 :       CPASSERT(ASSOCIATED(matrix_wz))
     394             : 
     395         132 :       NULLIFY (dft_control, ksmat, matrix_s, linres_control, rho)
     396             : 
     397         132 :       t1 = m_walltime()
     398             : 
     399             :       CALL get_qs_env(qs_env=qs_env, &
     400             :                       dft_control=dft_control, &
     401             :                       linres_control=linres_control, &
     402             :                       matrix_ks=ksmat, &
     403             :                       matrix_s=matrix_s, &
     404         132 :                       rho=rho)
     405         132 :       nspins = dft_control%nspins
     406             : 
     407         132 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
     408             : 
     409         132 :       solver_section => section_vals_get_subs_vals(qs_env%input, "DFT%ENERGY_CORRECTION%RESPONSE_SOLVER")
     410         132 :       CALL section_vals_val_get(solver_section, "S_SQRT_METHOD", i_val=s_sqrt_method)
     411         132 :       CALL section_vals_val_get(solver_section, "S_SQRT_ORDER", i_val=s_sqrt_order)
     412         132 :       CALL section_vals_val_get(solver_section, "EPS_LANCZOS", r_val=eps_lanczos)
     413         132 :       CALL section_vals_val_get(solver_section, "MAX_ITER_LANCZOS", i_val=max_iter_lanczos)
     414             : 
     415         132 :       eps_filter = linres_control%eps_filter
     416             : 
     417         132 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     418             : 
     419         924 :       ALLOCATE (alpha(nspins), beta(nspins), new_norm(nspins), norm_cA(nspins), norm_rr(nspins))
     420         264 :       ALLOCATE (tr_rz00(nspins))
     421             : 
     422             :       ! local matrix P, KS, and NSC
     423             :       ! to bring into orthogonal basis
     424         132 :       NULLIFY (matrix_p, matrix_ks, matrix_nsc)
     425         132 :       CALL dbcsr_allocate_matrix_set(matrix_p, nspins)
     426         132 :       CALL dbcsr_allocate_matrix_set(matrix_ks, nspins)
     427         132 :       CALL dbcsr_allocate_matrix_set(matrix_nsc, nspins)
     428         264 :       DO ispin = 1, nspins
     429         132 :          ALLOCATE (matrix_p(ispin)%matrix)
     430         132 :          ALLOCATE (matrix_ks(ispin)%matrix)
     431         132 :          ALLOCATE (matrix_nsc(ispin)%matrix)
     432             :          CALL dbcsr_create(matrix_p(ispin)%matrix, name="P_IN ORTHO", &
     433             :                            template=ksmat(1)%matrix, &
     434         132 :                            matrix_type=dbcsr_type_no_symmetry)
     435             :          CALL dbcsr_create(matrix_ks(ispin)%matrix, name="KS_IN ORTHO", &
     436             :                            template=ksmat(1)%matrix, &
     437         132 :                            matrix_type=dbcsr_type_no_symmetry)
     438             :          CALL dbcsr_create(matrix_nsc(ispin)%matrix, name="NSC IN ORTHO", &
     439             :                            template=ksmat(1)%matrix, &
     440         132 :                            matrix_type=dbcsr_type_no_symmetry)
     441             : 
     442         132 :          CALL dbcsr_desymmetrize(rho_ao(ispin)%matrix, matrix_p(ispin)%matrix)
     443         132 :          CALL dbcsr_desymmetrize(ksmat(ispin)%matrix, matrix_ks(ispin)%matrix)
     444         264 :          CALL dbcsr_desymmetrize(matrix_hz(ispin)%matrix, matrix_nsc(ispin)%matrix)
     445             :       END DO
     446             : 
     447             :       ! Scale matrix_p by factor 1/2 in closed-shell
     448         132 :       IF (nspins == 1) CALL dbcsr_scale(matrix_p(1)%matrix, 0.5_dp)
     449             : 
     450             :       ! Transform P, KS, and Harris kernel matrix into Orthonormal basis
     451             :       CALL dbcsr_create(matrix_s_sqrt, template=matrix_s(1)%matrix, &
     452         132 :                         matrix_type=dbcsr_type_no_symmetry)
     453             :       CALL dbcsr_create(matrix_s_sqrt_inv, template=matrix_s(1)%matrix, &
     454         132 :                         matrix_type=dbcsr_type_no_symmetry)
     455             : 
     456           0 :       SELECT CASE (s_sqrt_method)
     457             :       CASE (ls_s_sqrt_proot)
     458             :          CALL matrix_sqrt_proot(matrix_s_sqrt, matrix_s_sqrt_inv, &
     459             :                                 matrix_s(1)%matrix, eps_filter, &
     460           0 :                                 s_sqrt_order, eps_lanczos, max_iter_lanczos, symmetrize=.TRUE.)
     461             :       CASE (ls_s_sqrt_ns)
     462             :          CALL matrix_sqrt_Newton_Schulz(matrix_s_sqrt, matrix_s_sqrt_inv, &
     463             :                                         matrix_s(1)%matrix, eps_filter, &
     464         132 :                                         s_sqrt_order, eps_lanczos, max_iter_lanczos)
     465             :       CASE DEFAULT
     466         132 :          CPABORT("Unknown sqrt method.")
     467             :       END SELECT
     468             : 
     469             :       ! Transform into orthonormal Lowdin basis
     470         264 :       DO ispin = 1, nspins
     471         132 :          CALL transform_m_orth(matrix_p(ispin)%matrix, matrix_s_sqrt, eps_filter)
     472         132 :          CALL transform_m_orth(matrix_ks(ispin)%matrix, matrix_s_sqrt_inv, eps_filter)
     473         264 :          CALL transform_m_orth(matrix_nsc(ispin)%matrix, matrix_s_sqrt_inv, eps_filter)
     474             :       END DO
     475             : 
     476             :       !----------------------------------------
     477             :       ! Create non-symmetric work matrices: Ax, cg, res
     478             :       ! Content of Ax, cg, cg_z, res, z0 anti-symmetric
     479             :       ! Content of z symmetric
     480             :       !----------------------------------------
     481             : 
     482         132 :       CALL dbcsr_create(matrix_tmp, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     483             : 
     484         132 :       NULLIFY (matrix_Ax, matrix_cg, matrix_cg_z, matrix_res, matrix_z, matrix_z0)
     485         132 :       CALL dbcsr_allocate_matrix_set(matrix_Ax, nspins)
     486         132 :       CALL dbcsr_allocate_matrix_set(matrix_cg, nspins)
     487         132 :       CALL dbcsr_allocate_matrix_set(matrix_cg_z, nspins)
     488         132 :       CALL dbcsr_allocate_matrix_set(matrix_res, nspins)
     489         132 :       CALL dbcsr_allocate_matrix_set(matrix_z, nspins)
     490         132 :       CALL dbcsr_allocate_matrix_set(matrix_z0, nspins)
     491             : 
     492         264 :       DO ispin = 1, nspins
     493         132 :          ALLOCATE (matrix_Ax(ispin)%matrix)
     494         132 :          ALLOCATE (matrix_cg(ispin)%matrix)
     495         132 :          ALLOCATE (matrix_cg_z(ispin)%matrix)
     496         132 :          ALLOCATE (matrix_res(ispin)%matrix)
     497         132 :          ALLOCATE (matrix_z(ispin)%matrix)
     498         132 :          ALLOCATE (matrix_z0(ispin)%matrix)
     499             :          CALL dbcsr_create(matrix_Ax(ispin)%matrix, name="linop MATRIX", &
     500             :                            template=matrix_s(1)%matrix, &
     501         132 :                            matrix_type=dbcsr_type_no_symmetry)
     502             :          CALL dbcsr_create(matrix_cg(ispin)%matrix, name="TRIAL MATRIX", &
     503             :                            template=matrix_s(1)%matrix, &
     504         132 :                            matrix_type=dbcsr_type_no_symmetry)
     505             :          CALL dbcsr_create(matrix_cg_z(ispin)%matrix, name="MATRIX CG-Z", &
     506             :                            template=matrix_s(1)%matrix, &
     507         132 :                            matrix_type=dbcsr_type_no_symmetry)
     508             :          CALL dbcsr_create(matrix_res(ispin)%matrix, name="RESIDUE", &
     509             :                            template=matrix_s(1)%matrix, &
     510         132 :                            matrix_type=dbcsr_type_no_symmetry)
     511             :          CALL dbcsr_create(matrix_z(ispin)%matrix, name="Z-Matrix", &
     512             :                            template=matrix_s(1)%matrix, &
     513         132 :                            matrix_type=dbcsr_type_no_symmetry)
     514             :          CALL dbcsr_create(matrix_z0(ispin)%matrix, name="p after precondi-Matrix", &
     515             :                            template=matrix_s(1)%matrix, &
     516         264 :                            matrix_type=dbcsr_type_no_symmetry)
     517             :       END DO
     518             : 
     519             :       !----------------------------------------
     520             :       ! Get righ-hand-side operators
     521             :       !----------------------------------------
     522             : 
     523             :       ! Spin factor
     524         132 :       focc = -2.0_dp
     525         132 :       IF (nspins == 1) focc = -4.0_dp
     526             : 
     527             :       ! E^[1]_Harris = -4*G[\delta P]*Pin - Pin*G[\delta P] = -4*[G[\delta P], Pin]
     528         132 :       CALL commutator(matrix_nsc, matrix_p, matrix_res, eps_filter, .FALSE., alpha=focc)
     529             : 
     530             :       ! Initial guess cg_Z
     531         264 :       DO ispin = 1, nspins
     532         264 :          CALL dbcsr_copy(matrix_cg_z(ispin)%matrix, matrix_res(ispin)%matrix)
     533             :       END DO
     534             : 
     535             :       ! Projector on trial matrix
     536         132 :       CALL projector(qs_env, matrix_p, matrix_cg_z, eps_filter)
     537             : 
     538             :       ! Ax0
     539             :       CALL build_hessian_op(qs_env=qs_env, &
     540             :                             p_env=p_env, &
     541             :                             matrix_ks=matrix_ks, &
     542             :                             matrix_p=matrix_p, &   ! p
     543             :                             matrix_s_sqrt_inv=matrix_s_sqrt_inv, &
     544             :                             matrix_cg=matrix_cg_z, & ! cg
     545             :                             matrix_Ax=matrix_Ax, &
     546         132 :                             eps_filter=eps_filter)
     547             : 
     548             :       ! r_0 = b - Ax0
     549         264 :       DO ispin = 1, nspins
     550         264 :          CALL dbcsr_add(matrix_res(ispin)%matrix, matrix_Ax(ispin)%matrix, 1.0_dp, -1.0_dp)
     551             :       END DO
     552             : 
     553             :       ! Matrix projector T
     554         132 :       CALL projector(qs_env, matrix_p, matrix_res, eps_filter)
     555             : 
     556             :       ! Preconditioner
     557         132 :       linres_control%flag = ""
     558         132 :       IF (linres_control%preconditioner_type == precond_mlp) THEN
     559             :          ! M * z_0 = r_0
     560             :          ! Conjugate gradient returns z_0
     561             :          CALL preconditioner(qs_env=qs_env, &
     562             :                              matrix_ks=matrix_ks, &
     563             :                              matrix_p=matrix_p, &
     564             :                              matrix_rhs=matrix_res, &
     565             :                              matrix_cg_z=matrix_z0, &
     566             :                              eps_filter=eps_filter, &
     567         130 :                              iounit=iounit)
     568         130 :          linres_control%flag = "PCG-AO"
     569             :       ELSE
     570             :          ! z_0 = r_0
     571           4 :          DO ispin = 1, nspins
     572           2 :             CALL dbcsr_copy(matrix_z0(ispin)%matrix, matrix_res(ispin)%matrix)
     573           4 :             linres_control%flag = "CG-AO"
     574             :          END DO
     575             :       END IF
     576             : 
     577         132 :       norm_res = 0.0_dp
     578             : 
     579         264 :       DO ispin = 1, nspins
     580             :          ! cg = p_0 = z_0
     581         132 :          CALL dbcsr_copy(matrix_cg(ispin)%matrix, matrix_z0(ispin)%matrix)
     582             : 
     583             :          ! Tr(r_0 * z_0)
     584         132 :          CALL dbcsr_dot(matrix_res(ispin)%matrix, matrix_cg(ispin)%matrix, norm_rr(ispin))
     585             : 
     586         132 :          IF (norm_rr(ispin) .LT. 0.0_dp) CPABORT("norm_rr < 0")
     587         264 :          norm_res = MAX(norm_res, ABS(norm_rr(ispin)/REAL(nao, dp)))
     588             :       END DO
     589             : 
     590             :       ! eigenvalue shifting
     591         132 :       min_shift = 0.0_dp
     592         132 :       old_conv = norm_rr(1)
     593         132 :       shift = MIN(10.0_dp, MAX(min_shift, 0.05_dp*old_conv))
     594         132 :       old_conv = 100.0_dp
     595             : 
     596             :       ! header
     597         132 :       IF (iounit > 0) THEN
     598             :          WRITE (iounit, "(/,T3,A,T16,A,T25,A,T38,A,T52,A,/,T3,A)") &
     599          66 :             "Iteration", "Method", "Stepsize", "Convergence", "Time", &
     600         132 :             REPEAT("-", 80)
     601             :       END IF
     602             : 
     603         264 :       alpha(:) = 0.0_dp
     604         132 :       restart = .FALSE.
     605         132 :       should_stop = .FALSE.
     606         132 :       linres_control%converged = .FALSE.
     607             : 
     608             :       ! start iteration
     609         580 :       iteration: DO i = 1, linres_control%max_iter
     610             : 
     611             :          ! Convergence criteria
     612             :          ! default for eps 10E-6 in MO_linres
     613         534 :          IF (norm_res .LT. linres_control%eps) THEN
     614          86 :             linres_control%converged = .TRUE.
     615             :          END IF
     616             : 
     617         534 :          t2 = m_walltime()
     618             :          IF (i .EQ. 1 .OR. MOD(i, 1) .EQ. 0 .OR. linres_control%converged &
     619             :              .OR. restart .OR. should_stop) THEN
     620         534 :             IF (iounit > 0) THEN
     621             :                WRITE (iounit, "(T5,I5,T18,A3,T28,L1,T38,1E8.2,T48,F16.10,T68,F8.2)") &
     622         801 :                   i, linres_control%flag, restart, MAXVAL(alpha), norm_res, t2 - t1
     623         267 :                CALL m_flush(iounit)
     624             :             END IF
     625             :          END IF
     626         534 :          IF (linres_control%converged) THEN
     627          86 :             IF (iounit > 0) THEN
     628          43 :                WRITE (iounit, "(/,T2,A,I4,A,/)") "The linear solver converged in ", i, " iterations."
     629          43 :                CALL m_flush(iounit)
     630             :             END IF
     631             :             EXIT iteration
     632         448 :          ELSE IF (should_stop) THEN
     633           0 :             IF (iounit > 0) THEN
     634           0 :                WRITE (iounit, "(/,T2,A,I4,A,/)") "The linear solver did NOT converge! External stop"
     635           0 :                CALL m_flush(iounit)
     636             :             END IF
     637             :             EXIT iteration
     638             :          END IF
     639             : 
     640             :          ! Max number of iteration reached
     641         448 :          IF (i == linres_control%max_iter) THEN
     642          46 :             IF (iounit > 0) THEN
     643             :                WRITE (iounit, "(/,T2,A/)") &
     644          23 :                   "The linear solver didnt converge! Maximum number of iterations reached."
     645          23 :                CALL m_flush(iounit)
     646             :             END IF
     647          46 :             linres_control%converged = .FALSE.
     648             :          END IF
     649             : 
     650             :          ! Hessian Ax = [F,B] + [G(B),P]
     651             :          CALL build_hessian_op(qs_env=qs_env, &
     652             :                                p_env=p_env, &
     653             :                                matrix_ks=matrix_ks, &
     654             :                                matrix_p=matrix_p, &   ! p
     655             :                                matrix_s_sqrt_inv=matrix_s_sqrt_inv, &
     656             :                                matrix_cg=matrix_cg, & ! cg
     657             :                                matrix_Ax=matrix_Ax, &
     658         448 :                                eps_filter=eps_filter)
     659             : 
     660             :          ! Matrix projector T
     661         448 :          CALL projector(qs_env, matrix_p, matrix_Ax, eps_filter)
     662             : 
     663         896 :          DO ispin = 1, nspins
     664             : 
     665         448 :             CALL dbcsr_filter(matrix_Ax(ispin)%matrix, eps_filter)
     666             :             ! norm_cA = tr(Ap_j * p_j)
     667         448 :             CALL dbcsr_dot(matrix_cg(ispin)%matrix, matrix_Ax(ispin)%matrix, norm_cA(ispin))
     668             : 
     669         896 :             IF (norm_cA(ispin) .LT. 0.0_dp) THEN
     670             : 
     671             :                ! Recalculate w/o preconditioner
     672           0 :                IF (i > 1) THEN
     673             :                   ! p = -z + beta*p
     674             :                   CALL dbcsr_add(matrix_cg(ispin)%matrix, matrix_z0(ispin)%matrix, &
     675           0 :                                  beta(ispin), -1.0_dp)
     676           0 :                   CALL dbcsr_dot(matrix_res(ispin)%matrix, matrix_res(ispin)%matrix, new_norm(ispin))
     677           0 :                   beta(ispin) = new_norm(ispin)/tr_rz00(ispin)
     678             :                   CALL dbcsr_add(matrix_cg(ispin)%matrix, matrix_res(ispin)%matrix, &
     679           0 :                                  beta(ispin), 1.0_dp)
     680           0 :                   norm_rr(ispin) = new_norm(ispin)
     681             :                ELSE
     682           0 :                   CALL dbcsr_copy(matrix_res(ispin)%matrix, matrix_cg(ispin)%matrix)
     683           0 :                   CALL dbcsr_dot(matrix_res(ispin)%matrix, matrix_res(ispin)%matrix, norm_rr(ispin))
     684             :                END IF
     685             : 
     686             :                CALL build_hessian_op(qs_env=qs_env, &
     687             :                                      p_env=p_env, &
     688             :                                      matrix_ks=matrix_ks, &
     689             :                                      matrix_p=matrix_p, &   ! p
     690             :                                      matrix_s_sqrt_inv=matrix_s_sqrt_inv, &
     691             :                                      matrix_cg=matrix_cg, & ! cg
     692             :                                      matrix_Ax=matrix_Ax, &
     693           0 :                                      eps_filter=eps_filter)
     694             : 
     695             :                ! Matrix projector T
     696           0 :                CALL projector(qs_env, matrix_p, matrix_Ax, eps_filter)
     697             : 
     698           0 :                CALL dbcsr_dot(matrix_cg(ispin)%matrix, matrix_Ax(ispin)%matrix, norm_cA(ispin))
     699             : 
     700           0 :                CPABORT("tr(Ap_j*p_j) < 0")
     701           0 :                IF (abnormal_value(norm_cA(ispin))) &
     702           0 :                   CPABORT("Preconditioner: Tr[Ap_j*p_j] is an abnormal value (NaN/Inf)")
     703             : 
     704             :             END IF
     705             : 
     706             :          END DO
     707             : 
     708         896 :          DO ispin = 1, nspins
     709             :             ! Determine step-size
     710         448 :             IF (norm_cA(ispin) .LT. linres_control%eps) THEN
     711           0 :                alpha(ispin) = 1.0_dp
     712             :             ELSE
     713         448 :                alpha(ispin) = norm_rr(ispin)/norm_cA(ispin)
     714             :             END IF
     715             : 
     716             :             ! x_j+1 = x_j + alpha*p_j
     717             :             ! save response-denisty of this iteration
     718         896 :             CALL dbcsr_add(matrix_cg_z(ispin)%matrix, matrix_cg(ispin)%matrix, 1.0_dp, alpha(ispin))
     719             :          END DO
     720             : 
     721             :          ! need to recompute the residue
     722         448 :          restart = .FALSE.
     723         448 :          IF (MOD(i, linres_control%restart_every) .EQ. 0) THEN
     724             :             !
     725             :             ! r_j+1 = b - A * x_j+1
     726             :             CALL build_hessian_op(qs_env=qs_env, &
     727             :                                   p_env=p_env, &
     728             :                                   matrix_ks=matrix_ks, &
     729             :                                   matrix_p=matrix_p, &
     730             :                                   matrix_s_sqrt_inv=matrix_s_sqrt_inv, &
     731             :                                   matrix_cg=matrix_cg_z, & ! cg
     732             :                                   matrix_Ax=matrix_Ax, &
     733           0 :                                   eps_filter=eps_filter)
     734             :             ! b
     735           0 :             CALL commutator(matrix_nsc, matrix_p, matrix_res, eps_filter, .FALSE., alpha=focc)
     736             : 
     737           0 :             DO ispin = 1, nspins
     738           0 :                CALL dbcsr_add(matrix_res(ispin)%matrix, matrix_Ax(ispin)%matrix, 1.0_dp, -1.0_dp)
     739             :             END DO
     740             : 
     741           0 :             CALL projector(qs_env, matrix_p, matrix_res, eps_filter)
     742             :             !
     743           0 :             restart = .TRUE.
     744             :          ELSE
     745             :             ! proj Ap onto the virtual subspace
     746         448 :             CALL projector(qs_env, matrix_p, matrix_Ax, eps_filter)
     747             :             !
     748             :             ! r_j+1 = r_j - alpha * Ap_j
     749         896 :             DO ispin = 1, nspins
     750         896 :                CALL dbcsr_add(matrix_res(ispin)%matrix, matrix_Ax(ispin)%matrix, 1.0_dp, -alpha(ispin))
     751             :             END DO
     752         448 :             restart = .FALSE.
     753             :          END IF
     754             : 
     755             :          ! Preconditioner
     756         448 :          linres_control%flag = ""
     757         448 :          IF (linres_control%preconditioner_type == precond_mlp) THEN
     758             :             ! M * z_j+1 = r_j+1
     759             :             ! Conjugate gradient returns z_j+1
     760             :             CALL preconditioner(qs_env=qs_env, &
     761             :                                 matrix_ks=matrix_ks, &
     762             :                                 matrix_p=matrix_p, &
     763             :                                 matrix_rhs=matrix_res, &
     764             :                                 matrix_cg_z=matrix_z0, &
     765             :                                 eps_filter=eps_filter, &
     766         442 :                                 iounit=iounit)
     767         442 :             linres_control%flag = "PCG-AO"
     768             :          ELSE
     769          12 :             DO ispin = 1, nspins
     770          12 :                CALL dbcsr_copy(matrix_z0(ispin)%matrix, matrix_res(ispin)%matrix)
     771             :             END DO
     772           6 :             linres_control%flag = "CG-AO"
     773             :          END IF
     774             : 
     775         448 :          norm_res = 0.0_dp
     776             : 
     777         896 :          DO ispin = 1, nspins
     778             :             ! Tr[r_j+1*z_j+1]
     779         448 :             CALL dbcsr_dot(matrix_res(ispin)%matrix, matrix_z0(ispin)%matrix, new_norm(ispin))
     780         448 :             IF (new_norm(ispin) .LT. 0.0_dp) CPABORT("tr(r_j+1*z_j+1) < 0")
     781         448 :             IF (abnormal_value(new_norm(ispin))) &
     782           0 :                CPABORT("Preconditioner: Tr[r_j+1*z_j+1] is an abnormal value (NaN/Inf)")
     783         448 :             norm_res = MAX(norm_res, new_norm(ispin)/REAL(nao, dp))
     784             : 
     785         448 :             IF (norm_rr(ispin) .LT. linres_control%eps .OR. new_norm(ispin) .LT. linres_control%eps) THEN
     786          16 :                beta(ispin) = 0.0_dp
     787          16 :                linres_control%converged = .TRUE.
     788             :             ELSE
     789         432 :                beta(ispin) = new_norm(ispin)/norm_rr(ispin)
     790             :             END IF
     791             : 
     792             :             ! update new search vector (matrix cg)
     793             :             ! Here: cg_j+1 = z_j+1 + beta*cg_j
     794         448 :             CALL dbcsr_add(matrix_cg(ispin)%matrix, matrix_z0(ispin)%matrix, beta(ispin), 1.0_dp)
     795         448 :             CALL dbcsr_filter(matrix_cg(ispin)%matrix, eps_filter)
     796             : 
     797         448 :             tr_rz00(ispin) = norm_rr(ispin)
     798         896 :             norm_rr(ispin) = new_norm(ispin)
     799             :          END DO
     800             : 
     801             :          ! Can we exit the loop?
     802             :          CALL external_control(should_stop, "LS_SOLVER", target_time=qs_env%target_time, &
     803         494 :                                start_time=qs_env%start_time)
     804             : 
     805             :       END DO iteration
     806             : 
     807             :       ! Matrix projector
     808         132 :       CALL projector(qs_env, matrix_p, matrix_cg_z, eps_filter)
     809             : 
     810             :       ! Z = [cg_z,P]
     811         132 :       CALL commutator(matrix_cg_z, matrix_p, matrix_z, eps_filter, .TRUE., alpha=0.5_dp)
     812             : 
     813         264 :       DO ispin = 1, nspins
     814             :          ! Transform Z-matrix back into non-orthogonal basis
     815         132 :          CALL transform_m_orth(matrix_z(ispin)%matrix, matrix_s_sqrt_inv, eps_filter)
     816             : 
     817             :          ! Export Z-Matrix
     818         264 :          CALL dbcsr_copy(matrix_pz(ispin)%matrix, matrix_z(ispin)%matrix, keep_sparsity=.TRUE.)
     819             :       END DO
     820             : 
     821             :       ! Calculate energy-weighted response density matrix
     822             :       ! AO: Wz = 0.5*(Z*KS*P + P*KS*Z)
     823         132 :       CALL ec_wz_matrix(qs_env, matrix_pz, matrix_wz, eps_filter)
     824             : 
     825             :       ! Release matrices
     826         132 :       CALL dbcsr_release(matrix_tmp)
     827             : 
     828         132 :       CALL dbcsr_release(matrix_s_sqrt)
     829         132 :       CALL dbcsr_release(matrix_s_sqrt_inv)
     830             : 
     831         132 :       CALL dbcsr_deallocate_matrix_set(matrix_p)
     832         132 :       CALL dbcsr_deallocate_matrix_set(matrix_ks)
     833         132 :       CALL dbcsr_deallocate_matrix_set(matrix_nsc)
     834         132 :       CALL dbcsr_deallocate_matrix_set(matrix_z)
     835         132 :       CALL dbcsr_deallocate_matrix_set(matrix_Ax)
     836         132 :       CALL dbcsr_deallocate_matrix_set(matrix_res)
     837         132 :       CALL dbcsr_deallocate_matrix_set(matrix_cg)
     838         132 :       CALL dbcsr_deallocate_matrix_set(matrix_cg_z)
     839         132 :       CALL dbcsr_deallocate_matrix_set(matrix_z0)
     840             : 
     841         132 :       DEALLOCATE (alpha, beta, new_norm, norm_cA, norm_rr)
     842         132 :       DEALLOCATE (tr_rz00)
     843             : 
     844         132 :       CALL timestop(handle)
     845             : 
     846         396 :    END SUBROUTINE ec_response_ao
     847             : 
     848             : ! **************************************************************************************************
     849             : !> \brief Compute matrix_wz as needed for the forces
     850             : !>        Wz = 0.5*(Z*KS*P + P*KS*Z) (closed-shell)
     851             : !> \param qs_env ...
     852             : !> \param matrix_z The response density we just calculated
     853             : !> \param matrix_wz The energy weighted response-density matrix
     854             : !> \param eps_filter ...
     855             : !> \par History
     856             : !>       2020.2 created [Fabian Belleflamme]
     857             : !> \author Fabian Belleflamme
     858             : ! **************************************************************************************************
     859         132 :    SUBROUTINE ec_wz_matrix(qs_env, matrix_z, matrix_wz, eps_filter)
     860             : 
     861             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     862             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
     863             :          POINTER                                         :: matrix_z
     864             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     865             :          POINTER                                         :: matrix_wz
     866             :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
     867             : 
     868             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ec_wz_matrix'
     869             : 
     870             :       INTEGER                                            :: handle, ispin, nspins
     871             :       REAL(KIND=dp)                                      :: scaling
     872         132 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_p, matrix_s
     873             :       TYPE(dbcsr_type)                                   :: matrix_tmp, matrix_tmp2
     874             :       TYPE(dft_control_type), POINTER                    :: dft_control
     875             :       TYPE(qs_rho_type), POINTER                         :: rho
     876             : 
     877         132 :       CALL timeset(routineN, handle)
     878             : 
     879         132 :       CPASSERT(ASSOCIATED(qs_env))
     880         132 :       CPASSERT(ASSOCIATED(matrix_z))
     881         132 :       CPASSERT(ASSOCIATED(matrix_wz))
     882             : 
     883             :       CALL get_qs_env(qs_env=qs_env, &
     884             :                       dft_control=dft_control, &
     885             :                       matrix_ks=matrix_ks, &
     886             :                       matrix_s=matrix_s, &
     887         132 :                       rho=rho)
     888         132 :       nspins = dft_control%nspins
     889             : 
     890         132 :       CALL qs_rho_get(rho, rho_ao=matrix_p)
     891             : 
     892             :       ! Init temp matrices
     893             :       CALL dbcsr_create(matrix_tmp, template=matrix_z(1)%matrix, &
     894         132 :                         matrix_type=dbcsr_type_no_symmetry)
     895             :       CALL dbcsr_create(matrix_tmp2, template=matrix_z(1)%matrix, &
     896         132 :                         matrix_type=dbcsr_type_no_symmetry)
     897             : 
     898             :       ! Scale matrix_p by factor 1/2 in closed-shell
     899         132 :       scaling = 1.0_dp
     900         132 :       IF (nspins == 1) scaling = 0.5_dp
     901             : 
     902             :       ! Whz = ZFP + PFZ = Z(FP) + (Z(FP))^T
     903         264 :       DO ispin = 1, nspins
     904             : 
     905             :          ! tmp = FP
     906             :          CALL dbcsr_multiply("N", "N", scaling, matrix_ks(ispin)%matrix, matrix_p(ispin)%matrix, &
     907         132 :                              0.0_dp, matrix_tmp, filter_eps=eps_filter, retain_sparsity=.FALSE.)
     908             : 
     909             :          ! tmp2 = ZFP
     910             :          CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_z(ispin)%matrix, matrix_tmp, &
     911         132 :                              0.0_dp, matrix_tmp2, filter_eps=eps_filter, retain_sparsity=.FALSE.)
     912             : 
     913             :          ! tmp = (ZFP)^T
     914         132 :          CALL dbcsr_transposed(matrix_tmp, matrix_tmp2)
     915             : 
     916             :          ! tmp = ZFP + (ZFP)^T
     917         132 :          CALL dbcsr_add(matrix_tmp, matrix_tmp2, 1.0_dp, 1.0_dp)
     918             : 
     919         132 :          CALL dbcsr_filter(matrix_tmp, eps_filter)
     920             : 
     921             :          ! Whz = ZFP + PFZ
     922         264 :          CALL dbcsr_copy(matrix_wz(ispin)%matrix, matrix_tmp, keep_sparsity=.TRUE.)
     923             : 
     924             :       END DO
     925             : 
     926             :       ! Release matrices
     927         132 :       CALL dbcsr_release(matrix_tmp)
     928         132 :       CALL dbcsr_release(matrix_tmp2)
     929             : 
     930         132 :       CALL timestop(handle)
     931             : 
     932         132 :    END SUBROUTINE ec_wz_matrix
     933             : 
     934             : ! **************************************************************************************************
     935             : !> \brief  Calculate first term of electronic Hessian  M = [F, B]
     936             : !>         acting as liner transformation on trial matrix (matrix_cg)
     937             : !>         with intermediate response density  B = [cg,P] = cg*P - P*cg = cg*P + (cg*P)^T
     938             : !>
     939             : !>         All matrices are in orthonormal basis
     940             : !>
     941             : !> \param matrix_ks Ground-state Kohn-Sham matrix
     942             : !> \param matrix_p  Ground-state Density matrix
     943             : !> \param matrix_cg Trial matrix
     944             : !> \param matrix_b  Intermediate response density
     945             : !> \param matrix_Ax First term of electronic Hessian applied on trial matrix (matrix_cg)
     946             : !>
     947             : !> \param eps_filter ...
     948             : !> \date    12.2019
     949             : !> \author  Fabian Belleflamme
     950             : ! **************************************************************************************************
     951        4214 :    SUBROUTINE hessian_op1(matrix_ks, matrix_p, matrix_cg, matrix_b, matrix_Ax, eps_filter)
     952             : 
     953             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
     954             :          POINTER                                         :: matrix_ks, matrix_p, matrix_cg
     955             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
     956             :          POINTER                                         :: matrix_b, matrix_Ax
     957             :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
     958             : 
     959             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'hessian_op1'
     960             : 
     961             :       INTEGER                                            :: handle
     962             : 
     963        4214 :       CALL timeset(routineN, handle)
     964             : 
     965        4214 :       CPASSERT(ASSOCIATED(matrix_ks))
     966        4214 :       CPASSERT(ASSOCIATED(matrix_p))
     967        4214 :       CPASSERT(ASSOCIATED(matrix_cg))
     968        4214 :       CPASSERT(ASSOCIATED(matrix_b))
     969        4214 :       CPASSERT(ASSOCIATED(matrix_Ax))
     970             : 
     971             :       ! Build intermediate density matrix
     972             :       ! B = [cg, P] = cg*P - P*cg = cg*P + (cg*P)^T
     973        4214 :       CALL commutator(matrix_cg, matrix_p, matrix_b, eps_filter, .TRUE.)
     974             : 
     975             :       ! Build first part of operator
     976             :       ! Ax = [F,[cg,P]] = [F,B]
     977        4214 :       CALL commutator(matrix_ks, matrix_b, matrix_Ax, eps_filter, .FALSE.)
     978             : 
     979        4214 :       CALL timestop(handle)
     980             : 
     981        4214 :    END SUBROUTINE hessian_op1
     982             : 
     983             : ! **************************************************************************************************
     984             : !> \brief  calculate linear transformation of Hessian matrix on a trial matrix matrix_cg
     985             : !>         which is stored in response density B = [cg,P] = cg*P - P*cg = cg*P + (cg*P)^T
     986             : !>         Ax = [F, B] + [G(B), Pin] in orthonormal basis
     987             : !>
     988             : !> \param qs_env ...
     989             : !> \param p_env ...
     990             : !> \param matrix_ks Ground-state Kohn-Sham matrix
     991             : !> \param matrix_p  Ground-state Density matrix
     992             : !> \param matrix_s_sqrt_inv S^(-1/2) needed for transformation to/from orthonormal basis
     993             : !> \param matrix_cg Trial matrix
     994             : !> \param matrix_Ax Electronic Hessian applied on trial matrix (matrix_cg)
     995             : !> \param eps_filter ...
     996             : !>
     997             : !> \date    12.2019
     998             : !> \author  Fabian Belleflamme
     999             : ! **************************************************************************************************
    1000         580 :    SUBROUTINE build_hessian_op(qs_env, p_env, matrix_ks, matrix_p, matrix_s_sqrt_inv, &
    1001             :                                matrix_cg, matrix_Ax, eps_filter)
    1002             : 
    1003             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1004             :       TYPE(qs_p_env_type), POINTER                       :: p_env
    1005             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
    1006             :          POINTER                                         :: matrix_ks, matrix_p
    1007             :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix_s_sqrt_inv
    1008             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
    1009             :          POINTER                                         :: matrix_cg
    1010             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
    1011             :          POINTER                                         :: matrix_Ax
    1012             :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    1013             : 
    1014             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'build_hessian_op'
    1015             : 
    1016             :       INTEGER                                            :: handle, ispin, nspins
    1017             :       REAL(KIND=dp)                                      :: chksum
    1018         580 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_b, rho1_ao
    1019             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1020             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1021             :       TYPE(qs_rho_type), POINTER                         :: rho
    1022             : 
    1023         580 :       CALL timeset(routineN, handle)
    1024             : 
    1025         580 :       CPASSERT(ASSOCIATED(qs_env))
    1026         580 :       CPASSERT(ASSOCIATED(matrix_ks))
    1027         580 :       CPASSERT(ASSOCIATED(matrix_p))
    1028         580 :       CPASSERT(ASSOCIATED(matrix_cg))
    1029         580 :       CPASSERT(ASSOCIATED(matrix_Ax))
    1030             : 
    1031             :       CALL get_qs_env(qs_env=qs_env, &
    1032             :                       dft_control=dft_control, &
    1033             :                       para_env=para_env, &
    1034         580 :                       rho=rho)
    1035         580 :       nspins = dft_control%nspins
    1036             : 
    1037         580 :       NULLIFY (matrix_b)
    1038         580 :       CALL dbcsr_allocate_matrix_set(matrix_b, nspins)
    1039        1160 :       DO ispin = 1, nspins
    1040         580 :          ALLOCATE (matrix_b(ispin)%matrix)
    1041             :          CALL dbcsr_create(matrix_b(ispin)%matrix, name="[X,P] RSP DNSTY", &
    1042             :                            template=matrix_p(1)%matrix, &
    1043        1160 :                            matrix_type=dbcsr_type_no_symmetry)
    1044             :       END DO
    1045             : 
    1046             :       ! Build uncoupled term of Hessian linear transformation
    1047         580 :       CALL hessian_op1(matrix_ks, matrix_p, matrix_cg, matrix_b, matrix_Ax, eps_filter)
    1048             : 
    1049             :       ! Avoid the buildup of noisy blocks
    1050        1160 :       DO ispin = 1, nspins
    1051        1160 :          CALL dbcsr_filter(matrix_b(ispin)%matrix, eps_filter)
    1052             :       END DO
    1053             : 
    1054             :       chksum = 0.0_dp
    1055        1160 :       DO ispin = 1, nspins
    1056        1160 :          chksum = chksum + dbcsr_checksum(matrix_b(ispin)%matrix)
    1057             :       END DO
    1058             : 
    1059             :       ! skip the kernel if the DM is very small
    1060         580 :       IF (chksum .GT. 1.0E-14_dp) THEN
    1061             : 
    1062             :          ! Bring matrix B as density on grid
    1063             : 
    1064             :          ! prepare perturbation environment
    1065         576 :          CALL p_env_check_i_alloc(p_env, qs_env)
    1066             : 
    1067             :          ! Get response density matrix
    1068         576 :          CALL qs_rho_get(p_env%rho1, rho_ao=rho1_ao)
    1069             : 
    1070        1152 :          DO ispin = 1, nspins
    1071             :             ! Transform B into NON-ortho basis for collocation
    1072         576 :             CALL transform_m_orth(matrix_b(ispin)%matrix, matrix_s_sqrt_inv, eps_filter)
    1073             :             ! Filter
    1074         576 :             CALL dbcsr_filter(matrix_b(ispin)%matrix, eps_filter)
    1075             :             ! Keep symmetry of density matrix
    1076         576 :             CALL dbcsr_copy(rho1_ao(ispin)%matrix, matrix_b(ispin)%matrix, keep_sparsity=.TRUE.)
    1077        1152 :             CALL dbcsr_copy(p_env%p1(ispin)%matrix, matrix_b(ispin)%matrix, keep_sparsity=.TRUE.)
    1078             :          END DO
    1079             : 
    1080             :          ! Updates densities on grid wrt density matrix
    1081         576 :          CALL p_env_update_rho(p_env, qs_env)
    1082             : 
    1083        1152 :          DO ispin = 1, nspins
    1084         576 :             CALL dbcsr_set(p_env%kpp1(ispin)%matrix, 0.0_dp)
    1085        1152 :             IF (ASSOCIATED(p_env%kpp1_admm)) CALL dbcsr_set(p_env%kpp1_admm(ispin)%matrix, 0.0_dp)
    1086             :          END DO
    1087             : 
    1088             :          ! Calculate kernel
    1089             :          ! Ax = F*B - B*F + G(B)*P - P*G(B)
    1090             :          !                               IN/OUT     IN        IN                 IN
    1091         576 :          CALL hessian_op2(qs_env, p_env, matrix_Ax, matrix_p, matrix_s_sqrt_inv, eps_filter)
    1092             : 
    1093             :       END IF
    1094             : 
    1095         580 :       CALL dbcsr_deallocate_matrix_set(matrix_b)
    1096             : 
    1097         580 :       CALL timestop(handle)
    1098             : 
    1099         580 :    END SUBROUTINE build_hessian_op
    1100             : 
    1101             : ! **************************************************************************************************
    1102             : !> \brief  Calculate lin transformation of Hessian matrix on a trial matrix matrix_cg
    1103             : !>         which is stored in response density B = [cg,P] = cg*P - P*cg = cg*P + (cg*P)^T
    1104             : !>         Ax = [F, B] + [G(B), Pin] in orthonormal basis
    1105             : !>
    1106             : !> \param qs_env ...
    1107             : !> \param p_env p-environment with trial density environment
    1108             : !> \param matrix_Ax contains first part of Hessian linear transformation, kernel contribution
    1109             : !>                  is calculated and added in this routine
    1110             : !> \param matrix_p Density matrix in orthogonal basis
    1111             : !> \param matrix_s_sqrt_inv contains matrix S^(-1/2) for switching to orthonormal Lowdin basis
    1112             : !> \param eps_filter ...
    1113             : !>
    1114             : !> \date    12.2019
    1115             : !> \author  Fabian Belleflamme
    1116             : ! **************************************************************************************************
    1117         576 :    SUBROUTINE hessian_op2(qs_env, p_env, matrix_Ax, matrix_p, matrix_s_sqrt_inv, eps_filter)
    1118             : 
    1119             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1120             :       TYPE(qs_p_env_type), POINTER                       :: p_env
    1121             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
    1122             :          POINTER                                         :: matrix_Ax
    1123             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
    1124             :          POINTER                                         :: matrix_p
    1125             :       TYPE(dbcsr_type), INTENT(IN)                       :: matrix_s_sqrt_inv
    1126             :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    1127             : 
    1128             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'hessian_op2'
    1129             : 
    1130             :       INTEGER                                            :: handle, ispin, nspins
    1131             :       REAL(KIND=dp)                                      :: ekin_mol
    1132             :       TYPE(admm_type), POINTER                           :: admm_env
    1133         576 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_G, matrix_s, rho1_ao, rho_ao
    1134             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1135             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1136             :       TYPE(pw_c1d_gs_type)                               :: rho_tot_gspace, v_hartree_gspace
    1137         576 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho1_g
    1138             :       TYPE(pw_env_type), POINTER                         :: pw_env
    1139             :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
    1140         576 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    1141             :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1142             :       TYPE(pw_r3d_rs_type)                               :: v_hartree_rspace
    1143         576 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho1_r, rho_r, tau1_r, v_xc, v_xc_tau
    1144             :       TYPE(qs_kpp1_env_type), POINTER                    :: kpp1_env
    1145             :       TYPE(qs_rho_type), POINTER                         :: rho, rho_aux
    1146             :       TYPE(section_vals_type), POINTER                   :: input, xc_section, xc_section_aux
    1147             : 
    1148         576 :       CALL timeset(routineN, handle)
    1149             : 
    1150         576 :       NULLIFY (admm_env, dft_control, input, matrix_s, para_env, rho, rho_r, rho1_g, rho1_r)
    1151             : 
    1152             :       CALL get_qs_env(qs_env=qs_env, &
    1153             :                       admm_env=admm_env, &
    1154             :                       dft_control=dft_control, &
    1155             :                       input=input, &
    1156             :                       matrix_s=matrix_s, &
    1157             :                       para_env=para_env, &
    1158         576 :                       rho=rho)
    1159         576 :       nspins = dft_control%nspins
    1160             : 
    1161         576 :       CPASSERT(ASSOCIATED(p_env%kpp1))
    1162         576 :       CPASSERT(ASSOCIATED(p_env%kpp1_env))
    1163         576 :       kpp1_env => p_env%kpp1_env
    1164             : 
    1165             :       ! Get non-ortho input density matrix on grid
    1166         576 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
    1167             :       ! Get non-ortho trial density stored in p_env
    1168         576 :       CALL qs_rho_get(p_env%rho1, rho_g=rho1_g, rho_r=rho1_r, tau_r=tau1_r)
    1169             : 
    1170         576 :       NULLIFY (pw_env)
    1171         576 :       CALL get_qs_env(qs_env, pw_env=pw_env)
    1172         576 :       CPASSERT(ASSOCIATED(pw_env))
    1173             : 
    1174         576 :       NULLIFY (auxbas_pw_pool, poisson_env, pw_pools)
    1175             :       ! gets the tmp grids
    1176             :       CALL pw_env_get(pw_env=pw_env, &
    1177             :                       auxbas_pw_pool=auxbas_pw_pool, &
    1178             :                       pw_pools=pw_pools, &
    1179         576 :                       poisson_env=poisson_env)
    1180             : 
    1181             :       ! Calculate the NSC Hartree potential
    1182         576 :       CALL auxbas_pw_pool%create_pw(pw=v_hartree_gspace)
    1183         576 :       CALL auxbas_pw_pool%create_pw(pw=rho_tot_gspace)
    1184         576 :       CALL auxbas_pw_pool%create_pw(pw=v_hartree_rspace)
    1185             : 
    1186             :       ! XC-Kernel
    1187         576 :       NULLIFY (v_xc, v_xc_tau, xc_section)
    1188             : 
    1189         576 :       IF (dft_control%do_admm) THEN
    1190         132 :          xc_section => admm_env%xc_section_primary
    1191             :       ELSE
    1192         444 :          xc_section => section_vals_get_subs_vals(input, "DFT%XC")
    1193             :       END IF
    1194             : 
    1195             :       ! add xc-kernel
    1196             :       CALL create_kernel(qs_env, &
    1197             :                          vxc=v_xc, &
    1198             :                          vxc_tau=v_xc_tau, &
    1199             :                          rho=rho, &
    1200             :                          rho1_r=rho1_r, &
    1201             :                          rho1_g=rho1_g, &
    1202             :                          tau1_r=tau1_r, &
    1203         576 :                          xc_section=xc_section)
    1204             : 
    1205        1152 :       DO ispin = 1, nspins
    1206         576 :          CALL pw_scale(v_xc(ispin), v_xc(ispin)%pw_grid%dvol)
    1207        1152 :          IF (ASSOCIATED(v_xc_tau)) THEN
    1208          24 :             CALL pw_scale(v_xc_tau(ispin), v_xc_tau(ispin)%pw_grid%dvol)
    1209             :          END IF
    1210             :       END DO
    1211             : 
    1212             :       ! ADMM Correction
    1213         576 :       IF (dft_control%do_admm) THEN
    1214         132 :          IF (admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
    1215          70 :             IF (.NOT. ASSOCIATED(kpp1_env%deriv_set_admm)) THEN
    1216          16 :                xc_section_aux => admm_env%xc_section_aux
    1217          16 :                CALL get_admm_env(qs_env%admm_env, rho_aux_fit=rho_aux)
    1218          16 :                CALL qs_rho_get(rho_aux, rho_r=rho_r)
    1219         368 :                ALLOCATE (kpp1_env%deriv_set_admm, kpp1_env%rho_set_admm)
    1220             :                CALL xc_prep_2nd_deriv(kpp1_env%deriv_set_admm, kpp1_env%rho_set_admm, &
    1221             :                                       rho_r, auxbas_pw_pool, &
    1222          16 :                                       xc_section=xc_section_aux)
    1223             :             END IF
    1224             :          END IF
    1225             :       END IF
    1226             : 
    1227             :       ! take trial density to build G^{H}[B]
    1228         576 :       CALL pw_zero(rho_tot_gspace)
    1229        1152 :       DO ispin = 1, nspins
    1230        1152 :          CALL pw_axpy(rho1_g(ispin), rho_tot_gspace)
    1231             :       END DO
    1232             : 
    1233             :       ! get Hartree potential from rho_tot_gspace
    1234             :       CALL pw_poisson_solve(poisson_env, rho_tot_gspace, &
    1235         576 :                             vhartree=v_hartree_gspace)
    1236         576 :       CALL pw_transfer(v_hartree_gspace, v_hartree_rspace)
    1237         576 :       CALL pw_scale(v_hartree_rspace, v_hartree_rspace%pw_grid%dvol)
    1238             : 
    1239             :       ! Add v_xc + v_H
    1240        1152 :       DO ispin = 1, nspins
    1241        1152 :          CALL pw_axpy(v_hartree_rspace, v_xc(ispin))
    1242             :       END DO
    1243         576 :       IF (nspins == 1) THEN
    1244         576 :          CALL pw_scale(v_xc(1), 2.0_dp)
    1245         576 :          IF (ASSOCIATED(v_xc_tau)) CALL pw_scale(v_xc_tau(1), 2.0_dp)
    1246             :       END IF
    1247             : 
    1248        1152 :       DO ispin = 1, nspins
    1249             :          ! Integrate with ground-state density matrix, in non-orthogonal basis
    1250             :          CALL integrate_v_rspace(v_rspace=v_xc(ispin), &
    1251             :                                  pmat=rho_ao(ispin), &
    1252             :                                  hmat=p_env%kpp1(ispin), &
    1253             :                                  qs_env=qs_env, &
    1254             :                                  calculate_forces=.FALSE., &
    1255         576 :                                  basis_type="ORB")
    1256        1152 :          IF (ASSOCIATED(v_xc_tau)) THEN
    1257             :             CALL integrate_v_rspace(v_rspace=v_xc_tau(ispin), &
    1258             :                                     pmat=rho_ao(ispin), &
    1259             :                                     hmat=p_env%kpp1(ispin), &
    1260             :                                     qs_env=qs_env, &
    1261             :                                     compute_tau=.TRUE., &
    1262             :                                     calculate_forces=.FALSE., &
    1263          24 :                                     basis_type="ORB")
    1264             :          END IF
    1265             :       END DO
    1266             : 
    1267             :       ! Hartree-Fock contribution
    1268         576 :       CALL apply_hfx(qs_env, p_env)
    1269             :       ! Calculate ADMM exchange correction to kernel
    1270         576 :       CALL apply_xc_admm(qs_env, p_env)
    1271             :       ! Add contribution from ADMM exchange correction to kernel
    1272         576 :       CALL p_env_finish_kpp1(qs_env, p_env)
    1273             : 
    1274             :       ! Calculate KG correction to kernel
    1275         576 :       IF (dft_control%qs_control%do_kg) THEN
    1276          50 :          IF (qs_env%kg_env%tnadd_method == kg_tnadd_embed .OR. &
    1277             :              qs_env%kg_env%tnadd_method == kg_tnadd_embed_ri) THEN
    1278             : 
    1279          24 :             CPASSERT(dft_control%nimages == 1)
    1280             :             ekin_mol = 0.0_dp
    1281          24 :             CALL qs_rho_get(p_env%rho1, rho_ao=rho1_ao)
    1282             :             CALL kg_ekin_subset(qs_env=qs_env, &
    1283             :                                 ks_matrix=p_env%kpp1, &
    1284             :                                 ekin_mol=ekin_mol, &
    1285             :                                 calc_force=.FALSE., &
    1286             :                                 do_kernel=.TRUE., &
    1287          24 :                                 pmat_ext=rho1_ao)
    1288             :          END IF
    1289             :       END IF
    1290             : 
    1291             :       ! Init response kernel matrix
    1292             :       ! matrix G(B)
    1293         576 :       NULLIFY (matrix_G)
    1294         576 :       CALL dbcsr_allocate_matrix_set(matrix_G, nspins)
    1295        1152 :       DO ispin = 1, nspins
    1296         576 :          ALLOCATE (matrix_G(ispin)%matrix)
    1297             :          CALL dbcsr_copy(matrix_G(ispin)%matrix, p_env%kpp1(ispin)%matrix, &
    1298        1152 :                          name="MATRIX Kernel")
    1299             :       END DO
    1300             : 
    1301             :       ! Transforming G(B) into orthonormal basis
    1302             :       ! Careful, this de-symmetrizes matrix_G
    1303        1152 :       DO ispin = 1, nspins
    1304         576 :          CALL transform_m_orth(matrix_G(ispin)%matrix, matrix_s_sqrt_inv, eps_filter)
    1305        1152 :          CALL dbcsr_filter(matrix_G(ispin)%matrix, eps_filter)
    1306             :       END DO
    1307             : 
    1308             :       ! Hessian already contains  Ax = [F,B] (ORTHO), now adding
    1309             :       ! Ax = Ax + G(B)P - (G(B)P)^T
    1310         576 :       CALL commutator(matrix_G, matrix_p, matrix_Ax, eps_filter, .FALSE., 1.0_dp, 1.0_dp)
    1311             : 
    1312             :       ! release pw grids
    1313         576 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_gspace)
    1314         576 :       CALL auxbas_pw_pool%give_back_pw(v_hartree_rspace)
    1315         576 :       CALL auxbas_pw_pool%give_back_pw(rho_tot_gspace)
    1316        1152 :       DO ispin = 1, nspins
    1317        1152 :          CALL auxbas_pw_pool%give_back_pw(v_xc(ispin))
    1318             :       END DO
    1319         576 :       DEALLOCATE (v_xc)
    1320         576 :       IF (ASSOCIATED(v_xc_tau)) THEN
    1321          48 :          DO ispin = 1, nspins
    1322          48 :             CALL auxbas_pw_pool%give_back_pw(v_xc_tau(ispin))
    1323             :          END DO
    1324          24 :          DEALLOCATE (v_xc_tau)
    1325             :       END IF
    1326             : 
    1327         576 :       CALL dbcsr_deallocate_matrix_set(matrix_G)
    1328             : 
    1329         576 :       CALL timestop(handle)
    1330             : 
    1331         576 :    END SUBROUTINE hessian_op2
    1332             : 
    1333             : ! **************************************************************************************************
    1334             : !> \brief computes (anti-)commutator exploiting (anti-)symmetry:
    1335             : !>        A symmetric : RES = beta*RES + k*[A,B] = k*(AB-(AB)^T)
    1336             : !>        A anti-sym  : RES = beta*RES + k*{A,B} = k*(AB+(AB)^T)
    1337             : !>
    1338             : !> \param a          Matrix A
    1339             : !> \param b          Matrix B
    1340             : !> \param res        Commutator result
    1341             : !> \param eps_filter filtering threshold for sparse matrices
    1342             : !> \param anticomm   Calculate anticommutator
    1343             : !> \param alpha      Scaling of anti-/commutator
    1344             : !> \param beta       Scaling of inital content of result matrix
    1345             : !>
    1346             : !> \par History
    1347             : !>       2020.07 Fabian Belleflamme  (based on commutator_symm)
    1348             : ! **************************************************************************************************
    1349        9268 :    SUBROUTINE commutator(a, b, res, eps_filter, anticomm, alpha, beta)
    1350             : 
    1351             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
    1352             :          POINTER                                         :: a, b, res
    1353             :       REAL(KIND=dp)                                      :: eps_filter
    1354             :       LOGICAL                                            :: anticomm
    1355             :       REAL(KIND=dp), OPTIONAL                            :: alpha, beta
    1356             : 
    1357             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'commutator'
    1358             : 
    1359             :       INTEGER                                            :: handle, ispin
    1360             :       REAL(KIND=dp)                                      :: facc, myalpha, mybeta
    1361             :       TYPE(dbcsr_type)                                   :: work, work2
    1362             : 
    1363        9268 :       CALL timeset(routineN, handle)
    1364             : 
    1365        9268 :       CPASSERT(ASSOCIATED(a))
    1366        9268 :       CPASSERT(ASSOCIATED(b))
    1367        9268 :       CPASSERT(ASSOCIATED(res))
    1368             : 
    1369        9268 :       CALL dbcsr_create(work, template=a(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1370        9268 :       CALL dbcsr_create(work2, template=a(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
    1371             : 
    1372             :       ! Scaling of anti-/commutator
    1373        9268 :       myalpha = 1.0_dp
    1374        9268 :       IF (PRESENT(alpha)) myalpha = alpha
    1375             :       ! Scaling of result matrix
    1376        9268 :       mybeta = 0.0_dp
    1377        9268 :       IF (PRESENT(beta)) mybeta = beta
    1378             :       ! Add/subtract second term when calculating anti-/commutator
    1379        9268 :       facc = -1.0_dp
    1380        9268 :       IF (anticomm) facc = 1.0_dp
    1381             : 
    1382       18536 :       DO ispin = 1, SIZE(a)
    1383             : 
    1384             :          CALL dbcsr_multiply("N", "N", myalpha, a(ispin)%matrix, b(ispin)%matrix, &
    1385        9268 :                              0.0_dp, work, filter_eps=eps_filter)
    1386        9268 :          CALL dbcsr_transposed(work2, work)
    1387             : 
    1388             :          ! RES= beta*RES + alpha*{A,B} = beta*RES + alpha*[AB+(AB)T]
    1389             :          ! RES= beta*RES + alpha*[A,B] = beta*RES + alpha*[AB-(AB)T]
    1390        9268 :          CALL dbcsr_add(work, work2, 1.0_dp, facc)
    1391             : 
    1392       18536 :          CALL dbcsr_add(res(ispin)%matrix, work, mybeta, 1.0_dp)
    1393             : 
    1394             :       END DO
    1395             : 
    1396        9268 :       CALL dbcsr_release(work)
    1397        9268 :       CALL dbcsr_release(work2)
    1398             : 
    1399        9268 :       CALL timestop(handle)
    1400             : 
    1401        9268 :    END SUBROUTINE commutator
    1402             : 
    1403             : ! **************************************************************************************************
    1404             : !> \brief Projector P(M) = P*M*Q^T + Q*M*P^T
    1405             : !>        with P = D
    1406             : !>        with Q = (1-D)
    1407             : !>
    1408             : !> \param qs_env ...
    1409             : !> \param matrix_p  Ground-state density in orthonormal basis
    1410             : !> \param matrix_io Matrix to which projector is applied.
    1411             : !>
    1412             : !> \param eps_filter ...
    1413             : !> \date    06.2020
    1414             : !> \author  Fabian Belleflamme
    1415             : ! **************************************************************************************************
    1416        5498 :    SUBROUTINE projector(qs_env, matrix_p, matrix_io, eps_filter)
    1417             : 
    1418             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1419             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(IN), &
    1420             :          POINTER                                         :: matrix_p
    1421             :       TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
    1422             :          POINTER                                         :: matrix_io
    1423             :       REAL(KIND=dp), INTENT(IN)                          :: eps_filter
    1424             : 
    1425             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'projector'
    1426             : 
    1427             :       INTEGER                                            :: handle, ispin, nspins
    1428             :       TYPE(dbcsr_type)                                   :: matrix_q, matrix_tmp
    1429             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1430             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1431             : 
    1432        5498 :       CALL timeset(routineN, handle)
    1433             : 
    1434             :       CALL get_qs_env(qs_env=qs_env, &
    1435             :                       dft_control=dft_control, &
    1436        5498 :                       para_env=para_env)
    1437        5498 :       nspins = dft_control%nspins
    1438             : 
    1439             :       CALL dbcsr_create(matrix_q, template=matrix_p(1)%matrix, &
    1440        5498 :                         matrix_type=dbcsr_type_no_symmetry)
    1441             :       CALL dbcsr_create(matrix_tmp, template=matrix_p(1)%matrix, &
    1442        5498 :                         matrix_type=dbcsr_type_no_symmetry)
    1443             : 
    1444             :       ! Q = (1 - P)
    1445        5498 :       CALL dbcsr_copy(matrix_q, matrix_p(1)%matrix)
    1446        5498 :       CALL dbcsr_scale(matrix_q, -1.0_dp)
    1447        5498 :       CALL dbcsr_add_on_diag(matrix_q, 1.0_dp)
    1448        5498 :       CALL dbcsr_finalize(matrix_q)
    1449             : 
    1450             :       ! Proj(M) = P*M*Q + Q*M*P
    1451             :       ! with P = D = CC^T
    1452             :       ! and  Q = (1 - P)
    1453       10996 :       DO ispin = 1, nspins
    1454             : 
    1455             :          ! tmp1 = P*M
    1456             :          CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_p(ispin)%matrix, matrix_io(ispin)%matrix, &
    1457        5498 :                              0.0_dp, matrix_tmp, filter_eps=eps_filter)
    1458             :          ! m_io = P*M*Q
    1459             :          CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp, matrix_q, &
    1460        5498 :                              0.0_dp, matrix_io(ispin)%matrix, filter_eps=eps_filter)
    1461             : 
    1462             :          ! tmp = (P^T*M^T*Q^T)^T = -(P*M*Q)^T
    1463        5498 :          CALL dbcsr_transposed(matrix_tmp, matrix_io(ispin)%matrix)
    1464       10996 :          CALL dbcsr_add(matrix_io(ispin)%matrix, matrix_tmp, 1.0_dp, -1.0_dp)
    1465             : 
    1466             :       END DO
    1467             : 
    1468        5498 :       CALL dbcsr_release(matrix_tmp)
    1469        5498 :       CALL dbcsr_release(matrix_q)
    1470             : 
    1471        5498 :       CALL timestop(handle)
    1472             : 
    1473        5498 :    END SUBROUTINE projector
    1474             : 
    1475             : ! **************************************************************************************************
    1476             : !> \brief performs a tranformation of a matrix back to/into orthonormal basis
    1477             : !>        in case of P a scaling of 0.5 has to be applied for closed shell case
    1478             : !> \param matrix       matrix to be transformed
    1479             : !> \param matrix_trafo transformation matrix
    1480             : !> \param eps_filter   filtering threshold for sparse matrices
    1481             : !> \par History
    1482             : !>       2012.05 created [Florian Schiffmann]
    1483             : !> \author Florian Schiffmann
    1484             : !>
    1485             : ! **************************************************************************************************
    1486             : 
    1487        1680 :    SUBROUTINE transform_m_orth(matrix, matrix_trafo, eps_filter)
    1488             :       TYPE(dbcsr_type)                                   :: matrix, matrix_trafo
    1489             :       REAL(KIND=dp)                                      :: eps_filter
    1490             : 
    1491             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'transform_m_orth'
    1492             : 
    1493             :       INTEGER                                            :: handle
    1494             :       TYPE(dbcsr_type)                                   :: matrix_tmp, matrix_work
    1495             : 
    1496        1680 :       CALL timeset(routineN, handle)
    1497             : 
    1498        1680 :       CALL dbcsr_create(matrix_work, template=matrix, matrix_type=dbcsr_type_no_symmetry)
    1499        1680 :       CALL dbcsr_create(matrix_tmp, template=matrix, matrix_type=dbcsr_type_no_symmetry)
    1500             : 
    1501             :       CALL dbcsr_multiply("N", "N", 1.0_dp, matrix, matrix_trafo, &
    1502        1680 :                           0.0_dp, matrix_work, filter_eps=eps_filter)
    1503             :       CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_trafo, matrix_work, &
    1504        1680 :                           0.0_dp, matrix_tmp, filter_eps=eps_filter)
    1505             :       ! symmetrize results (this is again needed to make sure everything is stable)
    1506        1680 :       CALL dbcsr_transposed(matrix_work, matrix_tmp)
    1507        1680 :       CALL dbcsr_add(matrix_tmp, matrix_work, 0.5_dp, 0.5_dp)
    1508        1680 :       CALL dbcsr_copy(matrix, matrix_tmp)
    1509             : 
    1510             :       ! Avoid the buildup of noisy blocks
    1511        1680 :       CALL dbcsr_filter(matrix, eps_filter)
    1512             : 
    1513        1680 :       CALL dbcsr_release(matrix_tmp)
    1514        1680 :       CALL dbcsr_release(matrix_work)
    1515        1680 :       CALL timestop(handle)
    1516             : 
    1517        1680 :    END SUBROUTINE transform_m_orth
    1518             : 
    1519             : END MODULE ec_orth_solver

Generated by: LCOV version 1.15