LCOV - code coverage report
Current view: top level - src - qs_p_env_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 303 350 86.6 %
Date: 2024-12-21 06:28:57 Functions: 10 10 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief Utility functions for the perturbation calculations.
      10             : !> \note
      11             : !>      - routines are programmed with spins in mind
      12             : !>        but are as of now not tested with them
      13             : !> \par History
      14             : !>      22-08-2002, TCH, started development
      15             : ! **************************************************************************************************
      16             : MODULE qs_p_env_methods
      17             :    USE admm_methods,                    ONLY: admm_aux_response_density
      18             :    USE admm_types,                      ONLY: admm_gapw_r3d_rs_type,&
      19             :                                               admm_type,&
      20             :                                               get_admm_env
      21             :    USE atomic_kind_types,               ONLY: atomic_kind_type
      22             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      23             :    USE cp_control_types,                ONLY: dft_control_type
      24             :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      25             :                                               dbcsr_copy,&
      26             :                                               dbcsr_p_type,&
      27             :                                               dbcsr_release,&
      28             :                                               dbcsr_scale,&
      29             :                                               dbcsr_set,&
      30             :                                               dbcsr_type
      31             :    USE cp_dbcsr_operations,             ONLY: copy_fm_to_dbcsr,&
      32             :                                               cp_dbcsr_plus_fm_fm_t,&
      33             :                                               cp_dbcsr_sm_fm_multiply,&
      34             :                                               dbcsr_allocate_matrix_set
      35             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_symm,&
      36             :                                               cp_fm_triangular_multiply
      37             :    USE cp_fm_cholesky,                  ONLY: cp_fm_cholesky_decompose
      38             :    USE cp_fm_pool_types,                ONLY: cp_fm_pool_p_type,&
      39             :                                               cp_fm_pool_type,&
      40             :                                               fm_pool_create_fm,&
      41             :                                               fm_pool_get_el_struct,&
      42             :                                               fm_pool_give_back_fm,&
      43             :                                               fm_pools_create_fm_vect
      44             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      45             :                                               cp_fm_struct_get,&
      46             :                                               cp_fm_struct_release,&
      47             :                                               cp_fm_struct_type
      48             :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      49             :                                               cp_fm_get_info,&
      50             :                                               cp_fm_release,&
      51             :                                               cp_fm_set_all,&
      52             :                                               cp_fm_to_fm,&
      53             :                                               cp_fm_type
      54             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      55             :                                               cp_logger_type,&
      56             :                                               cp_to_string
      57             :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      58             :                                               cp_print_key_unit_nr
      59             :    USE hartree_local_methods,           ONLY: init_coulomb_local
      60             :    USE hartree_local_types,             ONLY: hartree_local_create
      61             :    USE input_constants,                 ONLY: do_admm_aux_exch_func_none,&
      62             :                                               ot_precond_none
      63             :    USE input_section_types,             ONLY: section_vals_get,&
      64             :                                               section_vals_get_subs_vals,&
      65             :                                               section_vals_type
      66             :    USE kinds,                           ONLY: default_string_length,&
      67             :                                               dp
      68             :    USE message_passing,                 ONLY: mp_para_env_type
      69             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      70             :    USE preconditioner_types,            ONLY: init_preconditioner
      71             :    USE pw_env_types,                    ONLY: pw_env_type
      72             :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      73             :                                               pw_r3d_rs_type
      74             :    USE qs_collocate_density,            ONLY: calculate_rho_elec
      75             :    USE qs_energy_types,                 ONLY: qs_energy_type
      76             :    USE qs_environment_types,            ONLY: get_qs_env,&
      77             :                                               qs_environment_type
      78             :    USE qs_kind_types,                   ONLY: qs_kind_type
      79             :    USE qs_kpp1_env_methods,             ONLY: kpp1_calc_k_p_p1,&
      80             :                                               kpp1_calc_k_p_p1_fdiff,&
      81             :                                               kpp1_create,&
      82             :                                               kpp1_did_change
      83             :    USE qs_ks_methods,                   ONLY: qs_ks_update_qs_env
      84             :    USE qs_ks_types,                     ONLY: qs_ks_did_change,&
      85             :                                               qs_ks_env_type
      86             :    USE qs_linres_types,                 ONLY: linres_control_type
      87             :    USE qs_local_rho_types,              ONLY: local_rho_set_create
      88             :    USE qs_matrix_pools,                 ONLY: mpools_get
      89             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      90             :                                               mo_set_type
      91             :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      92             :    USE qs_p_env_types,                  ONLY: qs_p_env_type
      93             :    USE qs_rho0_ggrid,                   ONLY: rho0_s_grid_create
      94             :    USE qs_rho0_methods,                 ONLY: init_rho0
      95             :    USE qs_rho_atom_methods,             ONLY: allocate_rho_atom_internals,&
      96             :                                               calculate_rho_atom_coeff
      97             :    USE qs_rho_methods,                  ONLY: qs_rho_rebuild,&
      98             :                                               qs_rho_update_rho
      99             :    USE qs_rho_types,                    ONLY: qs_rho_create,&
     100             :                                               qs_rho_get,&
     101             :                                               qs_rho_type
     102             :    USE string_utilities,                ONLY: compress
     103             :    USE task_list_types,                 ONLY: task_list_type
     104             : #include "./base/base_uses.f90"
     105             : 
     106             :    IMPLICIT NONE
     107             : 
     108             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_p_env_methods'
     109             :    LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .FALSE.
     110             : 
     111             :    PRIVATE
     112             :    PUBLIC :: p_env_create, p_env_psi0_changed
     113             :    PUBLIC :: p_op_l1, p_op_l2, p_preortho, p_postortho
     114             :    PUBLIC :: p_env_check_i_alloc, p_env_update_rho
     115             :    PUBLIC :: p_env_finish_kpp1
     116             : 
     117             : CONTAINS
     118             : 
     119             : ! **************************************************************************************************
     120             : !> \brief allocates and initializes the perturbation environment (no setup)
     121             : !> \param p_env the environment to initialize
     122             : !> \param qs_env the qs_environment for the system
     123             : !> \param p1_option ...
     124             : !> \param p1_admm_option ...
     125             : !> \param orthogonal_orbitals if the orbitals are orthogonal
     126             : !> \param linres_control ...
     127             : !> \par History
     128             : !>      07.2002 created [fawzi]
     129             : !> \author Fawzi Mohamed
     130             : ! **************************************************************************************************
     131        1646 :    SUBROUTINE p_env_create(p_env, qs_env, p1_option, p1_admm_option, &
     132             :                            orthogonal_orbitals, linres_control)
     133             : 
     134             :       TYPE(qs_p_env_type)                                :: p_env
     135             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     136             :       TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
     137             :          POINTER                                         :: p1_option, p1_admm_option
     138             :       LOGICAL, INTENT(in), OPTIONAL                      :: orthogonal_orbitals
     139             :       TYPE(linres_control_type), OPTIONAL, POINTER       :: linres_control
     140             : 
     141             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'p_env_create'
     142             : 
     143             :       INTEGER                                            :: handle, n_ao, n_mo, n_spins, natom, spin
     144             :       TYPE(admm_gapw_r3d_rs_type), POINTER               :: admm_gapw_env
     145             :       TYPE(admm_type), POINTER                           :: admm_env
     146        1646 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     147             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     148        1646 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_mo_fm_pools, mo_mo_fm_pools
     149             :       TYPE(cp_fm_type), POINTER                          :: qs_env_c
     150        1646 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, matrix_s_aux_fit
     151             :       TYPE(dft_control_type), POINTER                    :: dft_control
     152             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     153             :       TYPE(pw_env_type), POINTER                         :: pw_env
     154        1646 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     155             : 
     156        1646 :       CALL timeset(routineN, handle)
     157        1646 :       NULLIFY (ao_mo_fm_pools, mo_mo_fm_pools, matrix_s, dft_control, para_env, blacs_env)
     158             :       CALL get_qs_env(qs_env, &
     159             :                       matrix_s=matrix_s, &
     160             :                       dft_control=dft_control, &
     161             :                       para_env=para_env, &
     162        1646 :                       blacs_env=blacs_env)
     163             : 
     164        1646 :       n_spins = dft_control%nspins
     165             : 
     166        1646 :       p_env%new_preconditioner = .TRUE.
     167             : 
     168        1646 :       ALLOCATE (p_env%rho1)
     169        1646 :       CALL qs_rho_create(p_env%rho1)
     170        1646 :       ALLOCATE (p_env%rho1_xc)
     171        1646 :       CALL qs_rho_create(p_env%rho1_xc)
     172             : 
     173        1646 :       ALLOCATE (p_env%kpp1_env)
     174        1646 :       CALL kpp1_create(p_env%kpp1_env)
     175             : 
     176        1646 :       IF (PRESENT(p1_option)) THEN
     177         264 :          p_env%p1 => p1_option
     178             :       ELSE
     179        1382 :          CALL dbcsr_allocate_matrix_set(p_env%p1, n_spins)
     180        2964 :          DO spin = 1, n_spins
     181        1582 :             ALLOCATE (p_env%p1(spin)%matrix)
     182             :             CALL dbcsr_copy(p_env%p1(spin)%matrix, matrix_s(1)%matrix, &
     183        1582 :                             name="p_env%p1-"//TRIM(ADJUSTL(cp_to_string(spin))))
     184        2964 :             CALL dbcsr_set(p_env%p1(spin)%matrix, 0.0_dp)
     185             :          END DO
     186             :       END IF
     187             : 
     188        1646 :       IF (dft_control%do_admm) THEN
     189         314 :          CALL get_admm_env(qs_env%admm_env, matrix_s_aux_fit=matrix_s_aux_fit)
     190         314 :          IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
     191         194 :             ALLOCATE (p_env%rho1_admm)
     192         194 :             CALL qs_rho_create(p_env%rho1_admm)
     193             :          END IF
     194             : 
     195         314 :          IF (PRESENT(p1_admm_option)) THEN
     196           0 :             p_env%p1_admm => p1_admm_option
     197             :          ELSE
     198         314 :             CALL dbcsr_allocate_matrix_set(p_env%p1_admm, n_spins)
     199         674 :             DO spin = 1, n_spins
     200         360 :                ALLOCATE (p_env%p1_admm(spin)%matrix)
     201             :                CALL dbcsr_copy(p_env%p1_admm(spin)%matrix, matrix_s_aux_fit(1)%matrix, &
     202         360 :                                name="p_env%p1_admm-"//TRIM(ADJUSTL(cp_to_string(spin))))
     203         674 :                CALL dbcsr_set(p_env%p1_admm(spin)%matrix, 0.0_dp)
     204             :             END DO
     205             :          END IF
     206         314 :          CALL get_qs_env(qs_env, admm_env=admm_env)
     207         314 :          IF (admm_env%do_gapw) THEN
     208          28 :             CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set)
     209          28 :             admm_gapw_env => admm_env%admm_gapw_env
     210          28 :             CALL local_rho_set_create(p_env%local_rho_set_admm)
     211             :             CALL allocate_rho_atom_internals(p_env%local_rho_set_admm%rho_atom_set, atomic_kind_set, &
     212          28 :                                              admm_gapw_env%admm_kind_set, dft_control, para_env)
     213             :          END IF
     214             :       END IF
     215             : 
     216             :       CALL mpools_get(qs_env%mpools, ao_mo_fm_pools=ao_mo_fm_pools, &
     217        1646 :                       mo_mo_fm_pools=mo_mo_fm_pools)
     218             : 
     219        4938 :       p_env%n_mo = 0
     220        4938 :       p_env%n_ao = 0
     221        3578 :       DO spin = 1, n_spins
     222        1932 :          CALL get_mo_set(qs_env%mos(spin), mo_coeff=qs_env_c)
     223             :          CALL cp_fm_get_info(qs_env_c, &
     224        1932 :                              ncol_global=n_mo, nrow_global=n_ao)
     225        1932 :          p_env%n_mo(spin) = n_mo
     226        3578 :          p_env%n_ao(spin) = n_ao
     227             :       END DO
     228             : 
     229        1646 :       p_env%orthogonal_orbitals = .FALSE.
     230        1646 :       IF (PRESENT(orthogonal_orbitals)) &
     231        1646 :          p_env%orthogonal_orbitals = orthogonal_orbitals
     232             : 
     233             :       CALL fm_pools_create_fm_vect(ao_mo_fm_pools, elements=p_env%S_psi0, &
     234        1646 :                                    name="p_env%S_psi0")
     235             : 
     236             :       ! alloc m_epsilon
     237             :       CALL fm_pools_create_fm_vect(mo_mo_fm_pools, elements=p_env%m_epsilon, &
     238        1646 :                                    name="p_env%m_epsilon")
     239             : 
     240             :       ! alloc Smo_inv
     241        1646 :       IF (.NOT. p_env%orthogonal_orbitals) THEN
     242             :          CALL fm_pools_create_fm_vect(mo_mo_fm_pools, elements=p_env%Smo_inv, &
     243           0 :                                       name="p_env%Smo_inv")
     244             :       END IF
     245             : 
     246        1646 :       IF (.NOT. p_env%orthogonal_orbitals) THEN
     247             :          CALL fm_pools_create_fm_vect(ao_mo_fm_pools, &
     248             :                                       elements=p_env%psi0d, &
     249           0 :                                       name="p_env%psi0d")
     250             :       END IF
     251             : 
     252             :       !------------------------------!
     253             :       ! GAPW/GAPW_XC initializations !
     254             :       !------------------------------!
     255        1646 :       IF (dft_control%qs_control%gapw) THEN
     256             :          CALL get_qs_env(qs_env, &
     257             :                          atomic_kind_set=atomic_kind_set, &
     258             :                          natom=natom, &
     259             :                          pw_env=pw_env, &
     260         190 :                          qs_kind_set=qs_kind_set)
     261             : 
     262         190 :          CALL local_rho_set_create(p_env%local_rho_set)
     263             :          CALL allocate_rho_atom_internals(p_env%local_rho_set%rho_atom_set, atomic_kind_set, &
     264         190 :                                           qs_kind_set, dft_control, para_env)
     265             : 
     266             :          CALL init_rho0(p_env%local_rho_set, qs_env, dft_control%qs_control%gapw_control, &
     267         190 :                         zcore=0.0_dp)
     268         190 :          CALL rho0_s_grid_create(pw_env, p_env%local_rho_set%rho0_mpole)
     269         190 :          CALL hartree_local_create(p_env%hartree_local)
     270         190 :          CALL init_coulomb_local(p_env%hartree_local, natom)
     271        1456 :       ELSEIF (dft_control%qs_control%gapw_xc) THEN
     272             :          CALL get_qs_env(qs_env, &
     273             :                          atomic_kind_set=atomic_kind_set, &
     274          28 :                          qs_kind_set=qs_kind_set)
     275          28 :          CALL local_rho_set_create(p_env%local_rho_set)
     276             :          CALL allocate_rho_atom_internals(p_env%local_rho_set%rho_atom_set, atomic_kind_set, &
     277          28 :                                           qs_kind_set, dft_control, para_env)
     278             :       END IF
     279             : 
     280             :       !------------------------!
     281             :       ! LINRES initializations !
     282             :       !------------------------!
     283        1646 :       IF (PRESENT(linres_control)) THEN
     284             : 
     285        1634 :          IF (linres_control%preconditioner_type /= ot_precond_none) THEN
     286             :             ! Initialize the preconditioner matrix
     287        1630 :             IF (.NOT. ASSOCIATED(p_env%preconditioner)) THEN
     288             : 
     289        6802 :                ALLOCATE (p_env%preconditioner(n_spins))
     290        3542 :                DO spin = 1, n_spins
     291             :                   CALL init_preconditioner(p_env%preconditioner(spin), &
     292        3542 :                                            para_env=para_env, blacs_env=blacs_env)
     293             :                END DO
     294             : 
     295             :                CALL fm_pools_create_fm_vect(ao_mo_fm_pools, elements=p_env%PS_psi0, &
     296        1630 :                                             name="p_env%PS_psi0")
     297             :             END IF
     298             :          END IF
     299             : 
     300             :       END IF
     301             : 
     302        1646 :       CALL timestop(handle)
     303             : 
     304        1646 :    END SUBROUTINE p_env_create
     305             : 
     306             : ! **************************************************************************************************
     307             : !> \brief checks that the intenal storage is allocated, and allocs it if needed
     308             : !> \param p_env the environment to check
     309             : !> \param qs_env the qs environment this p_env lives in
     310             : !> \par History
     311             : !>      12.2002 created [fawzi]
     312             : !> \author Fawzi Mohamed
     313             : !> \note
     314             : !>      private routine
     315             : ! **************************************************************************************************
     316        9032 :    SUBROUTINE p_env_check_i_alloc(p_env, qs_env)
     317             :       TYPE(qs_p_env_type)                                :: p_env
     318             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     319             : 
     320             :       CHARACTER(len=*), PARAMETER :: routineN = 'p_env_check_i_alloc'
     321             : 
     322             :       CHARACTER(len=25)                                  :: name
     323             :       INTEGER                                            :: handle, ispin, nspins
     324             :       LOGICAL                                            :: gapw_xc
     325        9032 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     326             :       TYPE(dft_control_type), POINTER                    :: dft_control
     327             : 
     328        9032 :       CALL timeset(routineN, handle)
     329             : 
     330        9032 :       NULLIFY (dft_control, matrix_s)
     331             : 
     332        9032 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     333        9032 :       gapw_xc = dft_control%qs_control%gapw_xc
     334        9032 :       IF (.NOT. ASSOCIATED(p_env%kpp1)) THEN
     335        1430 :          CALL get_qs_env(qs_env, matrix_s=matrix_s)
     336        1430 :          nspins = dft_control%nspins
     337             : 
     338        1430 :          CALL dbcsr_allocate_matrix_set(p_env%kpp1, nspins)
     339        1430 :          name = "p_env%kpp1-"
     340        1430 :          CALL compress(name, full=.TRUE.)
     341        3068 :          DO ispin = 1, nspins
     342        1638 :             ALLOCATE (p_env%kpp1(ispin)%matrix)
     343             :             CALL dbcsr_copy(p_env%kpp1(ispin)%matrix, matrix_s(1)%matrix, &
     344        1638 :                             name=TRIM(name)//ADJUSTL(cp_to_string(ispin)))
     345        3068 :             CALL dbcsr_set(p_env%kpp1(ispin)%matrix, 0.0_dp)
     346             :          END DO
     347             : 
     348        1430 :          CALL qs_rho_rebuild(p_env%rho1, qs_env=qs_env)
     349        1430 :          IF (gapw_xc) THEN
     350          28 :             CALL qs_rho_rebuild(p_env%rho1_xc, qs_env=qs_env)
     351             :          END IF
     352             : 
     353             :       END IF
     354             : 
     355        9032 :       IF (dft_control%do_admm .AND. .NOT. ASSOCIATED(p_env%kpp1_admm)) THEN
     356         314 :          CALL get_admm_env(qs_env%admm_env, matrix_s_aux_fit=matrix_s)
     357         314 :          nspins = dft_control%nspins
     358             : 
     359         314 :          CALL dbcsr_allocate_matrix_set(p_env%kpp1_admm, nspins)
     360         314 :          name = "p_env%kpp1_admm-"
     361         314 :          CALL compress(name, full=.TRUE.)
     362         674 :          DO ispin = 1, nspins
     363         360 :             ALLOCATE (p_env%kpp1_admm(ispin)%matrix)
     364             :             CALL dbcsr_copy(p_env%kpp1_admm(ispin)%matrix, matrix_s(1)%matrix, &
     365         360 :                             name=TRIM(name)//ADJUSTL(cp_to_string(ispin)))
     366         674 :             CALL dbcsr_set(p_env%kpp1_admm(ispin)%matrix, 0.0_dp)
     367             :          END DO
     368             : 
     369         314 :          IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
     370         194 :             CALL qs_rho_rebuild(p_env%rho1_admm, qs_env=qs_env, admm=.TRUE.)
     371             :          END IF
     372             : 
     373             :       END IF
     374             : 
     375        9032 :       IF (.NOT. ASSOCIATED(p_env%rho1)) THEN
     376           0 :          CALL qs_rho_rebuild(p_env%rho1, qs_env=qs_env)
     377           0 :          IF (gapw_xc) THEN
     378           0 :             CALL qs_rho_rebuild(p_env%rho1_xc, qs_env=qs_env)
     379             :          END IF
     380             : 
     381           0 :          IF (dft_control%do_admm) THEN
     382           0 :             IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
     383           0 :                CALL qs_rho_rebuild(p_env%rho1_admm, qs_env=qs_env, admm=.TRUE.)
     384             :             END IF
     385             :          END IF
     386             : 
     387             :       END IF
     388             : 
     389        9032 :       CALL timestop(handle)
     390        9032 :    END SUBROUTINE p_env_check_i_alloc
     391             : 
     392             : ! **************************************************************************************************
     393             : !> \brief ...
     394             : !> \param p_env ...
     395             : !> \param qs_env ...
     396             : ! **************************************************************************************************
     397       10024 :    SUBROUTINE p_env_update_rho(p_env, qs_env)
     398             :       TYPE(qs_p_env_type), INTENT(IN)                    :: p_env
     399             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     400             : 
     401             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'p_env_update_rho'
     402             : 
     403             :       CHARACTER(LEN=default_string_length)               :: basis_type
     404             :       INTEGER                                            :: handle, ispin
     405             :       TYPE(admm_type), POINTER                           :: admm_env
     406       10024 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho1_ao
     407             :       TYPE(dft_control_type), POINTER                    :: dft_control
     408             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     409             :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     410       10024 :          POINTER                                         :: sab_aux_fit
     411       10024 :       TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER        :: rho_g_aux
     412       10024 :       TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER        :: rho_r_aux
     413             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     414             :       TYPE(task_list_type), POINTER                      :: task_list
     415             : 
     416       10024 :       CALL timeset(routineN, handle)
     417             : 
     418       10024 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     419             : 
     420       10024 :       IF (dft_control%do_admm) CALL admm_aux_response_density(qs_env, p_env%p1, p_env%p1_admm)
     421             : 
     422       10024 :       CALL qs_rho_get(p_env%rho1, rho_ao=rho1_ao)
     423       21454 :       DO ispin = 1, SIZE(rho1_ao)
     424       21454 :          CALL dbcsr_copy(rho1_ao(ispin)%matrix, p_env%p1(ispin)%matrix)
     425             :       END DO
     426             : 
     427             :       CALL qs_rho_update_rho(rho_struct=p_env%rho1, &
     428             :                              rho_xc_external=p_env%rho1_xc, &
     429             :                              local_rho_set=p_env%local_rho_set, &
     430       10024 :                              qs_env=qs_env)
     431             : 
     432       10024 :       IF (dft_control%do_admm) THEN
     433        2072 :          IF (qs_env%admm_env%aux_exch_func /= do_admm_aux_exch_func_none) THEN
     434        1160 :             NULLIFY (ks_env, rho1_ao, rho_g_aux, rho_r_aux, task_list)
     435             : 
     436        1160 :             CALL get_qs_env(qs_env, ks_env=ks_env, admm_env=admm_env)
     437        1160 :             basis_type = "AUX_FIT"
     438        1160 :             CALL get_admm_env(qs_env%admm_env, task_list_aux_fit=task_list)
     439        1160 :             IF (admm_env%do_gapw) THEN
     440         160 :                basis_type = "AUX_FIT_SOFT"
     441         160 :                task_list => admm_env%admm_gapw_env%task_list
     442             :             END IF
     443             :             CALL qs_rho_get(p_env%rho1_admm, &
     444             :                             rho_ao=rho1_ao, &
     445             :                             rho_g=rho_g_aux, &
     446        1160 :                             rho_r=rho_r_aux)
     447        2454 :             DO ispin = 1, SIZE(rho1_ao)
     448        1294 :                CALL dbcsr_copy(rho1_ao(ispin)%matrix, p_env%p1_admm(ispin)%matrix)
     449             :                CALL calculate_rho_elec(ks_env=ks_env, &
     450             :                                        matrix_p=rho1_ao(ispin)%matrix, &
     451             :                                        rho=rho_r_aux(ispin), &
     452             :                                        rho_gspace=rho_g_aux(ispin), &
     453             :                                        soft_valid=.FALSE., &
     454             :                                        basis_type=basis_type, &
     455        2454 :                                        task_list_external=task_list)
     456             :             END DO
     457        1160 :             IF (admm_env%do_gapw) THEN
     458         160 :                CALL get_qs_env(qs_env, para_env=para_env)
     459         160 :                CALL get_admm_env(admm_env, sab_aux_fit=sab_aux_fit)
     460             :                CALL calculate_rho_atom_coeff(qs_env, rho1_ao, &
     461             :                                              rho_atom_set=p_env%local_rho_set_admm%rho_atom_set, &
     462             :                                              qs_kind_set=admm_env%admm_gapw_env%admm_kind_set, &
     463         160 :                                              oce=admm_env%admm_gapw_env%oce, sab=sab_aux_fit, para_env=para_env)
     464             :             END IF
     465             :          END IF
     466             :       END IF
     467             : 
     468       10024 :       CALL timestop(handle)
     469             : 
     470       10024 :    END SUBROUTINE p_env_update_rho
     471             : 
     472             : ! **************************************************************************************************
     473             : !> \brief To be called after the value of psi0 has changed.
     474             : !>      Recalculates the quantities S_psi0 and m_epsilon.
     475             : !> \param p_env the perturbation environment to set
     476             : !> \param qs_env ...
     477             : !> \par History
     478             : !>      07.2002 created [fawzi]
     479             : !> \author Fawzi Mohamed
     480             : ! **************************************************************************************************
     481        1646 :    SUBROUTINE p_env_psi0_changed(p_env, qs_env)
     482             : 
     483             :       TYPE(qs_p_env_type)                                :: p_env
     484             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     485             : 
     486             :       CHARACTER(len=*), PARAMETER :: routineN = 'p_env_psi0_changed'
     487             : 
     488             :       INTEGER                                            :: handle, iounit, lfomo, n_spins, nmo, spin
     489             :       LOGICAL                                            :: was_present
     490             :       REAL(KIND=dp)                                      :: maxocc
     491        1646 :       TYPE(cp_fm_pool_p_type), DIMENSION(:), POINTER     :: ao_mo_fm_pools
     492        1646 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: psi0
     493             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     494             :       TYPE(cp_logger_type), POINTER                      :: logger
     495        1646 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s, rho_ao
     496             :       TYPE(dft_control_type), POINTER                    :: dft_control
     497        1646 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     498             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     499             :       TYPE(qs_energy_type), POINTER                      :: energy
     500             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     501             :       TYPE(qs_rho_type), POINTER                         :: rho
     502             :       TYPE(section_vals_type), POINTER                   :: input, lr_section
     503             : 
     504        1646 :       CALL timeset(routineN, handle)
     505             : 
     506        1646 :       NULLIFY (ao_mo_fm_pools, mos, psi0, matrix_s, mos, para_env, ks_env, rho, &
     507        1646 :                logger, input, lr_section, energy, matrix_ks, dft_control, rho_ao)
     508        1646 :       logger => cp_get_default_logger()
     509             : 
     510             :       CALL get_qs_env(qs_env, &
     511             :                       ks_env=ks_env, &
     512             :                       mos=mos, &
     513             :                       matrix_s=matrix_s, &
     514             :                       matrix_ks=matrix_ks, &
     515             :                       para_env=para_env, &
     516             :                       rho=rho, &
     517             :                       input=input, &
     518             :                       energy=energy, &
     519        1646 :                       dft_control=dft_control)
     520             : 
     521        1646 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     522             : 
     523        1646 :       n_spins = dft_control%nspins
     524             :       CALL mpools_get(qs_env%mpools, &
     525        1646 :                       ao_mo_fm_pools=ao_mo_fm_pools)
     526        6870 :       ALLOCATE (psi0(n_spins))
     527        3578 :       DO spin = 1, n_spins
     528        1932 :          CALL get_mo_set(mos(spin), mo_coeff=mo_coeff)
     529        1932 :          CALL cp_fm_create(psi0(spin), mo_coeff%matrix_struct)
     530        3578 :          CALL cp_fm_to_fm(mo_coeff, psi0(spin))
     531             :       END DO
     532             : 
     533        1646 :       lr_section => section_vals_get_subs_vals(input, "PROPERTIES%LINRES")
     534             :       ! def psi0d
     535        1646 :       IF (p_env%orthogonal_orbitals) THEN
     536        1646 :          IF (ASSOCIATED(p_env%psi0d)) THEN
     537           0 :             CALL cp_fm_release(p_env%psi0d)
     538             :          END IF
     539        1646 :          p_env%psi0d => psi0
     540             :       ELSE
     541             : 
     542           0 :          DO spin = 1, n_spins
     543             :             ! m_epsilon=cholesky_decomposition(psi0^T S psi0)^-1
     544             :             ! could be optimized by combining next two calls
     545             :             CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
     546             :                                          psi0(spin), &
     547             :                                          p_env%S_psi0(spin), &
     548           0 :                                          ncol=p_env%n_mo(spin), alpha=1.0_dp)
     549             :             CALL parallel_gemm(transa='T', transb='N', n=p_env%n_mo(spin), &
     550             :                                m=p_env%n_mo(spin), k=p_env%n_ao(spin), alpha=1.0_dp, &
     551             :                                matrix_a=psi0(spin), &
     552             :                                matrix_b=p_env%S_psi0(spin), &
     553           0 :                                beta=0.0_dp, matrix_c=p_env%m_epsilon(spin))
     554             :             CALL cp_fm_cholesky_decompose(p_env%m_epsilon(spin), &
     555           0 :                                           n=p_env%n_mo(spin))
     556             : 
     557             :             ! Smo_inv= (psi0^T S psi0)^-1
     558           0 :             CALL cp_fm_set_all(p_env%Smo_inv(spin), 0.0_dp, 1.0_dp)
     559             :             ! faster using cp_fm_cholesky_invert ?
     560             :             CALL cp_fm_triangular_multiply( &
     561             :                triangular_matrix=p_env%m_epsilon(spin), &
     562             :                matrix_b=p_env%Smo_inv(spin), side='R', &
     563             :                invert_tr=.TRUE., n_rows=p_env%n_mo(spin), &
     564           0 :                n_cols=p_env%n_mo(spin))
     565             :             CALL cp_fm_triangular_multiply( &
     566             :                triangular_matrix=p_env%m_epsilon(spin), &
     567             :                matrix_b=p_env%Smo_inv(spin), side='R', &
     568             :                transpose_tr=.TRUE., &
     569             :                invert_tr=.TRUE., n_rows=p_env%n_mo(spin), &
     570           0 :                n_cols=p_env%n_mo(spin))
     571             : 
     572             :             ! psi0d=psi0 (psi0^T S psi0)^-1
     573             :             ! faster using cp_fm_cholesky_invert ?
     574             :             CALL cp_fm_to_fm(psi0(spin), &
     575           0 :                              p_env%psi0d(spin))
     576             :             CALL cp_fm_triangular_multiply( &
     577             :                triangular_matrix=p_env%m_epsilon(spin), &
     578             :                matrix_b=p_env%psi0d(spin), side='R', &
     579             :                invert_tr=.TRUE., n_rows=p_env%n_ao(spin), &
     580           0 :                n_cols=p_env%n_mo(spin))
     581             :             CALL cp_fm_triangular_multiply( &
     582             :                triangular_matrix=p_env%m_epsilon(spin), &
     583             :                matrix_b=p_env%psi0d(spin), side='R', &
     584             :                transpose_tr=.TRUE., &
     585             :                invert_tr=.TRUE., n_rows=p_env%n_ao(spin), &
     586           0 :                n_cols=p_env%n_mo(spin))
     587             : 
     588             :             ! updates P
     589             :             CALL get_mo_set(mos(spin), lfomo=lfomo, &
     590           0 :                             nmo=nmo, maxocc=maxocc)
     591           0 :             IF (lfomo > nmo) THEN
     592           0 :                CALL dbcsr_set(rho_ao(spin)%matrix, 0.0_dp)
     593             :                CALL cp_dbcsr_plus_fm_fm_t(rho_ao(spin)%matrix, &
     594             :                                           matrix_v=psi0(spin), &
     595             :                                           matrix_g=p_env%psi0d(spin), &
     596           0 :                                           ncol=p_env%n_mo(spin))
     597           0 :                CALL dbcsr_scale(rho_ao(spin)%matrix, alpha_scalar=maxocc)
     598             :             ELSE
     599           0 :                CPABORT("symmetrized onesided smearing to do")
     600             :             END IF
     601             :          END DO
     602             : 
     603             :          ! updates rho
     604           0 :          CALL qs_rho_update_rho(rho_struct=rho, qs_env=qs_env)
     605             : 
     606             :          ! tells ks_env that p changed
     607           0 :          CALL qs_ks_did_change(ks_env=ks_env, rho_changed=.TRUE.)
     608             : 
     609             :       END IF
     610             : 
     611             :       ! updates K (if necessary)
     612        1646 :       CALL qs_ks_update_qs_env(qs_env)
     613             :       iounit = cp_print_key_unit_nr(logger, lr_section, "PRINT%PROGRAM_RUN_INFO", &
     614        1646 :                                     extension=".linresLog")
     615        1646 :       IF (iounit > 0) THEN
     616         798 :          CALL section_vals_get(lr_section, explicit=was_present)
     617         798 :          IF (was_present) THEN
     618             :             WRITE (UNIT=iounit, FMT="(/,(T3,A,T55,F25.14))") &
     619         159 :                "Total energy ground state:                     ", energy%total
     620             :          END IF
     621             :       END IF
     622             :       CALL cp_print_key_finished_output(iounit, logger, lr_section, &
     623        1646 :                                         "PRINT%PROGRAM_RUN_INFO")
     624             :       !-----------------------------------------------------------------------|
     625             :       ! calculates                                                            |
     626             :       ! m_epsilon = - psi0d^T times K times psi0d                             |
     627             :       !           = - [K times psi0d]^T times psi0d (because K is symmetric)  |
     628             :       !-----------------------------------------------------------------------|
     629        3578 :       DO spin = 1, n_spins
     630             :          ! S_psi0 = k times psi0d
     631             :          CALL cp_dbcsr_sm_fm_multiply(matrix_ks(spin)%matrix, &
     632             :                                       p_env%psi0d(spin), &
     633        1932 :                                       p_env%S_psi0(spin), p_env%n_mo(spin))
     634             :          ! m_epsilon = -1 times S_psi0^T times psi0d
     635             :          CALL parallel_gemm('T', 'N', &
     636             :                             p_env%n_mo(spin), p_env%n_mo(spin), p_env%n_ao(spin), &
     637             :                             -1.0_dp, p_env%S_psi0(spin), p_env%psi0d(spin), &
     638        3578 :                             0.0_dp, p_env%m_epsilon(spin))
     639             :       END DO
     640             : 
     641             :       !----------------------------------|
     642             :       ! calculates S_psi0 = S * psi0  |
     643             :       !----------------------------------|
     644             :       ! calculating this reduces the mat mult without storing a full aoxao
     645             :       ! matrix (for P). If nspin>1 you might consider calculating it on the
     646             :       ! fly to spare some memory
     647        1646 :       CALL get_qs_env(qs_env, matrix_s=matrix_s)
     648        3578 :       DO spin = 1, n_spins
     649             :          CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
     650             :                                       psi0(spin), &
     651             :                                       p_env%S_psi0(spin), &
     652        3578 :                                       p_env%n_mo(spin))
     653             :       END DO
     654             : 
     655             :       ! releases psi0
     656        1646 :       IF (p_env%orthogonal_orbitals) THEN
     657        1646 :          NULLIFY (psi0)
     658             :       ELSE
     659           0 :          CALL cp_fm_release(psi0)
     660             :       END IF
     661             : 
     662             :       ! tells kpp1_env about the change of psi0
     663        1646 :       CALL kpp1_did_change(p_env%kpp1_env)
     664             : 
     665        1646 :       CALL timestop(handle)
     666             : 
     667        1646 :    END SUBROUTINE p_env_psi0_changed
     668             : 
     669             : ! **************************************************************************************************
     670             : !> \brief Evaluates Fv (S_mo)^-1 - Sv(epsilon) and stores it in res
     671             : !> \param p_env perturbation calculation environment
     672             : !> \param qs_env the qs_env that is perturbed by this p_env
     673             : !> \param v the matrix to operate on
     674             : !> \param res the result
     675             : !> \par History
     676             : !>      10.2002, TCH, extracted single spin calculation
     677             : !> \author Thomas Chassaing
     678             : ! **************************************************************************************************
     679         544 :    SUBROUTINE p_op_l1(p_env, qs_env, v, res)
     680             : 
     681             :       ! argument
     682             :       TYPE(qs_p_env_type)                                :: p_env
     683             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     684             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(in)         :: v
     685             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(inout)      :: res
     686             : 
     687             :       INTEGER                                            :: n_spins, spin
     688             :       TYPE(dft_control_type), POINTER                    :: dft_control
     689             : 
     690         544 :       NULLIFY (dft_control)
     691         544 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     692             : 
     693         544 :       n_spins = dft_control%nspins
     694        1184 :       DO spin = 1, n_spins
     695             :          CALL p_op_l1_spin(p_env, qs_env, spin, v(spin), &
     696        1184 :                            res(spin))
     697             :       END DO
     698             : 
     699         544 :    END SUBROUTINE p_op_l1
     700             : 
     701             : ! **************************************************************************************************
     702             : !> \brief Evaluates Fv (S_mo)^-1 - Sv(epsilon) and stores it in res
     703             : !>      for a given spin
     704             : !> \param p_env perturbation calculation environment
     705             : !> \param qs_env the qs_env that is perturbed by this p_env
     706             : !> \param spin the spin to calculate (1 or 2 normally)
     707             : !> \param v the matrix to operate on
     708             : !> \param res the result
     709             : !> \par History
     710             : !>      10.2002, TCH, created
     711             : !> \author Thomas Chassaing
     712             : !> \note
     713             : !>      Same as p_op_l1 but takes a spin as additional argument.
     714             : ! **************************************************************************************************
     715        1920 :    SUBROUTINE p_op_l1_spin(p_env, qs_env, spin, v, res)
     716             : 
     717             :       ! argument
     718             :       TYPE(qs_p_env_type)                                :: p_env
     719             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     720             :       INTEGER, INTENT(IN)                                :: spin
     721             :       TYPE(cp_fm_type), INTENT(IN)                       :: v, res
     722             : 
     723             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'p_op_l1_spin'
     724             : 
     725             :       INTEGER                                            :: handle, ncol
     726             :       TYPE(cp_fm_type)                                   :: tmp
     727         640 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     728             :       TYPE(dbcsr_type), POINTER                          :: k_p
     729             :       TYPE(dft_control_type), POINTER                    :: dft_control
     730             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     731             : 
     732         640 :       CALL timeset(routineN, handle)
     733         640 :       NULLIFY (matrix_ks, matrix_s, dft_control)
     734             : 
     735             :       CALL get_qs_env(qs_env, &
     736             :                       para_env=para_env, &
     737             :                       matrix_s=matrix_s, &
     738             :                       matrix_ks=matrix_ks, &
     739         640 :                       dft_control=dft_control)
     740             : 
     741         640 :       CPASSERT(0 < spin)
     742         640 :       CPASSERT(spin <= dft_control%nspins)
     743             : 
     744         640 :       CALL cp_fm_create(tmp, v%matrix_struct)
     745             : 
     746         640 :       k_p => matrix_ks(spin)%matrix
     747         640 :       CALL cp_fm_get_info(v, ncol_global=ncol)
     748             : 
     749         640 :       IF (p_env%orthogonal_orbitals) THEN
     750         640 :          CALL cp_dbcsr_sm_fm_multiply(k_p, v, res, ncol)
     751             :       ELSE
     752           0 :          CALL cp_dbcsr_sm_fm_multiply(k_p, v, tmp, ncol)
     753             :          CALL cp_fm_symm('R', 'U', p_env%n_ao(spin), p_env%n_mo(spin), 1.0_dp, &
     754           0 :                          p_env%Smo_inv(spin), tmp, 0.0_dp, res)
     755             :       END IF
     756             : 
     757             :       CALL cp_fm_symm('R', 'U', p_env%n_ao(spin), p_env%n_mo(spin), 1.0_dp, &
     758         640 :                       p_env%m_epsilon(spin), v, 0.0_dp, tmp)
     759             :       CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, tmp, &
     760         640 :                                    res, p_env%n_mo(spin), alpha=1.0_dp, beta=1.0_dp)
     761             : 
     762         640 :       CALL cp_fm_release(tmp)
     763         640 :       CALL timestop(handle)
     764             : 
     765         640 :    END SUBROUTINE p_op_l1_spin
     766             : 
     767             : ! **************************************************************************************************
     768             : !> \brief evaluates res = alpha kpp1(v)*psi0 + beta res
     769             : !>      with kpp1 evaluated with p=qs_env%rho%rho_ao, p1=p1
     770             : !> \param p_env the perturbation environment
     771             : !> \param qs_env the qs_env that is perturbed by this p_env
     772             : !> \param p1 direction in which evaluate the second derivative
     773             : !> \param res place where to store the result
     774             : !> \param alpha scale factor of the result (defaults to 1.0)
     775             : !> \param beta scale factor of the old values (defaults to 0.0)
     776             : !> \par History
     777             : !>      02.09.2002 adapted for new qs_p_env_type (TC)
     778             : !>      03.2003 extended for p1 not taken from v (TC)
     779             : !> \author fawzi
     780             : !> \note
     781             : !>      qs_env%rho must be up to date
     782             : !>      it would be better to pass rho1, not p1
     783             : ! **************************************************************************************************
     784         478 :    SUBROUTINE p_op_l2(p_env, qs_env, p1, res, alpha, beta)
     785             : 
     786             :       TYPE(qs_p_env_type)                                :: p_env
     787             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     788             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: p1
     789             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT)      :: res
     790             :       REAL(KIND=dp), INTENT(in), OPTIONAL                :: alpha, beta
     791             : 
     792             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'p_op_l2'
     793             :       LOGICAL, PARAMETER                                 :: fdiff = .FALSE.
     794             : 
     795             :       INTEGER                                            :: handle, ispin, n_spins
     796             :       LOGICAL                                            :: gapw, gapw_xc
     797             :       REAL(KIND=dp)                                      :: my_alpha, my_beta
     798         478 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho1_ao
     799             :       TYPE(dft_control_type), POINTER                    :: dft_control
     800             :       TYPE(qs_rho_type), POINTER                         :: rho
     801             : 
     802         478 :       CALL timeset(routineN, handle)
     803         478 :       NULLIFY (dft_control, rho, rho1_ao)
     804             : 
     805         478 :       CALL get_qs_env(qs_env, dft_control=dft_control, rho=rho)
     806             : 
     807         478 :       gapw = dft_control%qs_control%gapw
     808         478 :       gapw_xc = dft_control%qs_control%gapw_xc
     809         478 :       my_alpha = 1.0_dp
     810         478 :       IF (PRESENT(alpha)) my_alpha = alpha
     811         478 :       my_beta = 0.0_dp
     812         478 :       IF (PRESENT(beta)) my_beta = beta
     813             : 
     814         478 :       CALL p_env_check_i_alloc(p_env, qs_env=qs_env)
     815         478 :       n_spins = dft_control%nspins
     816             : 
     817         478 :       CALL qs_rho_get(p_env%rho1, rho_ao=rho1_ao)
     818        1028 :       DO ispin = 1, SIZE(p1)
     819             :          ! hack to avoid crashes in ep regs
     820        1028 :          IF (.NOT. ASSOCIATED(rho1_ao(ispin)%matrix, p1(ispin)%matrix)) THEN
     821         550 :             CALL dbcsr_copy(rho1_ao(ispin)%matrix, p1(ispin)%matrix)
     822             :          END IF
     823             :       END DO
     824             : 
     825         478 :       IF (gapw) THEN
     826           0 :          CALL qs_rho_update_rho(rho_struct=p_env%rho1, qs_env=qs_env, local_rho_set=p_env%local_rho_set)
     827         478 :       ELSEIF (gapw_xc) THEN
     828             :          CALL qs_rho_update_rho(rho_struct=p_env%rho1, qs_env=qs_env, rho_xc_external=p_env%rho1_xc, &
     829           0 :                                 local_rho_set=p_env%local_rho_set)
     830             :       ELSE
     831         478 :          CALL qs_rho_update_rho(rho_struct=p_env%rho1, qs_env=qs_env)
     832             :       END IF
     833             : 
     834             :       IF (fdiff) THEN
     835             :          CPASSERT(.NOT. (gapw .OR. gapw_xc))
     836             :          CALL kpp1_calc_k_p_p1_fdiff(qs_env=qs_env, &
     837             :                                      k_p_p1=p_env%kpp1, rho=rho, rho1=p_env%rho1)
     838             :       ELSE
     839             :          CALL kpp1_calc_k_p_p1(p_env=p_env, qs_env=qs_env, &
     840         478 :                                rho1=p_env%rho1, rho1_xc=p_env%rho1_xc)
     841             :       END IF
     842             : 
     843        1028 :       DO ispin = 1, n_spins
     844             :          CALL cp_dbcsr_sm_fm_multiply(p_env%kpp1(ispin)%matrix, &
     845             :                                       p_env%psi0d(ispin), res(ispin), &
     846             :                                       ncol=p_env%n_mo(ispin), &
     847        1028 :                                       alpha=my_alpha, beta=my_beta)
     848             :       END DO
     849             : 
     850         478 :       CALL timestop(handle)
     851             : 
     852         478 :    END SUBROUTINE p_op_l2
     853             : 
     854             : ! **************************************************************************************************
     855             : !> \brief does a preorthogonalization of the given matrix:
     856             : !>      v = (I-PS)v
     857             : !> \param p_env the perturbation environment
     858             : !> \param qs_env the qs_env that is perturbed by this p_env
     859             : !> \param v matrix to orthogonalize
     860             : !> \param n_cols the number of columns of C to multiply (defaults to size(v,2))
     861             : !> \par History
     862             : !>      02.09.2002 adapted for new qs_p_env_type (TC)
     863             : !> \author Fawzi Mohamed
     864             : ! **************************************************************************************************
     865         544 :    SUBROUTINE p_preortho(p_env, qs_env, v, n_cols)
     866             : 
     867             :       TYPE(qs_p_env_type)                                :: p_env
     868             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     869             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(inout)      :: v
     870             :       INTEGER, DIMENSION(:), INTENT(in), OPTIONAL        :: n_cols
     871             : 
     872             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'p_preortho'
     873             : 
     874             :       INTEGER                                            :: cols, handle, max_cols, maxnmo, n_spins, &
     875             :                                                             nmo2, spin, v_cols, v_rows
     876             :       TYPE(cp_fm_pool_type), POINTER                     :: maxmo_maxmo_fm_pool
     877             :       TYPE(cp_fm_struct_type), POINTER                   :: maxmo_maxmo_fmstruct, tmp_fmstruct
     878             :       TYPE(cp_fm_type)                                   :: tmp_matrix
     879             :       TYPE(dft_control_type), POINTER                    :: dft_control
     880             : 
     881         544 :       CALL timeset(routineN, handle)
     882             : 
     883         544 :       NULLIFY (maxmo_maxmo_fm_pool, maxmo_maxmo_fmstruct, tmp_fmstruct, &
     884         544 :                dft_control)
     885             : 
     886         544 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     887         544 :       CALL mpools_get(qs_env%mpools, maxmo_maxmo_fm_pool=maxmo_maxmo_fm_pool)
     888         544 :       n_spins = dft_control%nspins
     889         544 :       maxmo_maxmo_fmstruct => fm_pool_get_el_struct(maxmo_maxmo_fm_pool)
     890         544 :       CALL cp_fm_struct_get(maxmo_maxmo_fmstruct, nrow_global=nmo2, ncol_global=maxnmo)
     891         544 :       CPASSERT(SIZE(v) >= n_spins)
     892             :       ! alloc tmp storage
     893         544 :       IF (PRESENT(n_cols)) THEN
     894           0 :          max_cols = MAXVAL(n_cols(1:n_spins))
     895             :       ELSE
     896         544 :          max_cols = 0
     897        1184 :          DO spin = 1, n_spins
     898         640 :             CALL cp_fm_get_info(v(spin), ncol_global=v_cols)
     899        1184 :             max_cols = MAX(max_cols, v_cols)
     900             :          END DO
     901             :       END IF
     902         544 :       IF (max_cols <= nmo2) THEN
     903         544 :          CALL fm_pool_create_fm(maxmo_maxmo_fm_pool, tmp_matrix)
     904             :       ELSE
     905             :          CALL cp_fm_struct_create(tmp_fmstruct, nrow_global=max_cols, &
     906           0 :                                   ncol_global=maxnmo, template_fmstruct=maxmo_maxmo_fmstruct)
     907           0 :          CALL cp_fm_create(tmp_matrix, matrix_struct=tmp_fmstruct)
     908           0 :          CALL cp_fm_struct_release(tmp_fmstruct)
     909             :       END IF
     910             : 
     911        1184 :       DO spin = 1, n_spins
     912             : 
     913             :          CALL cp_fm_get_info(v(spin), &
     914         640 :                              nrow_global=v_rows, ncol_global=v_cols)
     915         640 :          CPASSERT(v_rows >= p_env%n_ao(spin))
     916         640 :          cols = v_cols
     917         640 :          IF (PRESENT(n_cols)) THEN
     918           0 :             CPASSERT(n_cols(spin) <= cols)
     919           0 :             cols = n_cols(spin)
     920             :          END IF
     921         640 :          CPASSERT(cols <= max_cols)
     922             : 
     923             :          ! tmp_matrix = v^T (S psi0)
     924             :          CALL parallel_gemm(transa='T', transb='N', m=cols, n=p_env%n_mo(spin), &
     925             :                             k=p_env%n_ao(spin), alpha=1.0_dp, matrix_a=v(spin), &
     926             :                             matrix_b=p_env%S_psi0(spin), beta=0.0_dp, &
     927         640 :                             matrix_c=tmp_matrix)
     928             :          ! v = v - psi0d tmp_matrix^T = v - psi0d psi0^T S v
     929             :          CALL parallel_gemm(transa='N', transb='T', m=p_env%n_ao(spin), n=cols, &
     930             :                             k=p_env%n_mo(spin), alpha=-1.0_dp, &
     931             :                             matrix_a=p_env%psi0d(spin), matrix_b=tmp_matrix, &
     932        1824 :                             beta=1.0_dp, matrix_c=v(spin))
     933             : 
     934             :       END DO
     935             : 
     936         544 :       IF (max_cols <= nmo2) THEN
     937         544 :          CALL fm_pool_give_back_fm(maxmo_maxmo_fm_pool, tmp_matrix)
     938             :       ELSE
     939           0 :          CALL cp_fm_release(tmp_matrix)
     940             :       END IF
     941             : 
     942         544 :       CALL timestop(handle)
     943             : 
     944         544 :    END SUBROUTINE p_preortho
     945             : 
     946             : ! **************************************************************************************************
     947             : !> \brief does a postorthogonalization on the given matrix vector:
     948             : !>      v = (I-SP) v
     949             : !> \param p_env the perturbation environment
     950             : !> \param qs_env the qs_env that is perturbed by this p_env
     951             : !> \param v matrix to orthogonalize
     952             : !> \param n_cols the number of columns of C to multiply (defaults to size(v,2))
     953             : !> \par History
     954             : !>      07.2002 created [fawzi]
     955             : !> \author Fawzi Mohamed
     956             : ! **************************************************************************************************
     957         544 :    SUBROUTINE p_postortho(p_env, qs_env, v, n_cols)
     958             : 
     959             :       TYPE(qs_p_env_type)                                :: p_env
     960             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     961             :       TYPE(cp_fm_type), DIMENSION(:), INTENT(inout)      :: v
     962             :       INTEGER, DIMENSION(:), INTENT(in), OPTIONAL        :: n_cols
     963             : 
     964             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'p_postortho'
     965             : 
     966             :       INTEGER                                            :: cols, handle, max_cols, maxnmo, n_spins, &
     967             :                                                             nmo2, spin, v_cols, v_rows
     968             :       TYPE(cp_fm_pool_type), POINTER                     :: maxmo_maxmo_fm_pool
     969             :       TYPE(cp_fm_struct_type), POINTER                   :: maxmo_maxmo_fmstruct, tmp_fmstruct
     970             :       TYPE(cp_fm_type)                                   :: tmp_matrix
     971             :       TYPE(dft_control_type), POINTER                    :: dft_control
     972             : 
     973         544 :       CALL timeset(routineN, handle)
     974             : 
     975         544 :       NULLIFY (maxmo_maxmo_fm_pool, maxmo_maxmo_fmstruct, tmp_fmstruct, &
     976         544 :                dft_control)
     977             : 
     978         544 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     979         544 :       CALL mpools_get(qs_env%mpools, maxmo_maxmo_fm_pool=maxmo_maxmo_fm_pool)
     980         544 :       n_spins = dft_control%nspins
     981         544 :       maxmo_maxmo_fmstruct => fm_pool_get_el_struct(maxmo_maxmo_fm_pool)
     982         544 :       CALL cp_fm_struct_get(maxmo_maxmo_fmstruct, nrow_global=nmo2, ncol_global=maxnmo)
     983         544 :       CPASSERT(SIZE(v) >= n_spins)
     984             :       ! alloc tmp storage
     985         544 :       IF (PRESENT(n_cols)) THEN
     986           0 :          max_cols = MAXVAL(n_cols(1:n_spins))
     987             :       ELSE
     988         544 :          max_cols = 0
     989        1184 :          DO spin = 1, n_spins
     990         640 :             CALL cp_fm_get_info(v(spin), ncol_global=v_cols)
     991        1184 :             max_cols = MAX(max_cols, v_cols)
     992             :          END DO
     993             :       END IF
     994         544 :       IF (max_cols <= nmo2) THEN
     995         544 :          CALL fm_pool_create_fm(maxmo_maxmo_fm_pool, tmp_matrix)
     996             :       ELSE
     997             :          CALL cp_fm_struct_create(tmp_fmstruct, nrow_global=max_cols, &
     998           0 :                                   ncol_global=maxnmo, template_fmstruct=maxmo_maxmo_fmstruct)
     999           0 :          CALL cp_fm_create(tmp_matrix, matrix_struct=tmp_fmstruct)
    1000           0 :          CALL cp_fm_struct_release(tmp_fmstruct)
    1001             :       END IF
    1002             : 
    1003        1184 :       DO spin = 1, n_spins
    1004             : 
    1005             :          CALL cp_fm_get_info(v(spin), &
    1006         640 :                              nrow_global=v_rows, ncol_global=v_cols)
    1007         640 :          CPASSERT(v_rows >= p_env%n_ao(spin))
    1008         640 :          cols = v_cols
    1009         640 :          IF (PRESENT(n_cols)) THEN
    1010           0 :             CPASSERT(n_cols(spin) <= cols)
    1011           0 :             cols = n_cols(spin)
    1012             :          END IF
    1013         640 :          CPASSERT(cols <= max_cols)
    1014             : 
    1015             :          ! tmp_matrix = v^T psi0d
    1016             :          CALL parallel_gemm(transa='T', transb='N', m=cols, n=p_env%n_mo(spin), &
    1017             :                             k=p_env%n_ao(spin), alpha=1.0_dp, matrix_a=v(spin), &
    1018             :                             matrix_b=p_env%psi0d(spin), beta=0.0_dp, &
    1019         640 :                             matrix_c=tmp_matrix)
    1020             :          ! v = v - (S psi0) tmp_matrix^T = v - S psi0 psi0d^T v
    1021             :          CALL parallel_gemm(transa='N', transb='T', m=p_env%n_ao(spin), n=cols, &
    1022             :                             k=p_env%n_mo(spin), alpha=-1.0_dp, &
    1023             :                             matrix_a=p_env%S_psi0(spin), matrix_b=tmp_matrix, &
    1024        1824 :                             beta=1.0_dp, matrix_c=v(spin))
    1025             : 
    1026             :       END DO
    1027             : 
    1028         544 :       IF (max_cols <= nmo2) THEN
    1029         544 :          CALL fm_pool_give_back_fm(maxmo_maxmo_fm_pool, tmp_matrix)
    1030             :       ELSE
    1031           0 :          CALL cp_fm_release(tmp_matrix)
    1032             :       END IF
    1033             : 
    1034         544 :       CALL timestop(handle)
    1035             : 
    1036         544 :    END SUBROUTINE p_postortho
    1037             : 
    1038             : ! **************************************************************************************************
    1039             : !> \brief ...
    1040             : !> \param qs_env ...
    1041             : !> \param p_env ...
    1042             : ! **************************************************************************************************
    1043        2492 :    SUBROUTINE p_env_finish_kpp1(qs_env, p_env)
    1044             :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
    1045             :       TYPE(qs_p_env_type), INTENT(IN)                    :: p_env
    1046             : 
    1047             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'p_env_finish_kpp1'
    1048             : 
    1049             :       INTEGER                                            :: handle, ispin, nao, nao_aux
    1050             :       TYPE(admm_type), POINTER                           :: admm_env
    1051             :       TYPE(dbcsr_type)                                   :: work_hmat
    1052             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1053             : 
    1054        2492 :       CALL timeset(routineN, handle)
    1055             : 
    1056        2492 :       CALL get_qs_env(qs_env, dft_control=dft_control, admm_env=admm_env)
    1057             : 
    1058        2492 :       IF (dft_control%do_admm) THEN
    1059        2048 :          CALL dbcsr_copy(work_hmat, p_env%kpp1(1)%matrix)
    1060             : 
    1061        2048 :          CALL cp_fm_get_info(admm_env%A, nrow_global=nao_aux, ncol_global=nao)
    1062        4368 :          DO ispin = 1, SIZE(p_env%kpp1)
    1063             :             CALL cp_dbcsr_sm_fm_multiply(p_env%kpp1_admm(ispin)%matrix, admm_env%A, admm_env%work_aux_orb, &
    1064        2320 :                                          ncol=nao, alpha=1.0_dp, beta=0.0_dp)
    1065             :             CALL parallel_gemm('T', 'N', nao, nao, nao_aux, 1.0_dp, admm_env%A, &
    1066        2320 :                                admm_env%work_aux_orb, 0.0_dp, admm_env%work_orb_orb)
    1067        2320 :             CALL dbcsr_set(work_hmat, 0.0_dp)
    1068        2320 :             CALL copy_fm_to_dbcsr(admm_env%work_orb_orb, work_hmat, keep_sparsity=.TRUE.)
    1069        4368 :             CALL dbcsr_add(p_env%kpp1(ispin)%matrix, work_hmat, 1.0_dp, 1.0_dp)
    1070             :          END DO
    1071             : 
    1072        2048 :          CALL dbcsr_release(work_hmat)
    1073             :       END IF
    1074             : 
    1075        2492 :       CALL timestop(handle)
    1076             : 
    1077        2492 :    END SUBROUTINE p_env_finish_kpp1
    1078             : 
    1079             : END MODULE qs_p_env_methods

Generated by: LCOV version 1.15