LCOV - code coverage report
Current view: top level - src - rixs_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:1155b05) Lines: 96.8 % 222 215
Test Date: 2026-03-21 06:31:29 Functions: 100.0 % 3 3

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Methods for Resonant Inelastic XRAY Scattering (RIXS) calculations
      10              : !> \author BSG (02.2025)
      11              : ! **************************************************************************************************
      12              : MODULE rixs_methods
      13              :    USE bibliography,                    ONLY: VazdaCruz2021,&
      14              :                                               cite_reference
      15              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      16              :    USE cp_control_types,                ONLY: dft_control_type,&
      17              :                                               rixs_control_create,&
      18              :                                               rixs_control_release,&
      19              :                                               rixs_control_type
      20              :    USE cp_control_utils,                ONLY: read_rixs_control
      21              :    USE cp_dbcsr_api,                    ONLY: dbcsr_p_type
      22              :    USE cp_dbcsr_operations,             ONLY: cp_dbcsr_sm_fm_multiply
      23              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      24              :                                               cp_fm_struct_release,&
      25              :                                               cp_fm_struct_type
      26              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      27              :                                               cp_fm_get_info,&
      28              :                                               cp_fm_get_submatrix,&
      29              :                                               cp_fm_release,&
      30              :                                               cp_fm_to_fm_submat,&
      31              :                                               cp_fm_type
      32              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      33              :                                               cp_logger_get_default_io_unit,&
      34              :                                               cp_logger_type
      35              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      36              :                                               cp_print_key_unit_nr
      37              :    USE header,                          ONLY: rixs_header
      38              :    USE input_constants,                 ONLY: xas_1s_type,&
      39              :                                               xas_2p_type,&
      40              :                                               xas_2s_type
      41              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      42              :                                               section_vals_type
      43              :    USE kinds,                           ONLY: dp
      44              :    USE message_passing,                 ONLY: mp_para_env_type
      45              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      46              :    USE physcon,                         ONLY: evolt
      47              :    USE qs_environment_types,            ONLY: get_qs_env,&
      48              :                                               qs_environment_type
      49              :    USE qs_tddfpt2_methods,              ONLY: tddfpt
      50              :    USE rixs_types,                      ONLY: rixs_env_create,&
      51              :                                               rixs_env_release,&
      52              :                                               rixs_env_type,&
      53              :                                               tddfpt2_valence_type
      54              :    USE xas_tdp_methods,                 ONLY: xas_tdp
      55              :    USE xas_tdp_types,                   ONLY: donor_state_type,&
      56              :                                               xas_tdp_env_type
      57              : #include "./base/base_uses.f90"
      58              : 
      59              :    IMPLICIT NONE
      60              :    PRIVATE
      61              : 
      62              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'rixs_methods'
      63              : 
      64              :    PUBLIC :: rixs
      65              : 
      66              : CONTAINS
      67              : 
      68              : ! **************************************************************************************************
      69              : !> \brief Driver for RIXS calculations.
      70              : !> \param qs_env the inherited qs_environment
      71              : !> \author BSG
      72              : ! **************************************************************************************************
      73              : 
      74           16 :    SUBROUTINE rixs(qs_env)
      75              : 
      76              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      77              : 
      78              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'rixs'
      79              : 
      80              :       INTEGER                                            :: handle, output_unit
      81              :       TYPE(dft_control_type), POINTER                    :: dft_control
      82              :       TYPE(section_vals_type), POINTER                   :: rixs_section, tddfp2_section, &
      83              :                                                             xas_tdp_section
      84              : 
      85           16 :       CALL timeset(routineN, handle)
      86              : 
      87           16 :       NULLIFY (rixs_section)
      88           16 :       rixs_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%RIXS")
      89           16 :       output_unit = cp_logger_get_default_io_unit()
      90              : 
      91           16 :       qs_env%do_rixs = .TRUE.
      92              : 
      93           16 :       CALL cite_reference(VazdaCruz2021)
      94              : 
      95           16 :       CALL get_qs_env(qs_env, dft_control=dft_control)
      96              : 
      97           16 :       xas_tdp_section => section_vals_get_subs_vals(rixs_section, "XAS_TDP")
      98           16 :       tddfp2_section => section_vals_get_subs_vals(rixs_section, "TDDFPT")
      99              : 
     100           16 :       CALL rixs_core(rixs_section, qs_env)
     101              : 
     102           16 :       IF (output_unit > 0) THEN
     103              :          WRITE (UNIT=output_unit, FMT="(/,(T2,A79))") &
     104            8 :             "*******************************************************************************", &
     105            8 :             "!    Normal termination of Resonant Inelastic X-RAY Scattering calculation    !", &
     106           16 :             "*******************************************************************************"
     107              :       END IF
     108              : 
     109           16 :       CALL timestop(handle)
     110              : 
     111           16 :    END SUBROUTINE rixs
     112              : 
     113              : ! **************************************************************************************************
     114              : !> \brief Perform RIXS calculation.
     115              : !> \param rixs_section ...
     116              : !> \param qs_env ...
     117              : ! **************************************************************************************************
     118           16 :    SUBROUTINE rixs_core(rixs_section, qs_env)
     119              : 
     120              :       TYPE(section_vals_type), POINTER                   :: rixs_section
     121              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     122              : 
     123              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'rixs_core'
     124              : 
     125              :       INTEGER :: ax, c_nstates, current_state_index, handle, iatom, ispin, istate, k, &
     126              :          n_states_donor, nactive_max, nao, nex_atoms, nspins, output_unit, td_state, v_nstates
     127           16 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nactive, nocc
     128              :       LOGICAL                                            :: do_sc, do_sg, roks, uks
     129           16 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: w_i0, w_if
     130           16 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: dip_block, mu_i0
     131           16 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :, :)          :: mu_if
     132              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     133              :       TYPE(cp_fm_struct_type), POINTER :: core_evect_struct, cRc_struct, dip_0_struct, &
     134              :          gs_coeff_struct, i_dip_0_struct, matrix_struct, overlap_struct, Rc_struct
     135              :       TYPE(cp_fm_type)                                   :: dip_0
     136           16 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: core_evects, cRc, i_dip_0, mat_product, &
     137           16 :                                                             overlap_X, Rc, state_gs_coeffs, &
     138           16 :                                                             Y_overlap_X
     139           16 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: local_gs_coeffs, mo_active
     140           16 :       TYPE(cp_fm_type), DIMENSION(:, :), POINTER         :: valence_evects
     141              :       TYPE(cp_fm_type), POINTER                          :: target_ex_coeffs
     142           16 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: dipmat, matrix_s
     143              :       TYPE(dft_control_type), POINTER                    :: dft_control
     144              :       TYPE(donor_state_type), POINTER                    :: current_state
     145              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     146              :       TYPE(rixs_control_type), POINTER                   :: rixs_control
     147              :       TYPE(rixs_env_type), POINTER                       :: rixs_env
     148              :       TYPE(tddfpt2_valence_type), POINTER                :: valence_state
     149              :       TYPE(xas_tdp_env_type), POINTER                    :: core_state
     150              : 
     151           16 :       NULLIFY (rixs_control, dft_control, rixs_env)
     152           16 :       NULLIFY (valence_state, core_state)
     153           16 :       NULLIFY (para_env, blacs_env)
     154           16 :       NULLIFY (local_gs_coeffs, mo_active, valence_evects)
     155           16 :       NULLIFY (dipmat, dip_0_struct, i_dip_0_struct, &
     156           16 :                core_evect_struct, gs_coeff_struct)
     157              : 
     158           32 :       output_unit = cp_logger_get_default_io_unit()
     159              : 
     160              :       CALL get_qs_env(qs_env, &
     161              :                       dft_control=dft_control, &
     162              :                       matrix_s=matrix_s, &
     163              :                       para_env=para_env, &
     164           16 :                       blacs_env=blacs_env)
     165           16 :       CALL rixs_control_create(rixs_control)
     166           16 :       CALL read_rixs_control(rixs_control, rixs_section, dft_control%qs_control)
     167              : 
     168              :       ! create rixs_env
     169           16 :       CALL rixs_env_create(rixs_env)
     170              : 
     171              :       ! first, xas_tdp calculation
     172           16 :       CALL xas_tdp(qs_env, rixs_env)
     173              : 
     174           16 :       do_sg = rixs_control%xas_tdp_control%do_singlet
     175           16 :       do_sc = rixs_control%xas_tdp_control%do_spin_cons
     176              : 
     177           16 :       IF (rixs_control%xas_tdp_control%check_only) THEN
     178            0 :          CPWARN("CHECK_ONLY run for XAS_TDP requested, RIXS and TDDFPT will not be performed.")
     179              :       ELSE
     180              : 
     181              :          ! then, tddfpt calculation
     182           16 :          CALL tddfpt(qs_env, calc_forces=.FALSE., rixs_env=rixs_env)
     183              : 
     184           16 :          IF (output_unit > 0) THEN
     185            8 :             CALL rixs_header(output_unit)
     186              :          END IF
     187              : 
     188              :          ! timings for rixs only, excluding xas_tdp and tddft calls
     189           16 :          CALL timeset(routineN, handle)
     190              : 
     191           16 :          IF (do_sg) THEN ! singlet
     192              :             nspins = 1
     193            4 :          ELSE IF (do_sc) THEN ! spin-conserving
     194              :             nspins = 2
     195              :          ELSE
     196            0 :             CPABORT("RIXS only implemented for singlet and spin-conserving excitations")
     197              :          END IF
     198              : 
     199           16 :          roks = .FALSE.
     200           16 :          uks = .FALSE.
     201              : 
     202           16 :          IF (dft_control%uks) THEN
     203              :             uks = .TRUE.
     204           14 :          ELSE IF (dft_control%roks) THEN
     205            2 :             roks = .TRUE.
     206              :          END IF
     207              : 
     208           16 :          IF (output_unit > 0) THEN
     209            8 :             IF (uks) THEN
     210            1 :                WRITE (UNIT=output_unit, FMT="(T2,A)") "RIXS| Unrestricted Open-Shell Kohn-Sham"
     211            7 :             ELSE IF (roks) THEN
     212            1 :                WRITE (UNIT=output_unit, FMT="(T2,A)") "RIXS| Restricted Open-Shell Kohn-Sham"
     213              :             ELSE
     214            6 :                WRITE (UNIT=output_unit, FMT="(T2,A)") "RIXS| Restricted Closed-Shell Kohn-Sham"
     215              :             END IF
     216              :          END IF
     217              : 
     218           16 :          core_state => rixs_env%core_state
     219           16 :          valence_state => rixs_env%valence_state
     220              : 
     221              :          ! gs coefficients from tddfpt
     222           16 :          mo_active => valence_state%mos_active
     223              :          ! localised gs coefficients from xas_tdp
     224           16 :          local_gs_coeffs => core_state%mo_coeff
     225           16 :          valence_evects => valence_state%evects
     226              : 
     227              :          ! find max nactive for open-shell cases
     228           32 :          ALLOCATE (nactive(nspins))
     229           32 :          ALLOCATE (nocc(nspins))
     230           36 :          DO ispin = 1, nspins
     231           20 :             IF (roks) THEN
     232            4 :                CALL cp_fm_get_info(matrix=local_gs_coeffs(1), ncol_global=nocc(ispin))
     233              :             ELSE
     234           16 :                CALL cp_fm_get_info(matrix=local_gs_coeffs(ispin), ncol_global=nocc(ispin))
     235              :             END IF
     236           36 :             CALL cp_fm_get_info(matrix=mo_active(ispin), nrow_global=nao, ncol_global=nactive(ispin))
     237              :          END DO
     238           36 :          nactive_max = MAXVAL(nactive)
     239              : 
     240           16 :          nex_atoms = core_state%nex_atoms
     241           16 :          v_nstates = valence_state%nstates
     242           16 :          c_nstates = core_state%nstates
     243              : 
     244           16 :          IF (rixs_control%core_states > 0) THEN
     245            6 :             rixs_control%core_states = MIN(rixs_control%core_states, c_nstates)
     246              :          ELSE
     247           10 :             rixs_control%core_states = c_nstates
     248              :          END IF
     249           16 :          c_nstates = rixs_control%core_states
     250              : 
     251           16 :          IF (rixs_control%valence_states > 0) THEN
     252            4 :             rixs_control%valence_states = MIN(rixs_control%valence_states, v_nstates)
     253              :          ELSE
     254           12 :             rixs_control%valence_states = v_nstates
     255              :          END IF
     256           16 :          v_nstates = rixs_control%valence_states
     257              : 
     258           16 :          IF (output_unit > 0) THEN
     259              :             WRITE (UNIT=output_unit, FMT="(T2,A,I5,A,I5)") &
     260            8 :                "RIXS| Using ", c_nstates, " core states out of ", core_state%nstates
     261              :             WRITE (UNIT=output_unit, FMT="(T2,A,I5,A,I5,/)") &
     262            8 :                "RIXS| Using ", v_nstates, " valence states out of ", valence_state%nstates
     263              :          END IF
     264              : 
     265           16 :          dipmat => core_state%dipmat
     266              : 
     267           88 :          ALLOCATE (core_evects(nspins), state_gs_coeffs(nspins))
     268          176 :          ALLOCATE (dip_block(1, nspins), mu_i0(4, c_nstates), mu_if(4, c_nstates, v_nstates), w_i0(c_nstates), w_if(v_nstates))
     269           66 :          w_if(:) = valence_state%evals(1:v_nstates)*evolt
     270           52 :          ALLOCATE (i_dip_0(nspins))
     271           88 :          ALLOCATE (Rc(nspins), cRc(nspins))
     272          124 :          ALLOCATE (overlap_X(nspins), Y_overlap_X(nspins), mat_product(nspins))
     273              : 
     274              :          CALL cp_fm_struct_create(core_evect_struct, para_env=para_env, context=blacs_env, &
     275           16 :                                   nrow_global=nao, ncol_global=c_nstates)
     276              :          CALL cp_fm_struct_create(gs_coeff_struct, para_env=para_env, context=blacs_env, &
     277           16 :                                   nrow_global=nao, ncol_global=1)
     278              : 
     279              :          ! looping over ex_atoms and ex_kinds is enough as excited atoms have to be unique
     280           16 :          current_state_index = 1
     281           36 :          DO iatom = 1, nex_atoms
     282           20 :             current_state => core_state%donor_states(current_state_index)
     283              : 
     284           20 :             IF (current_state%state_type == xas_1s_type) THEN
     285           20 :                n_states_donor = 1
     286            0 :             ELSE IF (current_state%state_type == xas_2s_type) THEN
     287            0 :                n_states_donor = 1
     288            0 :             ELSE IF (current_state%state_type == xas_2p_type) THEN
     289            0 :                n_states_donor = 3
     290              :             ELSE
     291            0 :                CPABORT("Unsupported core state type")
     292              :             END IF
     293              : 
     294           20 :             IF (output_unit > 0) THEN
     295              :                WRITE (UNIT=output_unit, FMT="(T2,A,A,A,I3,A,A)") &
     296           10 :                   "RIXS| Calculating dipole moment from core-excited state ", &
     297           10 :                   core_state%state_type_char(current_state%state_type), " for atom ", &
     298           20 :                   current_state%at_index, " of kind ", TRIM(current_state%at_symbol)
     299              :             END IF
     300              : 
     301           20 :             IF (do_sg) THEN ! singlet
     302           16 :                target_ex_coeffs => current_state%sg_coeffs
     303          158 :                w_i0(:) = current_state%sg_evals(1:c_nstates)*evolt
     304            4 :             ELSE IF (do_sc) THEN ! spin-conserving
     305            4 :                target_ex_coeffs => current_state%sc_coeffs
     306           52 :                w_i0(:) = current_state%sc_evals(1:c_nstates)*evolt
     307              :             END IF
     308              : 
     309              :             ! reshape sc and sg coeffs (separate spins to columns)
     310           44 :             DO ispin = 1, nspins
     311           24 :                CALL cp_fm_create(core_evects(ispin), core_evect_struct)
     312              :                CALL cp_fm_to_fm_submat(msource=target_ex_coeffs, mtarget=core_evects(ispin), s_firstrow=1, &
     313           44 :                                        s_firstcol=(c_nstates*(ispin - 1) + 1), t_firstrow=1, t_firstcol=1, nrow=nao, ncol=c_nstates)
     314              :             END DO
     315           44 :             DO ispin = 1, nspins
     316           24 :                CALL cp_fm_create(state_gs_coeffs(ispin), gs_coeff_struct)
     317           44 :                IF (roks) THEN
     318              :                   ! store same coeffs for both spins, easier later on
     319              :                   CALL cp_fm_to_fm_submat(msource=current_state%gs_coeffs, mtarget=state_gs_coeffs(ispin), s_firstrow=1, &
     320            4 :                                           s_firstcol=1, t_firstrow=1, t_firstcol=1, nrow=nao, ncol=n_states_donor)
     321              :                ELSE
     322              :                   CALL cp_fm_to_fm_submat(msource=current_state%gs_coeffs, mtarget=state_gs_coeffs(ispin), s_firstrow=1, &
     323           20 :                                           s_firstcol=ispin, t_firstrow=1, t_firstcol=1, nrow=nao, ncol=n_states_donor)
     324              :                END IF
     325              :             END DO
     326              : 
     327              :             ! initialise matrices for i->0
     328              :             CALL cp_fm_struct_create(dip_0_struct, para_env=para_env, context=blacs_env, &
     329           20 :                                      nrow_global=nao, ncol_global=1)
     330           20 :             CALL cp_fm_create(dip_0, dip_0_struct)
     331              :             CALL cp_fm_struct_create(i_dip_0_struct, para_env=para_env, context=blacs_env, &
     332           20 :                                      nrow_global=c_nstates, ncol_global=1)
     333           44 :             DO ispin = 1, nspins
     334           44 :                CALL cp_fm_create(i_dip_0(ispin), i_dip_0_struct)
     335              :             END DO
     336              : 
     337           44 :             DO ispin = 1, nspins
     338              :                ! initialise cRc (nocc x nactive)
     339              :                CALL cp_fm_struct_create(Rc_struct, para_env=para_env, context=blacs_env, &
     340           24 :                                         nrow_global=nao, ncol_global=nactive(ispin))
     341              :                CALL cp_fm_struct_create(cRc_struct, para_env=para_env, context=blacs_env, &
     342           24 :                                         nrow_global=n_states_donor, ncol_global=nactive(ispin))
     343           24 :                CALL cp_fm_create(Rc(ispin), Rc_struct)
     344           24 :                CALL cp_fm_create(cRc(ispin), cRc_struct)
     345              : 
     346              :                CALL cp_fm_struct_create(overlap_struct, para_env=para_env, context=blacs_env, &
     347           24 :                                         nrow_global=c_nstates, ncol_global=nactive(ispin))
     348              : 
     349              :                CALL cp_fm_struct_create(matrix_struct, para_env=para_env, context=blacs_env, &
     350           24 :                                         nrow_global=c_nstates, ncol_global=n_states_donor)
     351              : 
     352              :                ! initialise overlap_X
     353           24 :                CALL cp_fm_create(overlap_X(ispin), Rc_struct) ! nao x nactive
     354              : 
     355              :                ! initialise Y_overlap_X
     356           24 :                CALL cp_fm_create(Y_overlap_X(ispin), overlap_struct) ! c_nstates x nactive
     357              : 
     358              :                ! initialise mat_product = Y_overlap_X * cRc
     359           24 :                CALL cp_fm_create(mat_product(ispin), matrix_struct) ! c_nstates x nocc
     360              : 
     361           24 :                CALL cp_fm_struct_release(cRc_struct)
     362           24 :                CALL cp_fm_struct_release(Rc_struct)
     363           24 :                CALL cp_fm_struct_release(overlap_struct)
     364           44 :                CALL cp_fm_struct_release(matrix_struct)
     365              :             END DO
     366              : 
     367          970 :             mu_i0 = 0.0_dp
     368         3038 :             mu_if = 0.0_dp
     369              :             ! 0 -> i
     370           80 :             DO ax = 1, 3
     371              : 
     372              :                ! i*R*0
     373          132 :                DO ispin = 1, nspins
     374           72 :                   CALL cp_dbcsr_sm_fm_multiply(dipmat(ax)%matrix, state_gs_coeffs(ispin), dip_0, ncol=1)
     375          132 :                   CALL parallel_gemm('T', 'N', c_nstates, 1, nao, 1.0_dp, core_evects(ispin), dip_0, 0.0_dp, i_dip_0(ispin))
     376              :                END DO
     377              : 
     378          650 :                DO istate = 1, c_nstates
     379         1998 :                   dip_block = 0.0_dp
     380         1284 :                   DO ispin = 1, nspins
     381              :                      CALL cp_fm_get_submatrix(fm=i_dip_0(ispin), target_m=dip_block, start_row=istate, &
     382          714 :                                               start_col=1, n_rows=1, n_cols=1)
     383         1284 :                      mu_i0(ax, istate) = mu_i0(ax, istate) + dip_block(1, 1)
     384              :                   END DO ! ispin
     385          630 :                   mu_i0(4, istate) = mu_i0(4, istate) + mu_i0(ax, istate)**2
     386              :                END DO ! istate
     387              : 
     388              :             END DO ! ax
     389              : 
     390              :             ! i -> f
     391           78 :             DO td_state = 1, v_nstates
     392              : 
     393           58 :                IF (output_unit > 0) THEN
     394              :                   WRITE (UNIT=output_unit, FMT="(T9,A,I3,A,F10.4)") &
     395           29 :                      "to valence-excited state ", td_state, " with energy ", w_if(td_state)
     396              :                END IF
     397              : 
     398          136 :                DO ispin = 1, nspins
     399              :                   ! 1) build S*X (nao x nactive)
     400              :                   CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, valence_evects(ispin, td_state), overlap_X(ispin), &
     401           78 :                                                ncol=nactive(ispin))
     402              :                   ! 2) build Y^T*S*X (c_states x nactive)
     403              :                   CALL parallel_gemm('T', 'N', c_nstates, nactive(ispin), nao, 1.0_dp, core_evects(ispin), &
     404          136 :                                      overlap_X(ispin), 0.0_dp, Y_overlap_X(ispin))
     405              :                END DO
     406              : 
     407          252 :                DO ax = 1, 3
     408              : 
     409          408 :                   DO ispin = 1, nspins
     410              :                      ! 3) build c_i^T*R*c (k x nactive)
     411          234 :                      CALL cp_dbcsr_sm_fm_multiply(dipmat(ax)%matrix, mo_active(ispin), Rc(ispin), ncol=nactive(ispin))
     412              :                      CALL parallel_gemm('T', 'N', n_states_donor, nactive(ispin), nao, 1.0_dp, state_gs_coeffs(ispin), &
     413          234 :                                         Rc(ispin), 0.0_dp, cRc(ispin))
     414              : 
     415              :                      ! 4) build mat_product (Y^T*S*X*c_i^T*R*c) (c_nstates x k)
     416              :                      CALL parallel_gemm('N', 'T', c_nstates, n_states_donor, nactive(ispin), 1.0_dp, Y_overlap_X(ispin), &
     417          408 :                                         cRc(ispin), 0.0_dp, mat_product(ispin))
     418              :                   END DO
     419              : 
     420         2008 :                   DO istate = 1, c_nstates
     421         3552 :                      DO k = 1, n_states_donor
     422         6768 :                         dip_block = 0.0_dp
     423         6048 :                         DO ispin = 1, nspins
     424              :                            CALL cp_fm_get_submatrix(fm=mat_product(ispin), target_m=dip_block, start_row=istate, &
     425         2496 :                                                     start_col=k, n_rows=1, n_cols=1)
     426         4272 :                            mu_if(ax, istate, td_state) = mu_if(ax, istate, td_state) + dip_block(1, 1)
     427              :                         END DO ! ispin
     428              :                      END DO ! k
     429         1950 :                      mu_if(4, istate, td_state) = mu_if(4, istate, td_state) + mu_if(ax, istate, td_state)**2
     430              :                   END DO ! istate (core)
     431              : 
     432              :                END DO ! ax
     433              : 
     434              :             END DO ! td_state
     435              : 
     436           20 :             IF (output_unit > 0) THEN
     437           10 :                WRITE (UNIT=output_unit, FMT="(/,T2,A,/)") "RIXS| Printing spectrum to file"
     438              :             END IF
     439           20 :             CALL print_rixs_to_file(current_state, mu_i0, mu_if, w_i0, w_if, rixs_env, rixs_section, rixs_control)
     440              : 
     441           20 :             current_state_index = current_state_index + 1
     442              : 
     443              :             ! cleanup
     444           44 :             DO ispin = 1, nspins
     445           24 :                CALL cp_fm_release(core_evects(ispin))
     446           24 :                CALL cp_fm_release(state_gs_coeffs(ispin))
     447           24 :                CALL cp_fm_release(i_dip_0(ispin))
     448           24 :                CALL cp_fm_release(Rc(ispin))
     449           24 :                CALL cp_fm_release(cRc(ispin))
     450           24 :                CALL cp_fm_release(overlap_X(ispin))
     451           24 :                CALL cp_fm_release(Y_overlap_X(ispin))
     452           44 :                CALL cp_fm_release(mat_product(ispin))
     453              :             END DO
     454           20 :             CALL cp_fm_struct_release(i_dip_0_struct)
     455           20 :             CALL cp_fm_struct_release(dip_0_struct)
     456           56 :             CALL cp_fm_release(dip_0)
     457              : 
     458              :          END DO ! iatom
     459              : 
     460              :          NULLIFY (current_state)
     461              : 
     462              :          ! cleanup
     463           16 :          CALL cp_fm_struct_release(core_evect_struct)
     464           32 :          CALL cp_fm_struct_release(gs_coeff_struct)
     465              : 
     466              :       END IF
     467              : 
     468              :       ! more cleanup
     469           16 :       CALL rixs_control_release(rixs_control)
     470           16 :       CALL rixs_env_release(rixs_env)
     471           16 :       NULLIFY (valence_state, core_state)
     472              : 
     473           16 :       CALL timestop(handle)
     474              : 
     475           32 :    END SUBROUTINE rixs_core
     476              : 
     477              : !**************************************************************************************************
     478              : !> \brief Print RIXS spectrum.
     479              : !> \param donor_state ...
     480              : !> \param mu_i0 ...
     481              : !> \param mu_if ...
     482              : !> \param w_i0 ...
     483              : !> \param w_if ...
     484              : !> \param rixs_env ...
     485              : !> \param rixs_section ...
     486              : !> \param rixs_control ...
     487              : ! **************************************************************************************************
     488           20 :    SUBROUTINE print_rixs_to_file(donor_state, mu_i0, mu_if, w_i0, w_if, &
     489              :                                  rixs_env, rixs_section, rixs_control)
     490              : 
     491              :       TYPE(donor_state_type), POINTER                    :: donor_state
     492              :       REAL(dp), DIMENSION(:, :)                          :: mu_i0
     493              :       REAL(dp), DIMENSION(:, :, :)                       :: mu_if
     494              :       REAL(dp), DIMENSION(:)                             :: w_i0, w_if
     495              :       TYPE(rixs_env_type), POINTER                       :: rixs_env
     496              :       TYPE(section_vals_type), POINTER                   :: rixs_section
     497              :       TYPE(rixs_control_type), POINTER                   :: rixs_control
     498              : 
     499              :       INTEGER                                            :: f, i, output_unit, rixs_unit
     500              :       TYPE(cp_logger_type), POINTER                      :: logger
     501              : 
     502           20 :       NULLIFY (logger)
     503           20 :       logger => cp_get_default_logger()
     504              : 
     505              :       rixs_unit = cp_print_key_unit_nr(logger, rixs_section, "PRINT%SPECTRUM", &
     506              :                                        extension=".rixs", file_position="APPEND", &
     507           20 :                                        file_action="WRITE", file_form="FORMATTED")
     508              : 
     509           20 :       output_unit = cp_logger_get_default_io_unit()
     510              : 
     511           20 :       IF (rixs_unit > 0) THEN
     512              : 
     513              :          WRITE (rixs_unit, FMT="(A,/,T2,A,A,A,I3,A,A,A/,A)") &
     514           10 :             "=====================================================================================", &
     515           10 :             "Excitation from ground-state (", &
     516           10 :             rixs_env%core_state%state_type_char(donor_state%state_type), " for atom ", &
     517           10 :             donor_state%at_index, " of kind ", TRIM(donor_state%at_symbol), &
     518           10 :             ") to core-excited state i ", &
     519           20 :             "====================================================================================="
     520              : 
     521              :          WRITE (rixs_unit, FMT="(T3,A)") &
     522           10 :             "w_0i (eV)            mu^x_0i (a.u.)  mu^y_0i (a.u.)  mu^z_0i (a.u.)  mu^2_0i (a.u.)"
     523          105 :          DO i = 1, rixs_control%core_states
     524              :             WRITE (rixs_unit, FMT="(T2,F10.4,T26,E12.5,T42,E12.5,T58,E12.5,T74,E12.5)") &
     525          105 :                w_i0(i), mu_i0(1, i), mu_i0(2, i), mu_i0(3, i), mu_i0(4, i)
     526              :          END DO
     527              : 
     528              :          WRITE (rixs_unit, FMT="(A,/,T2,A,/,A)") &
     529           10 :             "=====================================================================================", &
     530           10 :             "Emission from core-excited state i to valence-excited state f ", &
     531           20 :             "====================================================================================="
     532              : 
     533              :          WRITE (rixs_unit, FMT="(T3,A)") &
     534           10 :             "w_0i (eV) w_if (eV)  mu^x_if (a.u.)  mu^y_if (a.u.)  mu^z_if (a.u.)  mu^2_if (a.u.)"
     535              : 
     536          105 :          DO i = 1, rixs_control%core_states
     537          401 :             DO f = 1, rixs_control%valence_states
     538              :                WRITE (rixs_unit, FMT="(T2,F10.4,T14,F8.4,T26,E12.5,T42,E12.5,T58,E12.5,T74,E12.5)") &
     539          391 :                   w_i0(i), w_if(f), mu_if(1, i, f), mu_if(2, i, f), mu_if(3, i, f), mu_if(4, i, f)
     540              :             END DO
     541              :          END DO
     542              : 
     543              :       END IF
     544              : 
     545           20 :       CALL cp_print_key_finished_output(rixs_unit, logger, rixs_section, "PRINT%SPECTRUM")
     546              : 
     547           20 :    END SUBROUTINE print_rixs_to_file
     548              : 
     549              : END MODULE rixs_methods
        

Generated by: LCOV version 2.0-1