LCOV - code coverage report
Current view: top level - src - xas_tp_scf.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:e7e05ae) Lines: 212 260 81.5 %
Date: 2024-04-18 06:59:28 Functions: 3 3 100.0 %

          Line data    Source code
       1             : !--------------------------------------------------------------------------------------------------!
       2             : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3             : !   Copyright 2000-2024 CP2K developers group <https://cp2k.org>                                   !
       4             : !                                                                                                  !
       5             : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6             : !--------------------------------------------------------------------------------------------------!
       7             : 
       8             : ! **************************************************************************************************
       9             : !> \brief xas_scf for the tp method
      10             : !>       It is repeaated for every atom that have to be excited
      11             : !> \par History
      12             : !>      created 05.2005
      13             : !> \author MI (05.2005)
      14             : ! **************************************************************************************************
      15             : MODULE xas_tp_scf
      16             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      17             :                                               get_atomic_kind
      18             :    USE cell_types,                      ONLY: cell_type,&
      19             :                                               pbc
      20             :    USE cp_array_utils,                  ONLY: cp_2d_r_p_type
      21             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      22             :    USE cp_control_types,                ONLY: dft_control_type
      23             :    USE cp_external_control,             ONLY: external_control
      24             :    USE cp_fm_types,                     ONLY: cp_fm_get_submatrix,&
      25             :                                               cp_fm_init_random,&
      26             :                                               cp_fm_set_submatrix,&
      27             :                                               cp_fm_to_fm,&
      28             :                                               cp_fm_type
      29             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      30             :                                               cp_logger_get_default_io_unit,&
      31             :                                               cp_logger_type,&
      32             :                                               cp_to_string
      33             :    USE cp_output_handling,              ONLY: cp_add_iter_level,&
      34             :                                               cp_iterate,&
      35             :                                               cp_p_file,&
      36             :                                               cp_print_key_finished_output,&
      37             :                                               cp_print_key_should_output,&
      38             :                                               cp_print_key_unit_nr,&
      39             :                                               cp_rm_iter_level
      40             :    USE dbcsr_api,                       ONLY: dbcsr_copy,&
      41             :                                               dbcsr_p_type
      42             :    USE input_constants,                 ONLY: ot_precond_full_kinetic,&
      43             :                                               ot_precond_solver_default,&
      44             :                                               xas_dscf
      45             :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      46             :                                               section_vals_type
      47             :    USE kinds,                           ONLY: dp
      48             :    USE machine,                         ONLY: m_flush,&
      49             :                                               m_walltime
      50             :    USE message_passing,                 ONLY: mp_para_env_type
      51             :    USE particle_methods,                ONLY: get_particle_set
      52             :    USE particle_types,                  ONLY: particle_type
      53             :    USE preconditioner,                  ONLY: make_preconditioner
      54             :    USE preconditioner_types,            ONLY: destroy_preconditioner,&
      55             :                                               init_preconditioner,&
      56             :                                               preconditioner_type
      57             :    USE qs_charges_types,                ONLY: qs_charges_type
      58             :    USE qs_density_matrices,             ONLY: calculate_density_matrix
      59             :    USE qs_density_mixing_types,         ONLY: broyden_mixing_nr,&
      60             :                                               direct_mixing_nr,&
      61             :                                               gspace_mixing_nr,&
      62             :                                               multisecant_mixing_nr,&
      63             :                                               no_mixing_nr,&
      64             :                                               pulay_mixing_nr
      65             :    USE qs_energy_types,                 ONLY: qs_energy_type
      66             :    USE qs_environment_types,            ONLY: get_qs_env,&
      67             :                                               qs_environment_type
      68             :    USE qs_gspace_mixing,                ONLY: gspace_mixing
      69             :    USE qs_kind_types,                   ONLY: qs_kind_type
      70             :    USE qs_ks_methods,                   ONLY: qs_ks_update_qs_env
      71             :    USE qs_ks_types,                     ONLY: qs_ks_did_change,&
      72             :                                               qs_ks_env_type
      73             :    USE qs_loc_main,                     ONLY: qs_loc_driver
      74             :    USE qs_loc_types,                    ONLY: get_qs_loc_env,&
      75             :                                               localized_wfn_control_type,&
      76             :                                               qs_loc_env_type
      77             :    USE qs_mixing_utils,                 ONLY: self_consistency_check
      78             :    USE qs_mo_io,                        ONLY: write_mo_set_to_restart
      79             :    USE qs_mo_methods,                   ONLY: calculate_subspace_eigenvalues
      80             :    USE qs_mo_occupation,                ONLY: set_mo_occupation
      81             :    USE qs_mo_types,                     ONLY: get_mo_set,&
      82             :                                               mo_set_type
      83             :    USE qs_ot_eigensolver,               ONLY: ot_eigensolver
      84             :    USE qs_rho_methods,                  ONLY: qs_rho_update_rho
      85             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
      86             :                                               qs_rho_type
      87             :    USE qs_scf,                          ONLY: scf_env_cleanup,&
      88             :                                               scf_env_do_scf
      89             :    USE qs_scf_diagonalization,          ONLY: general_eigenproblem
      90             :    USE qs_scf_initialization,           ONLY: qs_scf_env_initialize
      91             :    USE qs_scf_methods,                  ONLY: scf_env_density_mixing
      92             :    USE qs_scf_output,                   ONLY: qs_scf_print_summary
      93             :    USE qs_scf_types,                    ONLY: general_diag_method_nr,&
      94             :                                               qs_scf_env_type
      95             :    USE scf_control_types,               ONLY: scf_control_type
      96             :    USE xas_control,                     ONLY: xas_control_type
      97             :    USE xas_env_types,                   ONLY: get_xas_env,&
      98             :                                               set_xas_env,&
      99             :                                               xas_environment_type
     100             :    USE xas_restart,                     ONLY: find_excited_core_orbital,&
     101             :                                               xas_write_restart
     102             : #include "./base/base_uses.f90"
     103             : 
     104             :    IMPLICIT NONE
     105             :    PRIVATE
     106             : 
     107             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xas_tp_scf'
     108             : 
     109             :    ! *** Public subroutines ***
     110             : 
     111             :    PUBLIC :: xas_do_tp_scf, xes_scf_once
     112             : 
     113             : CONTAINS
     114             : 
     115             : ! **************************************************************************************************
     116             : !> \brief perform an scf loop to calculate the xas spectrum
     117             : !>      given by the excitation of a inner state of a selected atom
     118             : !>      by using the transition potential method
     119             : !> \param dft_control ...
     120             : !> \param xas_env the environment for XAS  calculations
     121             : !> \param iatom ...
     122             : !> \param istate keeps track of the state index for restart writing
     123             : !> \param scf_env the scf_env where to perform the scf procedure
     124             : !> \param qs_env the qs_env, the scf_env and xas_env live in
     125             : !> \param xas_section ...
     126             : !> \param scf_section ...
     127             : !> \param converged ...
     128             : !> \param should_stop ...
     129             : !> \par History
     130             : !>      05.2005 created [MI]
     131             : !> \author MI
     132             : ! **************************************************************************************************
     133         160 :    SUBROUTINE xas_do_tp_scf(dft_control, xas_env, iatom, istate, scf_env, qs_env, &
     134             :                             xas_section, scf_section, converged, should_stop)
     135             : 
     136             :       TYPE(dft_control_type), POINTER                    :: dft_control
     137             :       TYPE(xas_environment_type), POINTER                :: xas_env
     138             :       INTEGER, INTENT(IN)                                :: iatom, istate
     139             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     140             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     141             :       TYPE(section_vals_type), POINTER                   :: xas_section, scf_section
     142             :       LOGICAL, INTENT(OUT)                               :: converged, should_stop
     143             : 
     144             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'xas_do_tp_scf'
     145             : 
     146             :       INTEGER                                            :: handle, handle2, hole_spin, ispin, &
     147             :                                                             iter_count, my_spin, nspin, occ_spin, &
     148             :                                                             output_unit
     149             :       LOGICAL                                            :: diis_step, energy_only, exit_loop, gapw
     150             :       REAL(KIND=dp)                                      :: t1, t2
     151          80 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     152             :       TYPE(cp_logger_type), POINTER                      :: logger
     153          80 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
     154          80 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: rho_ao_kp
     155          80 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     156             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     157          80 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     158             :       TYPE(qs_charges_type), POINTER                     :: qs_charges
     159             :       TYPE(qs_energy_type), POINTER                      :: energy
     160          80 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     161             :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     162             :       TYPE(qs_rho_type), POINTER                         :: rho
     163             :       TYPE(scf_control_type), POINTER                    :: scf_control
     164             :       TYPE(section_vals_type), POINTER                   :: dft_section
     165             :       TYPE(xas_control_type), POINTER                    :: xas_control
     166             : 
     167          80 :       CALL timeset(routineN, handle)
     168          80 :       NULLIFY (xas_control, matrix_s, matrix_ks, para_env, rho_ao_kp)
     169          80 :       NULLIFY (rho, energy, scf_control, logger, ks_env, mos, atomic_kind_set)
     170          80 :       NULLIFY (qs_charges, particle_set, qs_kind_set)
     171             : 
     172          80 :       logger => cp_get_default_logger()
     173          80 :       t1 = m_walltime()
     174          80 :       converged = .TRUE.
     175             : 
     176          80 :       CPASSERT(ASSOCIATED(xas_env))
     177          80 :       CPASSERT(ASSOCIATED(scf_env))
     178          80 :       CPASSERT(ASSOCIATED(qs_env))
     179             : 
     180             :       CALL get_qs_env(qs_env=qs_env, &
     181             :                       atomic_kind_set=atomic_kind_set, &
     182             :                       matrix_s=matrix_s, energy=energy, &
     183             :                       qs_charges=qs_charges, &
     184          80 :                       ks_env=ks_env, para_env=para_env)
     185             : 
     186          80 :       CALL get_xas_env(xas_env, scf_control=scf_control, spin_channel=my_spin)
     187             : 
     188          80 :       energy_only = .FALSE.
     189             :       output_unit = cp_print_key_unit_nr(logger, xas_section, "PRINT%PROGRAM_RUN_INFO", &
     190          80 :                                          extension=".xasLog")
     191          80 :       IF (output_unit > 0) THEN
     192          40 :          WRITE (UNIT=output_unit, FMT="(/,/,T2,A)") "XAS_TP_SCF WAVEFUNCTION OPTIMIZATION"
     193             :       END IF
     194             : 
     195             :       !   GAPW method must be used
     196          80 :       gapw = dft_control%qs_control%gapw
     197          80 :       CPASSERT(gapw)
     198          80 :       xas_control => dft_control%xas_control
     199             : 
     200          80 :       CALL cp_add_iter_level(logger%iter_info, "XAS_SCF")
     201             : 
     202          80 :       CALL get_qs_env(qs_env, matrix_ks=matrix_ks, rho=rho, mos=mos)
     203          80 :       CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp)
     204             : 
     205          80 :       iter_count = 0
     206          80 :       diis_step = .FALSE.
     207          80 :       nspin = dft_control%nspins
     208             : 
     209          80 :       IF (output_unit > 0) THEN
     210             :          WRITE (UNIT=output_unit, &
     211             :                 FMT="(/,T3,A,T12,A,T31,A,T40,A,T60,A,T75,A/,T3,A)") &
     212          40 :             "Step", "Update method", "Time", "Convergence", "Total energy", "Change", &
     213          80 :             REPEAT("-", 77)
     214             :       END IF
     215             : 
     216             :       !   *** SCF loop ***
     217             : 
     218          80 :       energy%tot_old = 0.0_dp
     219         704 :       scf_loop: DO
     220         704 :          CALL timeset(routineN//"_inner_loop", handle2)
     221             : 
     222         704 :          exit_loop = .FALSE.
     223         704 :          IF (output_unit > 0) CALL m_flush(output_unit)
     224             : 
     225         704 :          iter_count = iter_count + 1
     226         704 :          CALL cp_iterate(logger%iter_info, last=.FALSE., iter_nr=iter_count)
     227             : 
     228             :          ! ** here qs_env%rho%rho_r and qs_env%rho%rho_g should be up to date
     229             : 
     230         704 :          CALL qs_ks_update_qs_env(qs_env, calculate_forces=.FALSE., just_energy=energy_only)
     231             : 
     232         704 :          SELECT CASE (scf_env%method)
     233             :          CASE DEFAULT
     234             :             CALL cp_abort(__LOCATION__, &
     235             :                           "unknown scf method method for core level spectroscopy"// &
     236           0 :                           cp_to_string(scf_env%method))
     237             : 
     238             :          CASE (general_diag_method_nr) ! diagonalisation (default)
     239             : 
     240         704 :             scf_env%iter_count = iter_count
     241             :             CALL general_eigenproblem(scf_env, mos, matrix_ks, &
     242             :                                       matrix_s, scf_control, scf_section, &
     243         704 :                                       diis_step)
     244             : 
     245         704 :             CALL find_excited_core_orbital(xas_env, mos, matrix_s)
     246             : 
     247             :             ! set occupation for the respective spin channels
     248         704 :             IF (my_spin == 1) THEN
     249             :                hole_spin = 1 ! hole is generated in channel 1
     250             :                occ_spin = 2
     251             :             ELSE
     252           6 :                hole_spin = 2
     253           6 :                occ_spin = 1
     254             :             END IF
     255             :             CALL set_mo_occupation(mo_set=mos(hole_spin), &
     256             :                                    smear=scf_control%smear, &
     257         704 :                                    xas_env=xas_env)
     258             :             CALL set_mo_occupation(mo_set=mos(occ_spin), &
     259         704 :                                    smear=scf_control%smear)
     260        2112 :             DO ispin = 1, nspin
     261             :                ! does not yet handle k-points
     262             :                CALL calculate_density_matrix(mos(ispin), &
     263        2112 :                                              scf_env%p_mix_new(ispin, 1)%matrix)
     264             :             END DO
     265         704 :             energy%kTS = 0.0_dp
     266         704 :             energy%efermi = 0.0_dp
     267        2112 :             DO ispin = 1, nspin
     268        1408 :                energy%kTS = energy%kTS + mos(ispin)%kTS
     269        2112 :                energy%efermi = energy%efermi + mos(ispin)%mu
     270             :             END DO
     271        1408 :             energy%efermi = energy%efermi/REAL(nspin, KIND=dp)
     272             : 
     273             :          END SELECT
     274             : 
     275        1396 :          SELECT CASE (scf_env%mixing_method)
     276             :          CASE (direct_mixing_nr)
     277             :             CALL scf_env_density_mixing(scf_env%p_mix_new, &
     278             :                                         scf_env%mixing_store, rho_ao_kp, para_env, scf_env%iter_delta, scf_env%iter_count, &
     279         692 :                                         diis=diis_step)
     280             :          CASE (gspace_mixing_nr, pulay_mixing_nr, broyden_mixing_nr, &
     281             :                multisecant_mixing_nr)
     282             :             ! Compute the difference p_out-p_in
     283             :             CALL self_consistency_check(rho_ao_kp, scf_env%p_delta, para_env, scf_env%p_mix_new, &
     284          12 :                                         delta=scf_env%iter_delta)
     285             :          CASE (no_mixing_nr)
     286             :          CASE DEFAULT
     287             :             CALL cp_abort(__LOCATION__, &
     288             :                           "unknown scf mixing method: "// &
     289         704 :                           cp_to_string(scf_env%mixing_method))
     290             :          END SELECT
     291             : 
     292         704 :          t2 = m_walltime()
     293             : 
     294         704 :          IF (output_unit > 0 .AND. scf_env%print_iter_line) THEN
     295             :             WRITE (UNIT=output_unit, &
     296             :                    FMT="(T2,I5,1X,A,T20,E8.2,1X,F6.1,1X,F14.8,1X,F20.10,1X,ES9.2)") &
     297         352 :                iter_count, TRIM(scf_env%iter_method), &
     298         352 :                scf_env%iter_param, t2 - t1, scf_env%iter_delta, energy%total, &
     299         704 :                energy%total - energy%tot_old
     300             :          END IF
     301         704 :          energy%tot_old = energy%total
     302             : 
     303             :          ! ** convergence check
     304             :          CALL external_control(should_stop, "XASSCF", target_time=qs_env%target_time, &
     305         704 :                                start_time=qs_env%start_time)
     306         704 :          IF (scf_env%iter_delta < scf_control%eps_scf) THEN
     307          46 :             IF (output_unit > 0) THEN
     308             :                WRITE (UNIT=output_unit, FMT="(/,T3,A,I5,A/)") &
     309          23 :                   "*** SCF run converged in ", iter_count, " steps ***"
     310             :             END IF
     311             :             exit_loop = .TRUE.
     312         658 :          ELSE IF (should_stop .OR. iter_count == scf_control%max_scf) THEN
     313          34 :             IF (output_unit > 0) THEN
     314             :                WRITE (UNIT=output_unit, FMT="(/,T3,A,/)") &
     315          17 :                   "*** SCF run NOT converged ***"
     316             :             END IF
     317          34 :             converged = .FALSE.
     318             :             exit_loop = .TRUE.
     319             :          END IF
     320             :          !   *** Exit if we have finished with the SCF inner loop ***
     321             :          IF (exit_loop) THEN
     322             :             ! now, print out energies and charges corresponding to the obtained wfn
     323             :             ! (this actually is not 100% consistent at this point)!
     324          80 :             CALL qs_scf_print_summary(output_unit, qs_env)
     325          80 :             CALL cp_iterate(logger%iter_info, last=.TRUE., iter_nr=iter_count)
     326             :          END IF
     327             : 
     328             :          ! ** Write restart file **
     329             :          CALL xas_write_restart(xas_env, xas_section, qs_env, xas_control%xas_method, &
     330         704 :                                 iatom, istate)
     331             : 
     332         704 :          dft_section => section_vals_get_subs_vals(qs_env%input, "DFT")
     333         704 :          CALL get_qs_env(qs_env=qs_env, mos=mos, particle_set=particle_set, qs_kind_set=qs_kind_set)
     334         704 :          CALL write_mo_set_to_restart(mos, particle_set, dft_section=dft_section, qs_kind_set=qs_kind_set)
     335             : 
     336         704 :          IF (exit_loop) THEN
     337          80 :             CALL timestop(handle2)
     338             :             EXIT scf_loop
     339             :          END IF
     340             : 
     341         624 :          IF (.NOT. BTEST(cp_print_key_should_output(logger%iter_info, &
     342         624 :                                                     xas_section, "PRINT%ITERATION_INFO/TIME_CUMUL"), cp_p_file)) t1 = m_walltime()
     343             : 
     344             :          !   *** mixing methods have the new density matrix in p_mix_new
     345         624 :          IF (scf_env%mixing_method > 0) THEN
     346        1872 :             DO ispin = 1, nspin
     347             :                ! does not yet handle k-points
     348        1872 :                CALL dbcsr_copy(rho_ao_kp(ispin, 1)%matrix, scf_env%p_mix_new(ispin, 1)%matrix)
     349             :             END DO
     350             :          END IF
     351             : 
     352             :          ! ** update qs_env%rho
     353         624 :          CALL qs_rho_update_rho(rho, qs_env=qs_env)
     354         624 :          IF (scf_env%mixing_method >= gspace_mixing_nr) THEN
     355             :             CALL gspace_mixing(qs_env, scf_env%mixing_method, scf_env%mixing_store, rho, para_env, &
     356           6 :                                scf_env%iter_count)
     357             :          END IF
     358             : 
     359         624 :          CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
     360         624 :          CALL timestop(handle2)
     361             : 
     362             :       END DO scf_loop
     363             : 
     364          80 :       IF (output_unit > 0) THEN
     365             :          WRITE (UNIT=output_unit, FMT="(/,(T3,A,T55,F25.14))") &
     366          40 :             "Ionization potential of the excited atom:      ", xas_env%IP_energy
     367          40 :          CALL m_flush(output_unit)
     368             :       END IF
     369             : 
     370          80 :       CALL para_env%sync()
     371          80 :       CALL qs_ks_did_change(ks_env, rho_changed=.TRUE.)
     372             : 
     373          80 :       CALL cls_prepare_states(xas_control, xas_env, qs_env, iatom, xas_section, output_unit)
     374             : 
     375          80 :       CALL para_env%sync()
     376             : 
     377             :       CALL cp_print_key_finished_output(output_unit, logger, xas_section, &
     378          80 :                                         "PRINT%PROGRAM_RUN_INFO")
     379          80 :       CALL cp_rm_iter_level(logger%iter_info, "XAS_SCF")
     380             : 
     381          80 :       CALL timestop(handle)
     382             : 
     383          80 :    END SUBROUTINE xas_do_tp_scf
     384             : ! **************************************************************************************************
     385             : !> \brief  Post processing of the optimized wfn in XAS scheme, as preparation for
     386             : !>         the calculation of the spectrum
     387             : !> \param xas_control ...
     388             : !> \param xas_env the environment for XAS  calculations
     389             : !> \param qs_env the qs_env, the scf_env and xas_env live in
     390             : !> \param iatom index of the excited atom
     391             : !> \param xas_section ...
     392             : !> \param output_unit ...
     393             : !> \par History
     394             : !>      05.2005 created [MI]
     395             : !> \author MI
     396             : ! **************************************************************************************************
     397          80 :    SUBROUTINE cls_prepare_states(xas_control, xas_env, qs_env, iatom, xas_section, output_unit)
     398             : 
     399             :       TYPE(xas_control_type)                             :: xas_control
     400             :       TYPE(xas_environment_type), POINTER                :: xas_env
     401             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     402             :       INTEGER, INTENT(IN)                                :: iatom
     403             :       TYPE(section_vals_type), POINTER                   :: xas_section
     404             :       INTEGER, INTENT(IN)                                :: output_unit
     405             : 
     406             :       CHARACTER(LEN=*), PARAMETER :: routineN = 'cls_prepare_states'
     407             : 
     408             :       INTEGER :: handle, i, ikind, isgf, ispin, istate, j, my_kind, my_spin, my_state, nao, natom, &
     409             :          nexc_search, nmo, nvirtual2, uno_iter, xas_estate
     410          80 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: first_sgf
     411          80 :       INTEGER, DIMENSION(:), POINTER                     :: mykind_of_kind
     412          80 :       REAL(dp), DIMENSION(:, :), POINTER                 :: centers_wfn
     413             :       REAL(KIND=dp)                                      :: component, dist, max_overlap, ra(3), &
     414             :                                                             rac(3), rc(3), sto_state_overlap, &
     415             :                                                             uno_eps
     416          80 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: all_evals, eigenvalues, uno_evals
     417             :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: vecbuffer, vecbuffer2
     418             :       TYPE(atomic_kind_type), POINTER                    :: atomic_kind
     419             :       TYPE(cell_type), POINTER                           :: cell
     420          80 :       TYPE(cp_2d_r_p_type), DIMENSION(:), POINTER        :: stogto_overlap
     421             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     422             :       TYPE(cp_fm_type), POINTER                          :: all_vectors, excvec_coeff, &
     423             :                                                             excvec_overlap, mo_coeff, uno_orbs
     424          80 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: kinetic, matrix_ks, matrix_s
     425             :       TYPE(dft_control_type), POINTER                    :: dft_control
     426             :       TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
     427          80 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     428             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     429          80 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     430             :       TYPE(preconditioner_type), POINTER                 :: local_preconditioner
     431          80 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     432             :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
     433             :       TYPE(scf_control_type), POINTER                    :: scf_control
     434             :       TYPE(section_vals_type), POINTER                   :: loc_section, print_loc_section
     435             : 
     436          80 :       CALL timeset(routineN, handle)
     437             : 
     438          80 :       NULLIFY (atomic_kind, dft_control, matrix_s, matrix_ks, qs_kind_set, kinetic)
     439          80 :       NULLIFY (cell, particle_set, local_preconditioner, vecbuffer, vecbuffer2)
     440          80 :       NULLIFY (dft_control, loc_section, mos, mo_coeff, eigenvalues)
     441          80 :       NULLIFY (centers_wfn, mykind_of_kind, qs_loc_env, localized_wfn_control, stogto_overlap)
     442          80 :       NULLIFY (all_evals, all_vectors, excvec_coeff, excvec_overlap, uno_evals, para_env, blacs_env)
     443             : 
     444          80 :       CPASSERT(ASSOCIATED(xas_env))
     445             : 
     446             :       CALL get_qs_env(qs_env, &
     447             :                       cell=cell, &
     448             :                       dft_control=dft_control, &
     449             :                       matrix_ks=matrix_ks, &
     450             :                       matrix_s=matrix_s, &
     451             :                       kinetic=kinetic, &
     452             :                       mos=mos, &
     453             :                       particle_set=particle_set, &
     454             :                       qs_kind_set=qs_kind_set, &
     455             :                       para_env=para_env, &
     456          80 :                       blacs_env=blacs_env)
     457             : 
     458             :       ! Some elements from the xas_env
     459             :       CALL get_xas_env(xas_env=xas_env, &
     460             :                        all_vectors=all_vectors, all_evals=all_evals, &
     461             :                        excvec_coeff=excvec_coeff, &
     462             :                        nvirtual2=nvirtual2, xas_estate=xas_estate, &
     463             :                        excvec_overlap=excvec_overlap, nexc_search=nexc_search, &
     464          80 :                        spin_channel=my_spin, scf_control=scf_control)
     465          80 :       CPASSERT(ASSOCIATED(excvec_overlap))
     466             : 
     467             :       CALL get_mo_set(mos(my_spin), mo_coeff=mo_coeff, nao=nao, &
     468          80 :                       eigenvalues=eigenvalues)
     469             : 
     470         240 :       ALLOCATE (vecbuffer(1, nao))
     471        7160 :       vecbuffer = 0.0_dp
     472         240 :       ALLOCATE (vecbuffer2(1, nao))
     473        7160 :       vecbuffer2 = 0.0_dp
     474          80 :       natom = SIZE(particle_set, 1)
     475         240 :       ALLOCATE (first_sgf(natom))
     476          80 :       CALL get_particle_set(particle_set, qs_kind_set, first_sgf=first_sgf)
     477         240 :       ALLOCATE (centers_wfn(3, nexc_search))
     478        1712 :       centers_wfn = 0.0_dp
     479             : 
     480             :       ! Possible only for emission only
     481          80 :       IF (scf_control%use_ot) THEN
     482           0 :          IF (output_unit > 0) THEN
     483             :             WRITE (UNIT=output_unit, FMT="(/,/,T2,A)") " Eigenstates are derived "// &
     484             :                "from the MOs optimized by OT. Follows localization of the core states"// &
     485           0 :                " to identify the excited orbital. "
     486             :          END IF
     487             : 
     488             :          CALL get_xas_env(xas_env=xas_env, &
     489             :                           mykind_of_kind=mykind_of_kind, qs_loc_env=qs_loc_env, &
     490           0 :                           stogto_overlap=stogto_overlap)
     491             :          CALL get_qs_loc_env(qs_loc_env=qs_loc_env, &
     492           0 :                              localized_wfn_control=localized_wfn_control)
     493           0 :          loc_section => section_vals_get_subs_vals(xas_section, "LOCALIZE")
     494           0 :          print_loc_section => section_vals_get_subs_vals(loc_section, "PRINT")
     495           0 :          CALL qs_loc_driver(qs_env, qs_loc_env, print_loc_section, myspin=1)
     496           0 :          ra(1:3) = particle_set(iatom)%r(1:3)
     497             : 
     498           0 :          NULLIFY (atomic_kind)
     499           0 :          atomic_kind => particle_set(iatom)%atomic_kind
     500             :          CALL get_atomic_kind(atomic_kind=atomic_kind, &
     501           0 :                               kind_number=ikind)
     502           0 :          my_kind = mykind_of_kind(ikind)
     503             : 
     504           0 :          my_state = 0
     505             :          CALL cp_fm_get_submatrix(mo_coeff, vecbuffer2, 1, my_state, &
     506           0 :                                   nao, 1, transpose=.TRUE.)
     507             : 
     508             :          ! Rotate the wfn to get the eigenstate of the KS hamiltonian
     509             :          ! Only ispin=1 should be needed
     510           0 :          DO ispin = 1, dft_control%nspins
     511             :             CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nmo=nmo, &
     512           0 :                             eigenvalues=eigenvalues)
     513             :             CALL calculate_subspace_eigenvalues(mo_coeff, &
     514             :                                                 matrix_ks(ispin)%matrix, eigenvalues, &
     515           0 :                                                 do_rotation=.TRUE.)
     516             :          END DO ! ispin
     517             : 
     518             :          !Search for the core state to be excited
     519           0 :          max_overlap = 0.0_dp
     520           0 :          DO istate = 1, nexc_search
     521           0 :             centers_wfn(1, istate) = localized_wfn_control%centers_set(my_spin)%array(1, istate)
     522           0 :             centers_wfn(2, istate) = localized_wfn_control%centers_set(my_spin)%array(2, istate)
     523           0 :             centers_wfn(3, istate) = localized_wfn_control%centers_set(my_spin)%array(3, istate)
     524             : 
     525           0 :             rc(1:3) = centers_wfn(1:3, istate)
     526           0 :             rac = pbc(ra, rc, cell)
     527           0 :             dist = rac(1)*rac(1) + rac(2)*rac(2) + rac(3)*rac(3)
     528             : 
     529           0 :             IF (dist < 1.0_dp) THEN
     530             :                CALL cp_fm_get_submatrix(mo_coeff, vecbuffer, 1, istate, &
     531           0 :                                         nao, 1, transpose=.TRUE.)
     532           0 :                sto_state_overlap = 0.0_dp
     533           0 :                DO i = 1, SIZE(stogto_overlap(my_kind)%array, 1)
     534           0 :                   component = 0.0_dp
     535           0 :                   DO j = 1, SIZE(stogto_overlap(my_kind)%array, 2)
     536           0 :                      isgf = first_sgf(iatom) + j - 1
     537           0 :                      component = component + stogto_overlap(my_kind)%array(i, j)*vecbuffer(1, isgf)
     538             :                   END DO ! j size
     539             :                   sto_state_overlap = sto_state_overlap + &
     540           0 :                                       component*component
     541             :                END DO ! i size
     542             : 
     543           0 :                IF (sto_state_overlap .GT. max_overlap) THEN
     544           0 :                   max_overlap = sto_state_overlap
     545           0 :                   my_state = istate
     546             :                END IF
     547             :             END IF
     548           0 :             xas_estate = my_state
     549             :          END DO !  istate
     550             : 
     551           0 :          CALL get_mo_set(mos(my_spin), mo_coeff=mo_coeff)
     552             :          CALL cp_fm_get_submatrix(mo_coeff, vecbuffer, 1, xas_estate, &
     553           0 :                                   nao, 1, transpose=.TRUE.)
     554             :          CALL cp_fm_set_submatrix(excvec_coeff, vecbuffer2, 1, 1, &
     555           0 :                                   nao, 1, transpose=.TRUE.)
     556             :          !
     557             :       END IF
     558             : 
     559          80 :       CALL para_env%sync()
     560             :       !Calculate the virtual states from the KS matrix matrix_ks(1)
     561          80 :       IF (nvirtual2 .GT. 0) THEN
     562          76 :          NULLIFY (mo_coeff)
     563          76 :          CALL get_mo_set(mos(my_spin), mo_coeff=mo_coeff, nmo=nmo)
     564          76 :          IF (output_unit > 0) THEN
     565          38 :             WRITE (UNIT=output_unit, FMT="(/,/,T2,A,I5,A,I6,A)") " Calculation of ", nvirtual2, &
     566             :                " additional virtual states of the subspace complementary to the"// &
     567          76 :                " lowest ", nmo, " states"
     568             :          END IF
     569             : 
     570          76 :          NULLIFY (uno_orbs, uno_evals, local_preconditioner)
     571          76 :          ALLOCATE (local_preconditioner)
     572             :          CALL init_preconditioner(local_preconditioner, para_env=para_env, &
     573          76 :                                   blacs_env=blacs_env)
     574             : 
     575             :          CALL make_preconditioner(local_preconditioner, &
     576             :                                   precon_type=ot_precond_full_kinetic, &
     577             :                                   solver_type=ot_precond_solver_default, &
     578             :                                   matrix_h=matrix_ks(my_spin)%matrix, &
     579             :                                   matrix_s=matrix_s(1)%matrix, &
     580             :                                   matrix_t=kinetic(1)%matrix, &
     581             :                                   convert_precond_to_dbcsr=.TRUE., &
     582          76 :                                   mo_set=mos(my_spin), energy_gap=0.2_dp)
     583             : 
     584             :          CALL get_xas_env(xas_env=xas_env, unoccupied_orbs=uno_orbs, &
     585          76 :                           unoccupied_evals=uno_evals, unoccupied_eps=uno_eps, unoccupied_max_iter=uno_iter)
     586          76 :          CALL cp_fm_init_random(uno_orbs, nvirtual2)
     587             : 
     588             :          CALL ot_eigensolver(matrix_h=matrix_ks(my_spin)%matrix, matrix_s=matrix_s(1)%matrix, &
     589             :                              matrix_c_fm=uno_orbs, matrix_orthogonal_space_fm=mo_coeff, &
     590             :                              preconditioner=local_preconditioner, eps_gradient=uno_eps, &
     591          76 :                              iter_max=uno_iter, size_ortho_space=nmo)
     592             : 
     593             :          CALL calculate_subspace_eigenvalues(uno_orbs, matrix_ks(my_spin)%matrix, &
     594          76 :                                              uno_evals, do_rotation=.TRUE.)
     595          76 :          CALL destroy_preconditioner(local_preconditioner)
     596             : 
     597          76 :          DEALLOCATE (local_preconditioner)
     598             :       END IF
     599             : 
     600          80 :       CALL para_env%sync()
     601             :       ! Prapare arrays for the calculation of the spectrum
     602          80 :       IF (.NOT. xas_control%xas_method == xas_dscf) THEN
     603             :          ! Copy the final vectors in the array
     604          80 :          NULLIFY (all_vectors, all_evals)
     605             :          CALL get_xas_env(xas_env=xas_env, all_vectors=all_vectors, &
     606          80 :                           all_evals=all_evals)
     607             :          CALL get_mo_set(mos(my_spin), eigenvalues=eigenvalues, mo_coeff=mo_coeff, &
     608          80 :                          nmo=nmo)
     609             : 
     610             :          CALL cp_fm_to_fm(mo_coeff, all_vectors, ncol=nmo, &
     611          80 :                           source_start=1, target_start=1)
     612        1230 :          DO istate = 1, nmo
     613        1230 :             all_evals(istate) = eigenvalues(istate)
     614             :          END DO
     615          80 :          IF (nvirtual2 .GT. 0) THEN
     616             :             CALL cp_fm_to_fm(uno_orbs, all_vectors, ncol=nvirtual2, &
     617          76 :                              source_start=1, target_start=1 + nmo)
     618        2128 :             DO istate = 1, nvirtual2
     619        2128 :                all_evals(istate + nmo) = uno_evals(istate)
     620             :             END DO
     621             :          END IF
     622             :       END IF
     623             : 
     624          80 :       DEALLOCATE (vecbuffer)
     625          80 :       DEALLOCATE (vecbuffer2)
     626          80 :       DEALLOCATE (centers_wfn, first_sgf)
     627             : 
     628          80 :       CALL timestop(handle)
     629             : 
     630         240 :    END SUBROUTINE cls_prepare_states
     631             : 
     632             : ! **************************************************************************************************
     633             : !> \brief  SCF for emission spectra calculations: vacancy in valence
     634             : !> \param qs_env the qs_env, the scf_env and xas_env live in
     635             : !> \param xas_env the environment for XAS  calculations
     636             : !> \param converged ...
     637             : !> \param should_stop ...
     638             : !> \par History
     639             : !>      05.2005 created [MI]
     640             : !> \author MI
     641             : ! **************************************************************************************************
     642          20 :    SUBROUTINE xes_scf_once(qs_env, xas_env, converged, should_stop)
     643             : 
     644             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     645             :       TYPE(xas_environment_type), POINTER                :: xas_env
     646             :       LOGICAL, INTENT(OUT)                               :: converged, should_stop
     647             : 
     648             :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'xes_scf_once'
     649             : 
     650             :       INTEGER                                            :: handle, ispin, istate, my_spin, nmo, &
     651             :                                                             nvirtual, nvirtual2, output_unit, &
     652             :                                                             tsteps
     653           4 :       REAL(KIND=dp), DIMENSION(:), POINTER               :: all_evals, eigenvalues
     654             :       TYPE(cp_fm_type), POINTER                          :: all_vectors, mo_coeff
     655             :       TYPE(cp_logger_type), POINTER                      :: logger
     656           4 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
     657             :       TYPE(dft_control_type), POINTER                    :: dft_control
     658           4 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     659             :       TYPE(mp_para_env_type), POINTER                    :: para_env
     660             :       TYPE(qs_scf_env_type), POINTER                     :: scf_env
     661             :       TYPE(scf_control_type), POINTER                    :: scf_control
     662             :       TYPE(section_vals_type), POINTER                   :: dft_section, scf_section, xas_section
     663             :       TYPE(xas_control_type), POINTER                    :: xas_control
     664             : 
     665           4 :       NULLIFY (dft_control, scf_control, scf_env, matrix_ks, mos, para_env, xas_control)
     666           4 :       NULLIFY (dft_section, xas_section, scf_section, all_vectors, mo_coeff, all_evals, eigenvalues)
     667           4 :       NULLIFY (logger)
     668           8 :       logger => cp_get_default_logger()
     669           4 :       output_unit = cp_logger_get_default_io_unit(logger)
     670             : 
     671           4 :       CALL timeset(routineN, handle)
     672             : 
     673           4 :       CPASSERT(ASSOCIATED(xas_env))
     674             :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, &
     675           4 :                       matrix_ks=matrix_ks, mos=mos, para_env=para_env)
     676             : 
     677           4 :       xas_control => dft_control%xas_control
     678           4 :       CALL get_xas_env(xas_env, scf_control=scf_control, spin_channel=my_spin)
     679             : 
     680           4 :       dft_section => section_vals_get_subs_vals(qs_env%input, "DFT")
     681           4 :       xas_section => section_vals_get_subs_vals(dft_section, "XAS")
     682           4 :       scf_section => section_vals_get_subs_vals(xas_section, "SCF")
     683             : 
     684           4 :       IF (xas_env%homo_occ == 0) THEN
     685             : 
     686           2 :          NULLIFY (scf_env)
     687           2 :          CALL get_xas_env(xas_env, scf_env=scf_env)
     688           2 :          IF (.NOT. ASSOCIATED(scf_env)) THEN
     689           2 :             CALL qs_scf_env_initialize(qs_env, scf_env, scf_control, scf_section)
     690           2 :             CALL set_xas_env(xas_env, scf_env=scf_env)
     691             :          ELSE
     692           0 :             CALL qs_scf_env_initialize(qs_env, scf_env, scf_control, scf_section)
     693             :          END IF
     694             : 
     695             :          CALL scf_env_do_scf(scf_env=scf_env, scf_control=scf_control, qs_env=qs_env, &
     696           2 :                              converged=converged, should_stop=should_stop, total_scf_steps=tsteps)
     697           2 :          CALL scf_env_cleanup(scf_env)
     698             : 
     699             :       END IF
     700             : 
     701             :       !   The eigenstate of the KS Hamiltonian are nedeed
     702           4 :       NULLIFY (mo_coeff, eigenvalues)
     703           4 :       IF (scf_control%use_ot) THEN
     704           0 :          IF (output_unit > 0) THEN
     705             :             WRITE (UNIT=output_unit, FMT="(/,T10,A,/)") &
     706           0 :                "Get eigenstates and eigenvalues from ground state MOs"
     707             :          END IF
     708           0 :          DO ispin = 1, SIZE(mos)
     709             :             CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, &
     710           0 :                             eigenvalues=eigenvalues)
     711             :             CALL calculate_subspace_eigenvalues(mo_coeff, &
     712             :                                                 matrix_ks(ispin)%matrix, eigenvalues, &
     713           0 :                                                 do_rotation=.TRUE.)
     714             :          END DO
     715             :       END IF
     716             :       CALL get_xas_env(xas_env=xas_env, all_vectors=all_vectors, &
     717           4 :                        all_evals=all_evals, nvirtual2=nvirtual2)
     718           4 :       CALL get_mo_set(mos(my_spin), eigenvalues=eigenvalues, mo_coeff=mo_coeff, nmo=nmo)
     719             : 
     720             :       CALL cp_fm_to_fm(mo_coeff, all_vectors, ncol=nmo, &
     721           4 :                        source_start=1, target_start=1)
     722          36 :       DO istate = 1, nmo
     723          36 :          all_evals(istate) = eigenvalues(istate)
     724             :       END DO
     725             : 
     726           4 :       IF (nvirtual2 /= 0) THEN
     727           4 :          IF (output_unit > 0) THEN
     728             :             WRITE (UNIT=output_unit, FMT="(/,T10,A,/)") &
     729           2 :                "WARNING: for this XES calculation additional unoccupied MOs are not needed"
     730             :          END IF
     731           4 :          nvirtual2 = 0
     732           4 :          nvirtual = nmo
     733           4 :          CALL set_xas_env(xas_env=xas_env, nvirtual=nvirtual, nvirtual2=nvirtual2)
     734             :       END IF
     735             : 
     736           4 :       CALL timestop(handle)
     737             : 
     738           4 :    END SUBROUTINE xes_scf_once
     739             : 
     740             : END MODULE xas_tp_scf

Generated by: LCOV version 1.15