LCOV - code coverage report
Current view: top level - src - qs_scf_loop_utils.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:c740a4b) Lines: 182 208 87.5 %
Date: 2025-05-29 08:02:39 Functions: 11 11 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : ! **************************************************************************************************
       8             : !> \brief Utility routines for qs_scf
       9             : ! **************************************************************************************************
      10             : MODULE qs_scf_loop_utils
      11             :    USE cp_control_types,                ONLY: dft_control_type,&
      12             :                                               hairy_probes_type
      13             :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      14             :                                               dbcsr_get_info,&
      15             :                                               dbcsr_p_type,&
      16             :                                               dbcsr_type
      17             :    USE cp_external_control,             ONLY: external_control
      18             :    USE cp_log_handling,                 ONLY: cp_to_string
      19             :    USE input_section_types,             ONLY: section_vals_type
      20             :    USE kinds,                           ONLY: default_string_length,&
      21             :                                               dp
      22             :    USE kpoint_types,                    ONLY: kpoint_type
      23             :    USE message_passing,                 ONLY: mp_para_env_type
      24             :    USE qs_density_matrices,             ONLY: calculate_density_matrix
      25             :    USE qs_density_mixing_types,         ONLY: broyden_mixing_nr,&
      26             :                                               direct_mixing_nr,&
      27             :                                               gspace_mixing_nr,&
      28             :                                               multisecant_mixing_nr,&
      29             :                                               no_mixing_nr,&
      30             :                                               pulay_mixing_nr
      31             :    USE qs_energy_types,                 ONLY: qs_energy_type
      32             :    USE qs_environment_types,            ONLY: get_qs_env,&
      33             :                                               qs_environment_type
      34             :    USE qs_fb_env_methods,               ONLY: fb_env_do_diag
      35             :    USE qs_gspace_mixing,                ONLY: gspace_mixing
      36             :    USE qs_ks_types,                     ONLY: qs_ks_did_change,&
      37             :                                               qs_ks_env_type
      38             :    USE qs_mixing_utils,                 ONLY: self_consistency_check
      39             :    USE qs_mo_occupation,                ONLY: set_mo_occupation
      40             :    USE qs_mo_types,                     ONLY: mo_set_type
      41             :    USE qs_mom_methods,                  ONLY: do_mom_diag
      42             :    USE qs_ot_scf,                       ONLY: ot_scf_destroy,&
      43             :                                               ot_scf_mini
      44             :    USE qs_outer_scf,                    ONLY: outer_loop_gradient
      45             :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
      46             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      47             :                                               qs_rho_type
      48             :    USE qs_scf_diagonalization,          ONLY: do_block_davidson_diag,&
      49             :                                               do_block_krylov_diag,&
      50             :                                               do_general_diag,&
      51             :                                               do_general_diag_kp,&
      52             :                                               do_ot_diag,&
      53             :                                               do_roks_diag,&
      54             :                                               do_scf_diag_subspace,&
      55             :                                               do_special_diag
      56             :    USE qs_scf_methods,                  ONLY: scf_env_density_mixing
      57             :    USE qs_scf_output,                   ONLY: qs_scf_print_summary
      58             :    USE qs_scf_types,                    ONLY: &
      59             :         block_davidson_diag_method_nr, block_krylov_diag_method_nr, filter_matrix_diag_method_nr, &
      60             :         general_diag_method_nr, ot_diag_method_nr, ot_method_nr, qs_scf_env_type, &
      61             :         smeagol_method_nr, special_diag_method_nr
      62             :    USE scf_control_types,               ONLY: scf_control_type,&
      63             :                                               smear_type
      64             :    USE smeagol_interface,               ONLY: run_smeagol_emtrans
      65             : #include "./base/base_uses.f90"
      66             : 
      67             :    IMPLICIT NONE
      68             : 
      69             :    PRIVATE
      70             : 
      71             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_loop_utils'
      72             : 
      73             :    PUBLIC :: qs_scf_set_loop_flags, &
      74             :              qs_scf_new_mos, qs_scf_new_mos_kp, &
      75             :              qs_scf_density_mixing, qs_scf_check_inner_exit, &
      76             :              qs_scf_check_outer_exit, qs_scf_inner_finalize, qs_scf_rho_update
      77             : 
      78             : CONTAINS
      79             : 
      80             : ! **************************************************************************************************
      81             : !> \brief computes properties for a given hamiltonian using the current wfn
      82             : !> \param scf_env ...
      83             : !> \param diis_step ...
      84             : !> \param energy_only ...
      85             : !> \param just_energy ...
      86             : !> \param exit_inner_loop ...
      87             : ! **************************************************************************************************
      88       18429 :    SUBROUTINE qs_scf_set_loop_flags(scf_env, diis_step, &
      89             :                                     energy_only, just_energy, exit_inner_loop)
      90             : 
      91             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
      92             :       LOGICAL                                            :: diis_step, energy_only, just_energy, &
      93             :                                                             exit_inner_loop
      94             : 
      95             : ! Some flags needed to be set at the beginning of the loop
      96             : 
      97       18429 :       diis_step = .FALSE.
      98       18429 :       energy_only = .FALSE.
      99       18429 :       just_energy = .FALSE.
     100             : 
     101             :       ! SCF loop, optimisation of the wfn coefficients
     102             :       ! qs_env%rho%rho_r and qs_env%rho%rho_g should be up to date here
     103             : 
     104       18429 :       scf_env%iter_count = 0
     105       18429 :       exit_inner_loop = .FALSE.
     106             : 
     107       18429 :    END SUBROUTINE qs_scf_set_loop_flags
     108             : 
     109             : ! **************************************************************************************************
     110             : !> \brief takes known energy and derivatives and produces new wfns
     111             : !>        and or density matrix
     112             : !> \param qs_env ...
     113             : !> \param scf_env ...
     114             : !> \param scf_control ...
     115             : !> \param scf_section ...
     116             : !> \param diis_step ...
     117             : !> \param energy_only ...
     118             : !> \param probe ...
     119             : ! **************************************************************************************************
     120      153811 :    SUBROUTINE qs_scf_new_mos(qs_env, scf_env, scf_control, scf_section, diis_step, &
     121             :                              energy_only, probe)
     122             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     123             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     124             :       TYPE(scf_control_type), POINTER                    :: scf_control
     125             :       TYPE(section_vals_type), POINTER                   :: scf_section
     126             :       LOGICAL                                            :: diis_step, energy_only
     127             :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     128             :          POINTER                                         :: probe
     129             : 
     130             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_scf_new_mos'
     131             : 
     132             :       INTEGER                                            :: handle, ispin
     133             :       LOGICAL                                            :: has_unit_metric, skip_diag_sub
     134      153811 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     135             :       TYPE(dft_control_type), POINTER                    :: dft_control
     136      153811 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     137             :       TYPE(qs_energy_type), POINTER                      :: energy
     138             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     139             :       TYPE(qs_rho_type), POINTER                         :: rho
     140             : 
     141      153811 :       CALL timeset(routineN, handle)
     142             : 
     143      153811 :       NULLIFY (energy, ks_env, matrix_ks, matrix_s, rho, mos, dft_control)
     144             : 
     145             :       CALL get_qs_env(qs_env=qs_env, &
     146             :                       matrix_s=matrix_s, energy=energy, &
     147             :                       ks_env=ks_env, &
     148             :                       matrix_ks=matrix_ks, rho=rho, mos=mos, &
     149             :                       dft_control=dft_control, &
     150      153811 :                       has_unit_metric=has_unit_metric)
     151      153811 :       scf_env%iter_param = 0.0_dp
     152             : 
     153             :       ! transfer total_zeff_corr from qs_env to scf_env only if
     154             :       ! correct_el_density_dip is switched on [SGh]
     155      153811 :       IF (dft_control%correct_el_density_dip) THEN
     156          40 :          scf_env%sum_zeff_corr = qs_env%total_zeff_corr
     157          40 :          IF (ABS(qs_env%total_zeff_corr) > 0.0_dp) THEN
     158          40 :             IF (scf_env%method /= general_diag_method_nr) THEN
     159             :                CALL cp_abort(__LOCATION__, &
     160             :                              "Please use ALGORITHM STANDARD in "// &
     161             :                              "SCF%DIAGONALIZATION if "// &
     162             :                              "CORE_CORRECTION /= 0.0 and "// &
     163           0 :                              "SURFACE_DIPOLE_CORRECTION TRUE ")
     164          40 :             ELSEIF (dft_control%roks) THEN
     165             :                CALL cp_abort(__LOCATION__, &
     166             :                              "Combination of "// &
     167             :                              "CORE_CORRECTION /= 0.0 and "// &
     168             :                              "SURFACE_DIPOLE_CORRECTION TRUE "// &
     169           0 :                              "is not implemented with ROKS")
     170          40 :             ELSEIF (scf_control%diagonalization%mom) THEN
     171             :                CALL cp_abort(__LOCATION__, &
     172             :                              "Combination of "// &
     173             :                              "CORE_CORRECTION /= 0.0 and "// &
     174             :                              "SURFACE_DIPOLE_CORRECTION TRUE "// &
     175           0 :                              "is not implemented with SCF%MOM")
     176             :             END IF
     177             :          END IF
     178             :       END IF
     179             : 
     180      153811 :       SELECT CASE (scf_env%method)
     181             :       CASE DEFAULT
     182             :          CALL cp_abort(__LOCATION__, &
     183             :                        "unknown scf method: "// &
     184           0 :                        cp_to_string(scf_env%method))
     185             : 
     186             :          ! *************************************************************************
     187             :          ! Filter matrix diagonalisation: ugly implementation at this point of time
     188             :          ! *************************************************************************
     189             :       CASE (filter_matrix_diag_method_nr)
     190             : 
     191          80 :          IF (ABS(qs_env%total_zeff_corr) > 0.0_dp) THEN
     192             :             CALL cp_abort(__LOCATION__, &
     193             :                           "CORE_CORRECTION /= 0.0 plus SURFACE_DIPOLE_CORRECTION TRUE "// &
     194           0 :                           "requires SCF%DIAGONALIZATION: ALGORITHM STANDARD")
     195             :          END IF
     196             :          CALL fb_env_do_diag(scf_env%filter_matrix_env, qs_env, &
     197          80 :                              matrix_ks, matrix_s, scf_section, diis_step)
     198             : 
     199             :          ! Diagonlization in non orthonormal case
     200             :       CASE (general_diag_method_nr)
     201       65787 :          IF (dft_control%roks) THEN
     202             :             CALL do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
     203             :                               scf_control, scf_section, diis_step, &
     204         528 :                               has_unit_metric)
     205             :          ELSE
     206       65259 :             IF (scf_control%diagonalization%mom) THEN
     207             :                CALL do_mom_diag(scf_env, mos, matrix_ks, &
     208             :                                 matrix_s, scf_control, scf_section, &
     209         324 :                                 diis_step)
     210             :             ELSE
     211       64935 :                IF (dft_control%hairy_probes .EQV. .TRUE.) THEN
     212             :                   CALL do_general_diag(scf_env, mos, matrix_ks, &
     213             :                                        matrix_s, scf_control, scf_section, &
     214             :                                        diis_step, &
     215          14 :                                        probe)
     216             :                ELSE
     217             :                   CALL do_general_diag(scf_env, mos, matrix_ks, &
     218             :                                        matrix_s, scf_control, scf_section, &
     219       64921 :                                        diis_step)
     220             :                END IF
     221             :             END IF
     222       65259 :             IF (scf_control%do_diag_sub) THEN
     223             :                skip_diag_sub = (scf_env%subspace_env%eps_diag_sub > 0.0_dp) .AND. &
     224          10 :                                (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%subspace_env%eps_diag_sub)
     225             :                IF (.NOT. skip_diag_sub) THEN
     226             :                   CALL do_scf_diag_subspace(qs_env, scf_env, scf_env%subspace_env, mos, rho, &
     227          10 :                                             ks_env, scf_section, scf_control)
     228             :                END IF
     229             :             END IF
     230             :          END IF
     231             :          ! Diagonlization in orthonormal case
     232             :       CASE (special_diag_method_nr)
     233       18410 :          IF (dft_control%roks) THEN
     234             :             CALL do_roks_diag(scf_env, mos, matrix_ks, matrix_s, &
     235             :                               scf_control, scf_section, diis_step, &
     236         512 :                               has_unit_metric)
     237             :          ELSE
     238             :             CALL do_special_diag(scf_env, mos, matrix_ks, &
     239             :                                  scf_control, scf_section, &
     240       17898 :                                  diis_step)
     241             :          END IF
     242             :          ! OT diagonalization
     243             :       CASE (ot_diag_method_nr)
     244             :          CALL do_ot_diag(scf_env, mos, matrix_ks, matrix_s, &
     245          64 :                          scf_control, scf_section, diis_step)
     246             :          ! Block Krylov diagonlization
     247             :       CASE (block_krylov_diag_method_nr)
     248          40 :          IF ((scf_env%krylov_space%eps_std_diag > 0.0_dp) .AND. &
     249             :              (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%krylov_space%eps_std_diag)) THEN
     250           2 :             IF (scf_env%krylov_space%always_check_conv) THEN
     251             :                CALL do_block_krylov_diag(scf_env, mos, matrix_ks, &
     252           0 :                                          scf_control, scf_section, check_moconv_only=.TRUE.)
     253             :             END IF
     254             :             CALL do_general_diag(scf_env, mos, matrix_ks, &
     255           2 :                                  matrix_s, scf_control, scf_section, diis_step)
     256             :          ELSE
     257             :             CALL do_block_krylov_diag(scf_env, mos, matrix_ks, &
     258          38 :                                       scf_control, scf_section)
     259             :          END IF
     260          40 :          IF (scf_control%do_diag_sub) THEN
     261             :             skip_diag_sub = (scf_env%subspace_env%eps_diag_sub > 0.0_dp) .AND. &
     262           0 :                             (scf_env%iter_count == 1 .OR. scf_env%iter_delta > scf_env%subspace_env%eps_diag_sub)
     263             :             IF (.NOT. skip_diag_sub) THEN
     264             :                CALL do_scf_diag_subspace(qs_env, scf_env, scf_env%subspace_env, mos, rho, &
     265           0 :                                          ks_env, scf_section, scf_control)
     266             :             END IF
     267             :          END IF
     268             :          ! Block Davidson diagonlization
     269             :       CASE (block_davidson_diag_method_nr)
     270             :          CALL do_block_davidson_diag(qs_env, scf_env, mos, matrix_ks, matrix_s, scf_control, &
     271          84 :                                      scf_section, .FALSE.)
     272             :          ! OT without diagonlization. Needs special treatment for SCP runs
     273             :       CASE (ot_method_nr)
     274             :          CALL qs_scf_loop_do_ot(qs_env, scf_env, scf_control%smear, mos, rho, &
     275             :                                 qs_env%mo_derivs, energy%total, &
     276      153811 :                                 matrix_s, energy_only=energy_only, has_unit_metric=has_unit_metric)
     277             :       END SELECT
     278             : 
     279      153811 :       energy%kTS = 0.0_dp
     280      153811 :       energy%efermi = 0.0_dp
     281      153811 :       CALL get_qs_env(qs_env, mos=mos)
     282      330569 :       DO ispin = 1, SIZE(mos)
     283      176758 :          energy%kTS = energy%kTS + mos(ispin)%kTS
     284      330569 :          energy%efermi = energy%efermi + mos(ispin)%mu
     285             :       END DO
     286      153811 :       energy%efermi = energy%efermi/REAL(SIZE(mos), KIND=dp)
     287             : 
     288      153811 :       CALL timestop(handle)
     289             : 
     290      153811 :    END SUBROUTINE qs_scf_new_mos
     291             : 
     292             : ! **************************************************************************************************
     293             : !> \brief Updates MOs and density matrix using diagonalization
     294             : !>        Kpoint code
     295             : !> \param qs_env ...
     296             : !> \param scf_env ...
     297             : !> \param scf_control ...
     298             : !> \param diis_step ...
     299             : !> \param probe ...
     300             : ! **************************************************************************************************
     301        5464 :    SUBROUTINE qs_scf_new_mos_kp(qs_env, scf_env, scf_control, diis_step, probe)
     302             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     303             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     304             :       TYPE(scf_control_type), POINTER                    :: scf_control
     305             :       LOGICAL                                            :: diis_step
     306             :       TYPE(hairy_probes_type), DIMENSION(:), OPTIONAL, &
     307             :          POINTER                                         :: probe
     308             : 
     309             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_scf_new_mos_kp'
     310             : 
     311             :       INTEGER                                            :: handle, ispin
     312             :       LOGICAL                                            :: has_unit_metric
     313             :       REAL(dp)                                           :: diis_error
     314        5464 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: matrix_ks, matrix_s
     315             :       TYPE(dft_control_type), POINTER                    :: dft_control
     316             :       TYPE(kpoint_type), POINTER                         :: kpoints
     317        5464 :       TYPE(mo_set_type), DIMENSION(:, :), POINTER        :: mos
     318             :       TYPE(qs_energy_type), POINTER                      :: energy
     319             : 
     320        5464 :       CALL timeset(routineN, handle)
     321             : 
     322        5464 :       NULLIFY (dft_control, kpoints, matrix_ks, matrix_s)
     323             : 
     324        5464 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, kpoints=kpoints)
     325        5464 :       scf_env%iter_param = 0.0_dp
     326             : 
     327        5464 :       IF (dft_control%roks) &
     328           0 :          CPABORT("KP code: ROKS method not available: ")
     329             : 
     330        5464 :       SELECT CASE (scf_env%method)
     331             :       CASE DEFAULT
     332             :          CALL cp_abort(__LOCATION__, &
     333             :                        "KP code: Unknown scf method: "// &
     334           0 :                        cp_to_string(scf_env%method))
     335             :       CASE (general_diag_method_nr)
     336             :          ! Diagonlization in non orthonormal case
     337        5464 :          CALL get_qs_env(qs_env, matrix_ks_kp=matrix_ks, matrix_s_kp=matrix_s)
     338        5464 :          IF (dft_control%hairy_probes .EQV. .TRUE.) THEN
     339           0 :             scf_control%smear%do_smear = .FALSE.
     340             :             CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, .TRUE., &
     341           0 :                                     diis_step, diis_error, qs_env, probe)
     342             :          ELSE
     343             :             CALL do_general_diag_kp(matrix_ks, matrix_s, kpoints, scf_env, scf_control, .TRUE., &
     344        5464 :                                     diis_step, diis_error, qs_env)
     345             :          END IF
     346        5464 :          IF (diis_step) THEN
     347        2422 :             scf_env%iter_param = diis_error
     348        2422 :             scf_env%iter_method = "DIIS/Diag."
     349             :          ELSE
     350        3042 :             IF (scf_env%mixing_method == 0) THEN
     351           0 :                scf_env%iter_method = "NoMix/Diag."
     352        3042 :             ELSE IF (scf_env%mixing_method == 1) THEN
     353        2428 :                scf_env%iter_param = scf_env%p_mix_alpha
     354        2428 :                scf_env%iter_method = "P_Mix/Diag."
     355         614 :             ELSEIF (scf_env%mixing_method > 1) THEN
     356         614 :                scf_env%iter_param = scf_env%mixing_store%alpha
     357         614 :                scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/Diag."
     358             :             END IF
     359             :          END IF
     360             :       CASE (special_diag_method_nr)
     361           0 :          CALL get_qs_env(qs_env=qs_env, has_unit_metric=has_unit_metric)
     362           0 :          CPASSERT(has_unit_metric)
     363             :          ! Diagonlization in orthonormal case
     364             :          CALL cp_abort(__LOCATION__, &
     365             :                        "KP code: Scf method not available: "// &
     366           0 :                        cp_to_string(scf_env%method))
     367             :       CASE (ot_diag_method_nr, &
     368             :             block_krylov_diag_method_nr, &
     369             :             block_davidson_diag_method_nr, &
     370             :             ot_method_nr)
     371             :          CALL cp_abort(__LOCATION__, &
     372             :                        "KP code: Scf method not available: "// &
     373           0 :                        cp_to_string(scf_env%method))
     374             :       CASE (smeagol_method_nr)
     375             :          ! SMEAGOL interface
     376           0 :          diis_step = .FALSE.
     377           0 :          IF (scf_env%mixing_method == 0) THEN
     378           0 :             scf_env%iter_method = "NoMix/SMGL"
     379           0 :          ELSE IF (scf_env%mixing_method == 1) THEN
     380           0 :             scf_env%iter_param = scf_env%p_mix_alpha
     381           0 :             scf_env%iter_method = "P_Mix/SMGL"
     382           0 :          ELSE IF (scf_env%mixing_method > 1) THEN
     383           0 :             scf_env%iter_param = scf_env%mixing_store%alpha
     384           0 :             scf_env%iter_method = TRIM(scf_env%mixing_store%iter_method)//"/SMGL"
     385             :          END IF
     386        5464 :          CALL run_smeagol_emtrans(qs_env, last=.FALSE., iter=scf_env%iter_count, rho_ao_kp=scf_env%p_mix_new)
     387             :       END SELECT
     388             : 
     389        5464 :       CALL get_qs_env(qs_env=qs_env, energy=energy)
     390        5464 :       energy%kTS = 0.0_dp
     391        5464 :       energy%efermi = 0.0_dp
     392        5464 :       mos => kpoints%kp_env(1)%kpoint_env%mos
     393       11470 :       DO ispin = 1, SIZE(mos, 2)
     394        6006 :          energy%kTS = energy%kTS + mos(1, ispin)%kTS
     395       11470 :          energy%efermi = energy%efermi + mos(1, ispin)%mu
     396             :       END DO
     397        5464 :       energy%efermi = energy%efermi/REAL(SIZE(mos, 2), KIND=dp)
     398             : 
     399        5464 :       CALL timestop(handle)
     400             : 
     401        5464 :    END SUBROUTINE qs_scf_new_mos_kp
     402             : 
     403             : ! **************************************************************************************************
     404             : !> \brief the inner loop of scf, specific to using to the orbital transformation method
     405             : !>       basically, in goes the ks matrix out goes a new p matrix
     406             : !> \param qs_env ...
     407             : !> \param scf_env ...
     408             : !> \param smear ...
     409             : !> \param mos ...
     410             : !> \param rho ...
     411             : !> \param mo_derivs ...
     412             : !> \param total_energy ...
     413             : !> \param matrix_s ...
     414             : !> \param energy_only ...
     415             : !> \param has_unit_metric ...
     416             : !> \par History
     417             : !>      03.2006 created [Joost VandeVondele]
     418             : !>      2013    moved from qs_scf [Florian Schiffmann]
     419             : ! **************************************************************************************************
     420       69346 :    SUBROUTINE qs_scf_loop_do_ot(qs_env, scf_env, smear, mos, rho, mo_derivs, total_energy, &
     421             :                                 matrix_s, energy_only, has_unit_metric)
     422             : 
     423             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     424             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     425             :       TYPE(smear_type), POINTER                          :: smear
     426             :       TYPE(mo_set_type), DIMENSION(:), INTENT(INOUT)     :: mos
     427             :       TYPE(qs_rho_type), POINTER                         :: rho
     428             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: mo_derivs
     429             :       REAL(KIND=dp), INTENT(IN)                          :: total_energy
     430             :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     431             :       LOGICAL, INTENT(INOUT)                             :: energy_only
     432             :       LOGICAL, INTENT(IN)                                :: has_unit_metric
     433             : 
     434             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'qs_scf_loop_do_ot'
     435             : 
     436             :       INTEGER                                            :: handle, ispin
     437       69346 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: rho_ao
     438             :       TYPE(dbcsr_type), POINTER                          :: orthogonality_metric
     439             : 
     440       69346 :       CALL timeset(routineN, handle)
     441       69346 :       NULLIFY (rho_ao)
     442             : 
     443       69346 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     444             : 
     445       69346 :       IF (has_unit_metric) THEN
     446       18234 :          NULLIFY (orthogonality_metric)
     447             :       ELSE
     448       51112 :          orthogonality_metric => matrix_s(1)%matrix
     449             :       END IF
     450             : 
     451             :       ! in case of LSD the first spin qs_ot_env will drive the minimization
     452             :       ! in the case of a restricted calculation, it will make sure the spin orbitals are equal
     453             : 
     454             :       CALL ot_scf_mini(mos, mo_derivs, smear, orthogonality_metric, &
     455             :                        total_energy, energy_only, scf_env%iter_delta, &
     456       69346 :                        scf_env%qs_ot_env)
     457             : 
     458      150789 :       DO ispin = 1, SIZE(mos)
     459      150789 :          CALL set_mo_occupation(mo_set=mos(ispin), smear=smear)
     460             :       END DO
     461             : 
     462      150789 :       DO ispin = 1, SIZE(mos)
     463             :          CALL calculate_density_matrix(mos(ispin), &
     464             :                                        rho_ao(ispin)%matrix, &
     465      150789 :                                        use_dbcsr=.TRUE.)
     466             :       END DO
     467             : 
     468       69346 :       scf_env%iter_method = scf_env%qs_ot_env(1)%OT_METHOD_FULL
     469       69346 :       scf_env%iter_param = scf_env%qs_ot_env(1)%ds_min
     470       69346 :       qs_env%broyden_adaptive_sigma = scf_env%qs_ot_env(1)%broyden_adaptive_sigma
     471             : 
     472       69346 :       CALL timestop(handle)
     473             : 
     474       69346 :    END SUBROUTINE qs_scf_loop_do_ot
     475             : 
     476             : ! **************************************************************************************************
     477             : !> \brief Performs the requested density mixing if any needed
     478             : !> \param scf_env   Holds SCF environment information
     479             : !> \param rho       All data for the electron density
     480             : !> \param para_env  Parallel environment
     481             : !> \param diis_step Did we do a DIIS step?
     482             : ! **************************************************************************************************
     483      157135 :    SUBROUTINE qs_scf_density_mixing(scf_env, rho, para_env, diis_step)
     484             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     485             :       TYPE(qs_rho_type), POINTER                         :: rho
     486             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     487             :       LOGICAL                                            :: diis_step
     488             : 
     489      157135 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
     490             : 
     491      157135 :       NULLIFY (rho_ao_kp)
     492             : 
     493      157135 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
     494             : 
     495      242852 :       SELECT CASE (scf_env%mixing_method)
     496             :       CASE (direct_mixing_nr)
     497             :          CALL scf_env_density_mixing(scf_env%p_mix_new, &
     498             :                                      scf_env%mixing_store, rho_ao_kp, para_env, scf_env%iter_delta, scf_env%iter_count, &
     499       85717 :                                      diis=diis_step)
     500             :       CASE (gspace_mixing_nr, pulay_mixing_nr, broyden_mixing_nr, &
     501             :             multisecant_mixing_nr)
     502             :          ! Compute the difference p_out-p_in
     503             :          CALL self_consistency_check(rho_ao_kp, scf_env%p_delta, para_env, scf_env%p_mix_new, &
     504        2072 :                                      delta=scf_env%iter_delta)
     505             :       CASE (no_mixing_nr)
     506             :       CASE DEFAULT
     507             :          CALL cp_abort(__LOCATION__, &
     508             :                        "unknown scf mixing method: "// &
     509      157135 :                        cp_to_string(scf_env%mixing_method))
     510             :       END SELECT
     511             : 
     512      157135 :    END SUBROUTINE qs_scf_density_mixing
     513             : 
     514             : ! **************************************************************************************************
     515             : !> \brief checks whether exit conditions for outer loop are satisfied
     516             : !> \param qs_env ...
     517             : !> \param scf_env ...
     518             : !> \param scf_control ...
     519             : !> \param should_stop ...
     520             : !> \param outer_loop_converged ...
     521             : !> \param exit_outer_loop ...
     522             : ! **************************************************************************************************
     523       18941 :    SUBROUTINE qs_scf_check_outer_exit(qs_env, scf_env, scf_control, should_stop, &
     524             :                                       outer_loop_converged, exit_outer_loop)
     525             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     526             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     527             :       TYPE(scf_control_type), POINTER                    :: scf_control
     528             :       LOGICAL                                            :: should_stop, outer_loop_converged, &
     529             :                                                             exit_outer_loop
     530             : 
     531             :       REAL(KIND=dp)                                      :: outer_loop_eps
     532             : 
     533       18941 :       outer_loop_converged = .TRUE.
     534       18941 :       IF (scf_control%outer_scf%have_scf) THEN
     535             :          ! We have an outer SCF loop...
     536        5451 :          scf_env%outer_scf%iter_count = scf_env%outer_scf%iter_count + 1
     537        5451 :          outer_loop_converged = .FALSE.
     538             : 
     539        5451 :          CALL outer_loop_gradient(qs_env, scf_env)
     540             :          ! Multiple constraints: get largest deviation
     541       16439 :          outer_loop_eps = SQRT(MAXVAL(scf_env%outer_scf%gradient(:, scf_env%outer_scf%iter_count)**2))
     542             : 
     543        5451 :          IF (outer_loop_eps < scf_control%outer_scf%eps_scf) outer_loop_converged = .TRUE.
     544             :       END IF
     545             : 
     546             :       exit_outer_loop = should_stop .OR. outer_loop_converged .OR. &
     547       18941 :                         scf_env%outer_scf%iter_count > scf_control%outer_scf%max_scf
     548             : 
     549       18941 :    END SUBROUTINE qs_scf_check_outer_exit
     550             : 
     551             : ! **************************************************************************************************
     552             : !> \brief checks whether exit conditions for inner loop are satisfied
     553             : !> \param qs_env ...
     554             : !> \param scf_env ...
     555             : !> \param scf_control ...
     556             : !> \param should_stop ...
     557             : !> \param just_energy ...
     558             : !> \param exit_inner_loop ...
     559             : !> \param inner_loop_converged ...
     560             : !> \param output_unit ...
     561             : ! **************************************************************************************************
     562      157135 :    SUBROUTINE qs_scf_check_inner_exit(qs_env, scf_env, scf_control, should_stop, just_energy, &
     563             :                                       exit_inner_loop, inner_loop_converged, output_unit)
     564             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     565             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     566             :       TYPE(scf_control_type), POINTER                    :: scf_control
     567             :       LOGICAL                                            :: should_stop, just_energy, &
     568             :                                                             exit_inner_loop, inner_loop_converged
     569             :       INTEGER                                            :: output_unit
     570             : 
     571      157135 :       inner_loop_converged = .FALSE.
     572      157135 :       exit_inner_loop = .FALSE.
     573             : 
     574             :       CALL external_control(should_stop, "SCF", target_time=qs_env%target_time, &
     575      157135 :                             start_time=qs_env%start_time)
     576      157135 :       IF (scf_env%iter_delta < scf_control%eps_scf) THEN
     577       15539 :          IF (output_unit > 0) THEN
     578             :             WRITE (UNIT=output_unit, FMT="(/,T3,A,I5,A/)") &
     579        7953 :                "*** SCF run converged in ", scf_env%iter_count, " steps ***"
     580             :          END IF
     581       15539 :          inner_loop_converged = .TRUE.
     582       15539 :          exit_inner_loop = .TRUE.
     583      141596 :       ELSE IF (should_stop .OR. scf_env%iter_count >= scf_control%max_scf) THEN
     584        3810 :          inner_loop_converged = .FALSE.
     585        3810 :          IF (just_energy) THEN
     586         920 :             exit_inner_loop = .FALSE.
     587             :          ELSE
     588        2890 :             exit_inner_loop = .TRUE.
     589        2890 :             IF (output_unit > 0) THEN
     590             :                WRITE (UNIT=output_unit, FMT="(/,T3,A,I5,A/)") &
     591        1451 :                   "Leaving inner SCF loop after reaching ", scf_env%iter_count, " steps."
     592             :             END IF
     593             :          END IF
     594             :       END IF
     595             : 
     596      157135 :    END SUBROUTINE qs_scf_check_inner_exit
     597             : 
     598             : ! **************************************************************************************************
     599             : !> \brief undoing density mixing. Important upon convergence
     600             : !> \param scf_env ...
     601             : !> \param rho ...
     602             : !> \param dft_control ...
     603             : !> \param para_env ...
     604             : !> \param diis_step ...
     605             : ! **************************************************************************************************
     606       18429 :    SUBROUTINE qs_scf_undo_mixing(scf_env, rho, dft_control, para_env, diis_step)
     607             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     608             :       TYPE(qs_rho_type), POINTER                         :: rho
     609             :       TYPE(dft_control_type), POINTER                    :: dft_control
     610             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     611             :       LOGICAL                                            :: diis_step
     612             : 
     613             :       CHARACTER(len=default_string_length)               :: name
     614             :       INTEGER                                            :: ic, ispin, nc
     615       18429 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
     616             : 
     617       18429 :       NULLIFY (rho_ao_kp)
     618             : 
     619       18429 :       IF (scf_env%mixing_method > 0) THEN
     620       11828 :          CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
     621       11828 :          nc = SIZE(scf_env%p_mix_new, 2)
     622       23410 :          SELECT CASE (scf_env%mixing_method)
     623             :          CASE (direct_mixing_nr)
     624             :             CALL scf_env_density_mixing(scf_env%p_mix_new, scf_env%mixing_store, &
     625             :                                         rho_ao_kp, para_env, scf_env%iter_delta, &
     626             :                                         scf_env%iter_count, diis=diis_step, &
     627       11582 :                                         invert=.TRUE.)
     628       66758 :             DO ic = 1, nc
     629      133256 :                DO ispin = 1, dft_control%nspins
     630       66498 :                   CALL dbcsr_get_info(rho_ao_kp(ispin, ic)%matrix, name=name) ! keep the name
     631      121674 :                   CALL dbcsr_copy(rho_ao_kp(ispin, ic)%matrix, scf_env%p_mix_new(ispin, ic)%matrix, name=name)
     632             :                END DO
     633             :             END DO
     634             :          CASE (gspace_mixing_nr, pulay_mixing_nr, broyden_mixing_nr, &
     635             :                multisecant_mixing_nr)
     636       26728 :             DO ic = 1, nc
     637       29584 :                DO ispin = 1, dft_control%nspins
     638       14684 :                   CALL dbcsr_get_info(rho_ao_kp(ispin, ic)%matrix, name=name) ! keep the name
     639       29338 :                   CALL dbcsr_copy(rho_ao_kp(ispin, ic)%matrix, scf_env%p_mix_new(ispin, ic)%matrix, name=name)
     640             :                END DO
     641             :             END DO
     642             :          END SELECT
     643             :       END IF
     644       18429 :    END SUBROUTINE qs_scf_undo_mixing
     645             : 
     646             : ! **************************************************************************************************
     647             : !> \brief Performs the updates rho (takes care of mixing as well)
     648             : !> \param rho ...
     649             : !> \param qs_env ...
     650             : !> \param scf_env ...
     651             : !> \param ks_env ...
     652             : !> \param mix_rho ...
     653             : ! **************************************************************************************************
     654      157135 :    SUBROUTINE qs_scf_rho_update(rho, qs_env, scf_env, ks_env, mix_rho)
     655             :       TYPE(qs_rho_type), POINTER                         :: rho
     656             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     657             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     658             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     659             :       LOGICAL, INTENT(IN)                                :: mix_rho
     660             : 
     661             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     662             : 
     663      157135 :       NULLIFY (para_env)
     664      157135 :       CALL get_qs_env(qs_env, para_env=para_env)
     665             :       ! ** update qs_env%rho
     666      157135 :       CALL qs_rho_update_rho(rho, qs_env=qs_env)
     667             :       ! ** Density mixing through density matrix or on the reciprocal space grid (exclusive)
     668      157135 :       IF (mix_rho) THEN
     669             :          CALL gspace_mixing(qs_env, scf_env%mixing_method, scf_env%mixing_store, rho, &
     670        1826 :                             para_env, scf_env%iter_count)
     671             : 
     672             :       END IF
     673      157135 :       CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
     674             : 
     675      157135 :    END SUBROUTINE qs_scf_rho_update
     676             : 
     677             : ! **************************************************************************************************
     678             : !> \brief Performs the necessary steps before leaving innner scf loop
     679             : !> \param scf_env ...
     680             : !> \param qs_env ...
     681             : !> \param diis_step ...
     682             : !> \param output_unit ...
     683             : ! **************************************************************************************************
     684       18429 :    SUBROUTINE qs_scf_inner_finalize(scf_env, qs_env, diis_step, output_unit)
     685             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     686             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     687             :       LOGICAL                                            :: diis_step
     688             :       INTEGER, INTENT(IN)                                :: output_unit
     689             : 
     690             :       LOGICAL                                            :: do_kpoints
     691             :       TYPE(dft_control_type), POINTER                    :: dft_control
     692             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     693             :       TYPE(qs_energy_type), POINTER                      :: energy
     694             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     695             :       TYPE(qs_rho_type), POINTER                         :: rho
     696             : 
     697       18429 :       NULLIFY (energy, rho, dft_control, ks_env)
     698             : 
     699             :       CALL get_qs_env(qs_env=qs_env, energy=energy, ks_env=ks_env, &
     700             :                       rho=rho, dft_control=dft_control, para_env=para_env, &
     701       18429 :                       do_kpoints=do_kpoints)
     702             : 
     703       18429 :       CALL cleanup_scf_loop(scf_env)
     704             : 
     705             :       ! now, print out energies and charges corresponding to the obtained wfn
     706             :       ! (this actually is not 100% consistent at this point)!
     707       18429 :       CALL qs_scf_print_summary(output_unit, qs_env)
     708             : 
     709       18429 :       CALL qs_scf_undo_mixing(scf_env, rho, dft_control, para_env, diis_step)
     710             : 
     711             :       !   *** update rspace rho since the mo changed
     712             :       !   *** this might not always be needed (i.e. no post calculation / no forces )
     713             :       !   *** but guarantees that rho and wfn are consistent at this point
     714       18429 :       CALL qs_scf_rho_update(rho, qs_env, scf_env, ks_env, mix_rho=.FALSE.)
     715             : 
     716       18429 :    END SUBROUTINE qs_scf_inner_finalize
     717             : 
     718             : ! **************************************************************************************************
     719             : !> \brief perform cleanup operations at the end of an scf loop
     720             : !> \param scf_env ...
     721             : !> \par History
     722             : !>      03.2006 created [Joost VandeVondele]
     723             : ! **************************************************************************************************
     724       18429 :    SUBROUTINE cleanup_scf_loop(scf_env)
     725             :       TYPE(qs_scf_env_type), INTENT(INOUT)               :: scf_env
     726             : 
     727             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'cleanup_scf_loop'
     728             : 
     729             :       INTEGER                                            :: handle, ispin
     730             : 
     731       18429 :       CALL timeset(routineN, handle)
     732             : 
     733       25030 :       SELECT CASE (scf_env%method)
     734             :       CASE (ot_method_nr)
     735       14435 :          DO ispin = 1, SIZE(scf_env%qs_ot_env)
     736       14435 :             CALL ot_scf_destroy(scf_env%qs_ot_env(ispin))
     737             :          END DO
     738        6601 :          DEALLOCATE (scf_env%qs_ot_env)
     739             :       CASE (ot_diag_method_nr)
     740             :          !
     741             :       CASE (general_diag_method_nr)
     742             :          !
     743             :       CASE (special_diag_method_nr)
     744             :          !
     745             :       CASE (block_krylov_diag_method_nr, block_davidson_diag_method_nr)
     746             :          !
     747             :       CASE (filter_matrix_diag_method_nr)
     748             :          !
     749             :       CASE (smeagol_method_nr)
     750             :          !
     751             :       CASE DEFAULT
     752             :          CALL cp_abort(__LOCATION__, &
     753             :                        "unknown scf method method:"// &
     754       18429 :                        cp_to_string(scf_env%method))
     755             :       END SELECT
     756             : 
     757       18429 :       CALL timestop(handle)
     758             : 
     759       18429 :    END SUBROUTINE cleanup_scf_loop
     760             : 
     761             : END MODULE qs_scf_loop_utils

Generated by: LCOV version 1.15