LCOV - code coverage report
Current view: top level - src - xas_tdp_methods.F (source / functions) Hit Total Coverage
Test: CP2K Regtests (git:2fce0f8) Lines: 1298 1522 85.3 %
Date: 2024-12-21 06:28:57 Functions: 23 25 92.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 Methods for X-Ray absorption spectroscopy (XAS) using TDDFPT
      10             : !> \author AB (11.2017)
      11             : ! **************************************************************************************************
      12             : 
      13             : MODULE xas_tdp_methods
      14             :    USE admm_types,                      ONLY: admm_type
      15             :    USE admm_utils,                      ONLY: admm_correct_for_eigenvalues,&
      16             :                                               admm_uncorrect_for_eigenvalues
      17             :    USE atomic_kind_types,               ONLY: atomic_kind_type,&
      18             :                                               get_atomic_kind
      19             :    USE basis_set_types,                 ONLY: &
      20             :         allocate_sto_basis_set, create_gto_from_sto_basis, deallocate_gto_basis_set, &
      21             :         deallocate_sto_basis_set, get_gto_basis_set, gto_basis_set_type, init_orb_basis_set, &
      22             :         set_sto_basis_set, srules, sto_basis_set_type
      23             :    USE bibliography,                    ONLY: Bussy2021a,&
      24             :                                               cite_reference
      25             :    USE cell_types,                      ONLY: cell_type,&
      26             :                                               pbc
      27             :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      28             :    USE cp_control_types,                ONLY: dft_control_type
      29             :    USE cp_dbcsr_api,                    ONLY: &
      30             :         dbcsr_add_on_diag, dbcsr_complete_redistribute, dbcsr_copy, dbcsr_create, dbcsr_filter, &
      31             :         dbcsr_finalize, dbcsr_get_info, dbcsr_get_occupation, dbcsr_multiply, dbcsr_p_type, &
      32             :         dbcsr_release, dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, &
      33             :         dbcsr_type_symmetric
      34             :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      35             :                                               copy_fm_to_dbcsr,&
      36             :                                               cp_dbcsr_sm_fm_multiply
      37             :    USE cp_files,                        ONLY: close_file,&
      38             :                                               open_file
      39             :    USE cp_fm_basic_linalg,              ONLY: cp_fm_column_scale
      40             :    USE cp_fm_diag,                      ONLY: cp_fm_geeig,&
      41             :                                               cp_fm_power,&
      42             :                                               cp_fm_syevd
      43             :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      44             :                                               cp_fm_struct_release,&
      45             :                                               cp_fm_struct_type
      46             :    USE cp_fm_types,                     ONLY: &
      47             :         cp_fm_copy_general, cp_fm_create, cp_fm_get_diag, cp_fm_get_info, cp_fm_get_submatrix, &
      48             :         cp_fm_read_unformatted, cp_fm_release, cp_fm_set_all, cp_fm_to_fm, cp_fm_to_fm_submat, &
      49             :         cp_fm_type, cp_fm_write_unformatted
      50             :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      51             :                                               cp_logger_get_default_io_unit,&
      52             :                                               cp_logger_type,&
      53             :                                               cp_to_string
      54             :    USE cp_output_handling,              ONLY: cp_p_file,&
      55             :                                               cp_print_key_finished_output,&
      56             :                                               cp_print_key_generate_filename,&
      57             :                                               cp_print_key_should_output,&
      58             :                                               cp_print_key_unit_nr,&
      59             :                                               debug_print_level
      60             :    USE input_constants,                 ONLY: &
      61             :         do_admm_purify_cauchy_subspace, do_admm_purify_mo_diag, do_admm_purify_none, do_loc_none, &
      62             :         do_potential_coulomb, do_potential_id, do_potential_short, do_potential_truncated, &
      63             :         op_loc_berry, state_loc_list, tddfpt_singlet, tddfpt_spin_cons, tddfpt_spin_flip, &
      64             :         tddfpt_triplet, xas_1s_type, xas_2p_type, xas_2s_type, xas_dip_len, xas_dip_vel, &
      65             :         xas_not_excited, xas_tdp_by_index, xas_tdp_by_kind
      66             :    USE input_cp2k_loc,                  ONLY: create_localize_section
      67             :    USE input_section_types,             ONLY: section_release,&
      68             :                                               section_type,&
      69             :                                               section_vals_create,&
      70             :                                               section_vals_get_subs_vals,&
      71             :                                               section_vals_type,&
      72             :                                               section_vals_val_get,&
      73             :                                               section_vals_val_set
      74             :    USE kinds,                           ONLY: default_path_length,&
      75             :                                               default_string_length,&
      76             :                                               dp
      77             :    USE libint_wrapper,                  ONLY: cp_libint_static_init
      78             :    USE machine,                         ONLY: m_flush
      79             :    USE mathlib,                         ONLY: get_diag
      80             :    USE memory_utilities,                ONLY: reallocate
      81             :    USE message_passing,                 ONLY: mp_comm_type,&
      82             :                                               mp_para_env_type
      83             :    USE parallel_gemm_api,               ONLY: parallel_gemm
      84             :    USE parallel_rng_types,              ONLY: UNIFORM,&
      85             :                                               rng_stream_type
      86             :    USE particle_methods,                ONLY: get_particle_set
      87             :    USE particle_types,                  ONLY: particle_type
      88             :    USE periodic_table,                  ONLY: ptable
      89             :    USE physcon,                         ONLY: a_fine,&
      90             :                                               angstrom,&
      91             :                                               evolt
      92             :    USE qs_environment_types,            ONLY: get_qs_env,&
      93             :                                               qs_environment_type
      94             :    USE qs_interactions,                 ONLY: init_interaction_radii_orb_basis
      95             :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      96             :                                               qs_kind_type
      97             :    USE qs_loc_main,                     ONLY: qs_loc_driver
      98             :    USE qs_loc_methods,                  ONLY: centers_spreads_berry,&
      99             :                                               qs_print_cubes
     100             :    USE qs_loc_types,                    ONLY: get_qs_loc_env,&
     101             :                                               localized_wfn_control_create,&
     102             :                                               localized_wfn_control_type,&
     103             :                                               qs_loc_env_create,&
     104             :                                               qs_loc_env_release,&
     105             :                                               qs_loc_env_type
     106             :    USE qs_loc_utils,                    ONLY: qs_loc_control_init,&
     107             :                                               qs_loc_env_init,&
     108             :                                               set_loc_centers
     109             :    USE qs_mo_io,                        ONLY: write_mo_set_low
     110             :    USE qs_mo_methods,                   ONLY: calculate_subspace_eigenvalues
     111             :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
     112             :                                               deallocate_mo_set,&
     113             :                                               duplicate_mo_set,&
     114             :                                               get_mo_set,&
     115             :                                               init_mo_set,&
     116             :                                               mo_set_type
     117             :    USE qs_operators_ao,                 ONLY: p_xyz_ao,&
     118             :                                               rRc_xyz_ao
     119             :    USE qs_pdos,                         ONLY: calculate_projected_dos
     120             :    USE qs_rho_types,                    ONLY: qs_rho_get,&
     121             :                                               qs_rho_type
     122             :    USE qs_scf_types,                    ONLY: ot_method_nr
     123             :    USE util,                            ONLY: get_limit,&
     124             :                                               locate,&
     125             :                                               sort_unique
     126             :    USE xas_methods,                     ONLY: calc_stogto_overlap
     127             :    USE xas_tdp_atom,                    ONLY: init_xas_atom_env,&
     128             :                                               integrate_fxc_atoms,&
     129             :                                               integrate_soc_atoms
     130             :    USE xas_tdp_correction,              ONLY: GW2X_shift,&
     131             :                                               get_soc_splitting
     132             :    USE xas_tdp_integrals,               ONLY: compute_ri_3c_coulomb,&
     133             :                                               compute_ri_3c_exchange,&
     134             :                                               compute_ri_coulomb2_int,&
     135             :                                               compute_ri_exchange2_int
     136             :    USE xas_tdp_types,                   ONLY: &
     137             :         donor_state_create, donor_state_type, free_ds_memory, free_exat_memory, &
     138             :         read_xas_tdp_control, set_donor_state, set_xas_tdp_env, xas_atom_env_create, &
     139             :         xas_atom_env_release, xas_atom_env_type, xas_tdp_control_create, xas_tdp_control_release, &
     140             :         xas_tdp_control_type, xas_tdp_env_create, xas_tdp_env_release, xas_tdp_env_type
     141             :    USE xas_tdp_utils,                   ONLY: include_os_soc,&
     142             :                                               include_rcs_soc,&
     143             :                                               setup_xas_tdp_prob,&
     144             :                                               solve_xas_tdp_prob
     145             :    USE xc_write_output,                 ONLY: xc_write
     146             : #include "./base/base_uses.f90"
     147             : 
     148             :    IMPLICIT NONE
     149             :    PRIVATE
     150             : 
     151             :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xas_tdp_methods'
     152             : 
     153             :    PUBLIC :: xas_tdp, xas_tdp_init
     154             : 
     155             : CONTAINS
     156             : 
     157             : ! **************************************************************************************************
     158             : !> \brief Driver for XAS TDDFT calculations.
     159             : !> \param qs_env the inherited qs_environment
     160             : !> \author AB
     161             : !> \note Empty for now...
     162             : ! **************************************************************************************************
     163         100 :    SUBROUTINE xas_tdp(qs_env)
     164             : 
     165             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     166             : 
     167             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xas_tdp'
     168             : 
     169             :       CHARACTER(default_string_length)                   :: rst_filename
     170             :       INTEGER                                            :: handle, n_rep, output_unit
     171             :       LOGICAL                                            :: do_restart
     172             :       TYPE(section_vals_type), POINTER                   :: xas_tdp_section
     173             : 
     174          50 :       CALL timeset(routineN, handle)
     175             : 
     176             : !  Logger initialization and XAS TDP banner printing
     177          50 :       NULLIFY (xas_tdp_section)
     178          50 :       xas_tdp_section => section_vals_get_subs_vals(qs_env%input, "DFT%XAS_TDP")
     179          50 :       output_unit = cp_logger_get_default_io_unit()
     180             : 
     181          50 :       IF (output_unit > 0) THEN
     182             :          WRITE (UNIT=output_unit, FMT="(/,T3,A,/,T3,A,/,T3,A,/,T3,A,/)") &
     183          25 :             "!===========================================================================!", &
     184          25 :             "!                              XAS TDP                                      !", &
     185          25 :             "!    Starting TDDFPT driven X-rays absorption spectroscopy calculations     !", &
     186          50 :             "!===========================================================================!"
     187             :       END IF
     188             : 
     189          50 :       CALL cite_reference(Bussy2021a)
     190             : 
     191             : !  Check whether this is a restart calculation, i.e. is a restart file is provided
     192          50 :       CALL section_vals_val_get(xas_tdp_section, "RESTART_FROM_FILE", n_rep_val=n_rep)
     193             : 
     194          50 :       IF (n_rep < 1) THEN
     195             :          do_restart = .FALSE.
     196             :       ELSE
     197           2 :          CALL section_vals_val_get(xas_tdp_section, "RESTART_FROM_FILE", c_val=rst_filename)
     198             :          do_restart = .TRUE.
     199             :       END IF
     200             : 
     201             : !  Restart the calculation if needed
     202             :       IF (do_restart) THEN
     203             : 
     204           2 :          IF (output_unit > 0) THEN
     205             :             WRITE (UNIT=output_unit, FMT="(/,T3,A)") &
     206           1 :                "# This is a RESTART calculation for PDOS and/or CUBE printing"
     207             :          END IF
     208             : 
     209           2 :          CALL restart_calculation(rst_filename, xas_tdp_section, qs_env)
     210             : 
     211             : !  or run the core XAS_TDP routine if not
     212             :       ELSE
     213          48 :          CALL xas_tdp_core(xas_tdp_section, qs_env)
     214             :       END IF
     215             : 
     216          50 :       IF (output_unit > 0) THEN
     217             :          WRITE (UNIT=output_unit, FMT="(/,T3,A,/,T3,A,/,T3,A,/)") &
     218          25 :             "!===========================================================================!", &
     219          25 :             "!     End of TDDFPT driven X-rays absorption spectroscopy calculations      !", &
     220          50 :             "!===========================================================================!"
     221             :       END IF
     222             : 
     223          50 :       CALL timestop(handle)
     224             : 
     225          50 :    END SUBROUTINE xas_tdp
     226             : 
     227             : ! **************************************************************************************************
     228             : !> \brief The core workflow of the XAS_TDP method
     229             : !> \param xas_tdp_section the input values for XAS_TDP
     230             : !> \param qs_env ...
     231             : ! **************************************************************************************************
     232          48 :    SUBROUTINE xas_tdp_core(xas_tdp_section, qs_env)
     233             : 
     234             :       TYPE(section_vals_type), POINTER                   :: xas_tdp_section
     235             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     236             : 
     237             :       CHARACTER(LEN=default_string_length)               :: kind_name
     238             :       INTEGER :: batch_size, bo(2), current_state_index, iat, iatom, ibatch, ikind, ispin, istate, &
     239             :          nbatch, nex_atom, output_unit, tmp_index
     240          48 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: batch_atoms, ex_atoms_of_kind
     241          48 :       INTEGER, DIMENSION(:), POINTER                     :: atoms_of_kind
     242             :       LOGICAL                                            :: do_os, end_of_batch, unique
     243             :       TYPE(admm_type), POINTER                           :: admm_env
     244          48 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
     245          48 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
     246             :       TYPE(dft_control_type), POINTER                    :: dft_control
     247             :       TYPE(donor_state_type), POINTER                    :: current_state
     248             :       TYPE(gto_basis_set_type), POINTER                  :: tmp_basis
     249          48 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     250             :       TYPE(xas_atom_env_type), POINTER                   :: xas_atom_env
     251             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
     252             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
     253             : 
     254          48 :       NULLIFY (xas_tdp_env, xas_tdp_control, atomic_kind_set, atoms_of_kind, current_state)
     255          48 :       NULLIFY (xas_atom_env, dft_control, matrix_ks, admm_env, qs_kind_set, tmp_basis)
     256             : 
     257             : !  Initialization
     258          96 :       output_unit = cp_logger_get_default_io_unit()
     259             : 
     260          48 :       IF (output_unit > 0) THEN
     261             :          WRITE (UNIT=output_unit, FMT="(/,T3,A)") &
     262          24 :             "# Create and initialize the XAS_TDP environment"
     263             :       END IF
     264          48 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     265          48 :       CALL xas_tdp_init(xas_tdp_env, xas_tdp_control, qs_env)
     266          48 :       CALL print_info(output_unit, xas_tdp_control, qs_env)
     267             : 
     268          48 :       IF (output_unit > 0) THEN
     269          24 :          IF (xas_tdp_control%check_only) THEN
     270           0 :             CPWARN("This is a CHECK_ONLY run for donor MOs verification")
     271             :          END IF
     272             :       END IF
     273             : 
     274             : !  Localization of the core orbitals if requested (used for better identification of donor states)
     275          48 :       IF (xas_tdp_control%do_loc) THEN
     276          32 :          IF (output_unit > 0) THEN
     277             :             WRITE (UNIT=output_unit, FMT="(/,T3,A,/)") &
     278          16 :                "# Localizing core orbitals for better identification"
     279             :          END IF
     280             : !        closed shell or ROKS => myspin=1
     281          32 :          IF (xas_tdp_control%do_uks) THEN
     282           6 :             DO ispin = 1, dft_control%nspins
     283             :                CALL qs_loc_driver(qs_env, xas_tdp_env%qs_loc_env, &
     284           6 :                                   xas_tdp_control%print_loc_subsection, myspin=ispin)
     285             :             END DO
     286             :          ELSE
     287             :             CALL qs_loc_driver(qs_env, xas_tdp_env%qs_loc_env, &
     288          30 :                                xas_tdp_control%print_loc_subsection, myspin=1)
     289             :          END IF
     290             :       END IF
     291             : 
     292             : !  Find the MO centers
     293          48 :       CALL find_mo_centers(xas_tdp_env, xas_tdp_control, qs_env)
     294             : 
     295             : !  Assign lowest energy orbitals to excited atoms
     296          48 :       CALL assign_mos_to_ex_atoms(xas_tdp_env, xas_tdp_control, qs_env)
     297             : 
     298             : !  Once assigned, diagonalize the MOs wrt the KS matrix in the subspace associated to each atom
     299          48 :       IF (xas_tdp_control%do_loc) THEN
     300          32 :          IF (output_unit > 0) THEN
     301             :             WRITE (UNIT=output_unit, FMT="(/,T3,A,/,T5,A)") &
     302          16 :                "# Diagonalize localized MOs wrt the KS matrix in the subspace of each excited", &
     303          32 :                "atom for better donor state identification."
     304             :          END IF
     305          32 :          CALL diagonalize_assigned_mo_subset(xas_tdp_env, xas_tdp_control, qs_env)
     306             :          ! update MO centers
     307          32 :          CALL find_mo_centers(xas_tdp_env, xas_tdp_control, qs_env)
     308             :       END IF
     309             : 
     310          48 :       IF (output_unit > 0) THEN
     311             :          WRITE (UNIT=output_unit, FMT="(/,T3,A,I4,A,/)") &
     312          24 :             "# Assign the relevant subset of the ", xas_tdp_control%n_search, &
     313          48 :             "  lowest energy MOs to excited atoms"
     314             :       END IF
     315          48 :       CALL write_mos_to_ex_atoms_association(xas_tdp_env, xas_tdp_control, qs_env)
     316             : 
     317             : !  If CHECK_ONLY run, check the donor MOs
     318          48 :       IF (xas_tdp_control%check_only) CALL print_checks(xas_tdp_env, xas_tdp_control, qs_env)
     319             : 
     320             : !  If not simply exact exchange, setup a xas_atom_env and compute the xc integrals on the atomic grids
     321             : !  Also needed if SOC is included or XPS GW2X(). Done before looping on atoms as it's all done at once
     322             :       IF ((xas_tdp_control%do_xc .OR. xas_tdp_control%do_soc .OR. xas_tdp_control%do_gw2x) &
     323          48 :           .AND. .NOT. xas_tdp_control%check_only) THEN
     324             : 
     325          48 :          IF (output_unit > 0 .AND. xas_tdp_control%do_xc) THEN
     326             :             WRITE (UNIT=output_unit, FMT="(/,T3,A,I4,A)") &
     327          19 :                "# Integrating the xc kernel on the atomic grids ..."
     328          19 :             CALL m_flush(output_unit)
     329             :          END IF
     330             : 
     331          48 :          CALL xas_atom_env_create(xas_atom_env)
     332          48 :          CALL init_xas_atom_env(xas_atom_env, xas_tdp_env, xas_tdp_control, qs_env)
     333          48 :          do_os = xas_tdp_control%do_uks .OR. xas_tdp_control%do_roks
     334             : 
     335          48 :          IF (xas_tdp_control%do_xc .AND. (.NOT. xas_tdp_control%xps_only)) THEN
     336          38 :             CALL integrate_fxc_atoms(xas_tdp_env%ri_fxc, xas_atom_env, xas_tdp_control, qs_env)
     337             :          END IF
     338             : 
     339          48 :          IF (xas_tdp_control%do_soc .OR. xas_tdp_control%do_gw2x) THEN
     340          22 :             CALL integrate_soc_atoms(xas_tdp_env%orb_soc, xas_atom_env=xas_atom_env, qs_env=qs_env)
     341             :          END IF
     342             : 
     343          48 :          CALL xas_atom_env_release(xas_atom_env)
     344             :       END IF
     345             : 
     346             : !  Compute the 3-center Coulomb integrals for the whole system
     347          48 :       IF ((.NOT. (xas_tdp_control%check_only .OR. xas_tdp_control%xps_only)) .AND. &
     348             :           (xas_tdp_control%do_xc .OR. xas_tdp_control%do_coulomb)) THEN
     349          44 :          IF (output_unit > 0) THEN
     350             :             WRITE (UNIT=output_unit, FMT="(/,T3,A,I4,A)") &
     351          22 :                "# Computing the RI 3-center Coulomb integrals ..."
     352          22 :             CALL m_flush(output_unit)
     353             :          END IF
     354          44 :          CALL compute_ri_3c_coulomb(xas_tdp_env, qs_env)
     355             : 
     356             :       END IF
     357             : 
     358             : !  Loop over donor states for calculation
     359          48 :       CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set)
     360          48 :       current_state_index = 1
     361             : 
     362             : !     Loop over atomic kinds
     363         122 :       DO ikind = 1, SIZE(atomic_kind_set)
     364             : 
     365          74 :          IF (xas_tdp_control%check_only) EXIT
     366         102 :          IF (.NOT. ANY(xas_tdp_env%ex_kind_indices == ikind)) CYCLE
     367             : 
     368             :          CALL get_atomic_kind(atomic_kind=atomic_kind_set(ikind), name=kind_name, &
     369          52 :                               atom_list=atoms_of_kind)
     370             : 
     371             :          ! compute the RI coulomb2 inverse for this kind, and RI exchange2 if needed
     372          52 :          CALL compute_ri_coulomb2_int(ikind, xas_tdp_env, xas_tdp_control, qs_env)
     373          52 :          IF (xas_tdp_control%do_hfx) THEN
     374          42 :             CALL compute_ri_exchange2_int(ikind, xas_tdp_env, xas_tdp_control, qs_env)
     375             :          END IF
     376             : 
     377             :          !Randomly distribute excited atoms of current kinds into batches for optimal load balance
     378             :          !of RI 3c exchange integrals. Take batch sizes of 2 to avoid taxing memory too much, while
     379             :          !greatly improving load balance
     380          52 :          batch_size = 2
     381          52 :          CALL get_ri_3c_batches(ex_atoms_of_kind, nbatch, batch_size, atoms_of_kind, xas_tdp_env)
     382          52 :          nex_atom = SIZE(ex_atoms_of_kind)
     383             : 
     384             :          !Loop over batches
     385         104 :          DO ibatch = 1, nbatch
     386             : 
     387          52 :             bo = get_limit(nex_atom, nbatch, ibatch - 1)
     388          52 :             batch_size = bo(2) - bo(1) + 1
     389         156 :             ALLOCATE (batch_atoms(batch_size))
     390          52 :             iatom = 0
     391         110 :             DO iat = bo(1), bo(2)
     392          58 :                iatom = iatom + 1
     393         110 :                batch_atoms(iatom) = ex_atoms_of_kind(iat)
     394             :             END DO
     395          52 :             CALL sort_unique(batch_atoms, unique)
     396             : 
     397             :             !compute RI 3c exchange integrals on batch, if so required
     398          52 :             IF (xas_tdp_control%do_hfx) THEN
     399          42 :                IF (output_unit > 0) THEN
     400             :                   WRITE (UNIT=output_unit, FMT="(/,T3,A,I4,A,I4,A,I1,A,A)") &
     401          21 :                      "# Computing the RI 3-center Exchange integrals for batch ", ibatch, "(/", nbatch, ") of ", &
     402          42 :                      batch_size, " atoms of kind: ", TRIM(kind_name)
     403          21 :                   CALL m_flush(output_unit)
     404             :                END IF
     405          42 :                CALL compute_ri_3c_exchange(batch_atoms, xas_tdp_env, xas_tdp_control, qs_env)
     406             :             END IF
     407             : 
     408             : !           Loop over atoms of batch
     409         110 :             DO iat = 1, batch_size
     410          58 :                iatom = batch_atoms(iat)
     411             : 
     412          58 :                tmp_index = locate(xas_tdp_env%ex_atom_indices, iatom)
     413             : 
     414             :                !if dipole in length rep, compute the dipole in the AO basis for this atom
     415             :                !if quadrupole is required, compute it there too (in length rep)
     416          58 :                IF (xas_tdp_control%dipole_form == xas_dip_len .OR. xas_tdp_control%do_quad) THEN
     417          24 :                   CALL compute_lenrep_multipole(iatom, xas_tdp_env, xas_tdp_control, qs_env)
     418             :                END IF
     419             : 
     420             : !              Loop over states of excited atom of kind
     421         126 :                DO istate = 1, SIZE(xas_tdp_env%state_types, 1)
     422             : 
     423          68 :                   IF (xas_tdp_env%state_types(istate, tmp_index) == xas_not_excited) CYCLE
     424             : 
     425          68 :                   current_state => xas_tdp_env%donor_states(current_state_index)
     426             :                   CALL set_donor_state(current_state, at_index=iatom, &
     427             :                                        at_symbol=kind_name, kind_index=ikind, &
     428          68 :                                        state_type=xas_tdp_env%state_types(istate, tmp_index))
     429             : 
     430             : !                 Initial write for the donor state of interest
     431          68 :                   IF (output_unit > 0) THEN
     432             :                      WRITE (UNIT=output_unit, FMT="(/,T3,A,A2,A,I4,A,A,/)") &
     433          34 :                         "# Start of calculations for donor state of type ", &
     434          34 :                         xas_tdp_env%state_type_char(current_state%state_type), " for atom", &
     435          68 :                         current_state%at_index, " of kind ", TRIM(current_state%at_symbol)
     436          34 :                      CALL m_flush(output_unit)
     437             :                   END IF
     438             : 
     439             : !                 Assign best fitting MO(s) to current core donnor state
     440          68 :                   CALL assign_mos_to_donor_state(current_state, xas_tdp_env, xas_tdp_control, qs_env)
     441             : 
     442             : !                 Perform MO restricted Mulliken pop analysis for verification
     443          68 :                   CALL perform_mulliken_on_donor_state(current_state, qs_env)
     444             : 
     445             : !                 GW2X correction
     446          68 :                   IF (xas_tdp_control%do_gw2x) THEN
     447          30 :                      CALL GW2X_shift(current_state, xas_tdp_env, xas_tdp_control, qs_env)
     448             :                   END IF
     449             : 
     450             : !                 Do main XAS calculations here
     451          68 :                   IF (.NOT. xas_tdp_control%xps_only) THEN
     452          56 :                      CALL setup_xas_tdp_prob(current_state, qs_env, xas_tdp_env, xas_tdp_control)
     453             : 
     454          56 :                      IF (xas_tdp_control%do_spin_cons) THEN
     455             :                         CALL solve_xas_tdp_prob(current_state, xas_tdp_control, xas_tdp_env, qs_env, &
     456           8 :                                                 ex_type=tddfpt_spin_cons)
     457           8 :                         CALL compute_dipole_fosc(current_state, xas_tdp_control, xas_tdp_env)
     458           8 :                         IF (xas_tdp_control%do_quad) CALL compute_quadrupole_fosc(current_state, &
     459           0 :                                                                                   xas_tdp_control, xas_tdp_env)
     460             :                         CALL xas_tdp_post(tddfpt_spin_cons, current_state, xas_tdp_env, &
     461           8 :                                           xas_tdp_section, qs_env)
     462           8 :                         CALL write_donor_state_restart(tddfpt_spin_cons, current_state, xas_tdp_section, qs_env)
     463             :                      END IF
     464             : 
     465          56 :                      IF (xas_tdp_control%do_spin_flip) THEN
     466             :                         CALL solve_xas_tdp_prob(current_state, xas_tdp_control, xas_tdp_env, qs_env, &
     467           2 :                                                 ex_type=tddfpt_spin_flip)
     468             :                         !no dipole in spin-flip (spin-forbidden)
     469             :                         CALL xas_tdp_post(tddfpt_spin_flip, current_state, xas_tdp_env, &
     470           2 :                                           xas_tdp_section, qs_env)
     471           2 :                         CALL write_donor_state_restart(tddfpt_spin_flip, current_state, xas_tdp_section, qs_env)
     472             :                      END IF
     473             : 
     474          56 :                      IF (xas_tdp_control%do_singlet) THEN
     475             :                         CALL solve_xas_tdp_prob(current_state, xas_tdp_control, xas_tdp_env, qs_env, &
     476          48 :                                                 ex_type=tddfpt_singlet)
     477          48 :                         CALL compute_dipole_fosc(current_state, xas_tdp_control, xas_tdp_env)
     478          48 :                         IF (xas_tdp_control%do_quad) CALL compute_quadrupole_fosc(current_state, &
     479           0 :                                                                                   xas_tdp_control, xas_tdp_env)
     480             :                         CALL xas_tdp_post(tddfpt_singlet, current_state, xas_tdp_env, &
     481          48 :                                           xas_tdp_section, qs_env)
     482          48 :                         CALL write_donor_state_restart(tddfpt_singlet, current_state, xas_tdp_section, qs_env)
     483             :                      END IF
     484             : 
     485          56 :                      IF (xas_tdp_control%do_triplet) THEN
     486             :                         CALL solve_xas_tdp_prob(current_state, xas_tdp_control, xas_tdp_env, qs_env, &
     487           2 :                                                 ex_type=tddfpt_triplet)
     488             :                         !no dipole for triplets by construction
     489             :                         CALL xas_tdp_post(tddfpt_triplet, current_state, xas_tdp_env, &
     490           2 :                                           xas_tdp_section, qs_env)
     491           2 :                         CALL write_donor_state_restart(tddfpt_triplet, current_state, xas_tdp_section, qs_env)
     492             :                      END IF
     493             : 
     494             : !                    Include the SOC if required, only for 2p donor stataes
     495          56 :                      IF (xas_tdp_control%do_soc .AND. current_state%state_type == xas_2p_type) THEN
     496           4 :                         IF (xas_tdp_control%do_singlet .AND. xas_tdp_control%do_triplet) THEN
     497           2 :                            CALL include_rcs_soc(current_state, xas_tdp_env, xas_tdp_control, qs_env)
     498             :                         END IF
     499           4 :                         IF (xas_tdp_control%do_spin_cons .AND. xas_tdp_control%do_spin_flip) THEN
     500           2 :                            CALL include_os_soc(current_state, xas_tdp_env, xas_tdp_control, qs_env)
     501             :                         END IF
     502             :                      END IF
     503             : 
     504             : !                    Print the requested properties
     505          56 :                      CALL print_xas_tdp_to_file(current_state, xas_tdp_env, xas_tdp_control, xas_tdp_section)
     506             :                   END IF !xps_only
     507          68 :                   IF (xas_tdp_control%do_gw2x) CALL print_xps(current_state, xas_tdp_env, xas_tdp_control, qs_env)
     508             : 
     509             : !                 Free some unneeded attributes of current_state
     510          68 :                   CALL free_ds_memory(current_state)
     511             : 
     512          68 :                   current_state_index = current_state_index + 1
     513         126 :                   NULLIFY (current_state)
     514             : 
     515             :                END DO ! state type
     516             : 
     517          58 :                end_of_batch = .FALSE.
     518          58 :                IF (iat == batch_size) end_of_batch = .TRUE.
     519         110 :                CALL free_exat_memory(xas_tdp_env, iatom, end_of_batch)
     520             :             END DO ! atom of batch
     521         156 :             DEALLOCATE (batch_atoms)
     522             :          END DO !ibatch
     523         174 :          DEALLOCATE (ex_atoms_of_kind)
     524             :       END DO ! kind
     525             : 
     526             : !  Return to ususal KS matrix
     527          48 :       IF (dft_control%do_admm) THEN
     528           4 :          CALL get_qs_env(qs_env, matrix_ks=matrix_ks, admm_env=admm_env)
     529           8 :          DO ispin = 1, dft_control%nspins
     530           8 :             CALL admm_uncorrect_for_eigenvalues(ispin, admm_env, matrix_ks(ispin)%matrix)
     531             :          END DO
     532             :       END IF
     533             : 
     534             : !  Return to initial basis set radii
     535          48 :       IF (xas_tdp_control%eps_pgf > 0.0_dp) THEN
     536           0 :          CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
     537           0 :          DO ikind = 1, SIZE(atomic_kind_set)
     538           0 :             CALL get_qs_kind(qs_kind_set(ikind), basis_set=tmp_basis, basis_type="ORB")
     539           0 :             CALL init_interaction_radii_orb_basis(tmp_basis, eps_pgf_orb=dft_control%qs_control%eps_pgf_orb)
     540             :          END DO
     541             :       END IF
     542             : 
     543             : !  Clean-up
     544          48 :       CALL xas_tdp_env_release(xas_tdp_env)
     545          48 :       CALL xas_tdp_control_release(xas_tdp_control)
     546             : 
     547          96 :    END SUBROUTINE xas_tdp_core
     548             : 
     549             : ! **************************************************************************************************
     550             : !> \brief Overall control and  environment types initialization
     551             : !> \param xas_tdp_env the environment type to initialize
     552             : !> \param xas_tdp_control the control type to initialize
     553             : !> \param qs_env the inherited qs environement type
     554             : ! **************************************************************************************************
     555          48 :    SUBROUTINE xas_tdp_init(xas_tdp_env, xas_tdp_control, qs_env)
     556             : 
     557             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
     558             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
     559             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     560             : 
     561             :       CHARACTER(LEN=default_string_length)               :: kind_name
     562             :       INTEGER                                            :: at_ind, i, ispin, j, k, kind_ind, &
     563             :                                                             n_donor_states, n_kinds, nao, &
     564             :                                                             nat_of_kind, natom, nex_atoms, &
     565             :                                                             nex_kinds, nmatch, nspins
     566             :       INTEGER, DIMENSION(2)                              :: homo, n_mo, n_moloc
     567          48 :       INTEGER, DIMENSION(:), POINTER                     :: ind_of_kind
     568             :       LOGICAL                                            :: do_os, do_uks, unique
     569             :       REAL(dp)                                           :: fact
     570          48 :       REAL(dp), DIMENSION(:), POINTER                    :: mo_evals
     571             :       TYPE(admm_type), POINTER                           :: admm_env
     572          48 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: at_kind_set
     573             :       TYPE(cell_type), POINTER                           :: cell
     574             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
     575          48 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s, rho_ao
     576             :       TYPE(dbcsr_type)                                   :: matrix_tmp
     577             :       TYPE(dft_control_type), POINTER                    :: dft_control
     578             :       TYPE(gto_basis_set_type), POINTER                  :: tmp_basis
     579          48 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     580          48 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
     581          48 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
     582             :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
     583             :       TYPE(qs_rho_type), POINTER                         :: rho
     584             :       TYPE(section_type), POINTER                        :: dummy_section
     585             :       TYPE(section_vals_type), POINTER                   :: loc_section, xas_tdp_section
     586             : 
     587          48 :       NULLIFY (xas_tdp_section, at_kind_set, ind_of_kind, dft_control, qs_kind_set, tmp_basis)
     588          48 :       NULLIFY (qs_loc_env, loc_section, mos, particle_set, rho, rho_ao, mo_evals, cell)
     589          48 :       NULLIFY (mo_coeff, matrix_ks, admm_env, dummy_section)
     590             : 
     591             : !  XAS TDP control type initialization
     592          96 :       xas_tdp_section => section_vals_get_subs_vals(qs_env%input, "DFT%XAS_TDP")
     593             : 
     594          48 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     595          48 :       CALL xas_tdp_control_create(xas_tdp_control)
     596          48 :       CALL read_xas_tdp_control(xas_tdp_control, xas_tdp_section)
     597             : 
     598             : !  Check the qs_env for a LSD/ROKS calculation
     599          48 :       IF (dft_control%uks) xas_tdp_control%do_uks = .TRUE.
     600          48 :       IF (dft_control%roks) xas_tdp_control%do_roks = .TRUE.
     601          48 :       do_uks = xas_tdp_control%do_uks
     602          48 :       do_os = do_uks .OR. xas_tdp_control%do_roks
     603             : 
     604             : !  XAS TDP environment type initialization
     605          48 :       CALL xas_tdp_env_create(xas_tdp_env)
     606             : 
     607             : !  Retrieving the excited atoms indices and correspondig state types
     608          48 :       IF (xas_tdp_control%define_excited == xas_tdp_by_index) THEN
     609             : 
     610             : !        simply copy indices from xas_tdp_control
     611          26 :          nex_atoms = SIZE(xas_tdp_control%list_ex_atoms)
     612          26 :          CALL set_xas_tdp_env(xas_tdp_env, nex_atoms=nex_atoms)
     613          78 :          ALLOCATE (xas_tdp_env%ex_atom_indices(nex_atoms))
     614         104 :          ALLOCATE (xas_tdp_env%state_types(SIZE(xas_tdp_control%state_types, 1), nex_atoms))
     615          86 :          xas_tdp_env%ex_atom_indices = xas_tdp_control%list_ex_atoms
     616         146 :          xas_tdp_env%state_types = xas_tdp_control%state_types
     617             : 
     618             : !        Test that these indices are within the range of available atoms
     619          26 :          CALL get_qs_env(qs_env=qs_env, natom=natom)
     620          56 :          IF (ANY(xas_tdp_env%ex_atom_indices > natom)) THEN
     621           0 :             CPABORT("Invalid index for the ATOM_LIST keyword.")
     622             :          END IF
     623             : 
     624             : !        Check atom kinds and fill corresponding array
     625          52 :          ALLOCATE (xas_tdp_env%ex_kind_indices(nex_atoms))
     626          56 :          xas_tdp_env%ex_kind_indices = 0
     627          26 :          k = 0
     628          26 :          CALL get_qs_env(qs_env, particle_set=particle_set)
     629          56 :          DO i = 1, nex_atoms
     630          30 :             at_ind = xas_tdp_env%ex_atom_indices(i)
     631          30 :             CALL get_atomic_kind(particle_set(at_ind)%atomic_kind, kind_number=j)
     632          90 :             IF (ALL(ABS(xas_tdp_env%ex_kind_indices - j) .NE. 0)) THEN
     633          28 :                k = k + 1
     634          28 :                xas_tdp_env%ex_kind_indices(k) = j
     635             :             END IF
     636             :          END DO
     637          26 :          nex_kinds = k
     638          26 :          CALL set_xas_tdp_env(xas_tdp_env, nex_kinds=nex_kinds)
     639          26 :          CALL reallocate(xas_tdp_env%ex_kind_indices, 1, nex_kinds)
     640             : 
     641          22 :       ELSE IF (xas_tdp_control%define_excited == xas_tdp_by_kind) THEN
     642             : 
     643             : !        need to find out which atom of which kind is excited
     644          22 :          CALL get_qs_env(qs_env=qs_env, atomic_kind_set=at_kind_set)
     645          22 :          n_kinds = SIZE(at_kind_set)
     646          22 :          nex_atoms = 0
     647             : 
     648          22 :          nex_kinds = SIZE(xas_tdp_control%list_ex_kinds)
     649          66 :          ALLOCATE (xas_tdp_env%ex_kind_indices(nex_kinds))
     650          22 :          k = 0
     651             : 
     652          66 :          DO i = 1, n_kinds
     653             :             CALL get_atomic_kind(atomic_kind=at_kind_set(i), name=kind_name, &
     654          44 :                                  natom=nat_of_kind, kind_number=kind_ind)
     655          90 :             IF (ANY(xas_tdp_control%list_ex_kinds == kind_name)) THEN
     656          24 :                nex_atoms = nex_atoms + nat_of_kind
     657          24 :                k = k + 1
     658          24 :                xas_tdp_env%ex_kind_indices(k) = kind_ind
     659             :             END IF
     660             :          END DO
     661             : 
     662          66 :          ALLOCATE (xas_tdp_env%ex_atom_indices(nex_atoms))
     663          88 :          ALLOCATE (xas_tdp_env%state_types(SIZE(xas_tdp_control%state_types, 1), nex_atoms))
     664          22 :          nex_atoms = 0
     665          22 :          nmatch = 0
     666             : 
     667          66 :          DO i = 1, n_kinds
     668             :             CALL get_atomic_kind(atomic_kind=at_kind_set(i), name=kind_name, &
     669          44 :                                  natom=nat_of_kind, atom_list=ind_of_kind)
     670         116 :             DO j = 1, nex_kinds
     671          94 :                IF (xas_tdp_control%list_ex_kinds(j) == kind_name) THEN
     672          80 :                   xas_tdp_env%ex_atom_indices(nex_atoms + 1:nex_atoms + nat_of_kind) = ind_of_kind
     673          58 :                   DO k = 1, SIZE(xas_tdp_control%state_types, 1)
     674             :                      xas_tdp_env%state_types(k, nex_atoms + 1:nex_atoms + nat_of_kind) = &
     675          96 :                         xas_tdp_control%state_types(k, j)
     676             :                   END DO
     677          24 :                   nex_atoms = nex_atoms + nat_of_kind
     678          24 :                   nmatch = nmatch + 1
     679             :                END IF
     680             :             END DO
     681             :          END DO
     682             : 
     683          22 :          CALL set_xas_tdp_env(xas_tdp_env, nex_atoms=nex_atoms, nex_kinds=nex_kinds)
     684             : 
     685             : !        Verifying that the input was valid
     686          22 :          IF (nmatch .NE. SIZE(xas_tdp_control%list_ex_kinds)) THEN
     687           0 :             CPABORT("Invalid kind(s) for the KIND_LIST keyword.")
     688             :          END IF
     689             : 
     690             :       END IF
     691             : 
     692             : !  Sort the excited atoms indices (for convinience and use of locate function)
     693          48 :       CALL sort_unique(xas_tdp_env%ex_atom_indices, unique)
     694          48 :       IF (.NOT. unique) THEN
     695           0 :          CPABORT("Excited atoms not uniquely defined.")
     696             :       END IF
     697             : 
     698             : !  Check for periodicity
     699          48 :       CALL get_qs_env(qs_env, cell=cell)
     700         144 :       IF (ALL(cell%perd == 0)) THEN
     701          32 :          xas_tdp_control%is_periodic = .FALSE.
     702          64 :       ELSE IF (ALL(cell%perd == 1)) THEN
     703          16 :          xas_tdp_control%is_periodic = .TRUE.
     704             :       ELSE
     705           0 :          CPABORT("XAS TDP only implemented for full PBCs or non-PBCs")
     706             :       END IF
     707             : 
     708             : !  Allocating memory for the array of donor states
     709         174 :       n_donor_states = COUNT(xas_tdp_env%state_types /= xas_not_excited)
     710         212 :       ALLOCATE (xas_tdp_env%donor_states(n_donor_states))
     711         116 :       DO i = 1, n_donor_states
     712         116 :          CALL donor_state_create(xas_tdp_env%donor_states(i))
     713             :       END DO
     714             : 
     715             : !  In case of ADMM, for the whole duration of the XAS_TDP, we need the total KS matrix
     716          48 :       IF (dft_control%do_admm) THEN
     717           4 :          CALL get_qs_env(qs_env, admm_env=admm_env, matrix_ks=matrix_ks)
     718             : 
     719           8 :          DO ispin = 1, dft_control%nspins
     720           8 :             CALL admm_correct_for_eigenvalues(ispin, admm_env, matrix_ks(ispin)%matrix)
     721             :          END DO
     722             :       END IF
     723             : 
     724             : !  In case of externally imposed EPS_PGF_XAS, need to update ORB and RI_XAS interaction radii
     725          48 :       IF (xas_tdp_control%eps_pgf > 0.0_dp) THEN
     726           0 :          CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
     727             : 
     728           0 :          DO i = 1, SIZE(qs_kind_set)
     729           0 :             CALL get_qs_kind(qs_kind_set(i), basis_set=tmp_basis, basis_type="ORB")
     730           0 :             CALL init_interaction_radii_orb_basis(tmp_basis, eps_pgf_orb=xas_tdp_control%eps_pgf)
     731           0 :             CALL get_qs_kind(qs_kind_set(i), basis_set=tmp_basis, basis_type="RI_XAS")
     732           0 :             CALL init_interaction_radii_orb_basis(tmp_basis, eps_pgf_orb=xas_tdp_control%eps_pgf)
     733             :          END DO
     734             :       END IF
     735             : 
     736             : !  In case of ground state OT optimization, compute the MO eigenvalues and get canonical MOs
     737          48 :       IF (qs_env%scf_env%method == ot_method_nr) THEN
     738             : 
     739           4 :          CALL get_qs_env(qs_env, mos=mos, matrix_ks=matrix_ks)
     740           4 :          nspins = 1; IF (do_uks) nspins = 2
     741             : 
     742           8 :          DO ispin = 1, nspins
     743           4 :             CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, eigenvalues=mo_evals)
     744           8 :             CALL calculate_subspace_eigenvalues(mo_coeff, matrix_ks(ispin)%matrix, evals_arg=mo_evals)
     745             :          END DO
     746             :       END IF
     747             : 
     748             : !  Initializing the qs_loc_env from the LOCALIZE subsection of XAS_TDP (largely inpired by MI's XAS)
     749             : !  We create the LOCALIZE subsection here, since it is completely overwritten anyways
     750          48 :       CALL create_localize_section(dummy_section)
     751          48 :       CALL section_vals_create(xas_tdp_control%loc_subsection, dummy_section)
     752             :       CALL section_vals_val_set(xas_tdp_control%loc_subsection, "_SECTION_PARAMETERS_", &
     753          48 :                                 l_val=xas_tdp_control%do_loc)
     754          48 :       CALL section_release(dummy_section)
     755             :       xas_tdp_control%print_loc_subsection => section_vals_get_subs_vals( &
     756          48 :                                               xas_tdp_control%loc_subsection, "PRINT")
     757             : 
     758         336 :       ALLOCATE (xas_tdp_env%qs_loc_env)
     759          48 :       CALL qs_loc_env_create(xas_tdp_env%qs_loc_env)
     760          48 :       qs_loc_env => xas_tdp_env%qs_loc_env
     761          48 :       loc_section => xas_tdp_control%loc_subsection
     762             : !     getting the number of MOs
     763          48 :       CALL get_qs_env(qs_env, mos=mos)
     764          48 :       CALL get_mo_set(mos(1), nmo=n_mo(1), homo=homo(1), nao=nao)
     765          48 :       n_mo(2) = n_mo(1)
     766          48 :       homo(2) = homo(1)
     767          48 :       nspins = 1
     768          48 :       IF (do_os) CALL get_mo_set(mos(2), nmo=n_mo(2), homo=homo(2))
     769          48 :       IF (do_uks) nspins = 2 !in roks, same MOs for both spins
     770             : 
     771             :       ! by default, all (doubly occupied) homo are localized
     772         144 :       IF (xas_tdp_control%n_search < 0 .OR. xas_tdp_control%n_search > MINVAL(homo)) &
     773           0 :          xas_tdp_control%n_search = MINVAL(homo)
     774             :       CALL qs_loc_control_init(qs_loc_env, loc_section, do_homo=.TRUE., do_xas=.TRUE., &
     775          48 :                                nloc_xas=xas_tdp_control%n_search, spin_xas=1)
     776             : 
     777             :       ! do_xas argument above only prepares spin-alpha localization
     778          48 :       IF (do_uks) THEN
     779           6 :          qs_loc_env%localized_wfn_control%nloc_states(2) = xas_tdp_control%n_search
     780           6 :          qs_loc_env%localized_wfn_control%lu_bound_states(1, 2) = 1
     781           6 :          qs_loc_env%localized_wfn_control%lu_bound_states(2, 2) = xas_tdp_control%n_search
     782             :       END IF
     783             : 
     784             : !     final qs_loc_env initialization. Impose Berry operator
     785          48 :       qs_loc_env%localized_wfn_control%operator_type = op_loc_berry
     786          48 :       qs_loc_env%localized_wfn_control%max_iter = 25000
     787          48 :       IF (.NOT. xas_tdp_control%do_loc) THEN
     788          16 :          qs_loc_env%localized_wfn_control%localization_method = do_loc_none
     789             :       ELSE
     790          96 :          n_moloc = qs_loc_env%localized_wfn_control%nloc_states
     791          32 :          CALL set_loc_centers(qs_loc_env%localized_wfn_control, n_moloc, nspins)
     792          32 :          IF (do_uks) THEN
     793             :             CALL qs_loc_env_init(qs_loc_env, qs_loc_env%localized_wfn_control, &
     794           2 :                                  qs_env, do_localize=.TRUE.)
     795             :          ELSE
     796             :             CALL qs_loc_env_init(qs_loc_env, qs_loc_env%localized_wfn_control, &
     797          30 :                                  qs_env, do_localize=.TRUE., myspin=1)
     798             :          END IF
     799             :       END IF
     800             : 
     801             : !  Allocating memory for the array of excited atoms MOs. Worst case senario, all searched MOs are
     802             : !  associated to the same atom
     803         240 :       ALLOCATE (xas_tdp_env%mos_of_ex_atoms(xas_tdp_control%n_search, nex_atoms, nspins))
     804             : 
     805             : !  Compute the projector on the unoccupied, unperturbed ground state: Q = 1 - SP, sor each spin
     806          48 :       IF (do_os) nspins = 2
     807          48 :       CALL get_qs_env(qs_env, rho=rho, matrix_s=matrix_s)
     808          48 :       CALL qs_rho_get(rho, rho_ao=rho_ao)
     809             : 
     810         198 :       ALLOCATE (xas_tdp_env%q_projector(nspins))
     811          48 :       ALLOCATE (xas_tdp_env%q_projector(1)%matrix)
     812             :       CALL dbcsr_create(xas_tdp_env%q_projector(1)%matrix, name="Q PROJECTOR ALPHA", &
     813          48 :                         template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     814          48 :       IF (do_os) THEN
     815           6 :          ALLOCATE (xas_tdp_env%q_projector(2)%matrix)
     816             :          CALL dbcsr_create(xas_tdp_env%q_projector(2)%matrix, name="Q PROJECTOR BETA", &
     817           6 :                            template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
     818             :       END IF
     819             : 
     820             : !     In the case of spin-restricted calculations, rho_ao includes double occupency => 0.5 prefactor
     821          48 :       fact = -0.5_dp; IF (do_os) fact = -1.0_dp
     822             :       CALL dbcsr_multiply('N', 'N', fact, matrix_s(1)%matrix, rho_ao(1)%matrix, 0.0_dp, &
     823          48 :                           xas_tdp_env%q_projector(1)%matrix, filter_eps=xas_tdp_control%eps_filter)
     824          48 :       CALL dbcsr_add_on_diag(xas_tdp_env%q_projector(1)%matrix, 1.0_dp)
     825          48 :       CALL dbcsr_finalize(xas_tdp_env%q_projector(1)%matrix)
     826             : 
     827          48 :       IF (do_os) THEN
     828             :          CALL dbcsr_multiply('N', 'N', fact, matrix_s(1)%matrix, rho_ao(2)%matrix, 0.0_dp, &
     829           6 :                              xas_tdp_env%q_projector(2)%matrix, filter_eps=xas_tdp_control%eps_filter)
     830           6 :          CALL dbcsr_add_on_diag(xas_tdp_env%q_projector(2)%matrix, 1.0_dp)
     831           6 :          CALL dbcsr_finalize(xas_tdp_env%q_projector(2)%matrix)
     832             :       END IF
     833             : 
     834             : !  Create the structure for the dipole in the AO basis
     835         192 :       ALLOCATE (xas_tdp_env%dipmat(3))
     836         192 :       DO i = 1, 3
     837         144 :          ALLOCATE (xas_tdp_env%dipmat(i)%matrix)
     838         144 :          CALL dbcsr_copy(matrix_tmp, matrix_s(1)%matrix, name="XAS TDP dipole matrix")
     839         144 :          IF (xas_tdp_control%dipole_form == xas_dip_vel) THEN
     840             :             CALL dbcsr_create(xas_tdp_env%dipmat(i)%matrix, template=matrix_s(1)%matrix, &
     841          90 :                               matrix_type=dbcsr_type_antisymmetric)
     842          90 :             CALL dbcsr_complete_redistribute(matrix_tmp, xas_tdp_env%dipmat(i)%matrix)
     843             :          ELSE
     844             :             CALL dbcsr_create(xas_tdp_env%dipmat(i)%matrix, template=matrix_s(1)%matrix, &
     845          54 :                               matrix_type=dbcsr_type_symmetric)
     846          54 :             CALL dbcsr_copy(xas_tdp_env%dipmat(i)%matrix, matrix_tmp)
     847             :          END IF
     848         144 :          CALL dbcsr_set(xas_tdp_env%dipmat(i)%matrix, 0.0_dp)
     849         192 :          CALL dbcsr_release(matrix_tmp)
     850             :       END DO
     851             : 
     852             : !  Create the structure for the electric quadrupole in the AO basis, if required
     853          48 :       IF (xas_tdp_control%do_quad) THEN
     854           0 :          ALLOCATE (xas_tdp_env%quadmat(6))
     855           0 :          DO i = 1, 6
     856           0 :             ALLOCATE (xas_tdp_env%quadmat(i)%matrix)
     857           0 :             CALL dbcsr_copy(xas_tdp_env%quadmat(i)%matrix, matrix_s(1)%matrix, name="XAS TDP quadrupole matrix")
     858           0 :             CALL dbcsr_set(xas_tdp_env%quadmat(i)%matrix, 0.0_dp)
     859             :          END DO
     860             :       END IF
     861             : 
     862             : !     Precompute it in the velocity representation, if so chosen
     863          48 :       IF (xas_tdp_control%dipole_form == xas_dip_vel) THEN
     864             :          !enforce minimum image to avoid any PBCs related issues. Ok because very localized densities
     865          30 :          CALL p_xyz_ao(xas_tdp_env%dipmat, qs_env, minimum_image=.TRUE.)
     866             :       END IF
     867             : 
     868             : !  Allocate SOC in AO basis matrices
     869          48 :       IF (xas_tdp_control%do_soc .OR. xas_tdp_control%do_gw2x) THEN
     870          88 :          ALLOCATE (xas_tdp_env%orb_soc(3))
     871          88 :          DO i = 1, 3
     872         114 :             ALLOCATE (xas_tdp_env%orb_soc(i)%matrix)
     873             :          END DO
     874             :       END IF
     875             : 
     876             : !  Check that everything is allowed
     877          48 :       CALL safety_check(xas_tdp_control, qs_env)
     878             : 
     879             : !  Initialize libint for the 3-center integrals
     880          48 :       CALL cp_libint_static_init()
     881             : 
     882             : !  Compute LUMOs as guess for OT solver and/or for GW2X correction
     883          48 :       IF (xas_tdp_control%do_ot .OR. xas_tdp_control%do_gw2x) THEN
     884          20 :          CALL make_lumo_guess(xas_tdp_env, xas_tdp_control, qs_env)
     885             :       END IF
     886             : 
     887         144 :    END SUBROUTINE xas_tdp_init
     888             : 
     889             : ! **************************************************************************************************
     890             : !> \brief splits the excited atoms of a kind into batches for RI 3c integrals load balance
     891             : !> \param ex_atoms_of_kind the excited atoms for the current kind, randomly shuffled
     892             : !> \param nbatch number of batches to loop over
     893             : !> \param batch_size standard size of a batch
     894             : !> \param atoms_of_kind number of atoms for the current kind (excited or not)
     895             : !> \param xas_tdp_env ...
     896             : ! **************************************************************************************************
     897          52 :    SUBROUTINE get_ri_3c_batches(ex_atoms_of_kind, nbatch, batch_size, atoms_of_kind, xas_tdp_env)
     898             : 
     899             :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(INOUT)  :: ex_atoms_of_kind
     900             :       INTEGER, INTENT(OUT)                               :: nbatch
     901             :       INTEGER, INTENT(IN)                                :: batch_size
     902             :       INTEGER, DIMENSION(:), INTENT(IN)                  :: atoms_of_kind
     903             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
     904             : 
     905             :       INTEGER                                            :: iat, iatom, nex_atom
     906          52 :       TYPE(rng_stream_type), ALLOCATABLE                 :: rng_stream
     907             : 
     908             :       !Get the atoms from atoms_of_kind that are excited
     909          52 :       nex_atom = 0
     910         268 :       DO iat = 1, SIZE(atoms_of_kind)
     911         216 :          iatom = atoms_of_kind(iat)
     912         444 :          IF (.NOT. ANY(xas_tdp_env%ex_atom_indices == iatom)) CYCLE
     913         268 :          nex_atom = nex_atom + 1
     914             :       END DO
     915             : 
     916         156 :       ALLOCATE (ex_atoms_of_kind(nex_atom))
     917          52 :       nex_atom = 0
     918         268 :       DO iat = 1, SIZE(atoms_of_kind)
     919         216 :          iatom = atoms_of_kind(iat)
     920         444 :          IF (.NOT. ANY(xas_tdp_env%ex_atom_indices == iatom)) CYCLE
     921          58 :          nex_atom = nex_atom + 1
     922         268 :          ex_atoms_of_kind(nex_atom) = iatom
     923             :       END DO
     924             : 
     925             :       !We shuffle those atoms to spread them
     926          52 :       rng_stream = rng_stream_type(name="uniform_rng", distribution_type=UNIFORM)
     927          52 :       CALL rng_stream%shuffle(ex_atoms_of_kind(1:nex_atom))
     928             : 
     929          52 :       nbatch = nex_atom/batch_size
     930          52 :       IF (nbatch*batch_size .NE. nex_atom) nbatch = nbatch + 1
     931             : 
     932          52 :    END SUBROUTINE get_ri_3c_batches
     933             : 
     934             : ! **************************************************************************************************
     935             : !> \brief Checks for forbidden keywords combinations
     936             : !> \param xas_tdp_control ...
     937             : !> \param qs_env ...
     938             : ! **************************************************************************************************
     939          48 :    SUBROUTINE safety_check(xas_tdp_control, qs_env)
     940             : 
     941             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
     942             :       TYPE(qs_environment_type), POINTER                 :: qs_env
     943             : 
     944             :       TYPE(dft_control_type), POINTER                    :: dft_control
     945             : 
     946             :       !PB only available without exact exchange
     947             :       IF (xas_tdp_control%is_periodic .AND. xas_tdp_control%do_hfx &
     948          48 :           .AND. xas_tdp_control%x_potential%potential_type == do_potential_coulomb) THEN
     949           0 :          CPABORT("XAS TDP with Coulomb operator for exact exchange only supports non-periodic BCs")
     950             :       END IF
     951             : 
     952             :       !open-shell/closed-shell tests
     953          48 :       IF (xas_tdp_control%do_roks .OR. xas_tdp_control%do_uks) THEN
     954             : 
     955           6 :          IF (.NOT. (xas_tdp_control%do_spin_cons .OR. xas_tdp_control%do_spin_flip)) THEN
     956           0 :             CPABORT("Need spin-conserving and/or spin-flip excitations for open-shell systems")
     957             :          END IF
     958             : 
     959           6 :          IF (xas_tdp_control%do_singlet .OR. xas_tdp_control%do_triplet) THEN
     960           0 :             CPABORT("Singlet/triplet excitations only for restricted closed-shell systems")
     961             :          END IF
     962             : 
     963           6 :          IF (xas_tdp_control%do_soc .AND. .NOT. &
     964             :              (xas_tdp_control%do_spin_flip .AND. xas_tdp_control%do_spin_cons)) THEN
     965             : 
     966           0 :             CPABORT("Both spin-conserving and spin-flip excitations are required for SOC")
     967             :          END IF
     968             :       ELSE
     969             : 
     970          42 :          IF (.NOT. (xas_tdp_control%do_singlet .OR. xas_tdp_control%do_triplet)) THEN
     971           0 :             CPABORT("Need singlet and/or triplet excitations for closed-shell systems")
     972             :          END IF
     973             : 
     974          42 :          IF (xas_tdp_control%do_spin_cons .OR. xas_tdp_control%do_spin_flip) THEN
     975           0 :             CPABORT("Spin-conserving/spin-flip excitations only for open-shell systems")
     976             :          END IF
     977             : 
     978          42 :          IF (xas_tdp_control%do_soc .AND. .NOT. &
     979             :              (xas_tdp_control%do_singlet .AND. xas_tdp_control%do_triplet)) THEN
     980             : 
     981           0 :             CPABORT("Both singlet and triplet excitations are needed for SOC")
     982             :          END IF
     983             :       END IF
     984             : 
     985             :       !Warn against using E_RANGE with SOC
     986          48 :       IF (xas_tdp_control%do_soc .AND. xas_tdp_control%e_range > 0.0_dp) THEN
     987           0 :          CPWARN("Using E_RANGE and SOC together may lead to crashes, use N_EXCITED for safety.")
     988             :       END IF
     989             : 
     990             :       !TDA, full-TDDFT and diagonalization
     991          48 :       IF (.NOT. xas_tdp_control%tamm_dancoff) THEN
     992             : 
     993           6 :          IF (xas_tdp_control%do_spin_flip) THEN
     994           0 :             CPABORT("Spin-flip kernel only implemented for Tamm-Dancoff approximation")
     995             :          END IF
     996             : 
     997           6 :          IF (xas_tdp_control%do_ot) THEN
     998           0 :             CPABORT("OT diagonalization only available within the Tamm-Dancoff approximation")
     999             :          END IF
    1000             :       END IF
    1001             : 
    1002             :       !GW2X, need hfx kernel and LOCALIZE
    1003          48 :       IF (xas_tdp_control%do_gw2x) THEN
    1004          18 :          IF (.NOT. xas_tdp_control%do_hfx) THEN
    1005           0 :             CPABORT("GW2x requires the definition of the EXACT_EXCHANGE kernel")
    1006             :          END IF
    1007          18 :          IF (.NOT. xas_tdp_control%do_loc) THEN
    1008           0 :             CPABORT("GW2X requires the LOCALIZE keyword in DONOR_STATES")
    1009             :          END IF
    1010             :       END IF
    1011             : 
    1012             :       !Only allow ADMM schemes that correct for eigenvalues
    1013          48 :       CALL get_qs_env(qs_env, dft_control=dft_control)
    1014          48 :       IF (dft_control%do_admm) THEN
    1015             :          IF ((.NOT. qs_env%admm_env%purification_method == do_admm_purify_none) .AND. &
    1016           4 :              (.NOT. qs_env%admm_env%purification_method == do_admm_purify_cauchy_subspace) .AND. &
    1017             :              (.NOT. qs_env%admm_env%purification_method == do_admm_purify_mo_diag)) THEN
    1018             : 
    1019           0 :             CPABORT("XAS_TDP only compatible with ADMM purification NONE, CAUCHY_SUBSPACE and MO_DIAG")
    1020             : 
    1021             :          END IF
    1022             :       END IF
    1023             : 
    1024          48 :    END SUBROUTINE safety_check
    1025             : 
    1026             : ! **************************************************************************************************
    1027             : !> \brief Prints some basic info about the chosen parameters
    1028             : !> \param ou the output unis
    1029             : !> \param xas_tdp_control ...
    1030             : !> \param qs_env ...
    1031             : ! **************************************************************************************************
    1032          48 :    SUBROUTINE print_info(ou, xas_tdp_control, qs_env)
    1033             : 
    1034             :       INTEGER, INTENT(IN)                                :: ou
    1035             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    1036             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1037             : 
    1038             :       INTEGER                                            :: i
    1039             :       REAL(dp)                                           :: occ
    1040          48 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    1041             :       TYPE(dft_control_type), POINTER                    :: dft_control
    1042             :       TYPE(section_vals_type), POINTER                   :: input, kernel_section
    1043             : 
    1044          48 :       NULLIFY (input, kernel_section, dft_control, matrix_s)
    1045             : 
    1046          48 :       CALL get_qs_env(qs_env, input=input, dft_control=dft_control, matrix_s=matrix_s)
    1047             : 
    1048             :       !Overlap matrix sparsity
    1049          48 :       occ = dbcsr_get_occupation(matrix_s(1)%matrix)
    1050             : 
    1051          48 :       IF (ou .LE. 0) RETURN
    1052             : 
    1053             :       !Reference calculation
    1054          24 :       IF (xas_tdp_control%do_uks) THEN
    1055             :          WRITE (UNIT=ou, FMT="(/,T3,A)") &
    1056           3 :             "XAS_TDP| Reference calculation: Unrestricted Kohn-Sham"
    1057          21 :       ELSE IF (xas_tdp_control%do_roks) THEN
    1058             :          WRITE (UNIT=ou, FMT="(/,T3,A)") &
    1059           0 :             "XAS_TDP| Reference calculation: Restricted Open-Shell Kohn-Sham"
    1060             :       ELSE
    1061             :          WRITE (UNIT=ou, FMT="(/,T3,A)") &
    1062          21 :             "XAS_TDP| Reference calculation: Restricted Closed-Shell Kohn-Sham"
    1063             :       END IF
    1064             : 
    1065             :       !TDA
    1066          24 :       IF (xas_tdp_control%tamm_dancoff) THEN
    1067             :          WRITE (UNIT=ou, FMT="(T3,A)") &
    1068          21 :             "XAS_TDP| Tamm-Dancoff Approximation (TDA): On"
    1069             :       ELSE
    1070             :          WRITE (UNIT=ou, FMT="(T3,A)") &
    1071           3 :             "XAS_TDP| Tamm-Dancoff Approximation (TDA): Off"
    1072             :       END IF
    1073             : 
    1074             :       !Dipole form
    1075          24 :       IF (xas_tdp_control%dipole_form == xas_dip_vel) THEN
    1076             :          WRITE (UNIT=ou, FMT="(T3,A)") &
    1077          15 :             "XAS_TDP| Transition Dipole Representation: VELOCITY"
    1078             :       ELSE
    1079             :          WRITE (UNIT=ou, FMT="(T3,A)") &
    1080           9 :             "XAS_TDP| Transition Dipole Representation: LENGTH"
    1081             :       END IF
    1082             : 
    1083             :       !Quadrupole
    1084          24 :       IF (xas_tdp_control%do_quad) THEN
    1085             :          WRITE (UNIT=ou, FMT="(T3,A)") &
    1086           0 :             "XAS_TDP| Transition Quadrupole: On"
    1087             :       END IF
    1088             : 
    1089             :       !EPS_PGF
    1090          24 :       IF (xas_tdp_control%eps_pgf > 0.0_dp) THEN
    1091             :          WRITE (UNIT=ou, FMT="(T3,A,ES7.1)") &
    1092           0 :             "XAS_TDP| EPS_PGF_XAS: ", xas_tdp_control%eps_pgf
    1093             :       ELSE
    1094             :          WRITE (UNIT=ou, FMT="(T3,A,ES7.1,A)") &
    1095          24 :             "XAS_TDP| EPS_PGF_XAS: ", dft_control%qs_control%eps_pgf_orb, " (= EPS_PGF_ORB)"
    1096             :       END IF
    1097             : 
    1098             :       !EPS_FILTER
    1099             :       WRITE (UNIT=ou, FMT="(T3,A,ES7.1)") &
    1100          24 :          "XAS_TDP| EPS_FILTER: ", xas_tdp_control%eps_filter
    1101             : 
    1102             :       !Grid info
    1103          24 :       IF (xas_tdp_control%do_xc) THEN
    1104             :          WRITE (UNIT=ou, FMT="(T3,A)") &
    1105          19 :             "XAS_TDP| Radial Grid(s) Info: Kind,  na,  nr"
    1106          40 :          DO i = 1, SIZE(xas_tdp_control%grid_info, 1)
    1107             :             WRITE (UNIT=ou, FMT="(T3,A,A6,A,A,A,A)") &
    1108          21 :                "                            ", TRIM(xas_tdp_control%grid_info(i, 1)), ", ", &
    1109          61 :                TRIM(xas_tdp_control%grid_info(i, 2)), ", ", TRIM(xas_tdp_control%grid_info(i, 3))
    1110             :          END DO
    1111             :       END IF
    1112             : 
    1113             :       !No kernel
    1114          24 :       IF (.NOT. xas_tdp_control%do_coulomb) THEN
    1115             :          WRITE (UNIT=ou, FMT="(/,T3,A)") &
    1116           0 :             "XAS_TDP| No kernel (standard DFT)"
    1117             :       END IF
    1118             : 
    1119             :       !XC kernel
    1120          24 :       IF (xas_tdp_control%do_xc) THEN
    1121             : 
    1122             :          WRITE (UNIT=ou, FMT="(/,T3,A,F5.2,A)") &
    1123          19 :             "XAS_TDP| RI Region's Radius: ", xas_tdp_control%ri_radius*angstrom, " Ang"
    1124             : 
    1125             :          WRITE (UNIT=ou, FMT="(T3,A,/)") &
    1126          19 :             "XAS_TDP| XC Kernel Functional(s) used for the kernel:"
    1127             : 
    1128          19 :          kernel_section => section_vals_get_subs_vals(input, "DFT%XAS_TDP%KERNEL")
    1129          19 :          CALL xc_write(ou, kernel_section, lsd=.TRUE.)
    1130             :       END IF
    1131             : 
    1132             :       !HFX kernel
    1133          24 :       IF (xas_tdp_control%do_hfx) THEN
    1134             :          WRITE (UNIT=ou, FMT="(/,T3,A,/,/,T3,A,F5.3)") &
    1135          19 :             "XAS_TDP| Exact Exchange Kernel: Yes ", &
    1136          38 :             "EXACT_EXCHANGE| Scale: ", xas_tdp_control%sx
    1137          19 :          IF (xas_tdp_control%x_potential%potential_type == do_potential_coulomb) THEN
    1138             :             WRITE (UNIT=ou, FMT="(T3,A)") &
    1139          12 :                "EXACT_EXCHANGE| Potential : Coulomb"
    1140           7 :          ELSE IF (xas_tdp_control%x_potential%potential_type == do_potential_truncated) THEN
    1141             :             WRITE (UNIT=ou, FMT="(T3,A,/,T3,A,F5.2,A,/,T3,A,A)") &
    1142           3 :                "EXACT_EXCHANGE| Potential: Truncated Coulomb", &
    1143           3 :                "EXACT_EXCHANGE| Range: ", xas_tdp_control%x_potential%cutoff_radius*angstrom, ", (Ang)", &
    1144           6 :                "EXACT_EXCHANGE| T_C_G_DATA: ", TRIM(xas_tdp_control%x_potential%filename)
    1145           4 :          ELSE IF (xas_tdp_control%x_potential%potential_type == do_potential_short) THEN
    1146             :             WRITE (UNIT=ou, FMT="(T3,A,/,T3,A,F5.2,A,/,T3,A,F5.2,A,/,T3,A,ES7.1)") &
    1147           4 :                "EXACT_EXCHANGE| Potential: Short Range", &
    1148           4 :                "EXACT_EXCHANGE| Omega: ", xas_tdp_control%x_potential%omega, ", (1/a0)", &
    1149           4 :                "EXACT_EXCHANGE| Effective Range: ", xas_tdp_control%x_potential%cutoff_radius*angstrom, ", (Ang)", &
    1150           8 :                "EXACT_EXCHANGE| EPS_RANGE: ", xas_tdp_control%eps_range
    1151             :          END IF
    1152          19 :          IF (xas_tdp_control%eps_screen > 1.0E-16) THEN
    1153             :             WRITE (UNIT=ou, FMT="(T3,A,ES7.1)") &
    1154          19 :                "EXACT_EXCHANGE| EPS_SCREENING: ", xas_tdp_control%eps_screen
    1155             :          END IF
    1156             : 
    1157             :          !RI metric
    1158          19 :          IF (xas_tdp_control%do_ri_metric) THEN
    1159             : 
    1160             :             WRITE (UNIT=ou, FMT="(/,T3,A)") &
    1161           3 :                "EXACT_EXCHANGE| Using a RI metric"
    1162           3 :             IF (xas_tdp_control%ri_m_potential%potential_type == do_potential_id) THEN
    1163             :                WRITE (UNIT=ou, FMT="(T3,A)") &
    1164           1 :                   "EXACT_EXCHANGE RI_METRIC| Potential : Overlap"
    1165           2 :             ELSE IF (xas_tdp_control%ri_m_potential%potential_type == do_potential_truncated) THEN
    1166             :                WRITE (UNIT=ou, FMT="(T3,A,/,T3,A,F5.2,A,/,T3,A,A)") &
    1167           1 :                   "EXACT_EXCHANGE RI_METRIC| Potential: Truncated Coulomb", &
    1168           1 :                   "EXACT_EXCHANGE RI_METRIC| Range: ", xas_tdp_control%ri_m_potential%cutoff_radius &
    1169           1 :                   *angstrom, ", (Ang)", &
    1170           2 :                   "EXACT_EXCHANGE RI_METRIC| T_C_G_DATA: ", TRIM(xas_tdp_control%ri_m_potential%filename)
    1171           1 :             ELSE IF (xas_tdp_control%ri_m_potential%potential_type == do_potential_short) THEN
    1172             :                WRITE (UNIT=ou, FMT="(T3,A,/,T3,A,F5.2,A,/,T3,A,F5.2,A,/,T3,A,ES7.1)") &
    1173           1 :                   "EXACT_EXCHANGE RI_METRIC| Potential: Short Range", &
    1174           1 :                   "EXACT_EXCHANGE RI_METRIC| Omega: ", xas_tdp_control%ri_m_potential%omega, ", (1/a0)", &
    1175           1 :                   "EXACT_EXCHANGE RI_METRIC| Effective Range: ", &
    1176           1 :                   xas_tdp_control%ri_m_potential%cutoff_radius*angstrom, ", (Ang)", &
    1177           2 :                   "EXACT_EXCHANGE RI_METRIC| EPS_RANGE: ", xas_tdp_control%eps_range
    1178             :             END IF
    1179             :          END IF
    1180             :       ELSE
    1181             :          WRITE (UNIT=ou, FMT="(/,T3,A,/)") &
    1182           5 :             "XAS_TDP| Exact Exchange Kernel: No "
    1183             :       END IF
    1184             : 
    1185             :       !overlap mtrix occupation
    1186             :       WRITE (UNIT=ou, FMT="(/,T3,A,F5.2)") &
    1187          24 :          "XAS_TDP| Overlap matrix occupation: ", occ
    1188             : 
    1189             :       !GW2X parameter
    1190          24 :       IF (xas_tdp_control%do_gw2x) THEN
    1191             :          WRITE (UNIT=ou, FMT="(T3,A,/)") &
    1192           9 :             "XAS_TDP| GW2X correction enabled"
    1193             : 
    1194           9 :          IF (xas_tdp_control%xps_only) THEN
    1195             :             WRITE (UNIT=ou, FMT="(T3,A)") &
    1196           2 :                "GW2X| Only computing ionizations potentials for XPS"
    1197             :          END IF
    1198             : 
    1199           9 :          IF (xas_tdp_control%pseudo_canonical) THEN
    1200             :             WRITE (UNIT=ou, FMT="(T3,A)") &
    1201           8 :                "GW2X| Using the pseudo-canonical scheme"
    1202             :          ELSE
    1203             :             WRITE (UNIT=ou, FMT="(T3,A)") &
    1204           1 :                "GW2X| Using the GW2X* scheme"
    1205             :          END IF
    1206             : 
    1207             :          WRITE (UNIT=ou, FMT="(T3,A,ES7.1)") &
    1208           9 :             "GW2X| EPS_GW2X: ", xas_tdp_control%gw2x_eps
    1209             : 
    1210             :          WRITE (UNIT=ou, FMT="(T3,A,I5)") &
    1211           9 :             "GW2X| contraction batch size: ", xas_tdp_control%batch_size
    1212             : 
    1213           9 :          IF ((INT(xas_tdp_control%c_os) .NE. 1) .OR. (INT(xas_tdp_control%c_ss) .NE. 1)) THEN
    1214             :             WRITE (UNIT=ou, FMT="(T3,A,F7.4,/,T3,A,F7.4)") &
    1215           1 :                "GW2X| Same-spin scaling factor: ", xas_tdp_control%c_ss, &
    1216           2 :                "GW2X| Opposite-spin scaling factor: ", xas_tdp_control%c_os
    1217             :          END IF
    1218             : 
    1219             :       END IF
    1220             : 
    1221          48 :    END SUBROUTINE print_info
    1222             : 
    1223             : ! **************************************************************************************************
    1224             : !> \brief Assosciate (possibly localized) lowest energy  MOs to each excited atoms. The procedure
    1225             : !>        looks for MOs "centered" on the excited atoms by comparing distances. It
    1226             : !>        then fills the mos_of_ex_atoms arrays of the xas_tdp_env. Only the xas_tdp_control%n_search
    1227             : !>        lowest energy MOs are considered. Largely inspired by MI's implementation of XAS
    1228             : !>        It is assumed that the Berry phase is used to compute centers.
    1229             : !> \param xas_tdp_env ...
    1230             : !> \param xas_tdp_control ...
    1231             : !> \param qs_env ...
    1232             : !> \note Whether localization took place or not, the procedure is the same as centers are stored in
    1233             : !>       xas_tdp_env%qs_loc_env%localized_wfn_control%centers_set
    1234             : !>       Assumes that find_mo_centers has been run previously
    1235             : ! **************************************************************************************************
    1236          48 :    SUBROUTINE assign_mos_to_ex_atoms(xas_tdp_env, xas_tdp_control, qs_env)
    1237             : 
    1238             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    1239             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    1240             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1241             : 
    1242             :       INTEGER                                            :: at_index, iat, iat_memo, imo, ispin, &
    1243             :                                                             n_atoms, n_search, nex_atoms, nspins
    1244             :       INTEGER, DIMENSION(3)                              :: perd_init
    1245          48 :       INTEGER, DIMENSION(:, :, :), POINTER               :: mos_of_ex_atoms
    1246             :       REAL(dp)                                           :: dist, dist_min
    1247             :       REAL(dp), DIMENSION(3)                             :: at_pos, r_ac, wfn_center
    1248             :       TYPE(cell_type), POINTER                           :: cell
    1249             :       TYPE(localized_wfn_control_type), POINTER          :: localized_wfn_control
    1250          48 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1251             : 
    1252          48 :       NULLIFY (localized_wfn_control, mos_of_ex_atoms, cell, particle_set)
    1253             : 
    1254             : !  Initialization. mos_of_ex_atoms filled with -1, meaning no assigned state
    1255          48 :       mos_of_ex_atoms => xas_tdp_env%mos_of_ex_atoms
    1256         524 :       mos_of_ex_atoms(:, :, :) = -1
    1257          48 :       n_search = xas_tdp_control%n_search
    1258          48 :       nex_atoms = xas_tdp_env%nex_atoms
    1259          48 :       localized_wfn_control => xas_tdp_env%qs_loc_env%localized_wfn_control
    1260          48 :       CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, cell=cell)
    1261          48 :       n_atoms = SIZE(particle_set)
    1262          48 :       nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
    1263             : 
    1264             : !     Temporarly impose periodic BCs because of Berry's phase operator used for localization
    1265         192 :       perd_init = cell%perd
    1266         192 :       cell%perd = 1
    1267             : 
    1268             : !  Loop over n_search lowest energy MOs and all atoms, for each spin
    1269         102 :       DO ispin = 1, nspins
    1270         374 :          DO imo = 1, n_search
    1271             : !           retrieve MO wave function center coordinates.
    1272        1088 :             wfn_center(1:3) = localized_wfn_control%centers_set(ispin)%array(1:3, imo)
    1273         272 :             iat_memo = 0
    1274             : 
    1275             : !           a large enough value to avoid bad surprises
    1276         272 :             dist_min = 10000.0_dp
    1277        7590 :             DO iat = 1, n_atoms
    1278       29272 :                at_pos = particle_set(iat)%r
    1279        7318 :                r_ac = pbc(at_pos, wfn_center, cell)
    1280       29272 :                dist = NORM2(r_ac)
    1281             : 
    1282             : !              keep memory of which atom is the closest to the wave function center
    1283        7590 :                IF (dist < dist_min) THEN
    1284         646 :                   iat_memo = iat
    1285         646 :                   dist_min = dist
    1286             :                END IF
    1287             :             END DO
    1288             : 
    1289             : !           Verify that the closest atom is actually excited and assign the MO if so
    1290         556 :             IF (ANY(xas_tdp_env%ex_atom_indices == iat_memo)) THEN
    1291         114 :                at_index = locate(xas_tdp_env%ex_atom_indices, iat_memo)
    1292         114 :                mos_of_ex_atoms(imo, at_index, ispin) = 1
    1293             :             END IF
    1294             :          END DO !imo
    1295             :       END DO !ispin
    1296             : 
    1297             : !  Go back to initial BCs
    1298         192 :       cell%perd = perd_init
    1299             : 
    1300          48 :    END SUBROUTINE assign_mos_to_ex_atoms
    1301             : 
    1302             : ! **************************************************************************************************
    1303             : !> \brief Re-initialize the qs_loc_env to the current MOs.
    1304             : !> \param qs_loc_env the env to re-initialize
    1305             : !> \param n_loc_states the number of states to include
    1306             : !> \param do_uks in cas of spin unrestricted calculation, initialize for both spins
    1307             : !> \param qs_env ...
    1308             : !> \note  Useful when one needs to make use of qs_loc features and it is either with canonical MOs
    1309             : !>        or the localized MOs have been modified. do_localize is overwritten.
    1310             : !>        Same loc range for both spins
    1311             : ! **************************************************************************************************
    1312          80 :    SUBROUTINE reinit_qs_loc_env(qs_loc_env, n_loc_states, do_uks, qs_env)
    1313             : 
    1314             :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
    1315             :       INTEGER, INTENT(IN)                                :: n_loc_states
    1316             :       LOGICAL, INTENT(IN)                                :: do_uks
    1317             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1318             : 
    1319             :       INTEGER                                            :: i, nspins
    1320             :       TYPE(localized_wfn_control_type), POINTER          :: loc_wfn_control
    1321             : 
    1322             : !  First, release the old env
    1323          80 :       CALL qs_loc_env_release(qs_loc_env)
    1324             : 
    1325             : !  Re-create it
    1326          80 :       CALL qs_loc_env_create(qs_loc_env)
    1327          80 :       CALL localized_wfn_control_create(qs_loc_env%localized_wfn_control)
    1328          80 :       loc_wfn_control => qs_loc_env%localized_wfn_control
    1329             : 
    1330             : !  Initialize it
    1331          80 :       loc_wfn_control%localization_method = do_loc_none
    1332          80 :       loc_wfn_control%operator_type = op_loc_berry
    1333         240 :       loc_wfn_control%nloc_states(:) = n_loc_states
    1334          80 :       loc_wfn_control%eps_occ = 0.0_dp
    1335         240 :       loc_wfn_control%lu_bound_states(1, :) = 1
    1336         240 :       loc_wfn_control%lu_bound_states(2, :) = n_loc_states
    1337          80 :       loc_wfn_control%set_of_states = state_loc_list
    1338          80 :       loc_wfn_control%do_homo = .TRUE.
    1339         240 :       ALLOCATE (loc_wfn_control%loc_states(n_loc_states, 2))
    1340         550 :       DO i = 1, n_loc_states
    1341        1490 :          loc_wfn_control%loc_states(i, :) = i
    1342             :       END DO
    1343             : 
    1344          80 :       nspins = 1; IF (do_uks) nspins = 2
    1345          80 :       CALL set_loc_centers(loc_wfn_control, loc_wfn_control%nloc_states, nspins=nspins)
    1346             :       ! need to set do_localize=.TRUE. because otherwise no routine works
    1347          80 :       IF (do_uks) THEN
    1348           8 :          CALL qs_loc_env_init(qs_loc_env, loc_wfn_control, qs_env, do_localize=.TRUE.)
    1349             :       ELSE
    1350          72 :          CALL qs_loc_env_init(qs_loc_env, loc_wfn_control, qs_env, myspin=1, do_localize=.TRUE.)
    1351             :       END IF
    1352             : 
    1353          80 :    END SUBROUTINE reinit_qs_loc_env
    1354             : 
    1355             : ! *************************************************************************************************
    1356             : !> \brief Diagonalize the subset of previously localized MOs that are associated to each excited
    1357             : !>        atoms. Updates the MO coeffs accordingly.
    1358             : !> \param xas_tdp_env ...
    1359             : !> \param xas_tdp_control ...
    1360             : !> \param qs_env ...
    1361             : !> \note  Needed because after localization, the MOs loose their identity (1s, 2s , 2p, etc)
    1362             : ! **************************************************************************************************
    1363          32 :    SUBROUTINE diagonalize_assigned_mo_subset(xas_tdp_env, xas_tdp_control, qs_env)
    1364             : 
    1365             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    1366             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    1367             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1368             : 
    1369             :       INTEGER                                            :: i, iat, ilmo, ispin, nao, nlmo, nspins
    1370          32 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: evals
    1371             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1372             :       TYPE(cp_fm_struct_type), POINTER                   :: ks_struct, lmo_struct
    1373             :       TYPE(cp_fm_type)                                   :: evecs, ks_fm, lmo_fm, work
    1374             :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1375          32 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
    1376          32 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1377             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1378             : 
    1379          32 :       NULLIFY (mos, mo_coeff, matrix_ks, para_env, blacs_env, lmo_struct, ks_struct)
    1380             : 
    1381             :       ! Get what we need from qs_env
    1382          32 :       CALL get_qs_env(qs_env, mos=mos, matrix_ks=matrix_ks, para_env=para_env, blacs_env=blacs_env)
    1383             : 
    1384          32 :       nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
    1385             : 
    1386             :       ! Loop over the excited atoms and spin
    1387          66 :       DO ispin = 1, nspins
    1388         110 :          DO iat = 1, xas_tdp_env%nex_atoms
    1389             : 
    1390             :             ! get the MOs
    1391          44 :             CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nao=nao)
    1392             : 
    1393             :             ! count how many MOs are associated to this atom and create a fm/struct
    1394         342 :             nlmo = COUNT(xas_tdp_env%mos_of_ex_atoms(:, iat, ispin) == 1)
    1395             :             CALL cp_fm_struct_create(lmo_struct, nrow_global=nao, ncol_global=nlmo, &
    1396          44 :                                      para_env=para_env, context=blacs_env)
    1397          44 :             CALL cp_fm_create(lmo_fm, lmo_struct)
    1398          44 :             CALL cp_fm_create(work, lmo_struct)
    1399             : 
    1400             :             CALL cp_fm_struct_create(ks_struct, nrow_global=nlmo, ncol_global=nlmo, &
    1401          44 :                                      para_env=para_env, context=blacs_env)
    1402          44 :             CALL cp_fm_create(ks_fm, ks_struct)
    1403          44 :             CALL cp_fm_create(evecs, ks_struct)
    1404             : 
    1405             :             ! Loop over the localized MOs associated to this atom
    1406          44 :             i = 0
    1407         342 :             DO ilmo = 1, xas_tdp_control%n_search
    1408         298 :                IF (xas_tdp_env%mos_of_ex_atoms(ilmo, iat, ispin) == -1) CYCLE
    1409             : 
    1410          60 :                i = i + 1
    1411             :                ! put the coeff in our atom-restricted lmo_fm
    1412             :                CALL cp_fm_to_fm_submat(mo_coeff, lmo_fm, nrow=nao, ncol=1, s_firstrow=1, &
    1413         342 :                                        s_firstcol=ilmo, t_firstrow=1, t_firstcol=i)
    1414             : 
    1415             :             END DO !ilmo
    1416             : 
    1417             :             ! Computing the KS matrix in the subset of MOs
    1418          44 :             CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, lmo_fm, work, ncol=nlmo)
    1419          44 :             CALL parallel_gemm('T', 'N', nlmo, nlmo, nao, 1.0_dp, lmo_fm, work, 0.0_dp, ks_fm)
    1420             : 
    1421             :             ! Diagonalizing the KS matrix in the subset of MOs
    1422         132 :             ALLOCATE (evals(nlmo))
    1423          44 :             CALL cp_fm_syevd(ks_fm, evecs, evals)
    1424          44 :             DEALLOCATE (evals)
    1425             : 
    1426             :             ! Express the MOs in the basis that diagonalizes KS
    1427          44 :             CALL parallel_gemm('N', 'N', nao, nlmo, nlmo, 1.0_dp, lmo_fm, evecs, 0.0_dp, work)
    1428             : 
    1429             :             ! Replacing the new MOs back in the MO coeffs
    1430          44 :             i = 0
    1431         342 :             DO ilmo = 1, xas_tdp_control%n_search
    1432         298 :                IF (xas_tdp_env%mos_of_ex_atoms(ilmo, iat, ispin) == -1) CYCLE
    1433             : 
    1434          60 :                i = i + 1
    1435             :                CALL cp_fm_to_fm_submat(work, mo_coeff, nrow=nao, ncol=1, s_firstrow=1, &
    1436         342 :                                        s_firstcol=i, t_firstrow=1, t_firstcol=ilmo)
    1437             : 
    1438             :             END DO
    1439             : 
    1440             :             ! Excited atom clean-up
    1441          44 :             CALL cp_fm_release(lmo_fm)
    1442          44 :             CALL cp_fm_release(work)
    1443          44 :             CALL cp_fm_struct_release(lmo_struct)
    1444          44 :             CALL cp_fm_release(ks_fm)
    1445          44 :             CALL cp_fm_release(evecs)
    1446         210 :             CALL cp_fm_struct_release(ks_struct)
    1447             :          END DO !iat
    1448             :       END DO !ispin
    1449             : 
    1450          64 :    END SUBROUTINE diagonalize_assigned_mo_subset
    1451             : 
    1452             : ! **************************************************************************************************
    1453             : !> \brief Assign core MO(s) to a given donor_state, taking the type (1S, 2S, etc) into account.
    1454             : !>        The projection on a representative Slater-type orbital basis is used as a indicator.
    1455             : !>        It is assumed that MOs are already assigned to excited atoms based on their center
    1456             : !> \param donor_state the donor_state to which a MO must be assigned
    1457             : !> \param xas_tdp_env ...
    1458             : !> \param xas_tdp_control ...
    1459             : !> \param qs_env ...
    1460             : ! **************************************************************************************************
    1461          68 :    SUBROUTINE assign_mos_to_donor_state(donor_state, xas_tdp_env, xas_tdp_control, qs_env)
    1462             : 
    1463             :       TYPE(donor_state_type), POINTER                    :: donor_state
    1464             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    1465             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    1466             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1467             : 
    1468             :       INTEGER                                            :: at_index, i, iat, imo, ispin, l, my_mo, &
    1469             :                                                             n_search, n_states, nao, ndo_so, nj, &
    1470             :                                                             nsgf_kind, nsgf_sto, nspins, &
    1471             :                                                             output_unit, zval
    1472          68 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: my_mos
    1473             :       INTEGER, DIMENSION(2)                              :: next_best_overlap_ind
    1474             :       INTEGER, DIMENSION(4, 7)                           :: ne
    1475          68 :       INTEGER, DIMENSION(:), POINTER                     :: first_sgf, lq, nq
    1476          68 :       INTEGER, DIMENSION(:, :, :), POINTER               :: mos_of_ex_atoms
    1477             :       LOGICAL                                            :: unique
    1478             :       REAL(dp)                                           :: zeff
    1479          68 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: diag, overlap, sto_overlap
    1480          68 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: max_overlap
    1481             :       REAL(dp), DIMENSION(2)                             :: next_best_overlap
    1482          68 :       REAL(dp), DIMENSION(:), POINTER                    :: mo_evals, zeta
    1483          68 :       REAL(dp), DIMENSION(:, :), POINTER                 :: overlap_matrix, tmp_coeff
    1484             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1485             :       TYPE(cp_fm_struct_type), POINTER                   :: eval_mat_struct, gs_struct
    1486             :       TYPE(cp_fm_type)                                   :: eval_mat, work_mat
    1487             :       TYPE(cp_fm_type), POINTER                          :: gs_coeffs, mo_coeff
    1488          68 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks
    1489             :       TYPE(gto_basis_set_type), POINTER                  :: kind_basis_set, sto_to_gto_basis_set
    1490          68 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1491             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1492          68 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1493          68 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1494             :       TYPE(sto_basis_set_type), POINTER                  :: sto_basis_set
    1495             : 
    1496          68 :       NULLIFY (sto_basis_set, sto_to_gto_basis_set, qs_kind_set, kind_basis_set, lq, nq, zeta)
    1497          68 :       NULLIFY (overlap_matrix, mos, mo_coeff, mos_of_ex_atoms, tmp_coeff, first_sgf, particle_set)
    1498          68 :       NULLIFY (mo_evals, matrix_ks, para_env, blacs_env)
    1499          68 :       NULLIFY (eval_mat_struct, gs_struct, gs_coeffs)
    1500             : 
    1501         136 :       output_unit = cp_logger_get_default_io_unit()
    1502             : 
    1503             :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, mos=mos, particle_set=particle_set, &
    1504          68 :                       matrix_ks=matrix_ks, para_env=para_env, blacs_env=blacs_env)
    1505             : 
    1506          68 :       nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
    1507             : 
    1508             : !  Construction of a STO that fits the type of orbital we look for
    1509          68 :       ALLOCATE (zeta(1))
    1510          68 :       ALLOCATE (lq(1))
    1511          68 :       ALLOCATE (nq(1))
    1512             : !     Retrieving quantum numbers
    1513          68 :       IF (donor_state%state_type == xas_1s_type) THEN
    1514          54 :          nq(1) = 1
    1515          54 :          lq(1) = 0
    1516          54 :          n_states = 1
    1517          14 :       ELSE IF (donor_state%state_type == xas_2s_type) THEN
    1518           6 :          nq(1) = 2
    1519           6 :          lq(1) = 0
    1520           6 :          n_states = 1
    1521           8 :       ELSE IF (donor_state%state_type == xas_2p_type) THEN
    1522           8 :          nq(1) = 2
    1523           8 :          lq(1) = 1
    1524           8 :          n_states = 3
    1525             :       ELSE
    1526           0 :          CPABORT("Procedure for required type not implemented")
    1527             :       END IF
    1528         272 :       ALLOCATE (my_mos(n_states, nspins))
    1529         204 :       ALLOCATE (max_overlap(n_states, nspins))
    1530             : 
    1531             : !     Getting the atomic number
    1532          68 :       CALL get_qs_kind(qs_kind_set(donor_state%kind_index), zeff=zeff)
    1533          68 :       zval = INT(zeff)
    1534             : 
    1535             : !     Electronic configuration (copied from MI's XAS)
    1536          68 :       ne = 0
    1537         340 :       DO l = 1, 4
    1538         272 :          nj = 2*(l - 1) + 1
    1539        1836 :          DO i = l, 7
    1540        1496 :             ne(l, i) = ptable(zval)%e_conv(l - 1) - 2*nj*(i - l)
    1541        1496 :             ne(l, i) = MAX(ne(l, i), 0)
    1542        1768 :             ne(l, i) = MIN(ne(l, i), 2*nj)
    1543             :          END DO
    1544             :       END DO
    1545             : 
    1546             : !     computing zeta with the Slater sum rules
    1547          68 :       zeta(1) = srules(zval, ne, nq(1), lq(1))
    1548             : 
    1549             : !     Allocating memory and initiate STO
    1550          68 :       CALL allocate_sto_basis_set(sto_basis_set)
    1551          68 :       CALL set_sto_basis_set(sto_basis_set, nshell=1, nq=nq, lq=lq, zet=zeta)
    1552             : 
    1553             : !     Some clean-up
    1554          68 :       DEALLOCATE (nq, lq, zeta)
    1555             : 
    1556             : !  Expanding the STO into (normalized) GTOs for later calculations, use standard 3 gaussians
    1557             :       CALL create_gto_from_sto_basis(sto_basis_set=sto_basis_set, &
    1558             :                                      gto_basis_set=sto_to_gto_basis_set, &
    1559          68 :                                      ngauss=3)
    1560          68 :       sto_to_gto_basis_set%norm_type = 2
    1561          68 :       CALL init_orb_basis_set(sto_to_gto_basis_set)
    1562             : 
    1563             : !  Retrieving the atomic kind related GTO in which MOs are expanded
    1564          68 :       CALL get_qs_kind(qs_kind_set(donor_state%kind_index), basis_set=kind_basis_set)
    1565             : 
    1566             : !  Allocating and computing the overlap between the two basis (they share the same center)
    1567          68 :       CALL get_gto_basis_set(gto_basis_set=kind_basis_set, nsgf=nsgf_kind)
    1568          68 :       CALL get_gto_basis_set(gto_basis_set=sto_to_gto_basis_set, nsgf=nsgf_sto)
    1569         272 :       ALLOCATE (overlap_matrix(nsgf_sto, nsgf_kind))
    1570             : 
    1571             : !     Making use of MI's subroutine
    1572          68 :       CALL calc_stogto_overlap(sto_to_gto_basis_set, kind_basis_set, overlap_matrix)
    1573             : 
    1574             : !     Some clean-up
    1575          68 :       CALL deallocate_sto_basis_set(sto_basis_set)
    1576          68 :       CALL deallocate_gto_basis_set(sto_to_gto_basis_set)
    1577             : 
    1578             : !  Looping over the potential donor states to compute overlap with STO basis
    1579          68 :       mos_of_ex_atoms => xas_tdp_env%mos_of_ex_atoms
    1580          68 :       n_search = xas_tdp_control%n_search
    1581          68 :       at_index = donor_state%at_index
    1582          68 :       iat = locate(xas_tdp_env%ex_atom_indices, at_index)
    1583         204 :       ALLOCATE (first_sgf(SIZE(particle_set))) !probably do not need that
    1584          68 :       CALL get_particle_set(particle_set=particle_set, qs_kind_set=qs_kind_set, first_sgf=first_sgf)
    1585         204 :       ALLOCATE (tmp_coeff(nsgf_kind, 1))
    1586         136 :       ALLOCATE (sto_overlap(nsgf_kind))
    1587         204 :       ALLOCATE (overlap(n_search))
    1588             : 
    1589          68 :       next_best_overlap = 0.0_dp
    1590         240 :       max_overlap = 0.0_dp
    1591             : 
    1592         144 :       DO ispin = 1, nspins
    1593             : 
    1594          76 :          CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nao=nao)
    1595         482 :          overlap = 0.0_dp
    1596             : 
    1597          76 :          my_mo = 0
    1598         482 :          DO imo = 1, n_search
    1599         482 :             IF (mos_of_ex_atoms(imo, iat, ispin) > 0) THEN
    1600             : 
    1601        3960 :                sto_overlap = 0.0_dp
    1602        4124 :                tmp_coeff = 0.0_dp
    1603             : 
    1604             : !              Getting the relevant coefficients for the candidate state
    1605             :                CALL cp_fm_get_submatrix(fm=mo_coeff, target_m=tmp_coeff, start_row=first_sgf(at_index), &
    1606         164 :                                         start_col=imo, n_rows=nsgf_kind, n_cols=1, transpose=.FALSE.)
    1607             : 
    1608             : !              Computing the product overlap_matrix*coeffs
    1609             :                CALL dgemm('N', 'N', nsgf_sto, 1, nsgf_kind, 1.0_dp, overlap_matrix, nsgf_sto, &
    1610         164 :                           tmp_coeff, nsgf_kind, 0.0_dp, sto_overlap, nsgf_sto)
    1611             : 
    1612             : !              Each element of column vector sto_overlap is the overlap of a basis element of the
    1613             : !              generated STO basis with the kind specific orbital basis. Take the sum of the absolute
    1614             : !              values so that rotation (of the px, py, pz for example) does not hinder our search
    1615        3960 :                overlap(imo) = SUM(ABS(sto_overlap))
    1616             : 
    1617             :             END IF
    1618             :          END DO
    1619             : 
    1620             : !     Finding the best overlap(s)
    1621         172 :          DO i = 1, n_states
    1622         602 :             my_mo = MAXLOC(overlap, 1)
    1623          96 :             my_mos(i, ispin) = my_mo
    1624         698 :             max_overlap(i, ispin) = MAXVAL(overlap, 1)
    1625         172 :             overlap(my_mo) = 0.0_dp
    1626             :          END DO
    1627             : !        Getting the next best overlap (for validation purposes)
    1628         558 :          next_best_overlap(ispin) = MAXVAL(overlap, 1)
    1629         482 :          next_best_overlap_ind(ispin) = MAXLOC(overlap, 1)
    1630             : 
    1631             : !        Sort MO indices
    1632         220 :          CALL sort_unique(my_mos(:, ispin), unique)
    1633             : 
    1634             :       END DO !ispin
    1635             : 
    1636             : !     Some clean-up
    1637          68 :       DEALLOCATE (overlap_matrix, tmp_coeff)
    1638             : 
    1639             : !  Dealing with the result
    1640         480 :       IF (ALL(my_mos > 0) .AND. ALL(my_mos <= n_search)) THEN
    1641             : !        Assigning the MO indices to the donor_state
    1642         136 :          ALLOCATE (donor_state%mo_indices(n_states, nspins))
    1643         240 :          donor_state%mo_indices = my_mos
    1644          68 :          donor_state%ndo_mo = n_states
    1645             : 
    1646             : !        Storing the MOs in the donor_state, as vectors column: first columns alpha spin, then beta
    1647             :          CALL cp_fm_struct_create(gs_struct, nrow_global=nao, ncol_global=n_states*nspins, &
    1648          68 :                                   para_env=para_env, context=blacs_env)
    1649          68 :          ALLOCATE (donor_state%gs_coeffs)
    1650          68 :          CALL cp_fm_create(donor_state%gs_coeffs, gs_struct)
    1651             : 
    1652         144 :          DO ispin = 1, nspins
    1653          76 :             CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
    1654         240 :             DO i = 1, n_states
    1655             :                CALL cp_fm_to_fm_submat(msource=mo_coeff, mtarget=donor_state%gs_coeffs, nrow=nao, &
    1656             :                                        ncol=1, s_firstrow=1, s_firstcol=my_mos(i, ispin), &
    1657         172 :                                        t_firstrow=1, t_firstcol=(ispin - 1)*n_states + i)
    1658             :             END DO
    1659             :          END DO
    1660          68 :          gs_coeffs => donor_state%gs_coeffs
    1661             : 
    1662             :          !Keep the subset of the coeffs centered on the excited atom as global array (used a lot)
    1663         272 :          ALLOCATE (donor_state%contract_coeffs(nsgf_kind, n_states*nspins))
    1664             :          CALL cp_fm_get_submatrix(gs_coeffs, donor_state%contract_coeffs, start_row=first_sgf(at_index), &
    1665          68 :                                   start_col=1, n_rows=nsgf_kind, n_cols=n_states*nspins)
    1666             : 
    1667             : !     Assigning corresponding energy eigenvalues and writing some info in standard input file
    1668             : 
    1669             :          !standard eigenvalues as gotten from the KS diagonalization in the ground state
    1670          68 :          IF (.NOT. xas_tdp_control%do_loc .AND. .NOT. xas_tdp_control%do_roks) THEN
    1671          20 :             IF (output_unit > 0) THEN
    1672             :                WRITE (UNIT=output_unit, FMT="(T5,A,/,T5,A,/,T5,A)") &
    1673          10 :                   "The following canonical MO(s) have been associated with the donor state(s)", &
    1674          10 :                   "based on the overlap with the components of a minimal STO basis: ", &
    1675          20 :                   "                                         Spin   MO index     overlap(sum)"
    1676             :             END IF
    1677             : 
    1678          40 :             ALLOCATE (donor_state%energy_evals(n_states, nspins))
    1679          80 :             donor_state%energy_evals = 0.0_dp
    1680             : 
    1681             : !           Canonical MO, no change in eigenvalues, only diagonal elements
    1682          44 :             DO ispin = 1, nspins
    1683          24 :                CALL get_mo_set(mos(ispin), eigenvalues=mo_evals)
    1684          80 :                DO i = 1, n_states
    1685          36 :                   donor_state%energy_evals(i, ispin) = mo_evals(my_mos(i, ispin))
    1686             : 
    1687          60 :                   IF (output_unit > 0) THEN
    1688             :                      WRITE (UNIT=output_unit, FMT="(T46,I4,I11,F17.5)") &
    1689          18 :                         ispin, my_mos(i, ispin), max_overlap(i, ispin)
    1690             :                   END IF
    1691             :                END DO
    1692             :             END DO
    1693             : 
    1694             :             !either localization of MOs or ROKS, in both cases the MO eigenvalues from the KS
    1695             :             !digonalization mat have changed
    1696             :          ELSE
    1697          48 :             IF (output_unit > 0) THEN
    1698             :                WRITE (UNIT=output_unit, FMT="(T5,A,/,T5,A,/,T5,A)") &
    1699          24 :                   "The following localized MO(s) have been associated with the donor state(s)", &
    1700          24 :                   "based on the overlap with the components of a minimal STO basis: ", &
    1701          48 :                   "                                         Spin   MO index     overlap(sum)"
    1702             :             END IF
    1703             : 
    1704             : !           Loop over the donor states  and print
    1705         100 :             DO ispin = 1, nspins
    1706         160 :                DO i = 1, n_states
    1707             : 
    1708             : !                 Print info
    1709         112 :                   IF (output_unit > 0) THEN
    1710             :                      WRITE (UNIT=output_unit, FMT="(T46,I4,I11,F17.5)") &
    1711          30 :                         ispin, my_mos(i, ispin), max_overlap(i, ispin)
    1712             :                   END IF
    1713             :                END DO
    1714             :             END DO
    1715             : 
    1716             : !           MO have been rotated or non-physical ROKS MO eigrenvalues:
    1717             : !           => need epsilon_ij = <psi_i|F|psi_j> = sum_{pq} c_{qi}c_{pj} F_{pq}
    1718             : !           Note: only have digonal elements by construction
    1719          48 :             ndo_so = nspins*n_states
    1720          48 :             CALL cp_fm_create(work_mat, gs_struct)
    1721             :             CALL cp_fm_struct_create(eval_mat_struct, nrow_global=ndo_so, ncol_global=ndo_so, &
    1722          48 :                                      para_env=para_env, context=blacs_env)
    1723          48 :             CALL cp_fm_create(eval_mat, eval_mat_struct)
    1724         144 :             ALLOCATE (diag(ndo_so))
    1725             : 
    1726          48 :             IF (.NOT. xas_tdp_control%do_roks) THEN
    1727             : 
    1728          96 :                ALLOCATE (donor_state%energy_evals(n_states, nspins))
    1729         160 :                donor_state%energy_evals = 0.0_dp
    1730             : 
    1731             : !              Compute gs_coeff^T * matrix_ks * gs_coeff to get the epsilon_ij matrix
    1732         100 :                DO ispin = 1, nspins
    1733          52 :                   CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, gs_coeffs, work_mat, ncol=ndo_so)
    1734          52 :                   CALL parallel_gemm('T', 'N', ndo_so, ndo_so, nao, 1.0_dp, gs_coeffs, work_mat, 0.0_dp, eval_mat)
    1735             : 
    1736             : !                 Put the epsilon_ii into the donor_state. No off-diagonal element because of subset diag
    1737          52 :                   CALL cp_fm_get_diag(eval_mat, diag)
    1738         160 :                   donor_state%energy_evals(:, ispin) = diag((ispin - 1)*n_states + 1:ispin*n_states)
    1739             : 
    1740             :                END DO
    1741             : 
    1742             :             ELSE
    1743             :                ! If ROKS, slightly different procedure => 2 KS matrices but one type of MOs
    1744           0 :                ALLOCATE (donor_state%energy_evals(n_states, 2))
    1745           0 :                donor_state%energy_evals = 0.0_dp
    1746             : 
    1747             : !              Compute gs_coeff^T * matrix_ks * gs_coeff to get the epsilon_ij matrix
    1748           0 :                DO ispin = 1, 2
    1749           0 :                   CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, gs_coeffs, work_mat, ncol=ndo_so)
    1750           0 :                   CALL parallel_gemm('T', 'N', ndo_so, ndo_so, nao, 1.0_dp, gs_coeffs, work_mat, 0.0_dp, eval_mat)
    1751             : 
    1752           0 :                   CALL cp_fm_get_diag(eval_mat, diag)
    1753           0 :                   donor_state%energy_evals(:, ispin) = diag(:)
    1754             : 
    1755             :                END DO
    1756             : 
    1757           0 :                DEALLOCATE (diag)
    1758             :             END IF
    1759             : 
    1760             : !           Clean-up
    1761          48 :             CALL cp_fm_release(work_mat)
    1762          48 :             CALL cp_fm_release(eval_mat)
    1763         144 :             CALL cp_fm_struct_release(eval_mat_struct)
    1764             : 
    1765             :          END IF ! do_localize and/or ROKS
    1766             : 
    1767             : !        Allocate and initialize GW2X corrected IPs as energy_evals
    1768         272 :          ALLOCATE (donor_state%gw2x_evals(SIZE(donor_state%energy_evals, 1), SIZE(donor_state%energy_evals, 2)))
    1769         240 :          donor_state%gw2x_evals(:, :) = donor_state%energy_evals(:, :)
    1770             : 
    1771             : !        Clean-up
    1772          68 :          CALL cp_fm_struct_release(gs_struct)
    1773          68 :          DEALLOCATE (first_sgf)
    1774             : 
    1775          68 :          IF (output_unit > 0) WRITE (UNIT=output_unit, FMT="(T5,A)") " "
    1776             : 
    1777         144 :          DO ispin = 1, nspins
    1778         144 :             IF (output_unit > 0) THEN
    1779             :                WRITE (UNIT=output_unit, FMT="(T5,A,I1,A,F7.5,A,I4)") &
    1780          38 :                   "The next best overlap for spin ", ispin, " is ", next_best_overlap(ispin), &
    1781          76 :                   " for MO with index ", next_best_overlap_ind(ispin)
    1782             :             END IF
    1783             :          END DO
    1784          68 :          IF (output_unit > 0) WRITE (UNIT=output_unit, FMT="(T5,A)") " "
    1785             : 
    1786             :       ELSE
    1787           0 :          CPABORT("A core donor state could not be assigned MO(s). Increasing NSEARCH might help.")
    1788             :       END IF
    1789             : 
    1790         272 :    END SUBROUTINE assign_mos_to_donor_state
    1791             : 
    1792             : ! **************************************************************************************************
    1793             : !> \brief Compute the centers and spreads of (core) MOs using the Berry phase operator
    1794             : !> \param xas_tdp_env ...
    1795             : !> \param xas_tdp_control ...
    1796             : !> \param qs_env ...
    1797             : !> \note xas_tdp_env%qs_loc_env is used and modified. OK since no localization done after this
    1798             : !>       subroutine is used.
    1799             : ! **************************************************************************************************
    1800          80 :    SUBROUTINE find_mo_centers(xas_tdp_env, xas_tdp_control, qs_env)
    1801             : 
    1802             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    1803             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    1804             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1805             : 
    1806             :       INTEGER                                            :: dim_op, i, ispin, j, n_centers, nao, &
    1807             :                                                             nspins
    1808             :       REAL(dp), DIMENSION(6)                             :: weights
    1809             :       TYPE(cell_type), POINTER                           :: cell
    1810             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1811             :       TYPE(cp_fm_struct_type), POINTER                   :: tmp_fm_struct
    1812             :       TYPE(cp_fm_type)                                   :: opvec
    1813          80 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: zij_fm_set
    1814          80 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: moloc_coeff
    1815             :       TYPE(cp_fm_type), POINTER                          :: vectors
    1816          80 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: op_sm_set
    1817             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1818             :       TYPE(qs_loc_env_type), POINTER                     :: qs_loc_env
    1819             :       TYPE(section_vals_type), POINTER                   :: print_loc_section, prog_run_info
    1820             : 
    1821          80 :       NULLIFY (qs_loc_env, cell, print_loc_section, op_sm_set, moloc_coeff, vectors)
    1822          80 :       NULLIFY (tmp_fm_struct, para_env, blacs_env, prog_run_info)
    1823             : 
    1824             : !  Initialization
    1825          80 :       print_loc_section => xas_tdp_control%print_loc_subsection
    1826          80 :       n_centers = xas_tdp_control%n_search
    1827          80 :       CALL get_qs_env(qs_env=qs_env, para_env=para_env, blacs_env=blacs_env, cell=cell)
    1828             : 
    1829             : !  Set print option to debug to keep clean output file
    1830          80 :       prog_run_info => section_vals_get_subs_vals(print_loc_section, "PROGRAM_RUN_INFO")
    1831             :       CALL section_vals_val_set(prog_run_info, keyword_name="_SECTION_PARAMETERS_", &
    1832          80 :                                 i_val=debug_print_level)
    1833             : 
    1834             : !  Re-initialize the qs_loc_env to get the current MOs. Use force_loc because needed for centers
    1835          80 :       CALL reinit_qs_loc_env(xas_tdp_env%qs_loc_env, n_centers, xas_tdp_control%do_uks, qs_env)
    1836          80 :       qs_loc_env => xas_tdp_env%qs_loc_env
    1837             : 
    1838             : !  Get what we need from the qs_lovc_env
    1839             :       CALL get_qs_loc_env(qs_loc_env=qs_loc_env, weights=weights, op_sm_set=op_sm_set, &
    1840          80 :                           moloc_coeff=moloc_coeff)
    1841             : 
    1842             : !  Prepare for zij
    1843          80 :       vectors => moloc_coeff(1)
    1844          80 :       CALL cp_fm_get_info(vectors, nrow_global=nao)
    1845          80 :       CALL cp_fm_create(opvec, vectors%matrix_struct)
    1846             : 
    1847             :       CALL cp_fm_struct_create(tmp_fm_struct, para_env=para_env, context=blacs_env, &
    1848          80 :                                ncol_global=n_centers, nrow_global=n_centers)
    1849             : 
    1850          80 :       IF (cell%orthorhombic) THEN
    1851             :          dim_op = 3
    1852             :       ELSE
    1853           0 :          dim_op = 6
    1854             :       END IF
    1855         880 :       ALLOCATE (zij_fm_set(2, dim_op))
    1856         320 :       DO i = 1, dim_op
    1857         800 :          DO j = 1, 2
    1858         720 :             CALL cp_fm_create(zij_fm_set(j, i), tmp_fm_struct)
    1859             :          END DO
    1860             :       END DO
    1861             : 
    1862             :       !  If spin-unrestricted, need to go spin by spin
    1863          80 :       nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
    1864             : 
    1865         168 :       DO ispin = 1, nspins
    1866             : !     zij computation, copied from qs_loc_methods:optimize_loc_berry
    1867          88 :          vectors => moloc_coeff(ispin)
    1868         352 :          DO i = 1, dim_op
    1869         880 :             DO j = 1, 2
    1870         528 :                CALL cp_fm_set_all(zij_fm_set(j, i), 0.0_dp)
    1871         528 :                CALL cp_dbcsr_sm_fm_multiply(op_sm_set(j, i)%matrix, vectors, opvec, ncol=n_centers)
    1872             :                CALL parallel_gemm("T", "N", n_centers, n_centers, nao, 1.0_dp, vectors, opvec, 0.0_dp, &
    1873         792 :                                   zij_fm_set(j, i))
    1874             :             END DO
    1875             :          END DO
    1876             : 
    1877             : !     Compute centers (and spread)
    1878             :          CALL centers_spreads_berry(qs_loc_env=qs_loc_env, zij=zij_fm_set, nmoloc=n_centers, &
    1879             :                                     cell=cell, weights=weights, ispin=ispin, &
    1880         168 :                                     print_loc_section=print_loc_section, only_initial_out=.TRUE.)
    1881             :       END DO !ispins
    1882             : 
    1883             : !  Clean-up
    1884          80 :       CALL cp_fm_release(opvec)
    1885          80 :       CALL cp_fm_struct_release(tmp_fm_struct)
    1886          80 :       CALL cp_fm_release(zij_fm_set)
    1887             : 
    1888             : !  Make sure we leave with the correct do_loc value
    1889          80 :       qs_loc_env%do_localize = xas_tdp_control%do_loc
    1890             : 
    1891         240 :    END SUBROUTINE find_mo_centers
    1892             : 
    1893             : ! **************************************************************************************************
    1894             : !> \brief Prints the MO to donor_state assocaition with overlap and Mulliken population analysis
    1895             : !> \param xas_tdp_env ...
    1896             : !> \param xas_tdp_control ...
    1897             : !> \param qs_env ...
    1898             : !> \note  Called only in case of CHECK_ONLY run
    1899             : ! **************************************************************************************************
    1900           0 :    SUBROUTINE print_checks(xas_tdp_env, xas_tdp_control, qs_env)
    1901             : 
    1902             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    1903             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    1904             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1905             : 
    1906             :       CHARACTER(LEN=default_string_length)               :: kind_name
    1907             :       INTEGER                                            :: current_state_index, iat, iatom, ikind, &
    1908             :                                                             istate, output_unit, tmp_index
    1909           0 :       INTEGER, DIMENSION(:), POINTER                     :: atoms_of_kind
    1910           0 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1911             :       TYPE(donor_state_type), POINTER                    :: current_state
    1912             : 
    1913           0 :       NULLIFY (atomic_kind_set, atoms_of_kind, current_state)
    1914             : 
    1915           0 :       output_unit = cp_logger_get_default_io_unit()
    1916             : 
    1917           0 :       IF (output_unit > 0) THEN
    1918             :          WRITE (output_unit, "(/,T3,A,/,T3,A,/,T3,A)") &
    1919           0 :             "# Check the donor states for their quality. They need to have a well defined type ", &
    1920           0 :             "  (1s, 2s, etc) which is indicated by the overlap. They also need to be localized, ", &
    1921           0 :             "  for which the Mulliken population analysis is one indicator (must be close to 1.0)"
    1922             :       END IF
    1923             : 
    1924             : !  Loop over the donor states (as in the main xas_tdp loop)
    1925           0 :       CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set)
    1926           0 :       current_state_index = 1
    1927             : 
    1928             :       !loop over atomic kinds
    1929           0 :       DO ikind = 1, SIZE(atomic_kind_set)
    1930             : 
    1931             :          CALL get_atomic_kind(atomic_kind=atomic_kind_set(ikind), name=kind_name, &
    1932           0 :                               atom_list=atoms_of_kind)
    1933             : 
    1934           0 :          IF (.NOT. ANY(xas_tdp_env%ex_kind_indices == ikind)) CYCLE
    1935             : 
    1936             :          !loop over atoms of kind
    1937           0 :          DO iat = 1, SIZE(atoms_of_kind)
    1938           0 :             iatom = atoms_of_kind(iat)
    1939             : 
    1940           0 :             IF (.NOT. ANY(xas_tdp_env%ex_atom_indices == iatom)) CYCLE
    1941           0 :             tmp_index = locate(xas_tdp_env%ex_atom_indices, iatom)
    1942             : 
    1943             :             !loop over states of excited atom
    1944           0 :             DO istate = 1, SIZE(xas_tdp_env%state_types, 1)
    1945             : 
    1946           0 :                IF (xas_tdp_env%state_types(istate, tmp_index) == xas_not_excited) CYCLE
    1947             : 
    1948           0 :                current_state => xas_tdp_env%donor_states(current_state_index)
    1949             :                CALL set_donor_state(current_state, at_index=iatom, &
    1950             :                                     at_symbol=kind_name, kind_index=ikind, &
    1951           0 :                                     state_type=xas_tdp_env%state_types(istate, tmp_index))
    1952             : 
    1953           0 :                IF (output_unit > 0) THEN
    1954             :                   WRITE (output_unit, "(/,T4,A,A2,A,I4,A,A,A)") &
    1955           0 :                      "-Donor state of type ", xas_tdp_env%state_type_char(current_state%state_type), &
    1956           0 :                      " for atom", current_state%at_index, " of kind ", TRIM(current_state%at_symbol), ":"
    1957             :                END IF
    1958             : 
    1959             :                !Assign the MOs and perform Mulliken
    1960           0 :                CALL assign_mos_to_donor_state(current_state, xas_tdp_env, xas_tdp_control, qs_env)
    1961           0 :                CALL perform_mulliken_on_donor_state(current_state, qs_env)
    1962             : 
    1963           0 :                current_state_index = current_state_index + 1
    1964           0 :                NULLIFY (current_state)
    1965             : 
    1966             :             END DO !istate
    1967             :          END DO !iat
    1968             :       END DO !ikind
    1969             : 
    1970           0 :       IF (output_unit > 0) THEN
    1971             :          WRITE (output_unit, "(/,T5,A)") &
    1972           0 :             "Use LOCALIZE and/or increase N_SEARCH for better results, if so required."
    1973             :       END IF
    1974             : 
    1975           0 :    END SUBROUTINE print_checks
    1976             : 
    1977             : ! **************************************************************************************************
    1978             : !> \brief Computes the required multipole moment in the length representation for a given atom
    1979             : !> \param iatom index of the given atom
    1980             : !> \param xas_tdp_env ...
    1981             : !> \param xas_tdp_control ...
    1982             : !> \param qs_env ...
    1983             : !> \note Assumes that wither dipole or quadrupole in length rep is required
    1984             : ! **************************************************************************************************
    1985          24 :    SUBROUTINE compute_lenrep_multipole(iatom, xas_tdp_env, xas_tdp_control, qs_env)
    1986             : 
    1987             :       INTEGER, INTENT(IN)                                :: iatom
    1988             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    1989             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    1990             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1991             : 
    1992             :       INTEGER                                            :: i, order
    1993             :       REAL(dp), DIMENSION(3)                             :: rc
    1994          24 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: work
    1995          24 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1996             : 
    1997          24 :       NULLIFY (work, particle_set)
    1998             : 
    1999          24 :       CALL get_qs_env(qs_env, particle_set=particle_set)
    2000          96 :       rc = particle_set(iatom)%r
    2001             : 
    2002         240 :       ALLOCATE (work(9))
    2003          24 :       IF (xas_tdp_control%dipole_form == xas_dip_len) THEN
    2004          96 :          DO i = 1, 3
    2005          72 :             CALL dbcsr_set(xas_tdp_env%dipmat(i)%matrix, 0.0_dp)
    2006          96 :             work(i)%matrix => xas_tdp_env%dipmat(i)%matrix
    2007             :          END DO
    2008          24 :          order = 1
    2009             :       END IF
    2010          24 :       IF (xas_tdp_control%do_quad) THEN
    2011           0 :          DO i = 1, 6
    2012           0 :             CALL dbcsr_set(xas_tdp_env%quadmat(i)%matrix, 0.0_dp)
    2013           0 :             work(3 + i)%matrix => xas_tdp_env%quadmat(i)%matrix
    2014             :          END DO
    2015           0 :          order = 2
    2016           0 :          IF (xas_tdp_control%dipole_form == xas_dip_vel) order = -2
    2017             :       END IF
    2018             : 
    2019             :       !enforce minimum image to avoid PBCs related issues, ok because localized densities
    2020          24 :       CALL rRc_xyz_ao(work, qs_env, rc, order=order, minimum_image=.TRUE.)
    2021          24 :       DEALLOCATE (work)
    2022             : 
    2023          24 :    END SUBROUTINE compute_lenrep_multipole
    2024             : 
    2025             : ! **************************************************************************************************
    2026             : !> \brief Computes the oscillator strength based on the dipole moment (velocity or length rep) for
    2027             : !>        all available excitation energies and store the results in the donor_state. There is no
    2028             : !>        triplet dipole in the spin-restricted ground state.
    2029             : !> \param donor_state the donor state which is excited
    2030             : !> \param xas_tdp_control ...
    2031             : !> \param xas_tdp_env ...
    2032             : !> \note The oscillator strength is a scalar: osc_str = 2/(3*omega)*(dipole_v)^2 in the velocity rep
    2033             : !>       or : osc_str = 2/3*omega*(dipole_r)^2 in the length representation
    2034             : !>       The formulae for the dipoles come from the trace of the dipole operator with the transition
    2035             : !>       densities, i.e. what we get from solving the xas_tdp problem. Same procedure with or wo TDA
    2036             : ! **************************************************************************************************
    2037          56 :    SUBROUTINE compute_dipole_fosc(donor_state, xas_tdp_control, xas_tdp_env)
    2038             : 
    2039             :       TYPE(donor_state_type), POINTER                    :: donor_state
    2040             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    2041             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    2042             : 
    2043             :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_dipole_fosc'
    2044             : 
    2045             :       INTEGER                                            :: handle, iosc, j, nao, ndo_mo, ndo_so, &
    2046             :                                                             ngs, nosc, nspins
    2047             :       LOGICAL                                            :: do_sc, do_sg
    2048             :       REAL(dp)                                           :: osc_xyz, pref
    2049          56 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: tot_contr
    2050          56 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: dip_block
    2051          56 :       REAL(dp), DIMENSION(:), POINTER                    :: lr_evals
    2052          56 :       REAL(dp), DIMENSION(:, :), POINTER                 :: osc_str
    2053             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    2054             :       TYPE(cp_fm_struct_type), POINTER                   :: col_struct, mat_struct
    2055             :       TYPE(cp_fm_type)                                   :: col_work, mat_work
    2056             :       TYPE(cp_fm_type), POINTER                          :: lr_coeffs
    2057          56 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: dipmat
    2058             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2059             : 
    2060          56 :       NULLIFY (dipmat, col_struct, mat_struct, para_env, blacs_env, lr_coeffs)
    2061          56 :       NULLIFY (lr_evals, osc_str)
    2062             : 
    2063          56 :       CALL timeset(routineN, handle)
    2064             : 
    2065             : !  Initialization
    2066          56 :       do_sc = xas_tdp_control%do_spin_cons
    2067          56 :       do_sg = xas_tdp_control%do_singlet
    2068          56 :       IF (do_sc) THEN
    2069           8 :          nspins = 2
    2070           8 :          lr_evals => donor_state%sc_evals
    2071           8 :          lr_coeffs => donor_state%sc_coeffs
    2072          48 :       ELSE IF (do_sg) THEN
    2073          48 :          nspins = 1
    2074          48 :          lr_evals => donor_state%sg_evals
    2075          48 :          lr_coeffs => donor_state%sg_coeffs
    2076             :       ELSE
    2077           0 :          CPABORT("Dipole oscilaltor strength only for singlets and spin-conserving excitations.")
    2078             :       END IF
    2079          56 :       ndo_mo = donor_state%ndo_mo
    2080          56 :       ndo_so = ndo_mo*nspins
    2081          56 :       ngs = ndo_so; IF (xas_tdp_control%do_roks) ngs = ndo_mo !in ROKS, same gs coeffs
    2082          56 :       nosc = SIZE(lr_evals)
    2083         168 :       ALLOCATE (donor_state%osc_str(nosc, 4))
    2084          56 :       osc_str => donor_state%osc_str
    2085        3704 :       osc_str = 0.0_dp
    2086          56 :       dipmat => xas_tdp_env%dipmat
    2087             : 
    2088             :       ! do some work matrix initialization
    2089             :       CALL cp_fm_get_info(donor_state%gs_coeffs, matrix_struct=col_struct, para_env=para_env, &
    2090          56 :                           context=blacs_env, nrow_global=nao)
    2091             :       CALL cp_fm_struct_create(mat_struct, para_env=para_env, context=blacs_env, &
    2092          56 :                                nrow_global=ndo_so*nosc, ncol_global=ngs)
    2093          56 :       CALL cp_fm_create(mat_work, mat_struct)
    2094          56 :       CALL cp_fm_create(col_work, col_struct)
    2095             : 
    2096         336 :       ALLOCATE (tot_contr(ndo_mo), dip_block(ndo_so, ngs))
    2097          56 :       pref = 2.0_dp; IF (do_sc) pref = 1.0_dp !because of singlet definition u = 1/sqrt(2)(c_a+c_b)
    2098             : 
    2099             : !  Looping over cartesian coord
    2100         224 :       DO j = 1, 3
    2101             : 
    2102             :          !Compute dip*gs_coeffs
    2103         168 :          CALL cp_dbcsr_sm_fm_multiply(dipmat(j)%matrix, donor_state%gs_coeffs, col_work, ncol=ngs)
    2104             :          !compute lr_coeffs*dip*gs_coeffs
    2105         168 :          CALL parallel_gemm('T', 'N', ndo_so*nosc, ngs, nao, 1.0_dp, lr_coeffs, col_work, 0.0_dp, mat_work)
    2106             : 
    2107             :          !Loop over the excited states
    2108        2792 :          DO iosc = 1, nosc
    2109             : 
    2110        5424 :             tot_contr = 0.0_dp
    2111             :             CALL cp_fm_get_submatrix(fm=mat_work, target_m=dip_block, start_row=(iosc - 1)*ndo_so + 1, &
    2112        2568 :                                      start_col=1, n_rows=ndo_so, n_cols=ngs)
    2113        2568 :             IF (do_sg) THEN
    2114        1944 :                tot_contr(:) = get_diag(dip_block)
    2115         624 :             ELSE IF (do_sc .AND. xas_tdp_control%do_uks) THEN
    2116         624 :                tot_contr(:) = get_diag(dip_block(1:ndo_mo, 1:ndo_mo)) !alpha
    2117        1392 :                tot_contr(:) = tot_contr(:) + get_diag(dip_block(ndo_mo + 1:ndo_so, ndo_mo + 1:ndo_so)) !beta
    2118             :             ELSE
    2119             :                !roks
    2120           0 :                tot_contr(:) = get_diag(dip_block(1:ndo_mo, :)) !alpha
    2121           0 :                tot_contr(:) = tot_contr(:) + get_diag(dip_block(ndo_mo + 1:ndo_so, :)) !beta
    2122             :             END IF
    2123             : 
    2124        5424 :             osc_xyz = SUM(tot_contr)**2
    2125        2568 :             osc_str(iosc, 4) = osc_str(iosc, 4) + osc_xyz
    2126        2736 :             osc_str(iosc, j) = osc_xyz
    2127             : 
    2128             :          END DO !iosc
    2129             :       END DO !j
    2130             : 
    2131             :       !compute the prefactor
    2132         280 :       DO j = 1, 4
    2133         280 :          IF (xas_tdp_control%dipole_form == xas_dip_len) THEN
    2134        3248 :             osc_str(:, j) = pref*2.0_dp/3.0_dp*lr_evals(:)*osc_str(:, j)
    2135             :          ELSE
    2136        4048 :             osc_str(:, j) = pref*2.0_dp/3.0_dp/lr_evals(:)*osc_str(:, j)
    2137             :          END IF
    2138             :       END DO
    2139             : 
    2140             :       !clean-up
    2141          56 :       CALL cp_fm_release(mat_work)
    2142          56 :       CALL cp_fm_release(col_work)
    2143          56 :       CALL cp_fm_struct_release(mat_struct)
    2144             : 
    2145          56 :       CALL timestop(handle)
    2146             : 
    2147         224 :    END SUBROUTINE compute_dipole_fosc
    2148             : 
    2149             : ! **************************************************************************************************
    2150             : !> \brief Computes the oscillator strength due to the electric quadrupole moment and store it in
    2151             : !>        the donor_state (for singlet or spin-conserving)
    2152             : !> \param donor_state the donor state which is excited
    2153             : !> \param xas_tdp_control ...
    2154             : !> \param xas_tdp_env ...
    2155             : !> \note Formula: 1/20*a_fine^2*omega^3 * sum_ab (sum_i r_ia*r_ib - 1/3*ri^2*delta_ab)
    2156             : ! **************************************************************************************************
    2157           0 :    SUBROUTINE compute_quadrupole_fosc(donor_state, xas_tdp_control, xas_tdp_env)
    2158             : 
    2159             :       TYPE(donor_state_type), POINTER                    :: donor_state
    2160             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    2161             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    2162             : 
    2163             :       CHARACTER(len=*), PARAMETER :: routineN = 'compute_quadrupole_fosc'
    2164             : 
    2165             :       INTEGER                                            :: handle, iosc, j, nao, ndo_mo, ndo_so, &
    2166             :                                                             ngs, nosc, nspins
    2167             :       LOGICAL                                            :: do_sc, do_sg
    2168             :       REAL(dp)                                           :: pref
    2169           0 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: tot_contr, trace
    2170           0 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: quad_block
    2171           0 :       REAL(dp), DIMENSION(:), POINTER                    :: lr_evals, osc_str
    2172             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    2173             :       TYPE(cp_fm_struct_type), POINTER                   :: col_struct, mat_struct
    2174             :       TYPE(cp_fm_type)                                   :: col_work, mat_work
    2175             :       TYPE(cp_fm_type), POINTER                          :: lr_coeffs
    2176           0 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: quadmat
    2177             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2178             : 
    2179           0 :       NULLIFY (lr_evals, osc_str, lr_coeffs, col_struct, mat_struct, para_env)
    2180           0 :       NULLIFY (blacs_env)
    2181             : 
    2182           0 :       CALL timeset(routineN, handle)
    2183             : 
    2184             :       ! Initialization
    2185           0 :       do_sc = xas_tdp_control%do_spin_cons
    2186           0 :       do_sg = xas_tdp_control%do_singlet
    2187           0 :       IF (do_sc) THEN
    2188           0 :          nspins = 2
    2189           0 :          lr_evals => donor_state%sc_evals
    2190           0 :          lr_coeffs => donor_state%sc_coeffs
    2191           0 :       ELSE IF (do_sg) THEN
    2192           0 :          nspins = 1
    2193           0 :          lr_evals => donor_state%sg_evals
    2194           0 :          lr_coeffs => donor_state%sg_coeffs
    2195             :       ELSE
    2196           0 :          CPABORT("Quadrupole oscillator strengths only for singlet and spin-conserving excitations")
    2197             :       END IF
    2198           0 :       ndo_mo = donor_state%ndo_mo
    2199           0 :       ndo_so = ndo_mo*nspins
    2200           0 :       ngs = ndo_so; IF (xas_tdp_control%do_roks) ngs = ndo_mo !only alpha do_mo in ROKS
    2201           0 :       nosc = SIZE(lr_evals)
    2202           0 :       ALLOCATE (donor_state%quad_osc_str(nosc))
    2203           0 :       osc_str => donor_state%quad_osc_str
    2204           0 :       osc_str = 0.0_dp
    2205           0 :       quadmat => xas_tdp_env%quadmat
    2206             : 
    2207             :       !work matrices init
    2208             :       CALL cp_fm_get_info(donor_state%gs_coeffs, matrix_struct=col_struct, para_env=para_env, &
    2209           0 :                           context=blacs_env, nrow_global=nao)
    2210             :       CALL cp_fm_struct_create(mat_struct, para_env=para_env, context=blacs_env, &
    2211           0 :                                nrow_global=ndo_so*nosc, ncol_global=ngs)
    2212           0 :       CALL cp_fm_create(mat_work, mat_struct)
    2213           0 :       CALL cp_fm_create(col_work, col_struct)
    2214             : 
    2215           0 :       ALLOCATE (quad_block(ndo_so, ngs), tot_contr(ndo_mo))
    2216           0 :       pref = 2.0_dp; IF (do_sc) pref = 1.0_dp !because of singlet definition u = 1/sqrt(2)*...
    2217           0 :       ALLOCATE (trace(nosc))
    2218           0 :       trace = 0.0_dp
    2219             : 
    2220             :       !Loop over the cartesioan coord :x2, xy, xz, y2, yz, z2
    2221           0 :       DO j = 1, 6
    2222             : 
    2223             :          !Compute quad*gs_coeffs
    2224           0 :          CALL cp_dbcsr_sm_fm_multiply(quadmat(j)%matrix, donor_state%gs_coeffs, col_work, ncol=ngs)
    2225             :          !compute lr_coeffs*quadmat*gs_coeffs
    2226           0 :          CALL parallel_gemm('T', 'N', ndo_so*nosc, ngs, nao, 1.0_dp, lr_coeffs, col_work, 0.0_dp, mat_work)
    2227             : 
    2228             :          !Loop over the excited states
    2229           0 :          DO iosc = 1, nosc
    2230             : 
    2231           0 :             tot_contr = 0.0_dp
    2232             :             CALL cp_fm_get_submatrix(fm=mat_work, target_m=quad_block, start_row=(iosc - 1)*ndo_so + 1, &
    2233           0 :                                      start_col=1, n_rows=ndo_so, n_cols=ngs)
    2234             : 
    2235           0 :             IF (do_sg) THEN
    2236           0 :                tot_contr(:) = get_diag(quad_block)
    2237           0 :             ELSE IF (do_sc .AND. xas_tdp_control%do_uks) THEN
    2238           0 :                tot_contr(:) = get_diag(quad_block(1:ndo_mo, 1:ndo_mo)) !alpha
    2239           0 :                tot_contr(:) = tot_contr(:) + get_diag(quad_block(ndo_mo + 1:ndo_so, ndo_mo + 1:ndo_so)) !beta
    2240             :             ELSE
    2241             :                !roks
    2242           0 :                tot_contr(:) = get_diag(quad_block(1:ndo_mo, :)) !alpha
    2243           0 :                tot_contr(:) = tot_contr(:) + get_diag(quad_block(ndo_mo + 1:ndo_so, :)) !beta
    2244             :             END IF
    2245             : 
    2246             :             !if x2, y2, or z2 direction, need to update the trace (for later)
    2247           0 :             IF (j == 1 .OR. j == 4 .OR. j == 6) THEN
    2248           0 :                osc_str(iosc) = osc_str(iosc) + SUM(tot_contr)**2
    2249           0 :                trace(iosc) = trace(iosc) + SUM(tot_contr)
    2250             : 
    2251             :                !if xy, xz or yz, need to count twice the contribution (for yx, zx and zy)
    2252             :             ELSE
    2253           0 :                osc_str(iosc) = osc_str(iosc) + 2.0_dp*SUM(tot_contr)**2
    2254             :             END IF
    2255             : 
    2256             :          END DO !iosc
    2257             :       END DO !j
    2258             : 
    2259             :       !compute the prefactor, and remove 1/3*trace^2
    2260           0 :       osc_str(:) = pref*1._dp/20._dp*a_fine**2*lr_evals(:)**3*(osc_str(:) - 1._dp/3._dp*trace(:)**2)
    2261             : 
    2262             :       !clean-up
    2263           0 :       CALL cp_fm_release(mat_work)
    2264           0 :       CALL cp_fm_release(col_work)
    2265           0 :       CALL cp_fm_struct_release(mat_struct)
    2266             : 
    2267           0 :       CALL timestop(handle)
    2268             : 
    2269           0 :    END SUBROUTINE compute_quadrupole_fosc
    2270             : 
    2271             : ! **************************************************************************************************
    2272             : !> \brief Writes the core MOs to excited atoms associations in the main output file
    2273             : !> \param xas_tdp_env ...
    2274             : !> \param xas_tdp_control ...
    2275             : !> \param qs_env ...
    2276             : !> \note Look at alpha spin MOs, as we are dealing with core states and alpha/beta MOs are the same
    2277             : ! **************************************************************************************************
    2278          48 :    SUBROUTINE write_mos_to_ex_atoms_association(xas_tdp_env, xas_tdp_control, qs_env)
    2279             : 
    2280             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    2281             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    2282             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2283             : 
    2284             :       CHARACTER(LEN=default_string_length)               :: kind_name
    2285             :       INTEGER                                            :: at_index, imo, ispin, nmo, nspins, &
    2286             :                                                             output_unit, tmp_index
    2287             :       INTEGER, DIMENSION(3)                              :: perd_init
    2288          48 :       INTEGER, DIMENSION(:), POINTER                     :: ex_atom_indices
    2289          48 :       INTEGER, DIMENSION(:, :, :), POINTER               :: mos_of_ex_atoms
    2290             :       REAL(dp)                                           :: dist, mo_spread
    2291             :       REAL(dp), DIMENSION(3)                             :: at_pos, r_ac, wfn_center
    2292             :       TYPE(cell_type), POINTER                           :: cell
    2293          48 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2294             : 
    2295          48 :       NULLIFY (cell, particle_set, mos_of_ex_atoms, ex_atom_indices)
    2296             : 
    2297          96 :       output_unit = cp_logger_get_default_io_unit()
    2298             : 
    2299          48 :       IF (output_unit > 0) THEN
    2300             :          WRITE (UNIT=output_unit, FMT="(/,T3,A,/,T3,A,/,T3,A)") &
    2301          24 :             "                  Associated    Associated        Distance to   MO spread (Ang^2)", &
    2302          24 :             "Spin  MO index    atom index     atom kind    MO center (Ang)   -w_i ln(|z_ij|^2)", &
    2303          48 :             "---------------------------------------------------------------------------------"
    2304             :       END IF
    2305             : 
    2306             : !  Initialization
    2307          48 :       nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
    2308          48 :       mos_of_ex_atoms => xas_tdp_env%mos_of_ex_atoms
    2309          48 :       ex_atom_indices => xas_tdp_env%ex_atom_indices
    2310          48 :       nmo = xas_tdp_control%n_search
    2311          48 :       CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, cell=cell)
    2312             : 
    2313             : !     because the use of Berry's phase operator implies PBCs
    2314         192 :       perd_init = cell%perd
    2315         192 :       cell%perd = 1
    2316             : 
    2317             : !  Retrieving all the info for each MO and spin
    2318         304 :       DO imo = 1, nmo
    2319         576 :          DO ispin = 1, nspins
    2320             : 
    2321             : !           each Mo is associated to at most one atom (only 1 in array of -1)
    2322         758 :             IF (ANY(mos_of_ex_atoms(imo, :, ispin) == 1)) THEN
    2323         252 :                tmp_index = MAXLOC(mos_of_ex_atoms(imo, :, ispin), 1)
    2324         114 :                at_index = ex_atom_indices(tmp_index)
    2325         114 :                kind_name = particle_set(at_index)%atomic_kind%name
    2326             : 
    2327         456 :                at_pos = particle_set(at_index)%r
    2328         456 :                wfn_center = xas_tdp_env%qs_loc_env%localized_wfn_control%centers_set(ispin)%array(1:3, imo)
    2329         114 :                r_ac = pbc(at_pos, wfn_center, cell)
    2330         456 :                dist = NORM2(r_ac)
    2331             : !              convert distance from a.u. to Angstrom
    2332         114 :                dist = dist*angstrom
    2333             : 
    2334         114 :                mo_spread = xas_tdp_env%qs_loc_env%localized_wfn_control%centers_set(ispin)%array(4, imo)
    2335         114 :                mo_spread = mo_spread*angstrom*angstrom
    2336             : 
    2337         114 :                IF (output_unit > 0) THEN
    2338             :                   WRITE (UNIT=output_unit, FMT="(T3,I4,I10,I14,A14,ES19.3,ES20.3)") &
    2339          57 :                      ispin, imo, at_index, TRIM(kind_name), dist, mo_spread
    2340             :                END IF
    2341             : 
    2342             :             END IF
    2343             :          END DO !ispin
    2344             :       END DO !imo
    2345             : 
    2346          48 :       IF (output_unit > 0) THEN
    2347             :          WRITE (UNIT=output_unit, FMT="(T3,A,/)") &
    2348          24 :             "---------------------------------------------------------------------------------"
    2349             :       END IF
    2350             : 
    2351             : !  Go back to initial BCs
    2352         192 :       cell%perd = perd_init
    2353             : 
    2354          48 :    END SUBROUTINE write_mos_to_ex_atoms_association
    2355             : 
    2356             : ! **************************************************************************************************
    2357             : !> \brief Performs Mulliken population analysis for the MO(s) of a donor_state_type so that user
    2358             : !>        can verify it is indeed a core state
    2359             : !> \param donor_state ...
    2360             : !> \param qs_env ...
    2361             : !> \note This is a specific case of Mulliken analysis. In general one computes sum_i (SP)_ii, where
    2362             : !>       i labels the basis function centered on the atom of interest. For a specific MO with index
    2363             : !>       j, one need to compute sum_{ik} c_{ij} S_{ik} c_{kj}, k = 1,nao
    2364             : ! **************************************************************************************************
    2365          68 :    SUBROUTINE perform_mulliken_on_donor_state(donor_state, qs_env)
    2366             :       TYPE(donor_state_type), POINTER                    :: donor_state
    2367             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2368             : 
    2369             :       INTEGER                                            :: at_index, i, ispin, nao, natom, ndo_mo, &
    2370             :                                                             ndo_so, nsgf, nspins, output_unit
    2371          68 :       INTEGER, DIMENSION(:), POINTER                     :: first_sgf, last_sgf
    2372          68 :       INTEGER, DIMENSION(:, :), POINTER                  :: mo_indices
    2373          68 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: mul_pop, pop_mat
    2374          68 :       REAL(dp), DIMENSION(:, :), POINTER                 :: work_array
    2375             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    2376             :       TYPE(cp_fm_struct_type), POINTER                   :: col_vect_struct
    2377             :       TYPE(cp_fm_type)                                   :: work_vect
    2378             :       TYPE(cp_fm_type), POINTER                          :: gs_coeffs
    2379          68 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    2380             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2381          68 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2382          68 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2383             : 
    2384          68 :       NULLIFY (mo_indices, qs_kind_set, particle_set, first_sgf, work_array)
    2385          68 :       NULLIFY (matrix_s, para_env, blacs_env, col_vect_struct, last_sgf)
    2386             : 
    2387             : !  Initialization
    2388          68 :       at_index = donor_state%at_index
    2389          68 :       mo_indices => donor_state%mo_indices
    2390          68 :       ndo_mo = donor_state%ndo_mo
    2391          68 :       gs_coeffs => donor_state%gs_coeffs
    2392         136 :       output_unit = cp_logger_get_default_io_unit()
    2393          68 :       nspins = 1; IF (SIZE(mo_indices, 2) == 2) nspins = 2
    2394          68 :       ndo_so = ndo_mo*nspins
    2395         272 :       ALLOCATE (mul_pop(ndo_mo, nspins))
    2396         240 :       mul_pop = 0.0_dp
    2397             : 
    2398             :       CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, qs_kind_set=qs_kind_set, &
    2399          68 :                       para_env=para_env, blacs_env=blacs_env, matrix_s=matrix_s)
    2400          68 :       CALL cp_fm_get_info(gs_coeffs, nrow_global=nao, matrix_struct=col_vect_struct)
    2401             : 
    2402          68 :       natom = SIZE(particle_set, 1)
    2403         204 :       ALLOCATE (first_sgf(natom))
    2404         136 :       ALLOCATE (last_sgf(natom))
    2405             : 
    2406          68 :       CALL get_particle_set(particle_set, qs_kind_set, first_sgf=first_sgf, last_sgf=last_sgf)
    2407          68 :       nsgf = last_sgf(at_index) - first_sgf(at_index) + 1
    2408             : 
    2409          68 :       CALL cp_fm_create(work_vect, col_vect_struct)
    2410             : 
    2411             : !  Take the product of S*coeffs
    2412          68 :       CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, gs_coeffs, work_vect, ncol=ndo_so)
    2413             : 
    2414             : !  Only consider the product coeffs^T * S * coeffs on the atom of interest
    2415         272 :       ALLOCATE (work_array(nsgf, ndo_so))
    2416         272 :       ALLOCATE (pop_mat(ndo_so, ndo_so))
    2417             : 
    2418             :       CALL cp_fm_get_submatrix(fm=work_vect, target_m=work_array, start_row=first_sgf(at_index), &
    2419          68 :                                start_col=1, n_rows=nsgf, n_cols=ndo_so, transpose=.FALSE.)
    2420             : 
    2421             :       CALL dgemm('T', 'N', ndo_so, ndo_so, nsgf, 1.0_dp, donor_state%contract_coeffs, nsgf, &
    2422          68 :                  work_array, nsgf, 0.0_dp, pop_mat, ndo_so)
    2423             : 
    2424             : !  The Mullikan population for the MOs in on the diagonal.
    2425         144 :       DO ispin = 1, nspins
    2426         240 :          DO i = 1, ndo_mo
    2427         172 :             mul_pop(i, ispin) = pop_mat((ispin - 1)*ndo_mo + i, (ispin - 1)*ndo_mo + i)
    2428             :          END DO
    2429             :       END DO
    2430             : 
    2431             : !  Printing in main output file
    2432          68 :       IF (output_unit > 0) THEN
    2433             :          WRITE (UNIT=output_unit, FMT="(T5,A,/,T5,A)") &
    2434          34 :             "Mulliken population analysis retricted to the associated MO(s) yields: ", &
    2435          68 :             "                                              Spin  MO index     charge"
    2436          72 :          DO ispin = 1, nspins
    2437         120 :             DO i = 1, ndo_mo
    2438             :                WRITE (UNIT=output_unit, FMT="(T51,I4,I10,F11.3)") &
    2439          86 :                   ispin, mo_indices(i, ispin), mul_pop(i, ispin)
    2440             :             END DO
    2441             :          END DO
    2442             :       END IF
    2443             : 
    2444             : !  Clean-up
    2445          68 :       DEALLOCATE (first_sgf, last_sgf, work_array)
    2446          68 :       CALL cp_fm_release(work_vect)
    2447             : 
    2448         272 :    END SUBROUTINE perform_mulliken_on_donor_state
    2449             : 
    2450             : ! **************************************************************************************************
    2451             : !> \brief write the PDOS wrt the LR-orbitals for the current donor_state and/or the CUBES files
    2452             : !> \param ex_type the excitation type: singlet, triplet, spin-conserving, etc
    2453             : !> \param donor_state ...
    2454             : !> \param xas_tdp_env ...
    2455             : !> \param xas_tdp_section ...
    2456             : !> \param qs_env ...
    2457             : ! **************************************************************************************************
    2458          74 :    SUBROUTINE xas_tdp_post(ex_type, donor_state, xas_tdp_env, xas_tdp_section, qs_env)
    2459             : 
    2460             :       INTEGER, INTENT(IN)                                :: ex_type
    2461             :       TYPE(donor_state_type), POINTER                    :: donor_state
    2462             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    2463             :       TYPE(section_vals_type), POINTER                   :: xas_tdp_section
    2464             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2465             : 
    2466             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'xas_tdp_post'
    2467             : 
    2468             :       CHARACTER(len=default_string_length)               :: domo, domon, excite, pos, xas_mittle
    2469             :       INTEGER :: ex_state_idx, handle, ic, ido_mo, imo, irep, ispin, n_dependent, n_rep, nao, &
    2470             :          ncubes, ndo_mo, ndo_so, nlumo, nmo, nspins, output_unit
    2471          62 :       INTEGER, DIMENSION(:), POINTER                     :: bounds, list, state_list
    2472             :       LOGICAL                                            :: append_cube, do_cubes, do_pdos, &
    2473             :                                                             do_wfn_restart
    2474          62 :       REAL(dp), DIMENSION(:), POINTER                    :: lr_evals
    2475          62 :       REAL(dp), DIMENSION(:, :), POINTER                 :: centers
    2476          62 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    2477             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    2478             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, mo_struct
    2479             :       TYPE(cp_fm_type)                                   :: mo_coeff, work_fm
    2480             :       TYPE(cp_fm_type), POINTER                          :: lr_coeffs
    2481             :       TYPE(cp_logger_type), POINTER                      :: logger
    2482          62 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    2483          62 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    2484             :       TYPE(mo_set_type), POINTER                         :: mo_set
    2485             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2486          62 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    2487          62 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    2488             :       TYPE(section_vals_type), POINTER                   :: print_key
    2489             : 
    2490          62 :       NULLIFY (atomic_kind_set, particle_set, qs_kind_set, mo_set, lr_evals, lr_coeffs)
    2491          62 :       NULLIFY (mo_struct, para_env, blacs_env, fm_struct, matrix_s, print_key, logger)
    2492          62 :       NULLIFY (bounds, state_list, list, mos)
    2493             : 
    2494             :       !Tests on what to do
    2495         124 :       logger => cp_get_default_logger()
    2496          62 :       do_pdos = .FALSE.; do_cubes = .FALSE.; do_wfn_restart = .FALSE.
    2497             : 
    2498          62 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, xas_tdp_section, &
    2499           2 :                                            "PRINT%PDOS"), cp_p_file)) do_pdos = .TRUE.
    2500             : 
    2501          62 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, xas_tdp_section, &
    2502           2 :                                            "PRINT%CUBES"), cp_p_file)) do_cubes = .TRUE.
    2503             : 
    2504          62 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, xas_tdp_section, &
    2505           2 :                                            "PRINT%RESTART_WFN"), cp_p_file)) do_wfn_restart = .TRUE.
    2506             : 
    2507          62 :       IF (.NOT. (do_pdos .OR. do_cubes .OR. do_wfn_restart)) RETURN
    2508             : 
    2509           4 :       CALL timeset(routineN, handle)
    2510             : 
    2511             :       !Initialization
    2512             :       CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, particle_set=particle_set, &
    2513             :                       qs_kind_set=qs_kind_set, para_env=para_env, blacs_env=blacs_env, &
    2514           4 :                       matrix_s=matrix_s, mos=mos)
    2515             : 
    2516           4 :       SELECT CASE (ex_type)
    2517             :       CASE (tddfpt_spin_cons)
    2518           0 :          lr_evals => donor_state%sc_evals
    2519           0 :          lr_coeffs => donor_state%sc_coeffs
    2520           0 :          nspins = 2
    2521           0 :          excite = "spincons"
    2522             :       CASE (tddfpt_spin_flip)
    2523           0 :          lr_evals => donor_state%sf_evals
    2524           0 :          lr_coeffs => donor_state%sf_coeffs
    2525           0 :          nspins = 2
    2526           0 :          excite = "spinflip"
    2527             :       CASE (tddfpt_singlet)
    2528           4 :          lr_evals => donor_state%sg_evals
    2529           4 :          lr_coeffs => donor_state%sg_coeffs
    2530           4 :          nspins = 1
    2531           4 :          excite = "singlet"
    2532             :       CASE (tddfpt_triplet)
    2533           0 :          lr_evals => donor_state%tp_evals
    2534           0 :          lr_coeffs => donor_state%tp_coeffs
    2535           0 :          nspins = 1
    2536           4 :          excite = "triplet"
    2537             :       END SELECT
    2538             : 
    2539           8 :       SELECT CASE (donor_state%state_type)
    2540             :       CASE (xas_1s_type)
    2541           4 :          domo = "1s"
    2542             :       CASE (xas_2s_type)
    2543           0 :          domo = "2s"
    2544             :       CASE (xas_2p_type)
    2545           4 :          domo = "2p"
    2546             :       END SELECT
    2547             : 
    2548           4 :       ndo_mo = donor_state%ndo_mo
    2549           4 :       ndo_so = ndo_mo*nspins
    2550           4 :       nmo = SIZE(lr_evals)
    2551           4 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
    2552             : 
    2553             :       CALL cp_fm_struct_create(mo_struct, context=blacs_env, para_env=para_env, &
    2554           4 :                                nrow_global=nao, ncol_global=nmo)
    2555           4 :       CALL cp_fm_create(mo_coeff, mo_struct)
    2556             : 
    2557             :       !Dump the TDDFT excited state AMEW wavefunction into a file for restart in RTP
    2558           4 :       IF (do_wfn_restart) THEN
    2559           2 :          BLOCK
    2560           6 :             TYPE(mo_set_type), DIMENSION(2) :: restart_mos
    2561           2 :             IF (.NOT. (nspins == 1 .AND. donor_state%state_type == xas_1s_type)) THEN
    2562           0 :                CPABORT("RESTART.wfn file only available for RKS K-edge XAS spectroscopy")
    2563             :             END IF
    2564             : 
    2565           2 :             CALL section_vals_val_get(xas_tdp_section, "PRINT%RESTART_WFN%EXCITED_STATE_INDEX", n_rep_val=n_rep)
    2566             : 
    2567           4 :             DO irep = 1, n_rep
    2568             :                CALL section_vals_val_get(xas_tdp_section, "PRINT%RESTART_WFN%EXCITED_STATE_INDEX", &
    2569           2 :                                          i_rep_val=irep, i_val=ex_state_idx)
    2570           2 :                CPASSERT(ex_state_idx <= SIZE(lr_evals))
    2571             : 
    2572           6 :                DO ispin = 1, 2
    2573           4 :                   CALL duplicate_mo_set(restart_mos(ispin), mos(1))
    2574             :                   ! Set the new occupation number in the case of spin-independent based calculaltion since the restart is spin-depedent
    2575           4 :                   IF (SIZE(mos) == 1) &
    2576          26 :                      restart_mos(ispin)%occupation_numbers = mos(1)%occupation_numbers/2
    2577             :                END DO
    2578             : 
    2579             :                CALL cp_fm_to_fm_submat(msource=lr_coeffs, mtarget=restart_mos(1)%mo_coeff, nrow=nao, &
    2580             :                                        ncol=1, s_firstrow=1, s_firstcol=ex_state_idx, t_firstrow=1, &
    2581           2 :                                        t_firstcol=donor_state%mo_indices(1, 1))
    2582             : 
    2583             :                xas_mittle = 'xasat'//TRIM(ADJUSTL(cp_to_string(donor_state%at_index)))//'_'//TRIM(domo)// &
    2584           2 :                             '_'//TRIM(excite)//'_idx'//TRIM(ADJUSTL(cp_to_string(ex_state_idx)))
    2585             :                output_unit = cp_print_key_unit_nr(logger, xas_tdp_section, "PRINT%RESTART_WFN", &
    2586             :                                                   extension=".wfn", file_status="REPLACE", &
    2587             :                                                   file_action="WRITE", file_form="UNFORMATTED", &
    2588           2 :                                                   middle_name=xas_mittle)
    2589             : 
    2590             :                CALL write_mo_set_low(restart_mos, particle_set=particle_set, &
    2591           2 :                                      qs_kind_set=qs_kind_set, ires=output_unit)
    2592             : 
    2593           2 :                CALL cp_print_key_finished_output(output_unit, logger, xas_tdp_section, "PRINT%RESTART_WFN")
    2594             : 
    2595          10 :                DO ispin = 1, 2
    2596           6 :                   CALL deallocate_mo_set(restart_mos(ispin))
    2597             :                END DO
    2598             :             END DO
    2599             :          END BLOCK
    2600             :       END IF
    2601             : 
    2602             :       !PDOS related stuff
    2603           4 :       IF (do_pdos) THEN
    2604             : 
    2605             :          !If S^0.5 not yet stored, compute it once and for all
    2606           2 :          IF (.NOT. ASSOCIATED(xas_tdp_env%matrix_shalf) .AND. do_pdos) THEN
    2607             :             CALL cp_fm_struct_create(fm_struct, context=blacs_env, para_env=para_env, &
    2608           2 :                                      nrow_global=nao, ncol_global=nao)
    2609           2 :             ALLOCATE (xas_tdp_env%matrix_shalf)
    2610           2 :             CALL cp_fm_create(xas_tdp_env%matrix_shalf, fm_struct)
    2611           2 :             CALL cp_fm_create(work_fm, fm_struct)
    2612             : 
    2613           2 :             CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, xas_tdp_env%matrix_shalf)
    2614           2 :             CALL cp_fm_power(xas_tdp_env%matrix_shalf, work_fm, 0.5_dp, EPSILON(0.0_dp), n_dependent)
    2615             : 
    2616           2 :             CALL cp_fm_release(work_fm)
    2617           2 :             CALL cp_fm_struct_release(fm_struct)
    2618             :          END IF
    2619             : 
    2620             :          !Giving some PDOS info
    2621           2 :          output_unit = cp_logger_get_default_io_unit()
    2622           2 :          IF (output_unit > 0) THEN
    2623             :             WRITE (UNIT=output_unit, FMT="(/,T5,A,/,T5,A,/,T5,A)") &
    2624           1 :                "Computing the PDOS of linear-response orbitals for spectral features analysis", &
    2625           1 :                "Note: using standard PDOS routines => ignore mentions of KS states and MO ", &
    2626           2 :                "      occupation numbers. Eigenvalues in *.pdos files are excitations energies."
    2627             :          END IF
    2628             : 
    2629             :          !Check on NLUMO
    2630           2 :          CALL section_vals_val_get(xas_tdp_section, "PRINT%PDOS%NLUMO", i_val=nlumo)
    2631           2 :          IF (nlumo .NE. 0) THEN
    2632           0 :             CPWARN("NLUMO is irrelevant for XAS_TDP PDOS. It was overwritten to 0.")
    2633             :          END IF
    2634           2 :          CALL section_vals_val_set(xas_tdp_section, "PRINT%PDOS%NLUMO", i_val=0)
    2635             :       END IF
    2636             : 
    2637             :       !CUBES related stuff
    2638           4 :       IF (do_cubes) THEN
    2639             : 
    2640           2 :          print_key => section_vals_get_subs_vals(xas_tdp_section, "PRINT%CUBES")
    2641             : 
    2642           2 :          CALL section_vals_val_get(print_key, "CUBES_LU_BOUNDS", i_vals=bounds)
    2643           2 :          ncubes = bounds(2) - bounds(1) + 1
    2644           2 :          IF (ncubes > 0) THEN
    2645           0 :             ALLOCATE (state_list(ncubes))
    2646           0 :             DO ic = 1, ncubes
    2647           0 :                state_list(ic) = bounds(1) + ic - 1
    2648             :             END DO
    2649             :          END IF
    2650             : 
    2651           2 :          IF (.NOT. ASSOCIATED(state_list)) THEN
    2652           2 :             CALL section_vals_val_get(print_key, "CUBES_LIST", n_rep_val=n_rep)
    2653             : 
    2654           2 :             ncubes = 0
    2655           4 :             DO irep = 1, n_rep
    2656           2 :                NULLIFY (list)
    2657           2 :                CALL section_vals_val_get(print_key, "CUBES_LIST", i_rep_val=irep, i_vals=list)
    2658           4 :                IF (ASSOCIATED(list)) THEN
    2659           2 :                   CALL reallocate(state_list, 1, ncubes + SIZE(list))
    2660           4 :                   DO ic = 1, SIZE(list)
    2661           4 :                      state_list(ncubes + ic) = list(ic)
    2662             :                   END DO
    2663           2 :                   ncubes = ncubes + SIZE(list)
    2664             :                END IF
    2665             :             END DO
    2666             :          END IF
    2667             : 
    2668           2 :          IF (.NOT. ASSOCIATED(state_list)) THEN
    2669           0 :             ncubes = 1
    2670           0 :             ALLOCATE (state_list(1))
    2671           0 :             state_list(1) = 1
    2672             :          END IF
    2673             : 
    2674           2 :          CALL section_vals_val_get(print_key, "APPEND", l_val=append_cube)
    2675           2 :          pos = "REWIND"
    2676           2 :          IF (append_cube) pos = "APPEND"
    2677             : 
    2678           6 :          ALLOCATE (centers(6, ncubes))
    2679          18 :          centers = 0.0_dp
    2680             : 
    2681             :       END IF
    2682             : 
    2683             :       !Loop over MOs and spin, one PDOS/CUBE for each
    2684           8 :       DO ido_mo = 1, ndo_mo
    2685          12 :          DO ispin = 1, nspins
    2686             : 
    2687             :             !need to create a mo set for the LR-orbitals
    2688           4 :             ALLOCATE (mo_set)
    2689             :             CALL allocate_mo_set(mo_set, nao=nao, nmo=nmo, nelectron=nmo, n_el_f=REAL(nmo, dp), &
    2690           4 :                                  maxocc=1.0_dp, flexible_electron_count=0.0_dp)
    2691           4 :             CALL init_mo_set(mo_set, fm_ref=mo_coeff, name="PDOS XAS_TDP MOs")
    2692         156 :             mo_set%eigenvalues(:) = lr_evals(:)
    2693             : 
    2694             :             !get the actual coeff => most common case: closed-shell K-edge, can directly take lr_coeffs
    2695           4 :             IF (nspins == 1 .AND. ndo_mo == 1) THEN
    2696           4 :                CALL cp_fm_to_fm(lr_coeffs, mo_set%mo_coeff)
    2697             :             ELSE
    2698           0 :                DO imo = 1, nmo
    2699             :                   CALL cp_fm_to_fm_submat(msource=lr_coeffs, mtarget=mo_set%mo_coeff, &
    2700             :                                           nrow=nao, ncol=1, s_firstrow=1, &
    2701             :                                           s_firstcol=(imo - 1)*ndo_so + (ispin - 1)*ndo_mo + ido_mo, &
    2702           0 :                                           t_firstrow=1, t_firstcol=imo)
    2703             :                END DO
    2704             :             END IF
    2705             : 
    2706             :             !naming the output
    2707           4 :             domon = domo
    2708           4 :             IF (donor_state%state_type == xas_2p_type) domon = TRIM(domo)//TRIM(ADJUSTL(cp_to_string(ido_mo)))
    2709             :             xas_mittle = 'xasat'//TRIM(ADJUSTL(cp_to_string(donor_state%at_index)))//'_'// &
    2710           4 :                          TRIM(domon)//'_'//TRIM(excite)
    2711             : 
    2712           4 :             IF (do_pdos) THEN
    2713             :                CALL calculate_projected_dos(mo_set, atomic_kind_set, qs_kind_set, particle_set, &
    2714             :                                             qs_env, xas_tdp_section, ispin, xas_mittle, &
    2715           2 :                                             external_matrix_shalf=xas_tdp_env%matrix_shalf)
    2716             :             END IF
    2717             : 
    2718           4 :             IF (do_cubes) THEN
    2719             :                CALL qs_print_cubes(qs_env, mo_set%mo_coeff, ncubes, state_list, centers, &
    2720             :                                    print_key=print_key, root=xas_mittle, ispin=ispin, &
    2721           2 :                                    file_position=pos)
    2722             :             END IF
    2723             : 
    2724             :             !clean-up
    2725           4 :             CALL deallocate_mo_set(mo_set)
    2726           8 :             DEALLOCATE (mo_set)
    2727             : 
    2728             :          END DO
    2729             :       END DO
    2730             : 
    2731             :       !clean-up
    2732           4 :       CALL cp_fm_release(mo_coeff)
    2733           4 :       CALL cp_fm_struct_release(mo_struct)
    2734           4 :       IF (do_cubes) DEALLOCATE (centers, state_list)
    2735             : 
    2736           4 :       CALL timestop(handle)
    2737             : 
    2738          62 :    END SUBROUTINE xas_tdp_post
    2739             : 
    2740             : ! **************************************************************************************************
    2741             : !> \brief Computed the LUMOs for the OT eigensolver guesses
    2742             : !> \param xas_tdp_env ...
    2743             : !> \param xas_tdp_control ...
    2744             : !> \param qs_env ...
    2745             : !> \note Uses stendard diagonalization. Do not use the stendard make_lumo subroutine as it uses
    2746             : !>       the OT eigensolver and there is no guarantee that it will converge fast
    2747             : ! **************************************************************************************************
    2748          20 :    SUBROUTINE make_lumo_guess(xas_tdp_env, xas_tdp_control, qs_env)
    2749             : 
    2750             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    2751             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    2752             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2753             : 
    2754             :       CHARACTER(len=*), PARAMETER                        :: routineN = 'make_lumo_guess'
    2755             : 
    2756             :       INTEGER                                            :: handle, ispin, nao, nelec_spin(2), &
    2757             :                                                             nlumo(2), nocc(2), nspins
    2758             :       LOGICAL                                            :: do_os
    2759          20 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: evals
    2760             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    2761             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, lumo_struct
    2762             :       TYPE(cp_fm_type)                                   :: amatrix, bmatrix, evecs, work_fm
    2763          20 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_ks, matrix_s
    2764             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2765             : 
    2766          20 :       NULLIFY (matrix_ks, matrix_s, para_env, blacs_env)
    2767          20 :       NULLIFY (lumo_struct, fm_struct)
    2768             : 
    2769          20 :       CALL timeset(routineN, handle)
    2770             : 
    2771          20 :       do_os = xas_tdp_control%do_uks .OR. xas_tdp_control%do_roks
    2772           2 :       nspins = 1; IF (do_os) nspins = 2
    2773          62 :       ALLOCATE (xas_tdp_env%lumo_evecs(nspins))
    2774          62 :       ALLOCATE (xas_tdp_env%lumo_evals(nspins))
    2775             :       CALL get_qs_env(qs_env, matrix_ks=matrix_ks, matrix_s=matrix_s, nelectron_spin=nelec_spin, &
    2776          20 :                       para_env=para_env, blacs_env=blacs_env)
    2777          20 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
    2778             : 
    2779          20 :       IF (do_os) THEN
    2780           6 :          nlumo = nao - nelec_spin
    2781           2 :          nocc = nelec_spin
    2782             :       ELSE
    2783          54 :          nlumo = nao - nelec_spin(1)/2
    2784          54 :          nocc = nelec_spin(1)/2
    2785             :       END IF
    2786             : 
    2787          62 :       ALLOCATE (xas_tdp_env%ot_prec(nspins))
    2788             : 
    2789          42 :       DO ispin = 1, nspins
    2790             : 
    2791             :          !Going through fm to diagonalize
    2792             :          CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
    2793          22 :                                   nrow_global=nao, ncol_global=nao)
    2794          22 :          CALL cp_fm_create(amatrix, fm_struct)
    2795          22 :          CALL cp_fm_create(bmatrix, fm_struct)
    2796          22 :          CALL cp_fm_create(evecs, fm_struct)
    2797          22 :          CALL cp_fm_create(work_fm, fm_struct)
    2798          66 :          ALLOCATE (evals(nao))
    2799          66 :          ALLOCATE (xas_tdp_env%lumo_evals(ispin)%array(nlumo(ispin)))
    2800             : 
    2801          22 :          CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, amatrix)
    2802          22 :          CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, bmatrix)
    2803             : 
    2804             :          !The actual diagonalization through Cholesky decomposition
    2805          22 :          CALL cp_fm_geeig(amatrix, bmatrix, evecs, evals, work_fm)
    2806             : 
    2807             :          !Storing results
    2808             :          CALL cp_fm_struct_create(lumo_struct, para_env=para_env, context=blacs_env, &
    2809          22 :                                   nrow_global=nao, ncol_global=nlumo(ispin))
    2810          22 :          CALL cp_fm_create(xas_tdp_env%lumo_evecs(ispin), lumo_struct)
    2811             : 
    2812             :          CALL cp_fm_to_fm_submat(evecs, xas_tdp_env%lumo_evecs(ispin), nrow=nao, &
    2813             :                                  ncol=nlumo(ispin), s_firstrow=1, s_firstcol=nocc(ispin) + 1, &
    2814          22 :                                  t_firstrow=1, t_firstcol=1)
    2815             : 
    2816        1098 :          xas_tdp_env%lumo_evals(ispin)%array(1:nlumo(ispin)) = evals(nocc(ispin) + 1:nao)
    2817             : 
    2818          22 :          CALL build_ot_spin_prec(evecs, evals, ispin, xas_tdp_env, xas_tdp_control, qs_env)
    2819             : 
    2820             :          !clean-up
    2821          22 :          CALL cp_fm_release(amatrix)
    2822          22 :          CALL cp_fm_release(bmatrix)
    2823          22 :          CALL cp_fm_release(evecs)
    2824          22 :          CALL cp_fm_release(work_fm)
    2825          22 :          CALL cp_fm_struct_release(fm_struct)
    2826          22 :          CALL cp_fm_struct_release(lumo_struct)
    2827          64 :          DEALLOCATE (evals)
    2828             :       END DO
    2829             : 
    2830          20 :       CALL timestop(handle)
    2831             : 
    2832          60 :    END SUBROUTINE make_lumo_guess
    2833             : 
    2834             : ! **************************************************************************************************
    2835             : !> \brief Builds a preconditioner for the OT eigensolver, based on some heurstics that prioritize
    2836             : !>        LUMOs with lower eigenvalues
    2837             : !> \param evecs all the ground state eigenvectors
    2838             : !> \param evals all the ground state eigenvalues
    2839             : !> \param ispin ...
    2840             : !> \param xas_tdp_env ...
    2841             : !> \param xas_tdp_control ...
    2842             : !> \param qs_env ...
    2843             : !> \note assumes that the preconditioner matrix array is allocated
    2844             : ! **************************************************************************************************
    2845          22 :    SUBROUTINE build_ot_spin_prec(evecs, evals, ispin, xas_tdp_env, xas_tdp_control, qs_env)
    2846             : 
    2847             :       TYPE(cp_fm_type), INTENT(IN)                       :: evecs
    2848             :       REAL(dp), DIMENSION(:)                             :: evals
    2849             :       INTEGER                                            :: ispin
    2850             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    2851             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    2852             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2853             : 
    2854             :       CHARACTER(len=*), PARAMETER :: routineN = 'build_ot_spin_prec'
    2855             : 
    2856             :       INTEGER                                            :: handle, nao, nelec_spin(2), nguess, &
    2857             :                                                             nocc, nspins
    2858             :       LOGICAL                                            :: do_os
    2859             :       REAL(dp)                                           :: shift
    2860             :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: scaling
    2861             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    2862             :       TYPE(cp_fm_type)                                   :: fm_prec, work_fm
    2863          22 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    2864             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    2865             : 
    2866          22 :       NULLIFY (fm_struct, para_env, matrix_s)
    2867             : 
    2868          22 :       CALL timeset(routineN, handle)
    2869             : 
    2870          22 :       do_os = xas_tdp_control%do_uks .OR. xas_tdp_control%do_roks
    2871          22 :       CALL get_qs_env(qs_env, para_env=para_env, nelectron_spin=nelec_spin, matrix_s=matrix_s)
    2872          22 :       CALL cp_fm_get_info(evecs, nrow_global=nao, matrix_struct=fm_struct)
    2873          22 :       CALL cp_fm_create(fm_prec, fm_struct)
    2874          66 :       ALLOCATE (scaling(nao))
    2875          22 :       nocc = nelec_spin(1)/2
    2876          22 :       nspins = 1
    2877          22 :       IF (do_os) THEN
    2878           4 :          nocc = nelec_spin(ispin)
    2879           4 :          nspins = 2
    2880             :       END IF
    2881             : 
    2882             :       !rough estimate of the number of required evals
    2883          22 :       nguess = nao - nocc
    2884          22 :       IF (xas_tdp_control%n_excited > 0 .AND. xas_tdp_control%n_excited < nguess) THEN
    2885           4 :          nguess = xas_tdp_control%n_excited/nspins
    2886          18 :       ELSE IF (xas_tdp_control%e_range > 0.0_dp) THEN
    2887         514 :          nguess = COUNT(evals(nocc + 1:nao) - evals(nocc + 1) .LE. xas_tdp_control%e_range)
    2888             :       END IF
    2889             : 
    2890             :       !Give max weight to the first LUMOs
    2891         540 :       scaling(nocc + 1:nocc + nguess) = 100.0_dp
    2892             :       !Then gradually decrease weight
    2893          22 :       shift = evals(nocc + 1) - 0.01_dp
    2894         602 :       scaling(nocc + nguess:nao) = 1.0_dp/(evals(nocc + nguess:nao) - shift)
    2895             :       !HOMOs do not matter, but need well behaved matrix
    2896         616 :       scaling(1:nocc) = 1.0_dp
    2897             : 
    2898             :       !Building the precond as an fm
    2899          22 :       CALL cp_fm_create(work_fm, fm_struct)
    2900             : 
    2901          22 :       CALL cp_fm_copy_general(evecs, work_fm, para_env)
    2902          22 :       CALL cp_fm_column_scale(work_fm, scaling)
    2903             : 
    2904          22 :       CALL parallel_gemm('N', 'T', nao, nao, nao, 1.0_dp, work_fm, evecs, 0.0_dp, fm_prec)
    2905             : 
    2906             :       !Copy into dbcsr format
    2907          22 :       ALLOCATE (xas_tdp_env%ot_prec(ispin)%matrix)
    2908          22 :       CALL dbcsr_create(xas_tdp_env%ot_prec(ispin)%matrix, template=matrix_s(1)%matrix, name="OT_PREC")
    2909          22 :       CALL copy_fm_to_dbcsr(fm_prec, xas_tdp_env%ot_prec(ispin)%matrix)
    2910          22 :       CALL dbcsr_filter(xas_tdp_env%ot_prec(ispin)%matrix, xas_tdp_control%eps_filter)
    2911             : 
    2912          22 :       CALL cp_fm_release(work_fm)
    2913          22 :       CALL cp_fm_release(fm_prec)
    2914             : 
    2915          22 :       CALL timestop(handle)
    2916             : 
    2917          88 :    END SUBROUTINE build_ot_spin_prec
    2918             : 
    2919             : ! **************************************************************************************************
    2920             : !> \brief Prints GW2X corrected ionization potentials to main output file, including SOC splitting
    2921             : !> \param donor_state ...
    2922             : !> \param xas_tdp_env ...
    2923             : !> \param xas_tdp_control ...
    2924             : !> \param qs_env ...
    2925             : ! **************************************************************************************************
    2926          30 :    SUBROUTINE print_xps(donor_state, xas_tdp_env, xas_tdp_control, qs_env)
    2927             : 
    2928             :       TYPE(donor_state_type), POINTER                    :: donor_state
    2929             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    2930             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    2931             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    2932             : 
    2933             :       INTEGER                                            :: ido_mo, ispin, nspins, output_unit
    2934          30 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: IPs, soc_shifts
    2935             : 
    2936          30 :       output_unit = cp_logger_get_default_io_unit()
    2937             : 
    2938          30 :       nspins = 1; IF (xas_tdp_control%do_uks .OR. xas_tdp_control%do_roks) nspins = 2
    2939             : 
    2940         120 :       ALLOCATE (IPs(SIZE(donor_state%gw2x_evals, 1), SIZE(donor_state%gw2x_evals, 2)))
    2941         106 :       IPs(:, :) = donor_state%gw2x_evals(:, :)
    2942             : 
    2943             :       !IPs in PBCs cannot be trusted because of a lack of a potential reference
    2944          30 :       IF (.NOT. xas_tdp_control%is_periodic) THEN
    2945             : 
    2946             :          !Apply SOC splitting
    2947          26 :          IF (donor_state%ndo_mo > 1) THEN
    2948             :             CALL get_soc_splitting(soc_shifts, donor_state, xas_tdp_env, xas_tdp_control, qs_env)
    2949          20 :             IPs(:, :) = IPs(:, :) + soc_shifts
    2950             : 
    2951           4 :             IF (output_unit > 0) THEN
    2952             :                WRITE (output_unit, FMT="(/,T5,A,F23.6)") &
    2953           2 :                   "Ionization potentials for XPS (GW2X + SOC): ", -IPs(1, 1)*evolt
    2954             : 
    2955           4 :                DO ispin = 1, nspins
    2956          10 :                   DO ido_mo = 1, donor_state%ndo_mo
    2957             : 
    2958           6 :                      IF (ispin == 1 .AND. ido_mo == 1) CYCLE
    2959             : 
    2960             :                      WRITE (output_unit, FMT="(T5,A,F23.6)") &
    2961           8 :                         "                                            ", -IPs(ido_mo, ispin)*evolt
    2962             : 
    2963             :                   END DO
    2964             :                END DO
    2965             :             END IF
    2966             : 
    2967             :          ELSE
    2968             : 
    2969             :             ! No SOC, only 1 donor MO per spin
    2970          22 :             IF (output_unit > 0) THEN
    2971             :                WRITE (output_unit, FMT="(/,T5,A,F29.6)") &
    2972          11 :                   "Ionization potentials for XPS (GW2X): ", -IPs(1, 1)*evolt
    2973             : 
    2974          11 :                IF (nspins == 2) THEN
    2975             :                   WRITE (output_unit, FMT="(T5,A,F29.6)") &
    2976           2 :                      "                                      ", -IPs(1, 2)*evolt
    2977             :                END IF
    2978             :             END IF
    2979             : 
    2980             :          END IF
    2981             :       END IF
    2982             : 
    2983          30 :    END SUBROUTINE print_xps
    2984             : 
    2985             : ! **************************************************************************************************
    2986             : !> \brief Prints the excitation energies and the oscillator strengths for a given donor_state in a file
    2987             : !> \param donor_state the donor_state to print
    2988             : !> \param xas_tdp_env ...
    2989             : !> \param xas_tdp_control ...
    2990             : !> \param xas_tdp_section ...
    2991             : ! **************************************************************************************************
    2992          56 :    SUBROUTINE print_xas_tdp_to_file(donor_state, xas_tdp_env, xas_tdp_control, xas_tdp_section)
    2993             : 
    2994             :       TYPE(donor_state_type), POINTER                    :: donor_state
    2995             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    2996             :       TYPE(xas_tdp_control_type), POINTER                :: xas_tdp_control
    2997             :       TYPE(section_vals_type), POINTER                   :: xas_tdp_section
    2998             : 
    2999             :       INTEGER                                            :: i, output_unit, xas_tdp_unit
    3000             :       TYPE(cp_logger_type), POINTER                      :: logger
    3001             : 
    3002          56 :       NULLIFY (logger)
    3003          56 :       logger => cp_get_default_logger()
    3004             : 
    3005             :       xas_tdp_unit = cp_print_key_unit_nr(logger, xas_tdp_section, "PRINT%SPECTRUM", &
    3006             :                                           extension=".spectrum", file_position="APPEND", &
    3007          56 :                                           file_action="WRITE", file_form="FORMATTED")
    3008             : 
    3009          56 :       output_unit = cp_logger_get_default_io_unit()
    3010             : 
    3011          56 :       IF (output_unit > 0) THEN
    3012             :          WRITE (output_unit, FMT="(/,T5,A,/)") &
    3013          28 :             "Calculations done: "
    3014             :       END IF
    3015             : 
    3016          56 :       IF (xas_tdp_control%do_spin_cons) THEN
    3017           8 :          IF (xas_tdp_unit > 0) THEN
    3018             : 
    3019             : !           Printing the general donor state information
    3020             :             WRITE (xas_tdp_unit, FMT="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
    3021           4 :                "==================================================================================", &
    3022           4 :                "XAS TDP open-shell spin-conserving (no SOC) excitations for DONOR STATE: ", &
    3023           4 :                xas_tdp_env%state_type_char(donor_state%state_type), ",", &
    3024           4 :                "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
    3025           4 :                donor_state%kind_index, "/", TRIM(donor_state%at_symbol), &
    3026           8 :                "=================================================================================="
    3027             : 
    3028             : !           Simply dump the excitation energies/ oscillator strength as they come
    3029             : 
    3030           4 :             IF (xas_tdp_control%do_quad) THEN
    3031             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3032           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   fosc quadrupole (a.u.)"
    3033           0 :                DO i = 1, SIZE(donor_state%sc_evals)
    3034             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F25.6)") &
    3035           0 :                      i, donor_state%sc_evals(i)*evolt, donor_state%osc_str(i, 4), &
    3036           0 :                      donor_state%quad_osc_str(i)
    3037             :                END DO
    3038           4 :             ELSE IF (xas_tdp_control%xyz_dip) THEN
    3039             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3040           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   x-component   y-component   z-component"
    3041           0 :                DO i = 1, SIZE(donor_state%sc_evals)
    3042             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
    3043           0 :                      i, donor_state%sc_evals(i)*evolt, donor_state%osc_str(i, 4), &
    3044           0 :                      donor_state%osc_str(i, 1), donor_state%osc_str(i, 2), donor_state%osc_str(i, 3)
    3045             :                END DO
    3046             :             ELSE
    3047             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3048           4 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)"
    3049         108 :                DO i = 1, SIZE(donor_state%sc_evals)
    3050             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6)") &
    3051         108 :                      i, donor_state%sc_evals(i)*evolt, donor_state%osc_str(i, 4)
    3052             :                END DO
    3053             :             END IF
    3054             : 
    3055           4 :             WRITE (xas_tdp_unit, FMT="(A,/)") " "
    3056             :          END IF !xas_tdp_unit > 0
    3057             : 
    3058           8 :          IF (output_unit > 0) THEN
    3059             :             WRITE (output_unit, FMT="(T5,A,F17.6)") &
    3060           4 :                "First spin-conserving XAS excitation energy (eV): ", donor_state%sc_evals(1)*evolt
    3061             :          END IF
    3062             : 
    3063             :       END IF ! do_spin_cons
    3064             : 
    3065          56 :       IF (xas_tdp_control%do_spin_flip) THEN
    3066           2 :          IF (xas_tdp_unit > 0) THEN
    3067             : 
    3068             : !           Printing the general donor state information
    3069             :             WRITE (xas_tdp_unit, FMT="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
    3070           1 :                "==================================================================================", &
    3071           1 :                "XAS TDP open-shell spin-flip (no SOC) excitations for DONOR STATE: ", &
    3072           1 :                xas_tdp_env%state_type_char(donor_state%state_type), ",", &
    3073           1 :                "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
    3074           1 :                donor_state%kind_index, "/", TRIM(donor_state%at_symbol), &
    3075           2 :                "=================================================================================="
    3076             : 
    3077             : !           Simply dump the excitation energies/ oscillator strength as they come
    3078             : 
    3079           1 :             IF (xas_tdp_control%do_quad) THEN
    3080             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3081           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   fosc quadrupole (a.u.)"
    3082           0 :                DO i = 1, SIZE(donor_state%sf_evals)
    3083             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F25.6)") &
    3084           0 :                      i, donor_state%sf_evals(i)*evolt, 0.0_dp, 0.0_dp !spin-forbidden !
    3085             :                END DO
    3086           1 :             ELSE IF (xas_tdp_control%xyz_dip) THEN
    3087             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3088           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   x-component   y-component   z-component"
    3089           0 :                DO i = 1, SIZE(donor_state%sf_evals)
    3090             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
    3091           0 :                      i, donor_state%sf_evals(i)*evolt, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp
    3092             :                END DO
    3093             :             ELSE
    3094             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3095           1 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)"
    3096          13 :                DO i = 1, SIZE(donor_state%sf_evals)
    3097             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6)") &
    3098          13 :                      i, donor_state%sf_evals(i)*evolt, 0.0_dp
    3099             :                END DO
    3100             :             END IF
    3101             : 
    3102           1 :             WRITE (xas_tdp_unit, FMT="(A,/)") " "
    3103             :          END IF !xas_tdp_unit
    3104             : 
    3105           2 :          IF (output_unit > 0) THEN
    3106             :             WRITE (output_unit, FMT="(T5,A,F23.6)") &
    3107           1 :                "First spin-flip XAS excitation energy (eV): ", donor_state%sf_evals(1)*evolt
    3108             :          END IF
    3109             :       END IF ! do_spin_flip
    3110             : 
    3111          56 :       IF (xas_tdp_control%do_singlet) THEN
    3112          48 :          IF (xas_tdp_unit > 0) THEN
    3113             : 
    3114             : !           Printing the general donor state information
    3115             :             WRITE (xas_tdp_unit, FMT="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
    3116          24 :                "==================================================================================", &
    3117          24 :                "XAS TDP singlet excitations (no SOC) for DONOR STATE: ", &
    3118          24 :                xas_tdp_env%state_type_char(donor_state%state_type), ",", &
    3119          24 :                "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
    3120          24 :                donor_state%kind_index, "/", TRIM(donor_state%at_symbol), &
    3121          48 :                "=================================================================================="
    3122             : 
    3123             : !           Simply dump the excitation energies/ oscillator strength as they come
    3124             : 
    3125          24 :             IF (xas_tdp_control%do_quad) THEN
    3126             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3127           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   fosc quadrupole (a.u.)"
    3128           0 :                DO i = 1, SIZE(donor_state%sg_evals)
    3129             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F25.6)") &
    3130           0 :                      i, donor_state%sg_evals(i)*evolt, donor_state%osc_str(i, 4), &
    3131           0 :                      donor_state%quad_osc_str(i)
    3132             :                END DO
    3133          24 :             ELSE IF (xas_tdp_control%xyz_dip) THEN
    3134             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3135           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   x-component   y-component   z-component"
    3136           0 :                DO i = 1, SIZE(donor_state%sg_evals)
    3137             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
    3138           0 :                      i, donor_state%sg_evals(i)*evolt, donor_state%osc_str(i, 4), &
    3139           0 :                      donor_state%osc_str(i, 1), donor_state%osc_str(i, 2), donor_state%osc_str(i, 3)
    3140             :                END DO
    3141             :             ELSE
    3142             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3143          24 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)"
    3144         348 :                DO i = 1, SIZE(donor_state%sg_evals)
    3145             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6)") &
    3146         348 :                      i, donor_state%sg_evals(i)*evolt, donor_state%osc_str(i, 4)
    3147             :                END DO
    3148             :             END IF
    3149             : 
    3150          24 :             WRITE (xas_tdp_unit, FMT="(A,/)") " "
    3151             :          END IF !xas_tdp_unit
    3152             : 
    3153          48 :          IF (output_unit > 0) THEN
    3154             :             WRITE (output_unit, FMT="(T5,A,F25.6)") &
    3155          24 :                "First singlet XAS excitation energy (eV): ", donor_state%sg_evals(1)*evolt
    3156             :          END IF
    3157             :       END IF ! do_singlet
    3158             : 
    3159          56 :       IF (xas_tdp_control%do_triplet) THEN
    3160           2 :          IF (xas_tdp_unit > 0) THEN
    3161             : 
    3162             : !           Printing the general donor state information
    3163             :             WRITE (xas_tdp_unit, FMT="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
    3164           1 :                "==================================================================================", &
    3165           1 :                "XAS TDP triplet excitations (no SOC) for DONOR STATE: ", &
    3166           1 :                xas_tdp_env%state_type_char(donor_state%state_type), ",", &
    3167           1 :                "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
    3168           1 :                donor_state%kind_index, "/", TRIM(donor_state%at_symbol), &
    3169           2 :                "=================================================================================="
    3170             : 
    3171             : !           Simply dump the excitation energies/ oscillator strength as they come
    3172             : 
    3173           1 :             IF (xas_tdp_control%do_quad) THEN
    3174             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3175           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   fosc quadrupole (a.u.)"
    3176           0 :                DO i = 1, SIZE(donor_state%tp_evals)
    3177             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F25.6)") &
    3178           0 :                      i, donor_state%tp_evals(i)*evolt, 0.0_dp, 0.0_dp !spin-forbidden !
    3179             :                END DO
    3180           1 :             ELSE IF (xas_tdp_control%xyz_dip) THEN
    3181             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3182           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   x-component   y-component   z-component"
    3183           0 :                DO i = 1, SIZE(donor_state%tp_evals)
    3184             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
    3185           0 :                      i, donor_state%tp_evals(i)*evolt, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp
    3186             :                END DO
    3187             :             ELSE
    3188             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3189           1 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)"
    3190          13 :                DO i = 1, SIZE(donor_state%tp_evals)
    3191             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6)") &
    3192          13 :                      i, donor_state%tp_evals(i)*evolt, 0.0_dp
    3193             :                END DO
    3194             :             END IF
    3195             : 
    3196           1 :             WRITE (xas_tdp_unit, FMT="(A,/)") " "
    3197             :          END IF !xas_tdp_unit
    3198             : 
    3199           2 :          IF (output_unit > 0) THEN
    3200             :             WRITE (output_unit, FMT="(T5,A,F25.6)") &
    3201           1 :                "First triplet XAS excitation energy (eV): ", donor_state%tp_evals(1)*evolt
    3202             :          END IF
    3203             :       END IF ! do_triplet
    3204             : 
    3205          56 :       IF (xas_tdp_control%do_soc .AND. donor_state%state_type == xas_2p_type) THEN
    3206           4 :          IF (xas_tdp_unit > 0) THEN
    3207             : 
    3208             : !           Printing the general donor state information
    3209             :             WRITE (xas_tdp_unit, FMT="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
    3210           2 :                "==================================================================================", &
    3211           2 :                "XAS TDP  excitations after spin-orbit coupling for DONOR STATE: ", &
    3212           2 :                xas_tdp_env%state_type_char(donor_state%state_type), ",", &
    3213           2 :                "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
    3214           2 :                donor_state%kind_index, "/", TRIM(donor_state%at_symbol), &
    3215           4 :                "=================================================================================="
    3216             : 
    3217             : !           Simply dump the excitation energies/ oscillator strength as they come
    3218           2 :             IF (xas_tdp_control%do_quad) THEN
    3219             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3220           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   fosc quadrupole (a.u.)"
    3221           0 :                DO i = 1, SIZE(donor_state%soc_evals)
    3222             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F25.6)") &
    3223           0 :                      i, donor_state%soc_evals(i)*evolt, donor_state%soc_osc_str(i, 4), &
    3224           0 :                      donor_state%soc_quad_osc_str(i)
    3225             :                END DO
    3226           2 :             ELSE IF (xas_tdp_control%xyz_dip) THEN
    3227             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3228           0 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)   x-component   y-component   z-component"
    3229           0 :                DO i = 1, SIZE(donor_state%soc_evals)
    3230             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
    3231           0 :                      i, donor_state%soc_evals(i)*evolt, donor_state%soc_osc_str(i, 4), &
    3232           0 :                      donor_state%soc_osc_str(i, 1), donor_state%soc_osc_str(i, 2), donor_state%soc_osc_str(i, 3)
    3233             :                END DO
    3234             :             ELSE
    3235             :                WRITE (xas_tdp_unit, FMT="(T3,A)") &
    3236           2 :                   " Index     Excitation energy (eV)    fosc dipole (a.u.)"
    3237          74 :                DO i = 1, SIZE(donor_state%soc_evals)
    3238             :                   WRITE (xas_tdp_unit, FMT="(T3,I6,F27.6,F22.6)") &
    3239          74 :                      i, donor_state%soc_evals(i)*evolt, donor_state%soc_osc_str(i, 4)
    3240             :                END DO
    3241             :             END IF
    3242             : 
    3243           2 :             WRITE (xas_tdp_unit, FMT="(A,/)") " "
    3244             :          END IF !xas_tdp_unit
    3245             : 
    3246           4 :          IF (output_unit > 0) THEN
    3247             :             WRITE (output_unit, FMT="(T5,A,F29.6)") &
    3248           2 :                "First SOC XAS excitation energy (eV): ", donor_state%soc_evals(1)*evolt
    3249             :          END IF
    3250             :       END IF !do_soc
    3251             : 
    3252          56 :       CALL cp_print_key_finished_output(xas_tdp_unit, logger, xas_tdp_section, "PRINT%SPECTRUM")
    3253             : 
    3254          56 :    END SUBROUTINE print_xas_tdp_to_file
    3255             : 
    3256             : ! **************************************************************************************************
    3257             : !> \brief Prints the donor_state and excitation_type info into a RESTART file for cheap PDOS and/or
    3258             : !>        CUBE printing without expensive computation
    3259             : !> \param ex_type singlet, triplet, etc.
    3260             : !> \param donor_state ...
    3261             : !> \param xas_tdp_section ...
    3262             : !> \param qs_env ...
    3263             : ! **************************************************************************************************
    3264          64 :    SUBROUTINE write_donor_state_restart(ex_type, donor_state, xas_tdp_section, qs_env)
    3265             : 
    3266             :       INTEGER, INTENT(IN)                                :: ex_type
    3267             :       TYPE(donor_state_type), POINTER                    :: donor_state
    3268             :       TYPE(section_vals_type), POINTER                   :: xas_tdp_section
    3269             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3270             : 
    3271             :       CHARACTER(len=*), PARAMETER :: routineN = 'write_donor_state_restart'
    3272             : 
    3273             :       CHARACTER(len=default_path_length)                 :: filename
    3274             :       CHARACTER(len=default_string_length)               :: domo, excite, my_middle
    3275             :       INTEGER                                            :: ex_atom, handle, ispin, nao, ndo_mo, &
    3276             :                                                             nex, nspins, output_unit, rst_unit, &
    3277             :                                                             state_type
    3278          60 :       INTEGER, DIMENSION(:, :), POINTER                  :: mo_indices
    3279             :       LOGICAL                                            :: do_print
    3280          60 :       REAL(dp), DIMENSION(:), POINTER                    :: lr_evals
    3281             :       TYPE(cp_fm_type), POINTER                          :: lr_coeffs
    3282             :       TYPE(cp_logger_type), POINTER                      :: logger
    3283          60 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    3284             :       TYPE(section_vals_type), POINTER                   :: print_key
    3285             : 
    3286          60 :       NULLIFY (logger, lr_coeffs, lr_evals, print_key, mos)
    3287             : 
    3288             :       !Initialization
    3289         120 :       logger => cp_get_default_logger()
    3290          60 :       do_print = .FALSE.
    3291          60 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, xas_tdp_section, &
    3292             :                                            "PRINT%RESTART", used_print_key=print_key), cp_p_file)) do_print = .TRUE.
    3293             : 
    3294          58 :       IF (.NOT. do_print) RETURN
    3295             : 
    3296           2 :       CALL timeset(routineN, handle)
    3297             : 
    3298           2 :       output_unit = cp_logger_get_default_io_unit()
    3299             : 
    3300             :       !Get general info
    3301           2 :       SELECT CASE (ex_type)
    3302             :       CASE (tddfpt_spin_cons)
    3303           0 :          lr_evals => donor_state%sc_evals
    3304           0 :          lr_coeffs => donor_state%sc_coeffs
    3305           0 :          excite = "spincons"
    3306           0 :          nspins = 2
    3307             :       CASE (tddfpt_spin_flip)
    3308           0 :          lr_evals => donor_state%sf_evals
    3309           0 :          lr_coeffs => donor_state%sf_coeffs
    3310           0 :          excite = "spinflip"
    3311           0 :          nspins = 2
    3312             :       CASE (tddfpt_singlet)
    3313           2 :          lr_evals => donor_state%sg_evals
    3314           2 :          lr_coeffs => donor_state%sg_coeffs
    3315           2 :          excite = "singlet"
    3316           2 :          nspins = 1
    3317             :       CASE (tddfpt_triplet)
    3318           0 :          lr_evals => donor_state%tp_evals
    3319           0 :          lr_coeffs => donor_state%tp_coeffs
    3320           0 :          excite = "triplet"
    3321           2 :          nspins = 1
    3322             :       END SELECT
    3323             : 
    3324           4 :       SELECT CASE (donor_state%state_type)
    3325             :       CASE (xas_1s_type)
    3326           2 :          domo = "1s"
    3327             :       CASE (xas_2s_type)
    3328           0 :          domo = "2s"
    3329             :       CASE (xas_2p_type)
    3330           2 :          domo = "2p"
    3331             :       END SELECT
    3332             : 
    3333           2 :       ndo_mo = donor_state%ndo_mo
    3334           2 :       nex = SIZE(lr_evals)
    3335           2 :       CALL cp_fm_get_info(lr_coeffs, nrow_global=nao)
    3336           2 :       state_type = donor_state%state_type
    3337           2 :       ex_atom = donor_state%at_index
    3338           2 :       mo_indices => donor_state%mo_indices
    3339             : 
    3340             :       !Opening restart file
    3341           2 :       rst_unit = -1
    3342           2 :       my_middle = 'xasat'//TRIM(ADJUSTL(cp_to_string(ex_atom)))//'_'//TRIM(domo)//'_'//TRIM(excite)
    3343             :       rst_unit = cp_print_key_unit_nr(logger, xas_tdp_section, "PRINT%RESTART", extension=".rst", &
    3344             :                                       file_status="REPLACE", file_action="WRITE", &
    3345           2 :                                       file_form="UNFORMATTED", middle_name=TRIM(my_middle))
    3346             : 
    3347             :       filename = cp_print_key_generate_filename(logger, print_key, middle_name=TRIM(my_middle), &
    3348           2 :                                                 extension=".rst", my_local=.FALSE.)
    3349             : 
    3350           2 :       IF (output_unit > 0) THEN
    3351             :          WRITE (UNIT=output_unit, FMT="(/,T5,A,/T5,A,A,A)") &
    3352           1 :             "Linear-response orbitals and excitation energies are written in: ", &
    3353           2 :             '"', TRIM(filename), '"'
    3354             :       END IF
    3355             : 
    3356             :       !Writing
    3357           2 :       IF (rst_unit > 0) THEN
    3358           1 :          WRITE (rst_unit) ex_atom, state_type, ndo_mo, ex_type
    3359           1 :          WRITE (rst_unit) nao, nex, nspins
    3360           1 :          WRITE (rst_unit) mo_indices(:, :)
    3361           1 :          WRITE (rst_unit) lr_evals(:)
    3362             :       END IF
    3363           2 :       CALL cp_fm_write_unformatted(lr_coeffs, rst_unit)
    3364             : 
    3365             :       !The MOs as well (because the may have been localized)
    3366           2 :       CALL get_qs_env(qs_env, mos=mos)
    3367           4 :       DO ispin = 1, nspins
    3368           4 :          CALL cp_fm_write_unformatted(mos(ispin)%mo_coeff, rst_unit)
    3369             :       END DO
    3370             : 
    3371             :       !closing
    3372           2 :       CALL cp_print_key_finished_output(rst_unit, logger, xas_tdp_section, "PRINT%RESTART")
    3373             : 
    3374           2 :       CALL timestop(handle)
    3375             : 
    3376          60 :    END SUBROUTINE write_donor_state_restart
    3377             : 
    3378             : ! **************************************************************************************************
    3379             : !> \brief Reads donor_state info from a restart file
    3380             : !> \param donor_state the pre-allocated donor_state
    3381             : !> \param ex_type the excitations stored in this specific file
    3382             : !> \param filename the restart file to read from
    3383             : !> \param qs_env ...
    3384             : ! **************************************************************************************************
    3385           2 :    SUBROUTINE read_donor_state_restart(donor_state, ex_type, filename, qs_env)
    3386             : 
    3387             :       TYPE(donor_state_type), POINTER                    :: donor_state
    3388             :       INTEGER, INTENT(OUT)                               :: ex_type
    3389             :       CHARACTER(len=*), INTENT(IN)                       :: filename
    3390             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3391             : 
    3392             :       CHARACTER(len=*), PARAMETER :: routineN = 'read_donor_state_restart'
    3393             : 
    3394             :       INTEGER                                            :: handle, ispin, nao, nex, nspins, &
    3395             :                                                             output_unit, read_params(7), rst_unit
    3396           2 :       INTEGER, DIMENSION(:, :), POINTER                  :: mo_indices
    3397             :       LOGICAL                                            :: file_exists
    3398           2 :       REAL(dp), DIMENSION(:), POINTER                    :: lr_evals
    3399             :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    3400             :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    3401             :       TYPE(cp_fm_type), POINTER                          :: lr_coeffs
    3402           2 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    3403             :       TYPE(mp_comm_type)                                 :: group
    3404             :       TYPE(mp_para_env_type), POINTER                    :: para_env
    3405             : 
    3406           2 :       NULLIFY (lr_evals, lr_coeffs, para_env, fm_struct, blacs_env, mos)
    3407             : 
    3408           2 :       CALL timeset(routineN, handle)
    3409             : 
    3410           2 :       output_unit = cp_logger_get_default_io_unit()
    3411           2 :       CPASSERT(ASSOCIATED(donor_state))
    3412           2 :       CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
    3413           2 :       group = para_env
    3414             : 
    3415           2 :       file_exists = .FALSE.
    3416           2 :       rst_unit = -1
    3417             : 
    3418           2 :       IF (para_env%is_source()) THEN
    3419             : 
    3420           1 :          INQUIRE (FILE=filename, EXIST=file_exists)
    3421           1 :          IF (.NOT. file_exists) CPABORT("Trying to read non-existing XAS_TDP restart file")
    3422             : 
    3423             :          CALL open_file(file_name=TRIM(filename), file_action="READ", file_form="UNFORMATTED", &
    3424           1 :                         file_position="REWIND", file_status="OLD", unit_number=rst_unit)
    3425             :       END IF
    3426             : 
    3427           2 :       IF (output_unit > 0) THEN
    3428             :          WRITE (UNIT=output_unit, FMT="(/,T5,A,/,T5,A,A,A)") &
    3429           1 :             "Reading linear-response orbitals and excitation energies from file: ", &
    3430           2 :             '"', filename, '"'
    3431             :       END IF
    3432             : 
    3433             :       !read general params
    3434           2 :       IF (rst_unit > 0) THEN
    3435           1 :          READ (rst_unit) read_params(1:4)
    3436           1 :          READ (rst_unit) read_params(5:7)
    3437             :       END IF
    3438           2 :       CALL group%bcast(read_params)
    3439           2 :       donor_state%at_index = read_params(1)
    3440           2 :       donor_state%state_type = read_params(2)
    3441           2 :       donor_state%ndo_mo = read_params(3)
    3442           2 :       ex_type = read_params(4)
    3443           2 :       nao = read_params(5)
    3444           2 :       nex = read_params(6)
    3445           2 :       nspins = read_params(7)
    3446             : 
    3447           8 :       ALLOCATE (mo_indices(donor_state%ndo_mo, nspins))
    3448           2 :       IF (rst_unit > 0) THEN
    3449           1 :          READ (rst_unit) mo_indices(1:donor_state%ndo_mo, 1:nspins)
    3450             :       END IF
    3451          10 :       CALL group%bcast(mo_indices)
    3452           2 :       donor_state%mo_indices => mo_indices
    3453             : 
    3454             :       !read evals
    3455           6 :       ALLOCATE (lr_evals(nex))
    3456           2 :       IF (rst_unit > 0) READ (rst_unit) lr_evals(1:nex)
    3457          78 :       CALL group%bcast(lr_evals)
    3458             : 
    3459             :       !read evecs
    3460             :       CALL cp_fm_struct_create(fm_struct, context=blacs_env, para_env=para_env, &
    3461           2 :                                nrow_global=nao, ncol_global=nex*donor_state%ndo_mo*nspins)
    3462           2 :       ALLOCATE (lr_coeffs)
    3463           2 :       CALL cp_fm_create(lr_coeffs, fm_struct)
    3464           2 :       CALL cp_fm_read_unformatted(lr_coeffs, rst_unit)
    3465           2 :       CALL cp_fm_struct_release(fm_struct)
    3466             : 
    3467             :       !read MO coeffs and replace in qs_env
    3468           2 :       CALL get_qs_env(qs_env, mos=mos)
    3469           4 :       DO ispin = 1, nspins
    3470           4 :          CALL cp_fm_read_unformatted(mos(ispin)%mo_coeff, rst_unit)
    3471             :       END DO
    3472             : 
    3473             :       !closing file
    3474           2 :       IF (para_env%is_source()) THEN
    3475           1 :          CALL close_file(unit_number=rst_unit)
    3476             :       END IF
    3477             : 
    3478             :       !case study on excitation type
    3479           2 :       SELECT CASE (ex_type)
    3480             :       CASE (tddfpt_spin_cons)
    3481           0 :          donor_state%sc_evals => lr_evals
    3482           0 :          donor_state%sc_coeffs => lr_coeffs
    3483             :       CASE (tddfpt_spin_flip)
    3484           0 :          donor_state%sf_evals => lr_evals
    3485           0 :          donor_state%sf_coeffs => lr_coeffs
    3486             :       CASE (tddfpt_singlet)
    3487           2 :          donor_state%sg_evals => lr_evals
    3488           2 :          donor_state%sg_coeffs => lr_coeffs
    3489             :       CASE (tddfpt_triplet)
    3490           0 :          donor_state%tp_evals => lr_evals
    3491           2 :          donor_state%tp_coeffs => lr_coeffs
    3492             :       END SELECT
    3493             : 
    3494           2 :       CALL timestop(handle)
    3495             : 
    3496           4 :    END SUBROUTINE read_donor_state_restart
    3497             : 
    3498             : ! **************************************************************************************************
    3499             : !> \brief Checks whether this is a restart calculation and runs it if so
    3500             : !> \param rst_filename the file to read for restart
    3501             : !> \param xas_tdp_section ...
    3502             : !> \param qs_env ...
    3503             : ! **************************************************************************************************
    3504           4 :    SUBROUTINE restart_calculation(rst_filename, xas_tdp_section, qs_env)
    3505             : 
    3506             :       CHARACTER(len=*), INTENT(IN)                       :: rst_filename
    3507             :       TYPE(section_vals_type), POINTER                   :: xas_tdp_section
    3508             :       TYPE(qs_environment_type), POINTER                 :: qs_env
    3509             : 
    3510             :       INTEGER                                            :: ex_type
    3511             :       TYPE(donor_state_type), POINTER                    :: donor_state
    3512             :       TYPE(xas_tdp_env_type), POINTER                    :: xas_tdp_env
    3513             : 
    3514           2 :       NULLIFY (xas_tdp_env, donor_state)
    3515             : 
    3516             :       !create a donor_state that we fill with the information we read
    3517           2 :       ALLOCATE (donor_state)
    3518           2 :       CALL donor_state_create(donor_state)
    3519           2 :       CALL read_donor_state_restart(donor_state, ex_type, rst_filename, qs_env)
    3520             : 
    3521             :       !create a dummy xas_tdp_env and compute the post XAS_TDP stuff
    3522           2 :       CALL xas_tdp_env_create(xas_tdp_env)
    3523           2 :       CALL xas_tdp_post(ex_type, donor_state, xas_tdp_env, xas_tdp_section, qs_env)
    3524             : 
    3525             :       !clean-up
    3526           2 :       CALL xas_tdp_env_release(xas_tdp_env)
    3527           2 :       CALL free_ds_memory(donor_state)
    3528           2 :       DEALLOCATE (donor_state%mo_indices)
    3529           2 :       DEALLOCATE (donor_state)
    3530             : 
    3531           2 :    END SUBROUTINE restart_calculation
    3532             : 
    3533             : END MODULE xas_tdp_methods

Generated by: LCOV version 1.15