LCOV - code coverage report
Current view: top level - src - dm_ls_scf.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 92.6 % 476 441
Test Date: 2026-07-25 06:35:44 Functions: 100.0 % 12 12

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Routines for a linear scaling quickstep SCF run based on the density
      10              : !>        matrix
      11              : !> \par History
      12              : !>       2010.10 created [Joost VandeVondele]
      13              : !> \author Joost VandeVondele
      14              : ! **************************************************************************************************
      15              : MODULE dm_ls_scf
      16              :    USE arnoldi_api,                     ONLY: arnoldi_extremal
      17              :    USE bibliography,                    ONLY: Kolafa2004,&
      18              :                                               Kuhne2007,&
      19              :                                               cite_reference
      20              :    USE cp_control_types,                ONLY: dft_control_type
      21              :    USE cp_dbcsr_api,                    ONLY: &
      22              :         dbcsr_add, dbcsr_binary_read, dbcsr_binary_write, dbcsr_copy, dbcsr_create, &
      23              :         dbcsr_distribution_type, dbcsr_filter, dbcsr_get_info, dbcsr_get_occupation, &
      24              :         dbcsr_multiply, dbcsr_p_type, dbcsr_release, dbcsr_scale, dbcsr_set, dbcsr_type, &
      25              :         dbcsr_type_no_symmetry
      26              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_checksum
      27              :    USE cp_external_control,             ONLY: external_control
      28              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      29              :                                               cp_logger_get_default_unit_nr,&
      30              :                                               cp_logger_type
      31              :    USE dm_ls_chebyshev,                 ONLY: compute_chebyshev
      32              :    USE dm_ls_scf_create,                ONLY: ls_scf_create
      33              :    USE dm_ls_scf_curvy,                 ONLY: deallocate_curvy_data,&
      34              :                                               dm_ls_curvy_optimization
      35              :    USE dm_ls_scf_methods,               ONLY: apply_matrix_preconditioner,&
      36              :                                               compute_homo_lumo,&
      37              :                                               density_matrix_sign,&
      38              :                                               density_matrix_sign_fixed_mu,&
      39              :                                               density_matrix_tc2,&
      40              :                                               density_matrix_trs4,&
      41              :                                               ls_scf_init_matrix_S
      42              :    USE dm_ls_scf_qs,                    ONLY: &
      43              :         ls_nonscf_energy, ls_nonscf_ks, ls_scf_dm_to_ks, ls_scf_init_qs, ls_scf_qs_atomic_guess, &
      44              :         matrix_ls_create, matrix_ls_to_qs, matrix_qs_to_ls, rho_mixing_ls_init
      45              :    USE dm_ls_scf_types,                 ONLY: ls_scf_env_type
      46              :    USE ec_env_types,                    ONLY: energy_correction_type
      47              :    USE input_constants,                 ONLY: ls_cluster_atomic,&
      48              :                                               ls_scf_pexsi,&
      49              :                                               ls_scf_sign,&
      50              :                                               ls_scf_tc2,&
      51              :                                               ls_scf_trs4,&
      52              :                                               transport_transmission
      53              :    USE input_section_types,             ONLY: section_vals_type
      54              :    USE iterate_matrix,                  ONLY: purify_mcweeny
      55              :    USE kinds,                           ONLY: default_path_length,&
      56              :                                               default_string_length,&
      57              :                                               dp
      58              :    USE machine,                         ONLY: m_flush,&
      59              :                                               m_walltime
      60              :    USE mathlib,                         ONLY: binomial
      61              :    USE molecule_types,                  ONLY: molecule_type
      62              :    USE pao_main,                        ONLY: pao_optimization_end,&
      63              :                                               pao_optimization_start,&
      64              :                                               pao_post_scf,&
      65              :                                               pao_update
      66              :    USE pexsi_methods,                   ONLY: density_matrix_pexsi,&
      67              :                                               pexsi_finalize_scf,&
      68              :                                               pexsi_init_scf,&
      69              :                                               pexsi_set_convergence_tolerance,&
      70              :                                               pexsi_to_qs
      71              :    USE qs_diis,                         ONLY: qs_diis_b_clear_sparse,&
      72              :                                               qs_diis_b_create_sparse,&
      73              :                                               qs_diis_b_step_4lscf
      74              :    USE qs_diis_types,                   ONLY: qs_diis_b_release_sparse,&
      75              :                                               qs_diis_buffer_type_sparse
      76              :    USE qs_environment_types,            ONLY: get_qs_env,&
      77              :                                               qs_environment_type
      78              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      79              :    USE qs_nonscf_utils,                 ONLY: qs_nonscf_print_summary
      80              :    USE qs_scf_post_gpw,                 ONLY: qs_scf_post_moments,&
      81              :                                               write_mo_free_results
      82              :    USE qs_scf_post_tb,                  ONLY: scf_post_calculation_tb
      83              :    USE transport,                       ONLY: external_scf_method,&
      84              :                                               transport_initialize
      85              :    USE transport_env_types,             ONLY: transport_env_type
      86              : #include "./base/base_uses.f90"
      87              : 
      88              :    IMPLICIT NONE
      89              : 
      90              :    PRIVATE
      91              : 
      92              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dm_ls_scf'
      93              : 
      94              :    PUBLIC :: calculate_w_matrix_ls, ls_scf, post_scf_sparsities
      95              : 
      96              : CONTAINS
      97              : 
      98              : ! **************************************************************************************************
      99              : !> \brief perform an linear scaling scf procedure: entry point
     100              : !>
     101              : !> \param qs_env ...
     102              : !> \param nonscf ...
     103              : !> \par History
     104              : !>       2010.10 created [Joost VandeVondele]
     105              : !> \author Joost VandeVondele
     106              : ! **************************************************************************************************
     107          764 :    SUBROUTINE ls_scf(qs_env, nonscf)
     108              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     109              :       LOGICAL, INTENT(IN), OPTIONAL                      :: nonscf
     110              : 
     111              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ls_scf'
     112              : 
     113              :       INTEGER                                            :: handle
     114              :       LOGICAL                                            :: do_scf, pao_is_done
     115              :       TYPE(ls_scf_env_type), POINTER                     :: ls_scf_env
     116              : 
     117          764 :       CALL timeset(routineN, handle)
     118          764 :       do_scf = .TRUE.
     119          764 :       IF (PRESENT(nonscf)) do_scf = .NOT. nonscf
     120              : 
     121              :       ! Moved here from qs_environment to remove dependencies
     122          764 :       CALL ls_scf_create(qs_env)
     123          764 :       CALL get_qs_env(qs_env, ls_scf_env=ls_scf_env)
     124              : 
     125          764 :       IF (do_scf) THEN
     126          698 :          CALL pao_optimization_start(qs_env, ls_scf_env)
     127          698 :          pao_is_done = .FALSE.
     128         1614 :          DO WHILE (.NOT. pao_is_done)
     129          916 :             CALL ls_scf_init_scf(qs_env, ls_scf_env, .FALSE.)
     130          916 :             CALL pao_update(qs_env, ls_scf_env, pao_is_done)
     131          916 :             CALL ls_scf_main(qs_env, ls_scf_env, .FALSE.)
     132          916 :             CALL pao_post_scf(qs_env, ls_scf_env, pao_is_done)
     133          916 :             CALL ls_scf_post(qs_env, ls_scf_env)
     134              :          END DO
     135          698 :          CALL pao_optimization_end(ls_scf_env)
     136              :       ELSE
     137           66 :          CALL ls_scf_init_scf(qs_env, ls_scf_env, .TRUE.)
     138           66 :          CALL ls_scf_main(qs_env, ls_scf_env, .TRUE.)
     139           66 :          CALL ls_scf_post(qs_env, ls_scf_env)
     140              :       END IF
     141              : 
     142          764 :       CALL timestop(handle)
     143              : 
     144          764 :    END SUBROUTINE ls_scf
     145              : 
     146              : ! **************************************************************************************************
     147              : !> \brief initialization needed for scf
     148              : !> \param qs_env ...
     149              : !> \param ls_scf_env ...
     150              : !> \param nonscf ...
     151              : !> \par History
     152              : !>       2010.10 created [Joost VandeVondele]
     153              : !> \author Joost VandeVondele
     154              : ! **************************************************************************************************
     155          982 :    SUBROUTINE ls_scf_init_scf(qs_env, ls_scf_env, nonscf)
     156              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     157              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
     158              :       LOGICAL, INTENT(IN)                                :: nonscf
     159              : 
     160              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ls_scf_init_scf'
     161              : 
     162              :       INTEGER                                            :: handle, ispin, nspin, unit_nr
     163              :       TYPE(cp_logger_type), POINTER                      :: logger
     164          982 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, matrix_w
     165              :       TYPE(dft_control_type), POINTER                    :: dft_control
     166          982 :       TYPE(molecule_type), DIMENSION(:), POINTER         :: molecule_set
     167              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     168              :       TYPE(section_vals_type), POINTER                   :: input
     169              : 
     170          982 :       CALL timeset(routineN, handle)
     171              : 
     172              :       ! get a useful output_unit
     173          982 :       logger => cp_get_default_logger()
     174          982 :       IF (logger%para_env%is_source()) THEN
     175          491 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     176              :       ELSE
     177              :          unit_nr = -1
     178              :       END IF
     179              : 
     180              :       ! get basic quantities from the qs_env
     181              :       CALL get_qs_env(qs_env, nelectron_total=ls_scf_env%nelectron_total, &
     182              :                       matrix_s=matrix_s, &
     183              :                       matrix_w=matrix_w, &
     184              :                       ks_env=ks_env, &
     185              :                       dft_control=dft_control, &
     186              :                       molecule_set=molecule_set, &
     187              :                       input=input, &
     188              :                       has_unit_metric=ls_scf_env%has_unit_metric, &
     189              :                       para_env=ls_scf_env%para_env, &
     190          982 :                       nelectron_spin=ls_scf_env%nelectron_spin)
     191              : 
     192              :       ! needs forces ? There might be a better way to flag this
     193          982 :       ls_scf_env%calculate_forces = ASSOCIATED(matrix_w)
     194              : 
     195              :       ! some basic initialization of the QS side of things
     196          982 :       CALL ls_scf_init_qs(qs_env)
     197              : 
     198              :       ! create the matrix template for use in the ls procedures
     199              :       CALL matrix_ls_create(matrix_ls=ls_scf_env%matrix_s, matrix_qs=matrix_s(1)%matrix, &
     200          982 :                             ls_mstruct=ls_scf_env%ls_mstruct)
     201              : 
     202          982 :       nspin = ls_scf_env%nspins
     203          982 :       IF (ALLOCATED(ls_scf_env%matrix_p)) THEN
     204         1198 :          DO ispin = 1, SIZE(ls_scf_env%matrix_p)
     205         1198 :             CALL dbcsr_release(ls_scf_env%matrix_p(ispin))
     206              :          END DO
     207              :       ELSE
     208         1566 :          ALLOCATE (ls_scf_env%matrix_p(nspin))
     209              :       END IF
     210              : 
     211         1992 :       DO ispin = 1, nspin
     212              :          CALL dbcsr_create(ls_scf_env%matrix_p(ispin), template=ls_scf_env%matrix_s, &
     213         1992 :                            matrix_type=dbcsr_type_no_symmetry)
     214              :       END DO
     215              : 
     216         3956 :       ALLOCATE (ls_scf_env%matrix_ks(nspin))
     217         1992 :       DO ispin = 1, nspin
     218              :          CALL dbcsr_create(ls_scf_env%matrix_ks(ispin), template=ls_scf_env%matrix_s, &
     219         1992 :                            matrix_type=dbcsr_type_no_symmetry)
     220              :       END DO
     221              : 
     222              :       ! set up matrix S, and needed functions of S
     223          982 :       CALL ls_scf_init_matrix_s(matrix_s(1)%matrix, ls_scf_env)
     224              : 
     225              :       ! get the initial guess for the SCF
     226          982 :       CALL ls_scf_initial_guess(qs_env, ls_scf_env, nonscf)
     227              : 
     228          982 :       IF (ls_scf_env%do_rho_mixing) THEN
     229            0 :          CALL rho_mixing_ls_init(qs_env, ls_scf_env)
     230              :       END IF
     231              : 
     232          982 :       IF (ls_scf_env%do_pexsi) THEN
     233            0 :          CALL pexsi_init_scf(ks_env, ls_scf_env%pexsi, matrix_s(1)%matrix)
     234              :       END IF
     235              : 
     236          982 :       IF (qs_env%do_transport) THEN
     237            0 :          CALL transport_initialize(ks_env, qs_env%transport_env, matrix_s(1)%matrix)
     238              :       END IF
     239              : 
     240          982 :       CALL timestop(handle)
     241              : 
     242          982 :    END SUBROUTINE ls_scf_init_scf
     243              : 
     244              : ! **************************************************************************************************
     245              : !> \brief deal with the scf initial guess
     246              : !> \param qs_env ...
     247              : !> \param ls_scf_env ...
     248              : !> \param nonscf ...
     249              : !> \par History
     250              : !>       2012.11 created [Joost VandeVondele]
     251              : !> \author Joost VandeVondele
     252              : ! **************************************************************************************************
     253         1452 :    SUBROUTINE ls_scf_initial_guess(qs_env, ls_scf_env, nonscf)
     254              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     255              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
     256              :       LOGICAL, INTENT(IN)                                :: nonscf
     257              : 
     258              :       CHARACTER(len=*), PARAMETER :: routineN = 'ls_scf_initial_guess'
     259              :       INTEGER, PARAMETER                                 :: aspc_guess = 2, atomic_guess = 1, &
     260              :                                                             restart_guess = 3
     261              : 
     262              :       CHARACTER(LEN=default_path_length)                 :: file_name, project_name
     263              :       INTEGER                                            :: handle, iaspc, initial_guess_type, &
     264              :                                                             ispin, istore, naspc, unit_nr
     265              :       REAL(KIND=dp)                                      :: alpha, cs_pos
     266              :       TYPE(cp_logger_type), POINTER                      :: logger
     267              :       TYPE(dbcsr_distribution_type)                      :: dist
     268              :       TYPE(dbcsr_type)                                   :: matrix_tmp1
     269              : 
     270          512 :       IF (ls_scf_env%do_pao) RETURN ! pao has its own initial guess
     271              : 
     272          470 :       CALL timeset(routineN, handle)
     273              : 
     274              :       ! get a useful output_unit
     275          470 :       logger => cp_get_default_logger()
     276          470 :       IF (logger%para_env%is_source()) THEN
     277          235 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     278              :       ELSE
     279              :          unit_nr = -1
     280              :       END IF
     281              : 
     282          235 :       IF (unit_nr > 0) WRITE (unit_nr, '()')
     283              :       ! if there is no history go for the atomic guess, otherwise extrapolate the dm history
     284          470 :       IF (ls_scf_env%scf_history%istore == 0) THEN
     285          294 :          IF (ls_scf_env%restart_read) THEN
     286              :             initial_guess_type = restart_guess
     287              :          ELSE
     288              :             initial_guess_type = atomic_guess
     289              :          END IF
     290              :       ELSE
     291              :          initial_guess_type = aspc_guess
     292              :       END IF
     293              : 
     294              :       ! how to get the initial guess
     295              :       SELECT CASE (initial_guess_type)
     296              :       CASE (atomic_guess)
     297          290 :          CALL ls_scf_qs_atomic_guess(qs_env, ls_scf_env, ls_scf_env%energy_init, nonscf)
     298          290 :          IF (unit_nr > 0) WRITE (unit_nr, '()')
     299              :       CASE (restart_guess)
     300            4 :          project_name = logger%iter_info%project_name
     301            8 :          DO ispin = 1, SIZE(ls_scf_env%matrix_p)
     302            4 :             WRITE (file_name, '(A,I0,A)') TRIM(project_name)//"_LS_DM_SPIN_", ispin, "_RESTART.dm"
     303            4 :             CALL dbcsr_get_info(ls_scf_env%matrix_p(1), distribution=dist)
     304            4 :             CALL dbcsr_binary_read(file_name, distribution=dist, matrix_new=ls_scf_env%matrix_p(ispin))
     305            4 :             cs_pos = dbcsr_checksum(ls_scf_env%matrix_p(ispin), pos=.TRUE.)
     306           12 :             IF (unit_nr > 0) THEN
     307            2 :                WRITE (unit_nr, '(T2,A,E20.8)') "Read restart DM "//TRIM(file_name)//" with checksum: ", cs_pos
     308              :             END IF
     309              :          END DO
     310              : 
     311              :          ! directly go to computing the corresponding energy and ks matrix
     312            4 :          IF (nonscf) THEN
     313            0 :             CALL ls_nonscf_ks(qs_env, ls_scf_env, ls_scf_env%energy_init)
     314              :          ELSE
     315            4 :             CALL ls_scf_dm_to_ks(qs_env, ls_scf_env, ls_scf_env%energy_init, iscf=0)
     316              :          END IF
     317              :       CASE (aspc_guess)
     318          176 :          CALL cite_reference(Kolafa2004)
     319          176 :          CALL cite_reference(Kuhne2007)
     320          176 :          naspc = MIN(ls_scf_env%scf_history%istore, ls_scf_env%scf_history%nstore)
     321          358 :          DO ispin = 1, SIZE(ls_scf_env%matrix_p)
     322              :             ! actual extrapolation
     323          182 :             CALL dbcsr_set(ls_scf_env%matrix_p(ispin), 0.0_dp)
     324          900 :             DO iaspc = 1, naspc
     325              :                alpha = (-1.0_dp)**(iaspc + 1)*REAL(iaspc, KIND=dp)* &
     326          542 :                        binomial(2*naspc, naspc - iaspc)/binomial(2*naspc - 2, naspc - 1)
     327          542 :                istore = MOD(ls_scf_env%scf_history%istore - iaspc, ls_scf_env%scf_history%nstore) + 1
     328          724 :                CALL dbcsr_add(ls_scf_env%matrix_p(ispin), ls_scf_env%scf_history%matrix(ispin, istore), 1.0_dp, alpha)
     329              :             END DO
     330              :          END DO
     331              :       END SELECT
     332              : 
     333              :       ! which cases need getting purified and non-orthogonal ?
     334          176 :       SELECT CASE (initial_guess_type)
     335              :       CASE (atomic_guess, restart_guess)
     336              :          ! do nothing
     337              :       CASE (aspc_guess)
     338              :          ! purification can't be done on the pexsi matrix, which is not necessarily idempotent,
     339              :          ! and not stored in an ortho basis form
     340          176 :          IF (.NOT. (ls_scf_env%do_pexsi)) THEN
     341          358 :             DO ispin = 1, SIZE(ls_scf_env%matrix_p)
     342              :                ! linear combination of P's is not idempotent. A bit of McWeeny is needed to ensure it is again
     343          182 :                IF (SIZE(ls_scf_env%matrix_p) == 1) CALL dbcsr_scale(ls_scf_env%matrix_p(ispin), 0.5_dp)
     344              :                ! to ensure that noisy blocks do not build up during MD (in particular with curvy) filter that guess a bit more
     345          182 :                CALL dbcsr_filter(ls_scf_env%matrix_p(ispin), ls_scf_env%eps_filter**(2.0_dp/3.0_dp))
     346          182 :                CALL purify_mcweeny(ls_scf_env%matrix_p(ispin:ispin), ls_scf_env%eps_filter, 3)
     347          182 :                IF (SIZE(ls_scf_env%matrix_p) == 1) CALL dbcsr_scale(ls_scf_env%matrix_p(ispin), 2.0_dp)
     348              : 
     349          358 :                IF (ls_scf_env%use_s_sqrt) THEN
     350              :                   ! need to get P in the non-orthogonal basis if it was stored differently
     351              :                   CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, &
     352          182 :                                     matrix_type=dbcsr_type_no_symmetry)
     353              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_p(ispin), &
     354          182 :                                       0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
     355              :                   CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt_inv, &
     356              :                                       0.0_dp, ls_scf_env%matrix_p(ispin), &
     357          182 :                                       filter_eps=ls_scf_env%eps_filter)
     358          182 :                   CALL dbcsr_release(matrix_tmp1)
     359              : 
     360          182 :                   IF (ls_scf_env%has_s_preconditioner) THEN
     361              :                      CALL apply_matrix_preconditioner(ls_scf_env%matrix_p(ispin), "forward", &
     362          176 :                                                       ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
     363              :                   END IF
     364              :                END IF
     365              :             END DO
     366              :          END IF
     367              : 
     368              :          ! compute corresponding energy and ks matrix
     369          646 :          IF (nonscf) THEN
     370           60 :             CALL ls_nonscf_ks(qs_env, ls_scf_env, ls_scf_env%energy_init)
     371              :          ELSE
     372          116 :             CALL ls_scf_dm_to_ks(qs_env, ls_scf_env, ls_scf_env%energy_init, iscf=0)
     373              :          END IF
     374              :       END SELECT
     375              : 
     376          470 :       IF (unit_nr > 0) THEN
     377          235 :          WRITE (unit_nr, '(T2,A,F20.9)') "Energy with the initial guess:", ls_scf_env%energy_init
     378          235 :          WRITE (unit_nr, '()')
     379              :       END IF
     380              : 
     381          470 :       CALL timestop(handle)
     382              : 
     383          982 :    END SUBROUTINE ls_scf_initial_guess
     384              : 
     385              : ! **************************************************************************************************
     386              : !> \brief store a history of matrices for later use in ls_scf_initial_guess
     387              : !> \param ls_scf_env ...
     388              : !> \par History
     389              : !>       2012.11 created [Joost VandeVondele]
     390              : !> \author Joost VandeVondele
     391              : ! **************************************************************************************************
     392          470 :    SUBROUTINE ls_scf_store_result(ls_scf_env)
     393              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
     394              : 
     395              :       CHARACTER(len=*), PARAMETER :: routineN = 'ls_scf_store_result'
     396              : 
     397              :       CHARACTER(LEN=default_path_length)                 :: file_name, project_name
     398              :       INTEGER                                            :: handle, ispin, istore, unit_nr
     399              :       REAL(KIND=dp)                                      :: cs_pos
     400              :       TYPE(cp_logger_type), POINTER                      :: logger
     401              :       TYPE(dbcsr_type)                                   :: matrix_tmp1
     402              : 
     403          470 :       CALL timeset(routineN, handle)
     404              : 
     405              :       ! get a useful output_unit
     406          470 :       logger => cp_get_default_logger()
     407          470 :       IF (logger%para_env%is_source()) THEN
     408          235 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     409              :       ELSE
     410              :          unit_nr = -1
     411              :       END IF
     412              : 
     413          470 :       IF (ls_scf_env%restart_write) THEN
     414           12 :          DO ispin = 1, SIZE(ls_scf_env%matrix_p)
     415            6 :             project_name = logger%iter_info%project_name
     416            6 :             WRITE (file_name, '(A,I0,A)') TRIM(project_name)//"_LS_DM_SPIN_", ispin, "_RESTART.dm"
     417            6 :             cs_pos = dbcsr_checksum(ls_scf_env%matrix_p(ispin), pos=.TRUE.)
     418            6 :             IF (unit_nr > 0) THEN
     419            3 :                WRITE (unit_nr, '(T2,A,E20.8)') "Writing restart DM "//TRIM(file_name)//" with checksum: ", cs_pos
     420              :             END IF
     421            6 :             IF (ls_scf_env%do_transport .OR. ls_scf_env%do_pexsi) THEN
     422            0 :                IF (unit_nr > 0) THEN
     423            0 :                   WRITE (unit_nr, '(T6,A)') "The restart DM "//TRIM(file_name)//" has the sparsity of S, therefore,"
     424            0 :                   WRITE (unit_nr, '(T6,A)') "not compatible with methods that require a full DM! "
     425              :                END IF
     426              :             END IF
     427           12 :             CALL dbcsr_binary_write(ls_scf_env%matrix_p(ispin), file_name)
     428              :          END DO
     429              :       END IF
     430              : 
     431          470 :       IF (ls_scf_env%scf_history%nstore > 0) THEN
     432          462 :          ls_scf_env%scf_history%istore = ls_scf_env%scf_history%istore + 1
     433          952 :          DO ispin = 1, SIZE(ls_scf_env%matrix_p)
     434          490 :             istore = MOD(ls_scf_env%scf_history%istore - 1, ls_scf_env%scf_history%nstore) + 1
     435          490 :             CALL dbcsr_copy(ls_scf_env%scf_history%matrix(ispin, istore), ls_scf_env%matrix_p(ispin))
     436              : 
     437              :             ! if we have the sqrt around, we use it to go to the orthogonal basis
     438          952 :             IF (ls_scf_env%use_s_sqrt) THEN
     439              :                ! usually sqrt(S) * P * sqrt(S) should be available, or could be stored at least,
     440              :                ! so that the next multiplications could be saved.
     441              :                CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, &
     442          486 :                                  matrix_type=dbcsr_type_no_symmetry)
     443              : 
     444          486 :                IF (ls_scf_env%has_s_preconditioner) THEN
     445              :                   CALL apply_matrix_preconditioner(ls_scf_env%scf_history%matrix(ispin, istore), "backward", &
     446          440 :                                                    ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
     447              :                END IF
     448              :                CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt, ls_scf_env%scf_history%matrix(ispin, istore), &
     449          486 :                                    0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
     450              :                CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt, &
     451              :                                    0.0_dp, ls_scf_env%scf_history%matrix(ispin, istore), &
     452          486 :                                    filter_eps=ls_scf_env%eps_filter)
     453          486 :                CALL dbcsr_release(matrix_tmp1)
     454              :             END IF
     455              : 
     456              :          END DO
     457              :       END IF
     458              : 
     459          470 :       CALL timestop(handle)
     460              : 
     461          470 :    END SUBROUTINE ls_scf_store_result
     462              : 
     463              : ! **************************************************************************************************
     464              : !> \brief Main SCF routine. Can we keep it clean ?
     465              : !> \param qs_env ...
     466              : !> \param ls_scf_env ...
     467              : !> \param nonscf ...
     468              : !> \par History
     469              : !>       2010.10 created [Joost VandeVondele]
     470              : !> \author Joost VandeVondele
     471              : ! **************************************************************************************************
     472          982 :    SUBROUTINE ls_scf_main(qs_env, ls_scf_env, nonscf)
     473              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     474              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
     475              :       LOGICAL, INTENT(IN), OPTIONAL                      :: nonscf
     476              : 
     477              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ls_scf_main'
     478              : 
     479              :       INTEGER                                            :: handle, iscf, ispin, &
     480              :                                                             nelectron_spin_real, nmixing, nspin, &
     481              :                                                             unit_nr
     482              :       LOGICAL :: check_convergence, diis_step, do_transport, extra_scf, maxscf_reached, &
     483              :          scf_converged, should_stop, transm_maxscf_reached, transm_scf_converged
     484              :       REAL(KIND=dp)                                      :: energy_diff, energy_new, energy_old, &
     485              :                                                             eps_diis, t1, t2, tdiag
     486              :       TYPE(cp_logger_type), POINTER                      :: logger
     487          982 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     488          982 :       TYPE(dbcsr_type), ALLOCATABLE, DIMENSION(:)        :: matrix_ks_deviation, matrix_mixing_old
     489              :       TYPE(energy_correction_type), POINTER              :: ec_env
     490              :       TYPE(qs_diis_buffer_type_sparse), POINTER          :: diis_buffer
     491              :       TYPE(transport_env_type), POINTER                  :: transport_env
     492              : 
     493          982 :       CALL timeset(routineN, handle)
     494              : 
     495              :       ! get a useful output_unit
     496          982 :       logger => cp_get_default_logger()
     497          982 :       IF (logger%para_env%is_source()) THEN
     498          491 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     499              :       ELSE
     500          491 :          unit_nr = -1
     501              :       END IF
     502              : 
     503          982 :       nspin = ls_scf_env%nspins
     504              : 
     505              :       ! old quantities, useful for mixing
     506         5948 :       ALLOCATE (matrix_mixing_old(nspin), matrix_ks_deviation(nspin))
     507         1992 :       DO ispin = 1, nspin
     508         1010 :          CALL dbcsr_create(matrix_mixing_old(ispin), template=ls_scf_env%matrix_ks(ispin))
     509              : 
     510         1010 :          CALL dbcsr_create(matrix_ks_deviation(ispin), template=ls_scf_env%matrix_ks(ispin))
     511         1992 :          CALL dbcsr_set(matrix_ks_deviation(ispin), 0.0_dp)
     512              :       END DO
     513         2946 :       ls_scf_env%homo_spin(:) = 0.0_dp
     514         2946 :       ls_scf_env%lumo_spin(:) = 0.0_dp
     515              : 
     516          982 :       transm_scf_converged = .FALSE.
     517          982 :       transm_maxscf_reached = .FALSE.
     518              : 
     519          982 :       energy_old = 0.0_dp
     520          982 :       IF (ls_scf_env%scf_history%istore > 0) energy_old = ls_scf_env%energy_init
     521          982 :       check_convergence = .TRUE.
     522          982 :       iscf = 0
     523          982 :       IF (ls_scf_env%ls_diis) THEN
     524            4 :          diis_step = .FALSE.
     525            4 :          eps_diis = ls_scf_env%eps_diis
     526            4 :          nmixing = ls_scf_env%nmixing
     527              :          NULLIFY (diis_buffer)
     528            4 :          ALLOCATE (diis_buffer)
     529              :          CALL qs_diis_b_create_sparse(diis_buffer, &
     530            4 :                                       nbuffer=ls_scf_env%max_diis)
     531            4 :          CALL qs_diis_b_clear_sparse(diis_buffer)
     532            4 :          CALL get_qs_env(qs_env, matrix_s=matrix_s)
     533              :       END IF
     534              : 
     535          982 :       CALL get_qs_env(qs_env, transport_env=transport_env, do_transport=do_transport)
     536              : 
     537              :       ! the real SCF loop
     538         3156 :       DO
     539              : 
     540              :          ! check on max SCF or timing/exit
     541         3156 :          CALL external_control(should_stop, "SCF", start_time=qs_env%start_time, target_time=qs_env%target_time)
     542         3156 :          IF (do_transport) THEN
     543            0 :             maxscf_reached = should_stop .OR. iscf >= ls_scf_env%max_scf
     544              :             ! one extra scf step for post-processing in transmission calculations
     545            0 :             IF (transport_env%params%method == transport_transmission) THEN
     546            0 :                IF (transm_maxscf_reached) THEN
     547            0 :                   IF (unit_nr > 0) WRITE (unit_nr, '(T2,A)') "SCF not converged! "
     548              :                   EXIT
     549              :                END IF
     550              :                transm_maxscf_reached = maxscf_reached
     551              :             ELSE
     552            0 :                IF (maxscf_reached) THEN
     553            0 :                   IF (unit_nr > 0) WRITE (unit_nr, '(T2,A)') "SCF not converged! "
     554              :                   EXIT
     555              :                END IF
     556              :             END IF
     557              :          ELSE
     558         3156 :             IF (should_stop .OR. iscf >= ls_scf_env%max_scf) THEN
     559           46 :                IF (unit_nr > 0) WRITE (unit_nr, '(T2,A)') "SCF not converged! "
     560              :                ! Skip Harris functional calculation if ground-state is NOT converged
     561           46 :                IF (qs_env%energy_correction) THEN
     562            0 :                   CALL get_qs_env(qs_env, ec_env=ec_env)
     563            0 :                   IF (ec_env%skip_ec) ec_env%do_skip = .TRUE.
     564              :                END IF
     565              :                EXIT
     566              :             END IF
     567              :          END IF
     568              : 
     569         3110 :          t1 = m_walltime()
     570         3110 :          iscf = iscf + 1
     571              : 
     572              :          ! first get a copy of the current KS matrix
     573         3110 :          CALL get_qs_env(qs_env, matrix_ks=matrix_ks)
     574         6356 :          DO ispin = 1, nspin
     575              :             CALL matrix_qs_to_ls(ls_scf_env%matrix_ks(ispin), matrix_ks(ispin)%matrix, &
     576         3246 :                                  ls_scf_env%ls_mstruct, covariant=.TRUE.)
     577         3246 :             IF (ls_scf_env%has_s_preconditioner) THEN
     578              :                CALL apply_matrix_preconditioner(ls_scf_env%matrix_ks(ispin), "forward", &
     579         1756 :                                                 ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
     580              :             END IF
     581         6356 :             CALL dbcsr_filter(ls_scf_env%matrix_ks(ispin), ls_scf_env%eps_filter)
     582              :          END DO
     583              :          ! run curvy steps if required. Needs an idempotent DM (either perification or restart)
     584         3110 :          IF ((iscf > 1 .OR. ls_scf_env%scf_history%istore > 0) .AND. ls_scf_env%curvy_steps) THEN
     585           90 :             CALL dm_ls_curvy_optimization(ls_scf_env, energy_old, check_convergence)
     586              :          ELSE
     587              :             ! turn the KS matrix in a density matrix
     588         6164 :             DO ispin = 1, nspin
     589         3144 :                IF (nonscf) THEN
     590           66 :                   CALL dbcsr_copy(matrix_mixing_old(ispin), ls_scf_env%matrix_ks(ispin))
     591         3078 :                ELSE IF (ls_scf_env%do_rho_mixing) THEN
     592            0 :                   CALL dbcsr_copy(matrix_mixing_old(ispin), ls_scf_env%matrix_ks(ispin))
     593              :                ELSE
     594         3078 :                   IF (iscf == 1) THEN
     595              :                      ! initialize the mixing matrix with the current state if needed
     596          934 :                      CALL dbcsr_copy(matrix_mixing_old(ispin), ls_scf_env%matrix_ks(ispin))
     597              :                   ELSE
     598         2144 :                      IF (ls_scf_env%ls_diis) THEN ! ------- IF-DIIS+MIX--- START
     599           28 :                         IF (diis_step .AND. (iscf - 1) >= ls_scf_env%iter_ini_diis) THEN
     600           22 :                            IF (unit_nr > 0) THEN
     601              :                               WRITE (unit_nr, '(A61)') &
     602           11 :                                  '*************************************************************'
     603              :                               WRITE (unit_nr, '(A50,2(I3,A1),L1,A1)') &
     604           11 :                                  " Using DIIS mixed KS:  (iscf,INI_DIIS,DIIS_STEP)=(", &
     605           22 :                                  iscf, ",", ls_scf_env%iter_ini_diis, ",", diis_step, ")"
     606              :                               WRITE (unit_nr, '(A52)') &
     607           11 :                                  " KS_nw= DIIS-Linear-Combination-Previous KS matrices"
     608              :                               WRITE (unit_nr, '(61A)') &
     609           11 :                                  "*************************************************************"
     610              :                            END IF
     611              :                            CALL dbcsr_copy(matrix_mixing_old(ispin), & ! out
     612           22 :                                            ls_scf_env%matrix_ks(ispin)) ! in
     613              :                         ELSE
     614            6 :                            IF (unit_nr > 0) THEN
     615              :                               WRITE (unit_nr, '(A57)') &
     616            3 :                                  "*********************************************************"
     617              :                               WRITE (unit_nr, '(A23,F5.3,A25,I3)') &
     618            3 :                                  " Using MIXING_FRACTION=", ls_scf_env%mixing_fraction, &
     619            6 :                                  " to mix KS matrix:  iscf=", iscf
     620              :                               WRITE (unit_nr, '(A7,F5.3,A6,F5.3,A7)') &
     621            3 :                                  " KS_nw=", ls_scf_env%mixing_fraction, "*KS + ", &
     622            6 :                                  1.0_dp - ls_scf_env%mixing_fraction, "*KS_old"
     623              :                               WRITE (unit_nr, '(A57)') &
     624            3 :                                  "*********************************************************"
     625              :                            END IF
     626              :                            ! perform the mixing of ks matrices
     627              :                            CALL dbcsr_add(matrix_mixing_old(ispin), &
     628              :                                           ls_scf_env%matrix_ks(ispin), &
     629              :                                           1.0_dp - ls_scf_env%mixing_fraction, &
     630            6 :                                           ls_scf_env%mixing_fraction)
     631              :                         END IF
     632              :                      ELSE ! otherwise
     633         2116 :                         IF (unit_nr > 0) THEN
     634              :                            WRITE (unit_nr, '(A57)') &
     635         1058 :                               "*********************************************************"
     636              :                            WRITE (unit_nr, '(A23,F5.3,A25,I3)') &
     637         1058 :                               " Using MIXING_FRACTION=", ls_scf_env%mixing_fraction, &
     638         2116 :                               " to mix KS matrix:  iscf=", iscf
     639              :                            WRITE (unit_nr, '(A7,F5.3,A6,F5.3,A7)') &
     640         1058 :                               " KS_nw=", ls_scf_env%mixing_fraction, "*KS + ", &
     641         2116 :                               1.0_dp - ls_scf_env%mixing_fraction, "*KS_old"
     642              :                            WRITE (unit_nr, '(A57)') &
     643         1058 :                               "*********************************************************"
     644              :                         END IF
     645              :                         ! perform the mixing of ks matrices
     646              :                         CALL dbcsr_add(matrix_mixing_old(ispin), &
     647              :                                        ls_scf_env%matrix_ks(ispin), &
     648              :                                        1.0_dp - ls_scf_env%mixing_fraction, &
     649         2116 :                                        ls_scf_env%mixing_fraction)
     650              :                      END IF ! ------- IF-DIIS+MIX--- END
     651              :                   END IF
     652              :                END IF
     653              : 
     654              :                ! compute the density matrix that matches it
     655              :                ! we need the proper number of states
     656         3144 :                nelectron_spin_real = ls_scf_env%nelectron_spin(ispin)
     657         3144 :                IF (ls_scf_env%nspins == 1) nelectron_spin_real = nelectron_spin_real/2
     658              : 
     659         3144 :                IF (do_transport) THEN
     660            0 :                   IF (ls_scf_env%has_s_preconditioner) THEN
     661            0 :                      CPABORT("NOT YET IMPLEMENTED with S preconditioner. ")
     662              :                   END IF
     663            0 :                   IF (ls_scf_env%ls_mstruct%cluster_type /= ls_cluster_atomic) THEN
     664            0 :                      CPABORT("NOT YET IMPLEMENTED with molecular clustering. ")
     665              :                   END IF
     666              : 
     667            0 :                   extra_scf = maxscf_reached .OR. scf_converged
     668              :                   ! get the current Kohn-Sham matrix (ks) and return matrix_p evaluated using an external C routine
     669              :                   CALL external_scf_method(transport_env, ls_scf_env%matrix_s, matrix_mixing_old(ispin), &
     670              :                                            ls_scf_env%matrix_p(ispin), nelectron_spin_real, ls_scf_env%natoms, &
     671            0 :                                            energy_diff, iscf, extra_scf)
     672              : 
     673              :                ELSE
     674         4186 :                   SELECT CASE (ls_scf_env%purification_method)
     675              :                   CASE (ls_scf_sign)
     676              :                      CALL density_matrix_sign(ls_scf_env%matrix_p(ispin), ls_scf_env%mu_spin(ispin), ls_scf_env%fixed_mu, &
     677              :                                               ls_scf_env%sign_method, ls_scf_env%sign_order, matrix_mixing_old(ispin), &
     678              :                                               ls_scf_env%matrix_s, ls_scf_env%matrix_s_inv, nelectron_spin_real, &
     679              :                                               ls_scf_env%eps_filter, ls_scf_env%sign_symmetric, ls_scf_env%submatrix_sign_method, &
     680         1042 :                                               ls_scf_env%matrix_s_sqrt_inv)
     681              :                   CASE (ls_scf_tc2)
     682              :                      CALL density_matrix_tc2(ls_scf_env%matrix_p(ispin), matrix_mixing_old(ispin), ls_scf_env%matrix_s_sqrt_inv, &
     683              :                                              nelectron_spin_real, ls_scf_env%eps_filter, ls_scf_env%homo_spin(ispin), &
     684              :                                              ls_scf_env%lumo_spin(ispin), non_monotonic=ls_scf_env%non_monotonic, &
     685              :                                              eps_lanczos=ls_scf_env%eps_lanczos, max_iter_lanczos=ls_scf_env%max_iter_lanczos, &
     686          284 :                                              iounit=-1)
     687              :                   CASE (ls_scf_trs4)
     688              :                      CALL density_matrix_trs4(ls_scf_env%matrix_p(ispin), matrix_mixing_old(ispin), ls_scf_env%matrix_s_sqrt_inv, &
     689              :                                               nelectron_spin_real, ls_scf_env%eps_filter, ls_scf_env%homo_spin(ispin), &
     690              :                                               ls_scf_env%lumo_spin(ispin), ls_scf_env%mu_spin(ispin), &
     691              :                                               dynamic_threshold=ls_scf_env%dynamic_threshold, &
     692              :                                               matrix_ks_deviation=matrix_ks_deviation(ispin), &
     693              :                                               eps_lanczos=ls_scf_env%eps_lanczos, max_iter_lanczos=ls_scf_env%max_iter_lanczos, &
     694         1818 :                                               iounit=-1)
     695              :                   CASE (ls_scf_pexsi)
     696            0 :                      IF (ls_scf_env%has_s_preconditioner) THEN
     697            0 :                         CPABORT("S preconditioning not implemented in combination with the PEXSI library. ")
     698              :                      END IF
     699            0 :                      IF (ls_scf_env%ls_mstruct%cluster_type /= ls_cluster_atomic) THEN
     700              :                         CALL cp_abort(__LOCATION__, &
     701            0 :                                       "Molecular clustering not implemented in combination with the PEXSI library. ")
     702              :                      END IF
     703              :                      CALL density_matrix_pexsi(ls_scf_env%pexsi, ls_scf_env%matrix_p(ispin), ls_scf_env%pexsi%matrix_w(ispin), &
     704              :                                                ls_scf_env%pexsi%kTS(ispin), matrix_mixing_old(ispin), ls_scf_env%matrix_s, &
     705         3144 :                                                nelectron_spin_real, ls_scf_env%mu_spin(ispin), iscf, ispin)
     706              :                   END SELECT
     707              :                END IF
     708              : 
     709         3144 :                IF (ls_scf_env%has_s_preconditioner) THEN
     710              :                   CALL apply_matrix_preconditioner(ls_scf_env%matrix_p(ispin), "forward", &
     711         1756 :                                                    ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
     712              :                END IF
     713         3144 :                CALL dbcsr_filter(ls_scf_env%matrix_p(ispin), ls_scf_env%eps_filter)
     714              : 
     715         6164 :                IF (ls_scf_env%nspins == 1) CALL dbcsr_scale(ls_scf_env%matrix_p(ispin), 2.0_dp)
     716              : 
     717              :             END DO
     718              :          END IF
     719              : 
     720              :          ! compute the corresponding new energy KS matrix and new energy
     721         3110 :          IF (nonscf) THEN
     722           66 :             CALL ls_nonscf_energy(qs_env, ls_scf_env)
     723              :          ELSE
     724         3044 :             CALL ls_scf_dm_to_ks(qs_env, ls_scf_env, energy_new, iscf)
     725              :          END IF
     726              : 
     727         3110 :          IF (ls_scf_env%do_pexsi) THEN
     728            0 :             CALL pexsi_to_qs(ls_scf_env, qs_env, kTS=ls_scf_env%pexsi%kTS)
     729              :          END IF
     730              : 
     731         3110 :          t2 = m_walltime()
     732         3110 :          IF (nonscf) THEN
     733           66 :             tdiag = t2 - t1
     734           66 :             CALL qs_nonscf_print_summary(qs_env, tdiag, ls_scf_env%nelectron_total, unit_nr)
     735           66 :             EXIT
     736              :          ELSE
     737              :             ! report current SCF loop
     738         3044 :             energy_diff = energy_new - energy_old
     739         3044 :             energy_old = energy_new
     740         3044 :             IF (unit_nr > 0) THEN
     741         1522 :                WRITE (unit_nr, *)
     742         1522 :                WRITE (unit_nr, '(T2,A,I6,F20.9,F20.9,F12.6)') "SCF", iscf, energy_new, energy_diff, t2 - t1
     743         1522 :                WRITE (unit_nr, *)
     744         1522 :                CALL m_flush(unit_nr)
     745              :             END IF
     746              :          END IF
     747              : 
     748         3044 :          IF (do_transport) THEN
     749            0 :             scf_converged = check_convergence .AND. ABS(energy_diff) < ls_scf_env%eps_scf*ls_scf_env%nelectron_total
     750              :             ! one extra scf step for post-processing in transmission calculations
     751            0 :             IF (transport_env%params%method == transport_transmission) THEN
     752            0 :                IF (transm_scf_converged) EXIT
     753              :                transm_scf_converged = scf_converged
     754              :             ELSE
     755            0 :                IF (scf_converged) THEN
     756            0 :                   IF (unit_nr > 0) WRITE (unit_nr, '(/,T2,A,I5,A/)') "SCF run converged in ", iscf, " steps."
     757              :                   EXIT
     758              :                END IF
     759              :             END IF
     760              :          ELSE
     761              :             ! exit criterion on the energy only for the time being
     762         3044 :             IF (check_convergence .AND. ABS(energy_diff) < ls_scf_env%eps_scf*ls_scf_env%nelectron_total) THEN
     763          870 :                IF (unit_nr > 0) WRITE (unit_nr, '(/,T2,A,I5,A/)') "SCF run converged in ", iscf, " steps."
     764              :                ! Skip Harris functional calculation if ground-state is NOT converged
     765          870 :                IF (qs_env%energy_correction) THEN
     766           20 :                   CALL get_qs_env(qs_env, ec_env=ec_env)
     767           20 :                   IF (ec_env%skip_ec) ec_env%do_skip = .FALSE.
     768              :                END IF
     769              :                EXIT
     770              :             END IF
     771              :          END IF
     772              : 
     773         2174 :          IF (ls_scf_env%ls_diis) THEN
     774              : ! diis_buffer, buffer with 1) Kohn-Sham history matrix,
     775              : !                          2) KS error history matrix (f=KPS-SPK),
     776              : !                          3) B matrix (for finding DIIS weighting coefficients)
     777              :             CALL qs_diis_b_step_4lscf(diis_buffer, qs_env, ls_scf_env, unit_nr, &
     778              :                                       iscf, diis_step, eps_diis, nmixing, matrix_s(1)%matrix, &
     779           18 :                                       ls_scf_env%eps_filter)
     780              :          END IF
     781              : 
     782         2174 :          IF (ls_scf_env%do_pexsi) THEN
     783              :             CALL pexsi_set_convergence_tolerance(ls_scf_env%pexsi, energy_diff, &
     784              :                                                  ls_scf_env%eps_scf*ls_scf_env%nelectron_total, &
     785              :                                                  ! initialize in second scf step of first SCF cycle:
     786              :                                                  (iscf == 2) .AND. (ls_scf_env%scf_history%istore == 0), &
     787            0 :                                                  check_convergence)
     788              :          END IF
     789              : 
     790              :       END DO
     791              : 
     792              :       ! free storage
     793          982 :       IF (ls_scf_env%ls_diis) THEN
     794            4 :          CALL qs_diis_b_release_sparse(diis_buffer)
     795            4 :          DEALLOCATE (diis_buffer)
     796              :       END IF
     797         1992 :       DO ispin = 1, nspin
     798         1010 :          CALL dbcsr_release(matrix_mixing_old(ispin))
     799         1992 :          CALL dbcsr_release(matrix_ks_deviation(ispin))
     800              :       END DO
     801          982 :       DEALLOCATE (matrix_mixing_old, matrix_ks_deviation)
     802              : 
     803          982 :       CALL timestop(handle)
     804              : 
     805          982 :    END SUBROUTINE ls_scf_main
     806              : 
     807              : ! **************************************************************************************************
     808              : !> \brief after SCF we have a density matrix, and the self consistent KS matrix
     809              : !>        analyze its properties.
     810              : !> \param qs_env ...
     811              : !> \param ls_scf_env ...
     812              : !> \par History
     813              : !>       2010.10 created [Joost VandeVondele]
     814              : !> \author Joost VandeVondele
     815              : ! **************************************************************************************************
     816          982 :    SUBROUTINE ls_scf_post(qs_env, ls_scf_env)
     817              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     818              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
     819              : 
     820              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ls_scf_post'
     821              : 
     822              :       INTEGER                                            :: handle, ispin, unit_nr
     823              :       REAL(KIND=dp)                                      :: occ
     824              :       TYPE(cp_logger_type), POINTER                      :: logger
     825          982 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_w
     826              :       TYPE(dft_control_type), POINTER                    :: dft_control
     827              : 
     828          982 :       CALL timeset(routineN, handle)
     829              : 
     830          982 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     831              : 
     832              :       ! get a useful output_unit
     833          982 :       logger => cp_get_default_logger()
     834          982 :       IF (logger%para_env%is_source()) THEN
     835          491 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     836              :       ELSE
     837          491 :          unit_nr = -1
     838              :       END IF
     839              : 
     840              :       ! store the matrix for a next scf run
     841          982 :       IF (.NOT. ls_scf_env%do_pao) THEN
     842          470 :          CALL ls_scf_store_result(ls_scf_env)
     843              :       END IF
     844              : 
     845              :       ! write homo and lumo energy and occupation (if not already part of the output)
     846          982 :       IF (ls_scf_env%curvy_steps) THEN
     847           18 :          CALL post_scf_homo_lumo(ls_scf_env)
     848              : 
     849              :          ! always report P occ
     850           18 :          IF (unit_nr > 0) WRITE (unit_nr, *) ""
     851           38 :          DO ispin = 1, ls_scf_env%nspins
     852           20 :             occ = dbcsr_get_occupation(ls_scf_env%matrix_p(ispin))
     853           38 :             IF (unit_nr > 0) WRITE (unit_nr, '(T2,A,F20.12)') "Density matrix (P) occupation ", occ
     854              :          END DO
     855              :       END IF
     856              : 
     857              :       ! compute the matrix_w if associated
     858          982 :       IF (ls_scf_env%calculate_forces) THEN
     859          194 :          CALL get_qs_env(qs_env, matrix_w=matrix_w)
     860          194 :          CPASSERT(ASSOCIATED(matrix_w))
     861          194 :          IF (ls_scf_env%do_pexsi) THEN
     862            0 :             CALL pexsi_to_qs(ls_scf_env, qs_env, matrix_w=ls_scf_env%pexsi%matrix_w)
     863              :          ELSE
     864          194 :             CALL calculate_w_matrix_ls(matrix_w, ls_scf_env)
     865              :          END IF
     866              :       END IF
     867              : 
     868              :       ! compute properties
     869              : 
     870          982 :       IF (ls_scf_env%perform_mu_scan) CALL post_scf_mu_scan(ls_scf_env)
     871              : 
     872          982 :       IF (ls_scf_env%report_all_sparsities) CALL post_scf_sparsities(ls_scf_env)
     873              : 
     874          982 :       IF (dft_control%qs_control%dftb) THEN
     875           54 :          CALL scf_post_calculation_tb(qs_env, "DFTB", .TRUE.)
     876          928 :       ELSE IF (dft_control%qs_control%xtb) THEN
     877           94 :          CALL scf_post_calculation_tb(qs_env, "xTB", .TRUE.)
     878              :       ELSE
     879          834 :          CALL write_mo_free_results(qs_env)
     880              :       END IF
     881              : 
     882          982 :       IF (ls_scf_env%chebyshev%compute_chebyshev) CALL compute_chebyshev(qs_env, ls_scf_env)
     883              : 
     884          982 :       IF (.TRUE.) CALL post_scf_experiment()
     885              : 
     886          982 :       IF (dft_control%qs_control%dftb .OR. dft_control%qs_control%xtb) THEN
     887              :          !
     888              :       ELSE
     889          834 :          CALL qs_scf_post_moments(qs_env%input, logger, qs_env, unit_nr)
     890              :       END IF
     891              : 
     892              :       ! clean up used data
     893              : 
     894          982 :       CALL dbcsr_release(ls_scf_env%matrix_s)
     895          982 :       CALL deallocate_curvy_data(ls_scf_env%curvy_data)
     896              : 
     897          982 :       IF (ls_scf_env%has_s_preconditioner) THEN
     898          426 :          CALL dbcsr_release(ls_scf_env%matrix_bs_sqrt)
     899          426 :          CALL dbcsr_release(ls_scf_env%matrix_bs_sqrt_inv)
     900              :       END IF
     901              : 
     902          982 :       IF (ls_scf_env%needs_s_inv) THEN
     903          980 :          CALL dbcsr_release(ls_scf_env%matrix_s_inv)
     904              :       END IF
     905              : 
     906          982 :       IF (ls_scf_env%use_s_sqrt) THEN
     907          978 :          CALL dbcsr_release(ls_scf_env%matrix_s_sqrt)
     908          978 :          CALL dbcsr_release(ls_scf_env%matrix_s_sqrt_inv)
     909              :       END IF
     910              : 
     911         1992 :       DO ispin = 1, SIZE(ls_scf_env%matrix_ks)
     912         1992 :          CALL dbcsr_release(ls_scf_env%matrix_ks(ispin))
     913              :       END DO
     914          982 :       DEALLOCATE (ls_scf_env%matrix_ks)
     915              : 
     916          982 :       IF (ls_scf_env%do_pexsi) THEN
     917            0 :          CALL pexsi_finalize_scf(ls_scf_env%pexsi, ls_scf_env%mu_spin)
     918              :       END IF
     919              : 
     920          982 :       CALL timestop(handle)
     921              : 
     922          982 :    END SUBROUTINE ls_scf_post
     923              : 
     924              : ! **************************************************************************************************
     925              : !> \brief Compute the HOMO LUMO energies post SCF
     926              : !> \param ls_scf_env ...
     927              : !> \par History
     928              : !>       2013.06 created [Joost VandeVondele]
     929              : !> \author Joost VandeVondele
     930              : ! **************************************************************************************************
     931           18 :    SUBROUTINE post_scf_homo_lumo(ls_scf_env)
     932              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
     933              : 
     934              :       CHARACTER(len=*), PARAMETER :: routineN = 'post_scf_homo_lumo'
     935              : 
     936              :       INTEGER                                            :: handle, ispin, nspin, unit_nr
     937              :       LOGICAL                                            :: converged
     938              :       REAL(KIND=dp)                                      :: eps_max, eps_min, homo, lumo
     939              :       TYPE(cp_logger_type), POINTER                      :: logger
     940              :       TYPE(dbcsr_type)                                   :: matrix_k, matrix_p, matrix_tmp
     941              : 
     942           18 :       CALL timeset(routineN, handle)
     943              : 
     944              :       ! get a useful output_unit
     945           18 :       logger => cp_get_default_logger()
     946           18 :       IF (logger%para_env%is_source()) THEN
     947            9 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     948              :       ELSE
     949            9 :          unit_nr = -1
     950              :       END IF
     951              : 
     952           18 :       IF (unit_nr > 0) WRITE (unit_nr, '(T2,A)') ""
     953              : 
     954              :       ! TODO: remove these limitations
     955           18 :       CPASSERT(.NOT. ls_scf_env%has_s_preconditioner)
     956           18 :       CPASSERT(ls_scf_env%use_s_sqrt)
     957              : 
     958           18 :       nspin = ls_scf_env%nspins
     959              : 
     960           18 :       CALL dbcsr_create(matrix_p, template=ls_scf_env%matrix_p(1), matrix_type=dbcsr_type_no_symmetry)
     961              : 
     962           18 :       CALL dbcsr_create(matrix_k, template=ls_scf_env%matrix_p(1), matrix_type=dbcsr_type_no_symmetry)
     963              : 
     964           18 :       CALL dbcsr_create(matrix_tmp, template=ls_scf_env%matrix_p(1), matrix_type=dbcsr_type_no_symmetry)
     965              : 
     966           38 :       DO ispin = 1, nspin
     967              :          ! ortho basis ks
     968              :          CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_ks(ispin), &
     969           20 :                              0.0_dp, matrix_tmp, filter_eps=ls_scf_env%eps_filter)
     970              :          CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp, ls_scf_env%matrix_s_sqrt_inv, &
     971           20 :                              0.0_dp, matrix_k, filter_eps=ls_scf_env%eps_filter)
     972              : 
     973              :          ! extremal eigenvalues ks
     974              :          CALL arnoldi_extremal(matrix_k, eps_max, eps_min, max_iter=ls_scf_env%max_iter_lanczos, &
     975           20 :                                threshold=ls_scf_env%eps_lanczos, converged=converged)
     976              : 
     977              :          ! ortho basis p
     978              :          CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt, ls_scf_env%matrix_p(ispin), &
     979           20 :                              0.0_dp, matrix_tmp, filter_eps=ls_scf_env%eps_filter)
     980              :          CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp, ls_scf_env%matrix_s_sqrt, &
     981           20 :                              0.0_dp, matrix_p, filter_eps=ls_scf_env%eps_filter)
     982           20 :          IF (nspin == 1) CALL dbcsr_scale(matrix_p, 0.5_dp)
     983              : 
     984              :          ! go compute homo lumo
     985              :          CALL compute_homo_lumo(matrix_k, matrix_p, eps_min, eps_max, ls_scf_env%eps_filter, &
     986           58 :                                 ls_scf_env%max_iter_lanczos, ls_scf_env%eps_lanczos, homo, lumo, unit_nr)
     987              : 
     988              :       END DO
     989              : 
     990           18 :       CALL dbcsr_release(matrix_p)
     991           18 :       CALL dbcsr_release(matrix_k)
     992           18 :       CALL dbcsr_release(matrix_tmp)
     993              : 
     994           18 :       CALL timestop(handle)
     995              : 
     996           18 :    END SUBROUTINE post_scf_homo_lumo
     997              : 
     998              : ! **************************************************************************************************
     999              : !> \brief Compute the density matrix for various values of the chemical potential
    1000              : !> \param ls_scf_env ...
    1001              : !> \par History
    1002              : !>       2010.10 created [Joost VandeVondele]
    1003              : !> \author Joost VandeVondele
    1004              : ! **************************************************************************************************
    1005            2 :    SUBROUTINE post_scf_mu_scan(ls_scf_env)
    1006              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
    1007              : 
    1008              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'post_scf_mu_scan'
    1009              : 
    1010              :       INTEGER                                            :: handle, imu, ispin, nelectron_spin_real, &
    1011              :                                                             nmu, nspin, unit_nr
    1012              :       REAL(KIND=dp)                                      :: mu, t1, t2, trace
    1013              :       TYPE(cp_logger_type), POINTER                      :: logger
    1014              :       TYPE(dbcsr_type)                                   :: matrix_p
    1015              : 
    1016            2 :       CALL timeset(routineN, handle)
    1017              : 
    1018              :       ! get a useful output_unit
    1019            2 :       logger => cp_get_default_logger()
    1020            2 :       IF (logger%para_env%is_source()) THEN
    1021            1 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    1022              :       ELSE
    1023              :          unit_nr = -1
    1024              :       END IF
    1025              : 
    1026            2 :       nspin = ls_scf_env%nspins
    1027              : 
    1028            2 :       CALL dbcsr_create(matrix_p, template=ls_scf_env%matrix_p(1))
    1029              : 
    1030            2 :       nmu = 10
    1031           24 :       DO imu = 0, nmu
    1032              : 
    1033           22 :          t1 = m_walltime()
    1034              : 
    1035           22 :          mu = -0.4_dp + imu*(0.1_dp + 0.4_dp)/nmu
    1036              : 
    1037           22 :          IF (unit_nr > 0) WRITE (unit_nr, *) "------- starting with mu ", mu
    1038              : 
    1039           44 :          DO ispin = 1, nspin
    1040              :             ! we need the proper number of states
    1041           22 :             nelectron_spin_real = ls_scf_env%nelectron_spin(ispin)
    1042           22 :             IF (ls_scf_env%nspins == 1) nelectron_spin_real = nelectron_spin_real/2
    1043              : 
    1044              :             CALL density_matrix_sign_fixed_mu(matrix_p, trace, mu, ls_scf_env%sign_method, &
    1045              :                                               ls_scf_env%sign_order, ls_scf_env%matrix_ks(ispin), &
    1046              :                                               ls_scf_env%matrix_s, ls_scf_env%matrix_s_inv, &
    1047              :                                               ls_scf_env%eps_filter, ls_scf_env%sign_symmetric, &
    1048           44 :                                               ls_scf_env%submatrix_sign_method, ls_scf_env%matrix_s_sqrt_inv)
    1049              :          END DO
    1050              : 
    1051           22 :          t2 = m_walltime()
    1052              : 
    1053           24 :          IF (unit_nr > 0) WRITE (unit_nr, *) " obtained ", mu, trace, t2 - t1
    1054              : 
    1055              :       END DO
    1056              : 
    1057            2 :       CALL dbcsr_release(matrix_p)
    1058              : 
    1059            2 :       CALL timestop(handle)
    1060              : 
    1061            2 :    END SUBROUTINE post_scf_mu_scan
    1062              : 
    1063              : ! **************************************************************************************************
    1064              : !> \brief Report on the sparsities of various interesting matrices.
    1065              : !>
    1066              : !> \param ls_scf_env ...
    1067              : !> \par History
    1068              : !>       2010.10 created [Joost VandeVondele]
    1069              : !> \author Joost VandeVondele
    1070              : ! **************************************************************************************************
    1071          262 :    SUBROUTINE post_scf_sparsities(ls_scf_env)
    1072              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
    1073              : 
    1074              :       CHARACTER(len=*), PARAMETER :: routineN = 'post_scf_sparsities'
    1075              : 
    1076              :       CHARACTER(LEN=default_string_length)               :: title
    1077              :       INTEGER                                            :: handle, ispin, nspin, unit_nr
    1078              :       TYPE(cp_logger_type), POINTER                      :: logger
    1079              :       TYPE(dbcsr_type)                                   :: matrix_tmp1, matrix_tmp2
    1080              : 
    1081          262 :       CALL timeset(routineN, handle)
    1082              : 
    1083              :       ! get a useful output_unit
    1084          262 :       logger => cp_get_default_logger()
    1085          262 :       IF (logger%para_env%is_source()) THEN
    1086          131 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    1087              :       ELSE
    1088          131 :          unit_nr = -1
    1089              :       END IF
    1090              : 
    1091          262 :       nspin = ls_scf_env%nspins
    1092              : 
    1093          262 :       IF (unit_nr > 0) THEN
    1094          131 :          WRITE (unit_nr, '()')
    1095          131 :          WRITE (unit_nr, '(T2,A,E17.3)') "Sparsity reports for eps_filter: ", ls_scf_env%eps_filter
    1096          131 :          WRITE (unit_nr, '()')
    1097              :       END IF
    1098              : 
    1099              :       CALL report_matrix_sparsity(ls_scf_env%matrix_s, unit_nr, "overlap matrix (S)", &
    1100          262 :                                   ls_scf_env%eps_filter)
    1101              : 
    1102          532 :       DO ispin = 1, nspin
    1103          270 :          WRITE (title, '(A,I3)') "Kohn-Sham matrix (H) for spin ", ispin
    1104              :          CALL report_matrix_sparsity(ls_scf_env%matrix_ks(ispin), unit_nr, title, &
    1105          532 :                                      ls_scf_env%eps_filter)
    1106              :       END DO
    1107              : 
    1108          262 :       CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
    1109          262 :       CALL dbcsr_create(matrix_tmp2, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
    1110              : 
    1111          532 :       DO ispin = 1, nspin
    1112          270 :          WRITE (title, '(A,I3)') "Density matrix (P) for spin ", ispin
    1113              :          CALL report_matrix_sparsity(ls_scf_env%matrix_p(ispin), unit_nr, title, &
    1114          270 :                                      ls_scf_env%eps_filter)
    1115              : 
    1116              :          CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s, ls_scf_env%matrix_p(ispin), &
    1117          270 :                              0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
    1118              : 
    1119          270 :          WRITE (title, '(A,I3,A)') "S * P(", ispin, ")"
    1120          270 :          CALL report_matrix_sparsity(matrix_tmp1, unit_nr, title, ls_scf_env%eps_filter)
    1121              : 
    1122              :          CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s, &
    1123          270 :                              0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
    1124          270 :          WRITE (title, '(A,I3,A)') "S * P(", ispin, ") * S"
    1125          532 :          CALL report_matrix_sparsity(matrix_tmp2, unit_nr, title, ls_scf_env%eps_filter)
    1126              :       END DO
    1127              : 
    1128          262 :       IF (ls_scf_env%needs_s_inv) THEN
    1129              :          CALL report_matrix_sparsity(ls_scf_env%matrix_s_inv, unit_nr, "inv(S)", &
    1130          262 :                                      ls_scf_env%eps_filter)
    1131          532 :          DO ispin = 1, nspin
    1132              :             CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_inv, ls_scf_env%matrix_ks(ispin), &
    1133          270 :                                 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
    1134              : 
    1135          270 :             WRITE (title, '(A,I3,A)') "inv(S) * H(", ispin, ")"
    1136          532 :             CALL report_matrix_sparsity(matrix_tmp1, unit_nr, title, ls_scf_env%eps_filter)
    1137              :          END DO
    1138              :       END IF
    1139              : 
    1140          262 :       IF (ls_scf_env%use_s_sqrt) THEN
    1141              : 
    1142              :          CALL report_matrix_sparsity(ls_scf_env%matrix_s_sqrt, unit_nr, "sqrt(S)", &
    1143          260 :                                      ls_scf_env%eps_filter)
    1144              :          CALL report_matrix_sparsity(ls_scf_env%matrix_s_sqrt_inv, unit_nr, "inv(sqrt(S))", &
    1145          260 :                                      ls_scf_env%eps_filter)
    1146              : 
    1147          528 :          DO ispin = 1, nspin
    1148              :             CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt_inv, ls_scf_env%matrix_ks(ispin), &
    1149          268 :                                 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
    1150              :             CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt_inv, &
    1151          268 :                                 0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
    1152          268 :             WRITE (title, '(A,I3,A)') "inv(sqrt(S)) * H(", ispin, ") * inv(sqrt(S))"
    1153          528 :             CALL report_matrix_sparsity(matrix_tmp2, unit_nr, title, ls_scf_env%eps_filter)
    1154              :          END DO
    1155              : 
    1156          528 :          DO ispin = 1, nspin
    1157              :             CALL dbcsr_multiply("N", "N", 1.0_dp, ls_scf_env%matrix_s_sqrt, ls_scf_env%matrix_p(ispin), &
    1158          268 :                                 0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
    1159              :             CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_s_sqrt, &
    1160          268 :                                 0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
    1161          268 :             WRITE (title, '(A,I3,A)') "sqrt(S) * P(", ispin, ") * sqrt(S)"
    1162          528 :             CALL report_matrix_sparsity(matrix_tmp2, unit_nr, title, ls_scf_env%eps_filter)
    1163              :          END DO
    1164              : 
    1165              :       END IF
    1166              : 
    1167          262 :       CALL dbcsr_release(matrix_tmp1)
    1168          262 :       CALL dbcsr_release(matrix_tmp2)
    1169              : 
    1170          262 :       CALL timestop(handle)
    1171              : 
    1172          262 :    END SUBROUTINE post_scf_sparsities
    1173              : 
    1174              : ! **************************************************************************************************
    1175              : !> \brief Helper routine to report on the sparsity of a single matrix,
    1176              : !>        for several filtering values
    1177              : !> \param matrix ...
    1178              : !> \param unit_nr ...
    1179              : !> \param title ...
    1180              : !> \param eps ...
    1181              : !> \par History
    1182              : !>       2010.10 created [Joost VandeVondele]
    1183              : !> \author Joost VandeVondele
    1184              : ! **************************************************************************************************
    1185         2930 :    SUBROUTINE report_matrix_sparsity(matrix, unit_nr, title, eps)
    1186              :       TYPE(dbcsr_type)                                   :: matrix
    1187              :       INTEGER                                            :: unit_nr
    1188              :       CHARACTER(LEN=*)                                   :: title
    1189              :       REAL(KIND=dp)                                      :: eps
    1190              : 
    1191              :       CHARACTER(len=*), PARAMETER :: routineN = 'report_matrix_sparsity'
    1192              : 
    1193              :       INTEGER                                            :: handle
    1194              :       REAL(KIND=dp)                                      :: eps_local, occ
    1195              :       TYPE(dbcsr_type)                                   :: matrix_tmp
    1196              : 
    1197         2930 :       CALL timeset(routineN, handle)
    1198         2930 :       CALL dbcsr_create(matrix_tmp, template=matrix, name=TRIM(title))
    1199         2930 :       CALL dbcsr_copy(matrix_tmp, matrix, name=TRIM(title))
    1200              : 
    1201         2930 :       IF (unit_nr > 0) THEN
    1202         1465 :          WRITE (unit_nr, '(T2,A)') "Sparsity for : "//TRIM(title)
    1203              :       END IF
    1204              : 
    1205         2930 :       eps_local = MAX(eps, 10E-14_dp)
    1206        21902 :       DO
    1207        24832 :          IF (eps_local > 1.1_dp) EXIT
    1208        21902 :          CALL dbcsr_filter(matrix_tmp, eps_local)
    1209        21902 :          occ = dbcsr_get_occupation(matrix_tmp)
    1210        21902 :          IF (unit_nr > 0) WRITE (unit_nr, '(T2,F16.12,A3,F16.12)') eps_local, " : ", occ
    1211        21902 :          eps_local = eps_local*10
    1212              :       END DO
    1213              : 
    1214         2930 :       CALL dbcsr_release(matrix_tmp)
    1215              : 
    1216         2930 :       CALL timestop(handle)
    1217              : 
    1218         2930 :    END SUBROUTINE report_matrix_sparsity
    1219              : 
    1220              : ! **************************************************************************************************
    1221              : !> \brief Compute matrix_w as needed for the forces
    1222              : !> \param matrix_w ...
    1223              : !> \param ls_scf_env ...
    1224              : !> \par History
    1225              : !>       2010.11 created [Joost VandeVondele]
    1226              : !> \author Joost VandeVondele
    1227              : ! **************************************************************************************************
    1228          224 :    SUBROUTINE calculate_w_matrix_ls(matrix_w, ls_scf_env)
    1229              :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_w
    1230              :       TYPE(ls_scf_env_type)                              :: ls_scf_env
    1231              : 
    1232              :       CHARACTER(len=*), PARAMETER :: routineN = 'calculate_w_matrix_ls'
    1233              : 
    1234              :       INTEGER                                            :: handle, ispin
    1235              :       REAL(KIND=dp)                                      :: scaling
    1236              :       TYPE(dbcsr_type)                                   :: matrix_tmp1, matrix_tmp2, matrix_tmp3
    1237              : 
    1238          224 :       CALL timeset(routineN, handle)
    1239              : 
    1240          224 :       CALL dbcsr_create(matrix_tmp1, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
    1241          224 :       CALL dbcsr_create(matrix_tmp2, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
    1242          224 :       CALL dbcsr_create(matrix_tmp3, template=ls_scf_env%matrix_s, matrix_type=dbcsr_type_no_symmetry)
    1243              : 
    1244          224 :       IF (ls_scf_env%nspins == 1) THEN
    1245          216 :          scaling = 0.5_dp
    1246              :       ELSE
    1247            8 :          scaling = 1.0_dp
    1248              :       END IF
    1249              : 
    1250          456 :       DO ispin = 1, ls_scf_env%nspins
    1251              : 
    1252          232 :          CALL dbcsr_copy(matrix_tmp3, ls_scf_env%matrix_ks(ispin))
    1253          232 :          IF (ls_scf_env%has_s_preconditioner) THEN
    1254              :             CALL apply_matrix_preconditioner(matrix_tmp3, "backward", &
    1255          160 :                                              ls_scf_env%matrix_bs_sqrt, ls_scf_env%matrix_bs_sqrt_inv)
    1256              :          END IF
    1257          232 :          CALL dbcsr_filter(matrix_tmp3, ls_scf_env%eps_filter)
    1258              : 
    1259              :          CALL dbcsr_multiply("N", "N", scaling, ls_scf_env%matrix_p(ispin), matrix_tmp3, &
    1260          232 :                              0.0_dp, matrix_tmp1, filter_eps=ls_scf_env%eps_filter)
    1261              :          CALL dbcsr_multiply("N", "N", 1.0_dp, matrix_tmp1, ls_scf_env%matrix_p(ispin), &
    1262          232 :                              0.0_dp, matrix_tmp2, filter_eps=ls_scf_env%eps_filter)
    1263          456 :          CALL matrix_ls_to_qs(matrix_w(ispin)%matrix, matrix_tmp2, ls_scf_env%ls_mstruct, covariant=.FALSE.)
    1264              :       END DO
    1265              : 
    1266          224 :       CALL dbcsr_release(matrix_tmp1)
    1267          224 :       CALL dbcsr_release(matrix_tmp2)
    1268          224 :       CALL dbcsr_release(matrix_tmp3)
    1269              : 
    1270          224 :       CALL timestop(handle)
    1271              : 
    1272          224 :    END SUBROUTINE calculate_w_matrix_ls
    1273              : 
    1274              : ! **************************************************************************************************
    1275              : !> \brief a place for quick experiments
    1276              : !> \par History
    1277              : !>       2010.11 created [Joost VandeVondele]
    1278              : !> \author Joost VandeVondele
    1279              : ! **************************************************************************************************
    1280          982 :    SUBROUTINE post_scf_experiment()
    1281              : 
    1282              :       CHARACTER(len=*), PARAMETER :: routineN = 'post_scf_experiment'
    1283              : 
    1284              :       INTEGER                                            :: handle, unit_nr
    1285              :       TYPE(cp_logger_type), POINTER                      :: logger
    1286              : 
    1287          982 :       CALL timeset(routineN, handle)
    1288              : 
    1289              :       ! get a useful output_unit
    1290          982 :       logger => cp_get_default_logger()
    1291          982 :       IF (logger%para_env%is_source()) THEN
    1292          491 :          unit_nr = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
    1293              :       ELSE
    1294              :          unit_nr = -1
    1295              :       END IF
    1296              : 
    1297          982 :       CALL timestop(handle)
    1298          982 :    END SUBROUTINE post_scf_experiment
    1299              : 
    1300              : END MODULE dm_ls_scf
        

Generated by: LCOV version 2.0-1