LCOV - code coverage report
Current view: top level - src - ec_orth_solver.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:936074a) Lines: 93.8 % 514 482
Test Date: 2025-12-04 06:27:48 Functions: 100.0 % 9 9

            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 ec_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 = 'ec_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) < 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) < 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) < 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) < linres_control%eps*0.001_dp &
     275         3062 :                 .OR. new_norm(ispin) < 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 < linres_control%eps) THEN
     292          572 :             converged = .TRUE.
     293              :          END IF
     294              : 
     295         3062 :          t2 = m_walltime()
     296              :          IF (i == 1 .OR. MOD(i, 1) == 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 ec_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 ec_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) < 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 < linres_control%eps) THEN
     614           86 :             linres_control%converged = .TRUE.
     615              :          END IF
     616              : 
     617          534 :          t2 = m_walltime()
     618              :          IF (i == 1 .OR. MOD(i, 1) == 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) < 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) < 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) == 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 ec_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) < 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) < linres_control%eps .OR. new_norm(ispin) < 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 > 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 2.0-1