LCOV - code coverage report
Current view: top level - src - qs_tddfpt2_properties.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 92.3 % 625 577
Test Date: 2026-07-25 06:35:44 Functions: 75.0 % 8 6

            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              : MODULE qs_tddfpt2_properties
       9              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      10              :    USE bibliography,                    ONLY: Martin2003,&
      11              :                                               cite_reference
      12              :    USE bse_print,                       ONLY: print_exciton_descriptors
      13              :    USE bse_properties,                  ONLY: exciton_descr_type,&
      14              :                                               get_exciton_descriptors
      15              :    USE bse_util,                        ONLY: get_multipoles_mo
      16              :    USE cell_types,                      ONLY: cell_type
      17              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      18              :    USE cp_cfm_basic_linalg,             ONLY: cp_cfm_solve
      19              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      20              :                                               cp_cfm_release,&
      21              :                                               cp_cfm_set_all,&
      22              :                                               cp_cfm_to_fm,&
      23              :                                               cp_cfm_type,&
      24              :                                               cp_fm_to_cfm
      25              :    USE cp_control_types,                ONLY: dft_control_type,&
      26              :                                               tddfpt2_control_type
      27              :    USE cp_dbcsr_api,                    ONLY: &
      28              :         dbcsr_copy, dbcsr_get_block_p, dbcsr_get_info, dbcsr_init_p, dbcsr_iterator_blocks_left, &
      29              :         dbcsr_iterator_next_block, dbcsr_iterator_start, dbcsr_iterator_stop, dbcsr_iterator_type, &
      30              :         dbcsr_p_type, dbcsr_set, dbcsr_type
      31              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      32              :                                               copy_fm_to_dbcsr,&
      33              :                                               cp_dbcsr_sm_fm_multiply,&
      34              :                                               dbcsr_allocate_matrix_set,&
      35              :                                               dbcsr_deallocate_matrix_set
      36              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale,&
      37              :                                               cp_fm_scale_and_add,&
      38              :                                               cp_fm_trace
      39              :    USE cp_fm_diag,                      ONLY: choose_eigv_solver,&
      40              :                                               cp_fm_geeig
      41              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      42              :                                               cp_fm_struct_release,&
      43              :                                               cp_fm_struct_type
      44              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      45              :                                               cp_fm_get_info,&
      46              :                                               cp_fm_release,&
      47              :                                               cp_fm_set_all,&
      48              :                                               cp_fm_to_fm,&
      49              :                                               cp_fm_to_fm_submat_general,&
      50              :                                               cp_fm_type,&
      51              :                                               cp_fm_vectorsnorm
      52              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      53              :                                               cp_logger_get_default_io_unit,&
      54              :                                               cp_logger_type
      55              :    USE cp_output_handling,              ONLY: cp_p_file,&
      56              :                                               cp_print_key_finished_output,&
      57              :                                               cp_print_key_should_output,&
      58              :                                               cp_print_key_unit_nr
      59              :    USE cp_realspace_grid_cube,          ONLY: cp_pw_to_cube
      60              :    USE input_constants,                 ONLY: no_sf_tddfpt,&
      61              :                                               tddfpt_dipole_berry,&
      62              :                                               tddfpt_dipole_length,&
      63              :                                               tddfpt_dipole_scf_moment,&
      64              :                                               tddfpt_dipole_velocity,&
      65              :                                               tddfpt_dipole_velocity_old
      66              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      67              :                                               section_vals_type,&
      68              :                                               section_vals_val_get
      69              :    USE kinds,                           ONLY: default_path_length,&
      70              :                                               dp,&
      71              :                                               int_8
      72              :    USE mathconstants,                   ONLY: twopi,&
      73              :                                               z_one,&
      74              :                                               z_zero
      75              :    USE message_passing,                 ONLY: mp_comm_type,&
      76              :                                               mp_para_env_type,&
      77              :                                               mp_request_type
      78              :    USE molden_utils,                    ONLY: write_mos_molden
      79              :    USE moments_utils,                   ONLY: get_reference_point
      80              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      81              :    USE particle_list_types,             ONLY: particle_list_type
      82              :    USE particle_types,                  ONLY: particle_type
      83              :    USE physcon,                         ONLY: evolt
      84              :    USE pw_env_types,                    ONLY: pw_env_get,&
      85              :                                               pw_env_type
      86              :    USE pw_poisson_types,                ONLY: pw_poisson_type
      87              :    USE pw_pool_types,                   ONLY: pw_pool_p_type,&
      88              :                                               pw_pool_type
      89              :    USE pw_types,                        ONLY: pw_c1d_gs_type,&
      90              :                                               pw_r3d_rs_type
      91              :    USE qs_collocate_density,            ONLY: calculate_wavefunction
      92              :    USE qs_environment_types,            ONLY: get_qs_env,&
      93              :                                               qs_environment_type
      94              :    USE qs_kind_types,                   ONLY: qs_kind_type
      95              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      96              :    USE qs_mo_types,                     ONLY: allocate_mo_set,&
      97              :                                               deallocate_mo_set,&
      98              :                                               get_mo_set,&
      99              :                                               init_mo_set,&
     100              :                                               mo_set_type,&
     101              :                                               set_mo_set
     102              :    USE qs_moments,                      ONLY: build_berry_moment_matrix
     103              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
     104              :    USE qs_operators_ao,                 ONLY: rRc_xyz_ao
     105              :    USE qs_overlap,                      ONLY: build_overlap_matrix
     106              :    USE qs_subsys_types,                 ONLY: qs_subsys_get,&
     107              :                                               qs_subsys_type
     108              :    USE qs_tddfpt2_types,                ONLY: tddfpt_ground_state_mos
     109              :    USE string_utilities,                ONLY: integer_to_string
     110              :    USE util,                            ONLY: sort
     111              : #include "./base/base_uses.f90"
     112              : 
     113              :    IMPLICIT NONE
     114              : 
     115              :    PRIVATE
     116              : 
     117              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_properties'
     118              : 
     119              :    ! number of first derivative components (3: d/dx, d/dy, d/dz)
     120              :    INTEGER, PARAMETER, PRIVATE          :: nderivs = 3
     121              :    INTEGER, PARAMETER, PRIVATE          :: maxspins = 2
     122              : 
     123              :    PUBLIC :: tddfpt_dipole_operator, tddfpt_print_summary, tddfpt_print_excitation_analysis, &
     124              :              tddfpt_print_nto_analysis, tddfpt_print_exciton_descriptors
     125              : 
     126              : ! **************************************************************************************************
     127              : 
     128              : CONTAINS
     129              : 
     130              : ! **************************************************************************************************
     131              : !> \brief Compute the action of the dipole operator on the ground state wave function.
     132              : !> \param dipole_op_mos_occ  2-D array [x,y,z ; spin] of matrices where to put the computed quantity
     133              : !>                           (allocated and initialised on exit)
     134              : !> \param tddfpt_control     TDDFPT control parameters
     135              : !> \param gs_mos             molecular orbitals optimised for the ground state
     136              : !> \param qs_env             Quickstep environment
     137              : !> \par History
     138              : !>    * 05.2016 created as 'tddfpt_print_summary' [Sergey Chulkov]
     139              : !>    * 06.2018 dipole operator based on the Berry-phase formula [Sergey Chulkov]
     140              : !>    * 08.2018 splited of from 'tddfpt_print_summary' and merged with code from 'tddfpt'
     141              : !>              [Sergey Chulkov]
     142              : !> \note \parblock
     143              : !>       Adapted version of the subroutine find_contributions() which was originally created
     144              : !>       by Thomas Chassaing on 02.2005.
     145              : !>
     146              : !>       The relation between dipole integrals in velocity and length forms are the following:
     147              : !>       \f[<\psi_i|\nabla|\psi_a> = <\psi_i|\vec{r}|\hat{H}\psi_a> - <\hat{H}\psi_i|\vec{r}|\psi_a>
     148              : !>                                 = (\epsilon_a - \epsilon_i) <\psi_i|\vec{r}|\psi_a> .\f],
     149              : !>       due to the commutation identity:
     150              : !>       \f[\vec{r}\hat{H} - \hat{H}\vec{r} = [\vec{r},\hat{H}] = [\vec{r},-1/2 \nabla^2] = \nabla\f] .
     151              : !>       \endparblock
     152              : ! **************************************************************************************************
     153         1416 :    SUBROUTINE tddfpt_dipole_operator(dipole_op_mos_occ, tddfpt_control, gs_mos, qs_env)
     154              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :), &
     155              :          INTENT(inout)                                   :: dipole_op_mos_occ
     156              :       TYPE(tddfpt2_control_type), POINTER                :: tddfpt_control
     157              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     158              :          INTENT(in)                                      :: gs_mos
     159              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     160              : 
     161              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_dipole_operator'
     162              : 
     163              :       INTEGER                                            :: handle, i_cos_sin, icol, ideriv, irow, &
     164              :                                                             ispin, jderiv, nao, ncols_local, &
     165              :                                                             ndim_periodic, nrows_local, nspins
     166         1416 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     167              :       INTEGER, DIMENSION(maxspins)                       :: nmo_occ, nmo_virt
     168              :       REAL(kind=dp)                                      :: eval_occ
     169              :       REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
     170         1416 :          POINTER                                         :: local_data_ediff, local_data_wfm
     171              :       REAL(kind=dp), DIMENSION(3)                        :: kvec, reference_point
     172              :       TYPE(cell_type), POINTER                           :: cell
     173              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     174         1416 :       TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:)       :: gamma_00, gamma_inv_00
     175              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     176              :       TYPE(cp_fm_type)                                   :: ediff_inv, wfm_ao_ao, wfm_mo_virt_mo_occ
     177         1416 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: S_mos_virt
     178         1416 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: dBerry_mos_occ, gamma_real_imag, opvec
     179         1416 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: berry_cossin_xyz, matrix_s, rRc_xyz, scrm
     180              :       TYPE(dft_control_type), POINTER                    :: dft_control
     181              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     182         1416 :          POINTER                                         :: sab_orb
     183              :       TYPE(pw_env_type), POINTER                         :: pw_env
     184              :       TYPE(pw_poisson_type), POINTER                     :: poisson_env
     185              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     186              : 
     187         1416 :       CALL timeset(routineN, handle)
     188              : 
     189         1416 :       NULLIFY (blacs_env, cell, matrix_s, pw_env)
     190         1416 :       CALL get_qs_env(qs_env, blacs_env=blacs_env, cell=cell, matrix_s=matrix_s, pw_env=pw_env)
     191              : 
     192         1416 :       nspins = SIZE(gs_mos)
     193         1416 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
     194         3026 :       DO ispin = 1, nspins
     195         1610 :          nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
     196         3026 :          nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
     197              :       END DO
     198              : 
     199              :       ! +++ allocate dipole operator matrices (must be deallocated elsewhere)
     200        10688 :       ALLOCATE (dipole_op_mos_occ(nderivs, nspins))
     201         3026 :       DO ispin = 1, nspins
     202         1610 :          CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=fm_struct)
     203              : 
     204         7856 :          DO ideriv = 1, nderivs
     205         6440 :             CALL cp_fm_create(dipole_op_mos_occ(ideriv, ispin), fm_struct)
     206              :          END DO
     207              :       END DO
     208              : 
     209              :       ! +++ allocate work matrices
     210         5858 :       ALLOCATE (S_mos_virt(nspins))
     211         3026 :       DO ispin = 1, nspins
     212         1610 :          CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct)
     213         1610 :          CALL cp_fm_create(S_mos_virt(ispin), fm_struct)
     214              :          CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
     215              :                                       gs_mos(ispin)%mos_virt, &
     216              :                                       S_mos_virt(ispin), &
     217         3026 :                                       ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
     218              :       END DO
     219              : 
     220              :       ! check that the chosen dipole operator is consistent with the periodic boundary conditions used
     221         1416 :       CALL pw_env_get(pw_env, poisson_env=poisson_env)
     222         5664 :       ndim_periodic = COUNT(poisson_env%parameters%periodic == 1)
     223              : 
     224              :       ! select default for dipole form
     225         1416 :       IF (tddfpt_control%dipole_form == 0) THEN
     226          644 :          CALL get_qs_env(qs_env, dft_control=dft_control)
     227          644 :          IF (dft_control%qs_control%xtb) THEN
     228           44 :             IF (ndim_periodic == 0) THEN
     229            0 :                tddfpt_control%dipole_form = tddfpt_dipole_length
     230              :             ELSE
     231           44 :                tddfpt_control%dipole_form = tddfpt_dipole_velocity
     232              :             END IF
     233              :          ELSE
     234          600 :             tddfpt_control%dipole_form = tddfpt_dipole_velocity
     235              :          END IF
     236              :       END IF
     237              : 
     238         1420 :       SELECT CASE (tddfpt_control%dipole_form)
     239              :       CASE (tddfpt_dipole_berry)
     240            4 :          IF (ndim_periodic /= 3) THEN
     241              :             CALL cp_warn(__LOCATION__, &
     242              :                          "Fully periodic Poisson solver (PERIODIC xyz) "// &
     243              :                          "or a large supercell in non-periodic directions is needed "// &
     244            0 :                          "for oscillator strengths based on the Berry phase formula")
     245              :          END IF
     246              : 
     247            4 :          NULLIFY (berry_cossin_xyz)
     248              :          ! index: 1 = Re[exp(-i * G_t * t)],
     249              :          !        2 = Im[exp(-i * G_t * t)];
     250              :          ! t = x,y,z
     251            4 :          CALL dbcsr_allocate_matrix_set(berry_cossin_xyz, 2)
     252              : 
     253           12 :          DO i_cos_sin = 1, 2
     254            8 :             CALL dbcsr_init_p(berry_cossin_xyz(i_cos_sin)%matrix)
     255           12 :             CALL dbcsr_copy(berry_cossin_xyz(i_cos_sin)%matrix, matrix_s(1)%matrix)
     256              :          END DO
     257              : 
     258              :          ! +++ allocate berry-phase-related work matrices
     259           72 :          ALLOCATE (gamma_00(nspins), gamma_inv_00(nspins), gamma_real_imag(2, nspins), opvec(2, nspins))
     260           32 :          ALLOCATE (dBerry_mos_occ(nderivs, nspins))
     261           10 :          DO ispin = 1, nspins
     262            6 :             NULLIFY (fm_struct)
     263              :             CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_occ(ispin), &
     264            6 :                                      ncol_global=nmo_occ(ispin), context=blacs_env)
     265              : 
     266            6 :             CALL cp_cfm_create(gamma_00(ispin), fm_struct)
     267            6 :             CALL cp_cfm_create(gamma_inv_00(ispin), fm_struct)
     268              : 
     269           18 :             DO i_cos_sin = 1, 2
     270           18 :                CALL cp_fm_create(gamma_real_imag(i_cos_sin, ispin), fm_struct)
     271              :             END DO
     272            6 :             CALL cp_fm_struct_release(fm_struct)
     273              : 
     274              :             ! G_real C_0, G_imag C_0
     275            6 :             CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, matrix_struct=fm_struct)
     276           18 :             DO i_cos_sin = 1, 2
     277           18 :                CALL cp_fm_create(opvec(i_cos_sin, ispin), fm_struct)
     278              :             END DO
     279              : 
     280              :             ! dBerry * C_0
     281           28 :             DO ideriv = 1, nderivs
     282           18 :                CALL cp_fm_create(dBerry_mos_occ(ideriv, ispin), fm_struct)
     283           24 :                CALL cp_fm_set_all(dBerry_mos_occ(ideriv, ispin), 0.0_dp)
     284              :             END DO
     285              :          END DO
     286              : 
     287           16 :          DO ideriv = 1, nderivs
     288           48 :             kvec(:) = twopi*cell%h_inv(ideriv, :)
     289           36 :             DO i_cos_sin = 1, 2
     290           36 :                CALL dbcsr_set(berry_cossin_xyz(i_cos_sin)%matrix, 0.0_dp)
     291              :             END DO
     292              :             CALL build_berry_moment_matrix(qs_env, berry_cossin_xyz(1)%matrix, &
     293           12 :                                            berry_cossin_xyz(2)%matrix, kvec)
     294              : 
     295           34 :             DO ispin = 1, nspins
     296              :                ! i_cos_sin = 1: cos (real) component; opvec(1) = gamma_real C_0
     297              :                ! i_cos_sin = 2: sin (imaginary) component; opvec(2) = gamma_imag C_0
     298           54 :                DO i_cos_sin = 1, 2
     299              :                   CALL cp_dbcsr_sm_fm_multiply(berry_cossin_xyz(i_cos_sin)%matrix, &
     300              :                                                gs_mos(ispin)%mos_occ, &
     301              :                                                opvec(i_cos_sin, ispin), &
     302           54 :                                                ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
     303              :                END DO
     304              : 
     305              :                CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_occ(ispin), nao, &
     306              :                                   1.0_dp, gs_mos(ispin)%mos_occ, opvec(1, ispin), &
     307           18 :                                   0.0_dp, gamma_real_imag(1, ispin))
     308              : 
     309              :                CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_occ(ispin), nao, &
     310              :                                   -1.0_dp, gs_mos(ispin)%mos_occ, opvec(2, ispin), &
     311           18 :                                   0.0_dp, gamma_real_imag(2, ispin))
     312              : 
     313              :                CALL cp_fm_to_cfm(msourcer=gamma_real_imag(1, ispin), &
     314              :                                  msourcei=gamma_real_imag(2, ispin), &
     315           18 :                                  mtarget=gamma_00(ispin))
     316              : 
     317              :                ! gamma_inv_00 = Q = [C_0^T (gamma_real - i gamma_imag) C_0] ^ {-1}
     318           18 :                CALL cp_cfm_set_all(gamma_inv_00(ispin), z_zero, z_one)
     319           18 :                CALL cp_cfm_solve(gamma_00(ispin), gamma_inv_00(ispin))
     320              : 
     321              :                CALL cp_cfm_to_fm(msource=gamma_inv_00(ispin), &
     322              :                                  mtargetr=gamma_real_imag(1, ispin), &
     323           18 :                                  mtargeti=gamma_real_imag(2, ispin))
     324              : 
     325              :                ! dBerry_mos_occ is identical to dBerry_psi0 from qs_linres_op % polar_operators()
     326              :                CALL parallel_gemm("N", "N", nao, nmo_occ(ispin), nmo_occ(ispin), &
     327              :                                   1.0_dp, opvec(1, ispin), gamma_real_imag(2, ispin), &
     328           18 :                                   0.0_dp, dipole_op_mos_occ(1, ispin))
     329              :                CALL parallel_gemm("N", "N", nao, nmo_occ(ispin), nmo_occ(ispin), &
     330              :                                   -1.0_dp, opvec(2, ispin), gamma_real_imag(1, ispin), &
     331           18 :                                   1.0_dp, dipole_op_mos_occ(1, ispin))
     332              : 
     333           84 :                DO jderiv = 1, nderivs
     334              :                   CALL cp_fm_scale_and_add(1.0_dp, dBerry_mos_occ(jderiv, ispin), &
     335           72 :                                            cell%hmat(jderiv, ideriv), dipole_op_mos_occ(1, ispin))
     336              :                END DO
     337              :             END DO
     338              :          END DO
     339              : 
     340              :          ! --- release berry-phase-related work matrices
     341            4 :          CALL cp_fm_release(opvec)
     342            4 :          CALL cp_fm_release(gamma_real_imag)
     343           10 :          DO ispin = nspins, 1, -1
     344            6 :             CALL cp_cfm_release(gamma_inv_00(ispin))
     345           10 :             CALL cp_cfm_release(gamma_00(ispin))
     346              :          END DO
     347            4 :          DEALLOCATE (gamma_00, gamma_inv_00)
     348            4 :          CALL dbcsr_deallocate_matrix_set(berry_cossin_xyz)
     349              : 
     350              :          ! trans_dipole = 2|e|/|G_mu| * Tr Imag(evects^T * (gamma_real - i gamma_imag) * C_0 * gamma_inv_00) +
     351              :          !                2|e|/|G_mu| * Tr Imag(C_0^T * (gamma_real - i gamma_imag) * evects * gamma_inv_00) ,
     352              :          !
     353              :          ! Taking into account the symmetry of the matrices 'gamma_real' and 'gamma_imag' and the fact
     354              :          ! that the response wave-function is a real-valued function, the above expression can be simplified as
     355              :          ! trans_dipole = 4|e|/|G_mu| * Tr Imag(evects^T * (gamma_real - i gamma_imag) * C_0 * gamma_inv_00)
     356              :          !
     357              :          ! 1/|G_mu| = |lattice_vector_mu| / (2*pi) .
     358           10 :          DO ispin = 1, nspins
     359              : 
     360           28 :             DO ideriv = 1, nderivs
     361           24 :                CALL cp_fm_to_fm(dBerry_mos_occ(ideriv, ispin), dipole_op_mos_occ(ideriv, ispin))
     362              :             END DO
     363              :          END DO
     364              : 
     365            4 :          CALL cp_fm_release(wfm_ao_ao)
     366            4 :          CALL cp_fm_release(dBerry_mos_occ)
     367              : 
     368              :       CASE (tddfpt_dipole_length)
     369           20 :          IF (ndim_periodic /= 0) THEN
     370              :             CALL cp_warn(__LOCATION__, &
     371              :                          "Non-periodic Poisson solver (PERIODIC none) "// &
     372              :                          "or a large supercell approach is needed "// &
     373            4 :                          "for oscillator strengths based on the length operator")
     374              :          END IF
     375              : 
     376              :          ! compute components of the dipole operator in the length form
     377           20 :          NULLIFY (rRc_xyz)
     378           20 :          CALL dbcsr_allocate_matrix_set(rRc_xyz, nderivs)
     379              : 
     380           80 :          DO ideriv = 1, nderivs
     381           60 :             CALL dbcsr_init_p(rRc_xyz(ideriv)%matrix)
     382           80 :             CALL dbcsr_copy(rRc_xyz(ideriv)%matrix, matrix_s(1)%matrix)
     383              :          END DO
     384              : 
     385              :          CALL get_reference_point(reference_point, qs_env=qs_env, &
     386              :                                   reference=tddfpt_control%dipole_reference, &
     387           20 :                                   ref_point=tddfpt_control%dipole_ref_point)
     388              : 
     389              :          CALL rRc_xyz_ao(op=rRc_xyz, qs_env=qs_env, rc=reference_point, order=1, &
     390           20 :                          minimum_image=.FALSE., soft=.FALSE.)
     391              : 
     392           42 :          DO ispin = 1, nspins
     393              : 
     394          108 :             DO ideriv = 1, nderivs
     395              :                CALL cp_dbcsr_sm_fm_multiply(rRc_xyz(ideriv)%matrix, &
     396              :                                             gs_mos(ispin)%mos_occ, &
     397              :                                             dipole_op_mos_occ(ideriv, ispin), &
     398           88 :                                             ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
     399              :             END DO
     400              : 
     401              :          END DO
     402              : 
     403           20 :          CALL dbcsr_deallocate_matrix_set(rRc_xyz)
     404              : 
     405              :       CASE (tddfpt_dipole_velocity)
     406              :          ! generate overlap derivatives
     407         1388 :          CALL get_qs_env(qs_env, ks_env=ks_env, sab_orb=sab_orb)
     408         1388 :          NULLIFY (scrm)
     409              :          CALL build_overlap_matrix(ks_env, matrix_s=scrm, nderivative=1, &
     410              :                                    basis_type_a="ORB", basis_type_b="ORB", &
     411         1388 :                                    sab_nl=sab_orb)
     412              : 
     413         2964 :          DO ispin = 1, nspins
     414         6304 :             DO ideriv = 1, nderivs
     415              :                CALL cp_dbcsr_sm_fm_multiply(scrm(ideriv + 1)%matrix, &
     416              :                                             gs_mos(ispin)%mos_occ, &
     417              :                                             dipole_op_mos_occ(ideriv, ispin), &
     418         6304 :                                             ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
     419              :             END DO
     420              : 
     421         2964 :             CALL cp_fm_release(wfm_mo_virt_mo_occ)
     422              :          END DO
     423         1388 :          CALL dbcsr_deallocate_matrix_set(scrm)
     424              : 
     425              :       CASE (tddfpt_dipole_velocity_old)
     426              :          ! generate overlap derivatives
     427            4 :          CALL get_qs_env(qs_env, ks_env=ks_env, sab_orb=sab_orb)
     428            4 :          NULLIFY (scrm)
     429              :          CALL build_overlap_matrix(ks_env, matrix_s=scrm, nderivative=1, &
     430              :                                    basis_type_a="ORB", basis_type_b="ORB", &
     431            4 :                                    sab_nl=sab_orb)
     432              : 
     433           10 :          DO ispin = 1, nspins
     434            6 :             NULLIFY (fm_struct)
     435              :             CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_virt(ispin), &
     436            6 :                                      ncol_global=nmo_occ(ispin), context=blacs_env)
     437            6 :             CALL cp_fm_create(ediff_inv, fm_struct)
     438            6 :             CALL cp_fm_create(wfm_mo_virt_mo_occ, fm_struct)
     439            6 :             CALL cp_fm_struct_release(fm_struct)
     440              : 
     441              :             CALL cp_fm_get_info(ediff_inv, nrow_local=nrows_local, ncol_local=ncols_local, &
     442            6 :                                 row_indices=row_indices, col_indices=col_indices, local_data=local_data_ediff)
     443            6 :             CALL cp_fm_get_info(wfm_mo_virt_mo_occ, local_data=local_data_wfm)
     444              : 
     445              : !$OMP       PARALLEL DO DEFAULT(NONE), &
     446              : !$OMP                PRIVATE(eval_occ, icol, irow), &
     447            6 : !$OMP                SHARED(col_indices, gs_mos, ispin, local_data_ediff, ncols_local, nrows_local, row_indices)
     448              :             DO icol = 1, ncols_local
     449              :                ! E_occ_i ; imo_occ = col_indices(icol)
     450              :                eval_occ = gs_mos(ispin)%evals_occ(col_indices(icol))
     451              : 
     452              :                DO irow = 1, nrows_local
     453              :                   ! ediff_inv_weights(a, i) = 1.0 / (E_virt_a - E_occ_i)
     454              :                   ! imo_virt = row_indices(irow)
     455              :                   local_data_ediff(irow, icol) = 1.0_dp/(gs_mos(ispin)%evals_virt(row_indices(irow)) - eval_occ)
     456              :                END DO
     457              :             END DO
     458              : !$OMP       END PARALLEL DO
     459              : 
     460           24 :             DO ideriv = 1, nderivs
     461              :                CALL cp_dbcsr_sm_fm_multiply(scrm(ideriv + 1)%matrix, &
     462              :                                             gs_mos(ispin)%mos_occ, &
     463              :                                             dipole_op_mos_occ(ideriv, ispin), &
     464           18 :                                             ncol=nmo_occ(ispin), alpha=1.0_dp, beta=0.0_dp)
     465              : 
     466              :                CALL parallel_gemm('T', 'N', nmo_virt(ispin), nmo_occ(ispin), nao, &
     467              :                                   1.0_dp, gs_mos(ispin)%mos_virt, dipole_op_mos_occ(ideriv, ispin), &
     468           18 :                                   0.0_dp, wfm_mo_virt_mo_occ)
     469              : 
     470              :                ! in-place element-wise (Schur) product;
     471              :                ! avoid allocation of a temporary [nmo_virt x nmo_occ] matrix which is needed
     472              :                ! for cp_fm_schur_product() subroutine call
     473              : 
     474              : !$OMP          PARALLEL DO DEFAULT(NONE), &
     475              : !$OMP                   PRIVATE(icol, irow), &
     476           18 : !$OMP                   SHARED(ispin, local_data_ediff, local_data_wfm, ncols_local, nrows_local)
     477              :                DO icol = 1, ncols_local
     478              :                   DO irow = 1, nrows_local
     479              :                      local_data_wfm(irow, icol) = local_data_wfm(irow, icol)*local_data_ediff(irow, icol)
     480              :                   END DO
     481              :                END DO
     482              : !$OMP          END PARALLEL DO
     483              : 
     484              :                CALL parallel_gemm('N', 'N', nao, nmo_occ(ispin), nmo_virt(ispin), &
     485              :                                   1.0_dp, S_mos_virt(ispin), wfm_mo_virt_mo_occ, &
     486           24 :                                   0.0_dp, dipole_op_mos_occ(ideriv, ispin))
     487              :             END DO
     488              : 
     489            6 :             CALL cp_fm_release(wfm_mo_virt_mo_occ)
     490           22 :             CALL cp_fm_release(ediff_inv)
     491              :          END DO
     492            4 :          CALL dbcsr_deallocate_matrix_set(scrm)
     493              : 
     494              :       CASE DEFAULT
     495         1416 :          CPABORT("Unimplemented form of the dipole operator")
     496              :       END SELECT
     497              : 
     498              :       ! --- release work matrices
     499         1416 :       CALL cp_fm_release(S_mos_virt)
     500              : 
     501         1416 :       CALL timestop(handle)
     502         4248 :    END SUBROUTINE tddfpt_dipole_operator
     503              : 
     504              : ! **************************************************************************************************
     505              : !> \brief Print final TDDFPT excitation energies and oscillator strengths.
     506              : !> \param log_unit           output unit
     507              : !> \param evects             TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
     508              : !>                           SIZE(evects,2) -- number of excited states to print)
     509              : !> \param evals              TDDFPT eigenvalues
     510              : !> \param gs_mos ...
     511              : !> \param ostrength          TDDFPT oscillator strength
     512              : !> \param mult               multiplicity
     513              : !> \param dipole_op_mos_occ  action of the dipole operator on the ground state wave function
     514              : !>                           [x,y,z ; spin]
     515              : !> \param dipole_form ...
     516              : !> \par History
     517              : !>    * 05.2016 created [Sergey Chulkov]
     518              : !>    * 06.2016 transition dipole moments and oscillator strengths [Sergey Chulkov]
     519              : !>    * 07.2016 spin-unpolarised electron density [Sergey Chulkov]
     520              : !>    * 08.2018 compute 'dipole_op_mos_occ' in a separate subroutine [Sergey Chulkov]
     521              : !> \note \parblock
     522              : !>       Adapted version of the subroutine find_contributions() which was originally created
     523              : !>       by Thomas Chassaing on 02.2005.
     524              : !>
     525              : !>       Transition dipole moment along direction 'd' is computed as following:
     526              : !>       \f[ t_d(spin) = Tr[evects^T dipole\_op\_mos\_occ(d, spin)] .\f]
     527              : !>       \endparblock
     528              : ! **************************************************************************************************
     529         2852 :    SUBROUTINE tddfpt_print_summary(log_unit, evects, evals, gs_mos, ostrength, mult, &
     530         1426 :                                    dipole_op_mos_occ, dipole_form)
     531              :       INTEGER, INTENT(in)                                :: log_unit
     532              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in)      :: evects
     533              :       REAL(kind=dp), DIMENSION(:), INTENT(in)            :: evals
     534              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     535              :          POINTER                                         :: gs_mos
     536              :       REAL(kind=dp), DIMENSION(:), INTENT(inout)         :: ostrength
     537              :       INTEGER, INTENT(in)                                :: mult
     538              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in)      :: dipole_op_mos_occ
     539              :       INTEGER, INTENT(in)                                :: dipole_form
     540              : 
     541              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_print_summary'
     542              : 
     543              :       CHARACTER(len=1)                                   :: lsd_str
     544              :       CHARACTER(len=20)                                  :: mult_str
     545              :       INTEGER                                            :: handle, i, ideriv, ispin, istate, j, &
     546              :                                                             nactive, nao, nocc, nspins, nstates
     547              :       REAL(kind=dp)                                      :: osc_strength
     548         1426 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :)     :: trans_dipoles
     549              :       TYPE(cp_fm_struct_type), POINTER                   :: matrix_struct
     550              :       TYPE(cp_fm_type)                                   :: dipact
     551              : 
     552         1426 :       CALL timeset(routineN, handle)
     553              : 
     554         1426 :       nspins = SIZE(evects, 1)
     555         1426 :       nstates = SIZE(evects, 2)
     556              : 
     557         1426 :       IF (nspins > 1) THEN
     558          172 :          lsd_str = 'U'
     559              :       ELSE
     560         1254 :          lsd_str = 'R'
     561              :       END IF
     562              : 
     563              :       ! *** summary header ***
     564         1426 :       IF (log_unit > 0) THEN
     565          713 :          CALL integer_to_string(mult, mult_str)
     566          713 :          WRITE (log_unit, '(/,1X,A1,A,1X,A)') lsd_str, "-TDDFPT states of multiplicity", TRIM(mult_str)
     567          715 :          SELECT CASE (dipole_form)
     568              :          CASE (tddfpt_dipole_berry)
     569            2 :             WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using Berry operator formulation"
     570              :          CASE (tddfpt_dipole_length)
     571           14 :             WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using length formulation"
     572              :          CASE (tddfpt_dipole_velocity)
     573          695 :             WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using velocity formulation"
     574              :          CASE (tddfpt_dipole_velocity_old)
     575            2 :             WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using old velocity formulation"
     576              :          CASE (tddfpt_dipole_scf_moment)
     577            0 :             WRITE (log_unit, '(1X,A,/)') "Transition dipoles calculated using SCF-MO moment formulation"
     578              :          CASE DEFAULT
     579          713 :             CPABORT("Unimplemented form of the dipole operator")
     580              :          END SELECT
     581              : 
     582          713 :          WRITE (log_unit, '(T10,A,T19,A,T37,A,T69,A)') "State", "Excitation", &
     583         1426 :             "Transition dipole (a.u.)", "Oscillator"
     584          713 :          WRITE (log_unit, '(T10,A,T19,A,T37,A,T49,A,T61,A,T67,A)') "number", "energy (eV)", &
     585         1426 :             "x", "y", "z", "strength (a.u.)"
     586          713 :          WRITE (log_unit, '(T10,72("-"))')
     587              :       END IF
     588              : 
     589              :       ! transition dipole moment
     590         5704 :       ALLOCATE (trans_dipoles(nstates, nderivs, nspins))
     591         1426 :       trans_dipoles(:, :, :) = 0.0_dp
     592              : 
     593              :       ! nspins == 1 .AND. mult == 3 : spin-flip transitions are forbidden due to symmetry reasons
     594         1426 :       IF (nspins > 1 .OR. mult == 1) THEN
     595         2568 :          DO ispin = 1, nspins
     596         1370 :             CALL cp_fm_get_info(dipole_op_mos_occ(1, ispin), nrow_global=nao, ncol_global=nocc)
     597         1370 :             CALL cp_fm_get_info(evects(ispin, 1), ncol_global=nactive)
     598         2568 :             IF (nocc == nactive) THEN
     599         5416 :                DO ideriv = 1, nderivs
     600              :                   CALL cp_fm_trace(evects(ispin, :), dipole_op_mos_occ(ideriv, ispin), &
     601         5416 :                                    trans_dipoles(:, ideriv, ispin))
     602              :                END DO
     603              :             ELSE ! res
     604           16 :                CALL cp_fm_get_info(evects(ispin, 1), matrix_struct=matrix_struct)
     605           16 :                CALL cp_fm_create(dipact, matrix_struct)
     606           64 :                DO ideriv = 1, nderivs
     607          144 :                   DO i = 1, nactive
     608           96 :                      j = gs_mos(ispin)%index_active(i)
     609              :                      CALL cp_fm_to_fm(dipole_op_mos_occ(ideriv, ispin), dipact, &
     610          144 :                                       ncol=1, source_start=j, target_start=i)
     611              :                   END DO
     612           64 :                   CALL cp_fm_trace(evects(ispin, :), dipact, trans_dipoles(:, ideriv, ispin))
     613              :                END DO
     614           16 :                CALL cp_fm_release(dipact)
     615              :             END IF
     616              :          END DO
     617              : 
     618         1198 :          IF (nspins == 1) THEN
     619        11040 :             trans_dipoles(:, :, 1) = SQRT(2.0_dp)*trans_dipoles(:, :, 1)
     620              :          ELSE
     621         2500 :             trans_dipoles(:, :, 1) = trans_dipoles(:, :, 1) + trans_dipoles(:, :, 2)
     622              :          END IF
     623              :       END IF
     624              : 
     625              :       ! *** summary information ***
     626         5080 :       DO istate = 1, nstates
     627              : 
     628         3666 :          SELECT CASE (dipole_form)
     629              :          CASE (tddfpt_dipole_berry)
     630           48 :             osc_strength = 2.0_dp/3.0_dp*evals(istate)*SUM(trans_dipoles(istate, :, 1)**2)
     631              :          CASE (tddfpt_dipole_length)
     632          416 :             osc_strength = 2.0_dp/3.0_dp*evals(istate)*SUM(trans_dipoles(istate, :, 1)**2)
     633              :          CASE (tddfpt_dipole_velocity)
     634        14104 :             osc_strength = 2.0_dp/3.0_dp/evals(istate)*SUM(trans_dipoles(istate, :, 1)**2)
     635              :          CASE (tddfpt_dipole_velocity_old)
     636           48 :             osc_strength = 2.0_dp/3.0_dp*evals(istate)*SUM(trans_dipoles(istate, :, 1)**2)
     637              :          CASE DEFAULT
     638         3654 :             CPABORT("Unimplemented form of the dipole operator")
     639              :          END SELECT
     640              : 
     641         3654 :          ostrength(istate) = osc_strength
     642         5080 :          IF (log_unit > 0) THEN
     643              :             WRITE (log_unit, '(1X,A,T9,I7,T19,F11.5,T31,3(1X,ES11.4E2),T69,ES12.5E2)') &
     644         1827 :                "TDDFPT|", istate, evals(istate)*evolt, trans_dipoles(istate, 1:nderivs, 1), osc_strength
     645              :          END IF
     646              :       END DO
     647              : 
     648              :       ! punch a checksum for the regs
     649         1426 :       IF (log_unit > 0) THEN
     650         2540 :          WRITE (log_unit, '(/,T2,A,E16.8)') 'TDDFPT : CheckSum E = ', SQRT(SUM(evals**2))
     651         2540 :          WRITE (log_unit, '(/,T2,A,E16.8)') 'TDDFPT : CheckSum F = ', SQRT(SUM(ostrength**2))
     652              :       END IF
     653              : 
     654         1426 :       DEALLOCATE (trans_dipoles)
     655              : 
     656         1426 :       CALL timestop(handle)
     657         1426 :    END SUBROUTINE tddfpt_print_summary
     658              : 
     659              : ! **************************************************************************************************
     660              : !> \brief Print excitation analysis.
     661              : !> \param log_unit           output unit
     662              : !> \param evects             TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
     663              : !>                           SIZE(evects,2) -- number of excited states to print)
     664              : !> \param evals              TDDFPT eigenvalues
     665              : !> \param gs_mos             molecular orbitals optimised for the ground state
     666              : !> \param matrix_s           overlap matrix
     667              : !> \param spinflip ...
     668              : !> \param min_amplitude      the smallest excitation amplitude to print
     669              : !> \par History
     670              : !>    * 05.2016 created as 'tddfpt_print_summary' [Sergey Chulkov]
     671              : !>    * 08.2018 splited of from 'tddfpt_print_summary' [Sergey Chulkov]
     672              : ! **************************************************************************************************
     673         1426 :    SUBROUTINE tddfpt_print_excitation_analysis(log_unit, evects, evals, gs_mos, matrix_s, spinflip, &
     674              :                                                min_amplitude)
     675              :       INTEGER, INTENT(in)                                :: log_unit
     676              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in)      :: evects
     677              :       REAL(kind=dp), DIMENSION(:), INTENT(in)            :: evals
     678              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     679              :          INTENT(in)                                      :: gs_mos
     680              :       TYPE(dbcsr_type), POINTER                          :: matrix_s
     681              :       INTEGER                                            :: spinflip
     682              :       REAL(kind=dp), INTENT(in)                          :: min_amplitude
     683              : 
     684              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_print_excitation_analysis'
     685              : 
     686              :       CHARACTER(len=5)                                   :: spin_label, spin_label2
     687              :       INTEGER                                            :: handle, icol, iproc, irow, ispin, &
     688              :                                                             istate, nao, ncols_local, nrows_local, &
     689              :                                                             nspins, nstates, spin2, state_spin, &
     690              :                                                             state_spin2
     691              :       INTEGER(kind=int_8)                                :: iexc, imo_act, imo_occ, imo_virt, ind, &
     692              :                                                             nexcs, nexcs_local, nexcs_max_local, &
     693              :                                                             nmo_virt_occ, nmo_virt_occ_alpha
     694         1426 :       INTEGER(kind=int_8), ALLOCATABLE, DIMENSION(:)     :: inds_local, inds_recv, nexcs_recv
     695              :       INTEGER(kind=int_8), DIMENSION(1)                  :: nexcs_send
     696              :       INTEGER(kind=int_8), DIMENSION(maxspins)           :: nactive8, nmo_occ8, nmo_virt8
     697         1426 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: inds
     698         1426 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     699              :       INTEGER, DIMENSION(maxspins)                       :: nactive, nmo_occ, nmo_virt
     700              :       LOGICAL                                            :: do_exc_analysis
     701         1426 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:)           :: weights_local, weights_neg_abs_recv, &
     702         1426 :                                                             weights_recv
     703              :       REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
     704         1426 :          POINTER                                         :: local_data
     705              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     706              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
     707         1426 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: S_mos_virt, weights_fm
     708              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     709              :       TYPE(mp_request_type)                              :: send_handler, send_handler2
     710         1426 :       TYPE(mp_request_type), ALLOCATABLE, DIMENSION(:)   :: recv_handlers, recv_handlers2
     711              : 
     712         1426 :       CALL timeset(routineN, handle)
     713              : 
     714         1426 :       nspins = SIZE(gs_mos, 1)
     715         1426 :       nstates = SIZE(evects, 2)
     716         1426 :       do_exc_analysis = min_amplitude < 1.0_dp
     717              : 
     718         1426 :       CALL cp_fm_get_info(gs_mos(1)%mos_occ, context=blacs_env, para_env=para_env)
     719         1426 :       CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
     720              : 
     721         3046 :       DO ispin = 1, nspins
     722         1620 :          nactive(ispin) = gs_mos(ispin)%nmo_active
     723              :          nactive8(ispin) = INT(nactive(ispin), kind=int_8)
     724         1620 :          nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
     725         1620 :          nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
     726         1620 :          nmo_occ8(ispin) = SIZE(gs_mos(ispin)%evals_occ, kind=int_8)
     727         3046 :          nmo_virt8(ispin) = SIZE(gs_mos(ispin)%evals_virt, kind=int_8)
     728              :       END DO
     729              : 
     730              :       ! *** excitation analysis ***
     731         1426 :       IF (do_exc_analysis) THEN
     732         1426 :          CPASSERT(log_unit <= 0 .OR. para_env%is_source())
     733         1426 :          nmo_virt_occ_alpha = INT(nmo_virt(1), int_8)*INT(nmo_occ(1), int_8)
     734              : 
     735         1426 :          IF (log_unit > 0) THEN
     736          713 :             WRITE (log_unit, "(1X,A)") "", &
     737          713 :                "-------------------------------------------------------------------------------", &
     738          713 :                "-                            Excitation analysis                              -", &
     739         1426 :                "-------------------------------------------------------------------------------"
     740          713 :             WRITE (log_unit, '(8X,A,T27,A,T49,A,T69,A)') "State", "Occupied", "Virtual", "Excitation"
     741          713 :             WRITE (log_unit, '(8X,A,T28,A,T49,A,T69,A)') "number", "orbital", "orbital", "amplitude"
     742          713 :             WRITE (log_unit, '(1X,79("-"))')
     743              : 
     744          713 :             IF (nspins == 1) THEN
     745          616 :                state_spin = 1
     746          616 :                state_spin2 = 2
     747          616 :                spin_label = '     '
     748          616 :                spin_label2 = '     '
     749           97 :             ELSE IF (spinflip /= no_sf_tddfpt) THEN
     750           11 :                state_spin = 1
     751           11 :                state_spin2 = 2
     752           11 :                spin_label = '(alp)'
     753           11 :                spin_label2 = '(bet)'
     754              :             END IF
     755              :          END IF
     756              : 
     757         8900 :          ALLOCATE (S_mos_virt(SIZE(evects, 1)), weights_fm(SIZE(evects, 1)))
     758         3024 :          DO ispin = 1, SIZE(evects, 1)
     759         1598 :             IF (spinflip == no_sf_tddfpt) THEN
     760              :                spin2 = ispin
     761              :             ELSE
     762           22 :                spin2 = 2
     763              :             END IF
     764         1598 :             CALL cp_fm_get_info(gs_mos(spin2)%mos_virt, matrix_struct=fm_struct)
     765         1598 :             CALL cp_fm_create(S_mos_virt(ispin), fm_struct)
     766              :             CALL cp_dbcsr_sm_fm_multiply(matrix_s, &
     767              :                                          gs_mos(spin2)%mos_virt, &
     768              :                                          S_mos_virt(ispin), &
     769         1598 :                                          ncol=nmo_virt(spin2), alpha=1.0_dp, beta=0.0_dp)
     770              : 
     771         1598 :             NULLIFY (fm_struct)
     772              :             CALL cp_fm_struct_create(fm_struct, nrow_global=nmo_virt(spin2), ncol_global=nactive(ispin), &
     773         1598 :                                      context=blacs_env)
     774         1598 :             CALL cp_fm_create(weights_fm(ispin), fm_struct)
     775         1598 :             CALL cp_fm_set_all(weights_fm(ispin), 0.0_dp)
     776         3024 :             CALL cp_fm_struct_release(fm_struct)
     777              :          END DO
     778              : 
     779         3024 :          nexcs_max_local = 0
     780         3024 :          DO ispin = 1, SIZE(evects, 1)
     781         1598 :             CALL cp_fm_get_info(weights_fm(ispin), nrow_local=nrows_local, ncol_local=ncols_local)
     782         3024 :             nexcs_max_local = nexcs_max_local + INT(nrows_local, int_8)*INT(ncols_local, int_8)
     783              :          END DO
     784              : 
     785         5704 :          ALLOCATE (weights_local(nexcs_max_local), inds_local(nexcs_max_local))
     786              : 
     787         5080 :          DO istate = 1, nstates
     788         7912 :             nexcs_local = 0
     789         7912 :             nmo_virt_occ = 0
     790              : 
     791              :             ! analyse matrix elements locally and transfer only significant
     792              :             ! excitations to the master node for subsequent ordering
     793         7912 :             DO ispin = 1, SIZE(evects, 1)
     794         4258 :                IF (spinflip == no_sf_tddfpt) THEN
     795              :                   spin2 = ispin
     796              :                ELSE
     797           90 :                   spin2 = 2
     798              :                END IF
     799              :                ! compute excitation amplitudes
     800              :                CALL parallel_gemm('T', 'N', nmo_virt(spin2), nactive(ispin), nao, 1.0_dp, S_mos_virt(ispin), &
     801         4258 :                                   evects(ispin, istate), 0.0_dp, weights_fm(ispin))
     802              : 
     803              :                CALL cp_fm_get_info(weights_fm(ispin), nrow_local=nrows_local, ncol_local=ncols_local, &
     804         4258 :                                    row_indices=row_indices, col_indices=col_indices, local_data=local_data)
     805              : 
     806              :                ! locate single excitations with significant amplitudes (>= min_amplitude)
     807        23404 :                DO icol = 1, ncols_local
     808       237641 :                   DO irow = 1, nrows_local
     809       233383 :                      IF (ABS(local_data(irow, icol)) >= min_amplitude) THEN
     810              :                         ! number of non-negligible excitations
     811         2925 :                         nexcs_local = nexcs_local + 1
     812              :                         ! excitation amplitude
     813         2925 :                         weights_local(nexcs_local) = local_data(irow, icol)
     814              :                         ! index of single excitation (ivirt, iocc, ispin) in compressed form
     815              :                         inds_local(nexcs_local) = nmo_virt_occ + INT(row_indices(irow), int_8) + &
     816         2925 :                                                   INT(col_indices(icol) - 1, int_8)*nmo_virt8(spin2)
     817              :                      END IF
     818              :                   END DO
     819              :                END DO
     820              : 
     821        12170 :                nmo_virt_occ = nmo_virt_occ + nmo_virt8(spin2)*nmo_occ8(ispin)
     822              :             END DO
     823              : 
     824         3654 :             IF (para_env%is_source()) THEN
     825              :                ! master node
     826        18270 :                ALLOCATE (nexcs_recv(para_env%num_pe), recv_handlers(para_env%num_pe), recv_handlers2(para_env%num_pe))
     827              : 
     828              :                ! collect number of non-negligible excitations from other nodes
     829         5481 :                DO iproc = 1, para_env%num_pe
     830         5481 :                   IF (iproc - 1 /= para_env%mepos) THEN
     831         1827 :                      CALL para_env%irecv(nexcs_recv(iproc:iproc), iproc - 1, recv_handlers(iproc), 0)
     832              :                   ELSE
     833         1827 :                      nexcs_recv(iproc) = nexcs_local
     834              :                   END IF
     835              :                END DO
     836              : 
     837         5481 :                DO iproc = 1, para_env%num_pe
     838         5481 :                   IF (iproc - 1 /= para_env%mepos) THEN
     839         1827 :                      CALL recv_handlers(iproc)%wait()
     840              :                   END IF
     841              :                END DO
     842              : 
     843              :                ! compute total number of non-negligible excitations
     844         1827 :                nexcs = 0
     845         5481 :                DO iproc = 1, para_env%num_pe
     846         5481 :                   nexcs = nexcs + nexcs_recv(iproc)
     847              :                END DO
     848              : 
     849              :                ! receive indices and amplitudes of selected excitations
     850         7308 :                ALLOCATE (weights_recv(nexcs), weights_neg_abs_recv(nexcs))
     851         7308 :                ALLOCATE (inds_recv(nexcs), inds(nexcs))
     852              : 
     853         5481 :                nmo_virt_occ = 0
     854         5481 :                DO iproc = 1, para_env%num_pe
     855         5481 :                   IF (nexcs_recv(iproc) > 0) THEN
     856         1915 :                      IF (iproc - 1 /= para_env%mepos) THEN
     857              :                         ! excitation amplitudes
     858              :                         CALL para_env%irecv(weights_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)), &
     859          253 :                                             iproc - 1, recv_handlers(iproc), 1)
     860              :                         ! compressed indices
     861              :                         CALL para_env%irecv(inds_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)), &
     862          253 :                                             iproc - 1, recv_handlers2(iproc), 2)
     863              :                      ELSE
     864              :                         ! data on master node
     865         4294 :                         weights_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)) = weights_local(1:nexcs_recv(iproc))
     866         4294 :                         inds_recv(nmo_virt_occ + 1:nmo_virt_occ + nexcs_recv(iproc)) = inds_local(1:nexcs_recv(iproc))
     867              :                      END IF
     868              : 
     869         1915 :                      nmo_virt_occ = nmo_virt_occ + nexcs_recv(iproc)
     870              :                   END IF
     871              :                END DO
     872              : 
     873         5481 :                DO iproc = 1, para_env%num_pe
     874         5481 :                   IF (iproc - 1 /= para_env%mepos .AND. nexcs_recv(iproc) > 0) THEN
     875          253 :                      CALL recv_handlers(iproc)%wait()
     876          253 :                      CALL recv_handlers2(iproc)%wait()
     877              :                   END IF
     878              :                END DO
     879              : 
     880         1827 :                DEALLOCATE (nexcs_recv, recv_handlers, recv_handlers2)
     881              :             ELSE
     882              :                ! working node: send the number of selected excited states to the master node
     883         1827 :                nexcs_send(1) = nexcs_local
     884         1827 :                CALL para_env%isend(nexcs_send, para_env%source, send_handler, 0)
     885         1827 :                CALL send_handler%wait()
     886              : 
     887         1827 :                IF (nexcs_local > 0) THEN
     888              :                   ! send excitation amplitudes
     889          253 :                   CALL para_env%isend(weights_local(1:nexcs_local), para_env%source, send_handler, 1)
     890              :                   ! send compressed indices
     891          253 :                   CALL para_env%isend(inds_local(1:nexcs_local), para_env%source, send_handler2, 2)
     892              : 
     893          253 :                   CALL send_handler%wait()
     894          253 :                   CALL send_handler2%wait()
     895              :                END IF
     896              :             END IF
     897              : 
     898              :             ! sort non-negligible excitations on the master node according to their amplitudes,
     899              :             ! uncompress indices and print summary information
     900         3654 :             IF (para_env%is_source() .AND. log_unit > 0) THEN
     901         4752 :                weights_neg_abs_recv(:) = -ABS(weights_recv)
     902         1827 :                CALL sort(weights_neg_abs_recv, INT(nexcs), inds)
     903              : 
     904         1827 :                WRITE (log_unit, '(T7,I8,F10.5,A)') istate, evals(istate)*evolt, " eV"
     905              : 
     906              :                ! This reinitialization is needed to prevent the intel fortran compiler from introduce
     907              :                ! a bug when using optimization level 3 flag
     908         1827 :                state_spin = 1
     909         1827 :                state_spin2 = 1
     910         1827 :                IF (spinflip /= no_sf_tddfpt) THEN
     911           45 :                   state_spin = 1
     912           45 :                   state_spin2 = 2
     913              :                END IF
     914         4752 :                DO iexc = 1, nexcs
     915         2925 :                   ind = inds_recv(inds(iexc)) - 1
     916         2925 :                   IF ((nspins > 1) .AND. (spinflip == no_sf_tddfpt)) THEN
     917          627 :                      IF (ind < nmo_virt_occ_alpha) THEN
     918          285 :                         state_spin = 1
     919          285 :                         state_spin2 = 1
     920          285 :                         spin_label = '(alp)'
     921          285 :                         spin_label2 = '(alp)'
     922              :                      ELSE
     923          342 :                         state_spin = 2
     924          342 :                         state_spin2 = 2
     925          342 :                         ind = ind - nmo_virt_occ_alpha
     926          342 :                         spin_label = '(bet)'
     927          342 :                         spin_label2 = '(bet)'
     928              :                      END IF
     929              :                   END IF
     930         2925 :                   imo_act = ind/nmo_virt8(state_spin2) + 1
     931         2925 :                   imo_occ = gs_mos(state_spin)%index_active(imo_act)
     932         2925 :                   imo_virt = MOD(ind, nmo_virt8(state_spin2)) + 1
     933              : 
     934         2925 :                   WRITE (log_unit, '(T27,I8,1X,A5,T48,I8,1X,A5,T70,F9.6)') imo_occ, spin_label, &
     935         7677 :                      nmo_occ8(state_spin2) + imo_virt, spin_label2, weights_recv(inds(iexc))
     936              :                END DO
     937              :             END IF
     938              : 
     939              :             ! deallocate temporary arrays
     940         5080 :             IF (para_env%is_source()) THEN
     941         1827 :                DEALLOCATE (weights_recv, weights_neg_abs_recv, inds_recv, inds)
     942              :             END IF
     943              :          END DO
     944              : 
     945         1426 :          DEALLOCATE (weights_local, inds_local)
     946         1426 :          IF (log_unit > 0) THEN
     947              :             WRITE (log_unit, "(1X,A)") &
     948          713 :                "-------------------------------------------------------------------------------"
     949              :          END IF
     950              :       END IF
     951              : 
     952         1426 :       CALL cp_fm_release(weights_fm)
     953         1426 :       CALL cp_fm_release(S_mos_virt)
     954              : 
     955         1426 :       CALL timestop(handle)
     956              : 
     957         2852 :    END SUBROUTINE tddfpt_print_excitation_analysis
     958              : 
     959              : ! **************************************************************************************************
     960              : !> \brief Print natural transition orbital analysis.
     961              : !> \param qs_env             Information on Kinds and Particles
     962              : !> \param evects             TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
     963              : !>                           SIZE(evects,2) -- number of excited states to print)
     964              : !> \param evals              TDDFPT eigenvalues
     965              : !> \param ostrength ...
     966              : !> \param gs_mos             molecular orbitals optimised for the ground state
     967              : !> \param matrix_s           overlap matrix
     968              : !> \param print_section      ...
     969              : !> \par History
     970              : !>    * 06.2019 created [JGH]
     971              : ! **************************************************************************************************
     972         1426 :    SUBROUTINE tddfpt_print_nto_analysis(qs_env, evects, evals, ostrength, gs_mos, matrix_s, print_section)
     973              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     974              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in)      :: evects
     975              :       REAL(kind=dp), DIMENSION(:), INTENT(in)            :: evals, ostrength
     976              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     977              :          INTENT(in)                                      :: gs_mos
     978              :       TYPE(dbcsr_type), POINTER                          :: matrix_s
     979              :       TYPE(section_vals_type), POINTER                   :: print_section
     980              : 
     981              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_print_nto_analysis'
     982              :       INTEGER, PARAMETER                                 :: ntomax = 10
     983              : 
     984              :       CHARACTER(LEN=20), DIMENSION(2)                    :: nto_name
     985              :       INTEGER                                            :: handle, i, ia, icg, iounit, ispin, &
     986              :                                                             istate, j, nao, nlist, nmax, nmo, &
     987              :                                                             nnto, nspins, nstates
     988              :       INTEGER, DIMENSION(2)                              :: iv
     989              :       INTEGER, DIMENSION(2, ntomax)                      :: ia_index
     990         1426 :       INTEGER, DIMENSION(:), POINTER                     :: slist, stride
     991              :       LOGICAL                                            :: append_cube, cube_file, explicit
     992              :       REAL(KIND=dp)                                      :: os_threshold, sume, threshold
     993         1426 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigvals
     994         1426 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: eigenvalues
     995              :       REAL(KIND=dp), DIMENSION(ntomax)                   :: ia_eval
     996              :       TYPE(cell_type), POINTER                           :: cell
     997              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_mo_struct, fm_struct
     998              :       TYPE(cp_fm_type)                                   :: Sev, smat, tmat, wmat, work, wvec
     999         1426 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: teig
    1000              :       TYPE(cp_logger_type), POINTER                      :: logger
    1001         1426 :       TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:)       :: nto_set
    1002         1426 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1003         1426 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1004              :       TYPE(section_vals_type), POINTER                   :: molden_section, nto_section
    1005              : 
    1006         1426 :       CALL timeset(routineN, handle)
    1007              : 
    1008         1426 :       logger => cp_get_default_logger()
    1009         1426 :       iounit = cp_logger_get_default_io_unit(logger)
    1010              : 
    1011         1426 :       IF (BTEST(cp_print_key_should_output(logger%iter_info, print_section, &
    1012              :                                            "NTO_ANALYSIS"), cp_p_file)) THEN
    1013              : 
    1014          224 :          CALL cite_reference(Martin2003)
    1015              : 
    1016          224 :          CALL section_vals_val_get(print_section, "NTO_ANALYSIS%THRESHOLD", r_val=threshold)
    1017          224 :          CALL section_vals_val_get(print_section, "NTO_ANALYSIS%INTENSITY_THRESHOLD", r_val=os_threshold)
    1018          224 :          CALL section_vals_val_get(print_section, "NTO_ANALYSIS%STATE_LIST", EXPLICIT=explicit)
    1019              : 
    1020          224 :          IF (explicit) THEN
    1021            4 :             CALL section_vals_val_get(print_section, "NTO_ANALYSIS%STATE_LIST", i_vals=slist)
    1022            4 :             nlist = SIZE(slist)
    1023              :          ELSE
    1024              :             nlist = 0
    1025              :          END IF
    1026              : 
    1027          224 :          IF (iounit > 0) THEN
    1028          112 :             WRITE (iounit, "(1X,A)") "", &
    1029          112 :                "-------------------------------------------------------------------------------", &
    1030          112 :                "-                            Natural Orbital analysis                         -", &
    1031          224 :                "-------------------------------------------------------------------------------"
    1032              :          END IF
    1033              : 
    1034          224 :          nspins = SIZE(evects, 1)
    1035          224 :          nstates = SIZE(evects, 2)
    1036          224 :          CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
    1037              : 
    1038          548 :          DO istate = 1, nstates
    1039          324 :             IF (os_threshold > ostrength(istate)) THEN
    1040           54 :                IF (iounit > 0) THEN
    1041           27 :                   WRITE (iounit, "(1X,A,I6)") "  Skipping state ", istate
    1042              :                END IF
    1043              :                CYCLE
    1044              :             END IF
    1045          270 :             IF (nlist > 0) THEN
    1046            0 :                IF (.NOT. ANY(slist == istate)) THEN
    1047            0 :                   IF (iounit > 0) THEN
    1048            0 :                      WRITE (iounit, "(1X,A,I6)") "  Skipping state ", istate
    1049              :                   END IF
    1050              :                   CYCLE
    1051              :                END IF
    1052              :             END IF
    1053          270 :             IF (iounit > 0) THEN
    1054          135 :                WRITE (iounit, "(1X,A,I6,T30,F10.5,A)") "  STATE NR. ", istate, evals(istate)*evolt, " eV"
    1055              :             END IF
    1056              :             nmax = 0
    1057          546 :             DO ispin = 1, nspins
    1058          276 :                CALL cp_fm_get_info(evects(ispin, istate), matrix_struct=fm_struct, ncol_global=nmo)
    1059          546 :                nmax = MAX(nmax, nmo)
    1060              :             END DO
    1061         1080 :             ALLOCATE (eigenvalues(nmax, nspins))
    1062          270 :             eigenvalues = 0.0_dp
    1063              :             ! SET 1: Hole states
    1064              :             ! SET 2: Particle states
    1065          270 :             nto_name(1) = 'Hole_states'
    1066          270 :             nto_name(2) = 'Particle_states'
    1067          810 :             ALLOCATE (nto_set(2))
    1068          810 :             DO i = 1, 2
    1069          540 :                CALL allocate_mo_set(nto_set(i), nao, ntomax, 0, 0.0_dp, 1.0_dp, 0.0_dp)
    1070          540 :                CALL cp_fm_get_info(evects(1, istate), matrix_struct=fm_struct)
    1071              :                CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
    1072          540 :                                         ncol_global=ntomax)
    1073          540 :                CALL cp_fm_create(tmat, fm_mo_struct)
    1074          540 :                CALL init_mo_set(nto_set(i), fm_ref=tmat, name=nto_name(i))
    1075          540 :                CALL cp_fm_release(tmat)
    1076         1350 :                CALL cp_fm_struct_release(fm_mo_struct)
    1077              :             END DO
    1078              :             !
    1079         1086 :             ALLOCATE (teig(nspins))
    1080              :             ! hole states
    1081              :             ! Diagonalize X(T)*S*X
    1082          546 :             DO ispin = 1, nspins
    1083              :                ASSOCIATE (ev => evects(ispin, istate))
    1084          276 :                   CALL cp_fm_get_info(ev, matrix_struct=fm_struct, ncol_global=nmo)
    1085          276 :                   CALL cp_fm_create(Sev, fm_struct)
    1086              :                   CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
    1087          276 :                                            nrow_global=nmo, ncol_global=nmo)
    1088          276 :                   CALL cp_fm_create(tmat, fm_mo_struct)
    1089          276 :                   CALL cp_fm_create(teig(ispin), fm_mo_struct)
    1090          276 :                   CALL cp_dbcsr_sm_fm_multiply(matrix_s, ev, Sev, ncol=nmo, alpha=1.0_dp, beta=0.0_dp)
    1091          276 :                   CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, ev, Sev, 0.0_dp, tmat)
    1092              :                END ASSOCIATE
    1093              : 
    1094          276 :                CALL choose_eigv_solver(tmat, teig(ispin), eigenvalues(1:nmo, ispin))
    1095              : 
    1096          276 :                CALL cp_fm_struct_release(fm_mo_struct)
    1097          276 :                CALL cp_fm_release(tmat)
    1098         1098 :                CALL cp_fm_release(Sev)
    1099              :             END DO
    1100              :             ! find major determinants i->a
    1101          270 :             ia_index = 0
    1102          270 :             sume = 0.0_dp
    1103          270 :             nnto = 0
    1104          326 :             DO i = 1, ntomax
    1105         3452 :                iv = MAXLOC(eigenvalues)
    1106          326 :                ia_eval(i) = eigenvalues(iv(1), iv(2))
    1107          978 :                ia_index(1:2, i) = iv(1:2)
    1108          326 :                sume = sume + ia_eval(i)
    1109          326 :                eigenvalues(iv(1), iv(2)) = 0.0_dp
    1110          326 :                nnto = nnto + 1
    1111          326 :                IF (sume > threshold) EXIT
    1112              :             END DO
    1113              :             ! store hole states
    1114          270 :             CALL set_mo_set(nto_set(1), nmo=nnto)
    1115          596 :             DO i = 1, nnto
    1116          326 :                ia = ia_index(1, i)
    1117          326 :                ispin = ia_index(2, i)
    1118          326 :                CALL cp_fm_get_info(gs_mos(ispin)%mos_occ, ncol_global=nmo)
    1119          326 :                CALL cp_fm_get_info(teig(ispin), matrix_struct=fm_struct)
    1120              :                CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
    1121          326 :                                         nrow_global=nmo, ncol_global=1)
    1122          326 :                CALL cp_fm_create(tmat, fm_mo_struct)
    1123          326 :                CALL cp_fm_struct_release(fm_mo_struct)
    1124          326 :                CALL cp_fm_get_info(gs_mos(1)%mos_occ, matrix_struct=fm_struct)
    1125              :                CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
    1126          326 :                                         ncol_global=1)
    1127          326 :                CALL cp_fm_create(wvec, fm_mo_struct)
    1128          326 :                CALL cp_fm_struct_release(fm_mo_struct)
    1129          326 :                CALL cp_fm_to_fm(teig(ispin), tmat, 1, ia, 1)
    1130              :                CALL parallel_gemm('N', 'N', nao, 1, nmo, 1.0_dp, gs_mos(ispin)%mos_occ, &
    1131          326 :                                   tmat, 0.0_dp, wvec)
    1132          326 :                CALL cp_fm_to_fm(wvec, nto_set(1)%mo_coeff, 1, 1, i)
    1133          326 :                CALL cp_fm_release(wvec)
    1134         1574 :                CALL cp_fm_release(tmat)
    1135              :             END DO
    1136              :             ! particle states
    1137              :             ! Solve generalized eigenvalue equation:  (S*X)*(S*X)(T)*v = lambda*S*v
    1138          270 :             CALL set_mo_set(nto_set(2), nmo=nnto)
    1139          546 :             DO ispin = 1, nspins
    1140              :                ASSOCIATE (ev => evects(ispin, istate))
    1141          276 :                   CALL cp_fm_get_info(ev, matrix_struct=fm_struct, nrow_global=nao, ncol_global=nmo)
    1142          828 :                   ALLOCATE (eigvals(nao))
    1143          276 :                   eigvals = 0.0_dp
    1144          276 :                   CALL cp_fm_create(Sev, fm_struct)
    1145          552 :                   CALL cp_dbcsr_sm_fm_multiply(matrix_s, ev, Sev, ncol=nmo, alpha=1.0_dp, beta=0.0_dp)
    1146              :                END ASSOCIATE
    1147              :                CALL cp_fm_struct_create(fmstruct=fm_mo_struct, template_fmstruct=fm_struct, &
    1148          276 :                                         nrow_global=nao, ncol_global=nao)
    1149          276 :                CALL cp_fm_create(tmat, fm_mo_struct)
    1150          276 :                CALL cp_fm_create(smat, fm_mo_struct)
    1151          276 :                CALL cp_fm_create(wmat, fm_mo_struct)
    1152          276 :                CALL cp_fm_create(work, fm_mo_struct)
    1153          276 :                CALL cp_fm_struct_release(fm_mo_struct)
    1154          276 :                CALL copy_dbcsr_to_fm(matrix_s, smat)
    1155          276 :                CALL parallel_gemm('N', 'T', nao, nao, nmo, 1.0_dp, Sev, Sev, 0.0_dp, tmat)
    1156          276 :                CALL cp_fm_geeig(tmat, smat, wmat, eigvals, work)
    1157          610 :                DO i = 1, nnto
    1158          610 :                   IF (ispin == ia_index(2, i)) THEN
    1159          326 :                      icg = 0
    1160         7984 :                      DO j = 1, nao
    1161         7984 :                         IF (ABS(eigvals(j) - ia_eval(i)) < 1.E-6_dp) THEN
    1162          326 :                            icg = j
    1163          326 :                            EXIT
    1164              :                         END IF
    1165              :                      END DO
    1166          326 :                      IF (icg == 0) THEN
    1167              :                         CALL cp_warn(__LOCATION__, &
    1168            0 :                                      "Could not locate particle state associated with hole state.")
    1169              :                      ELSE
    1170          326 :                         CALL cp_fm_to_fm(wmat, nto_set(2)%mo_coeff, 1, icg, i)
    1171              :                      END IF
    1172              :                   END IF
    1173              :                END DO
    1174          276 :                DEALLOCATE (eigvals)
    1175          276 :                CALL cp_fm_release(Sev)
    1176          276 :                CALL cp_fm_release(tmat)
    1177          276 :                CALL cp_fm_release(smat)
    1178          276 :                CALL cp_fm_release(wmat)
    1179          822 :                CALL cp_fm_release(work)
    1180              :             END DO
    1181              :             ! print
    1182          270 :             IF (iounit > 0) THEN
    1183          135 :                sume = 0.0_dp
    1184          298 :                DO i = 1, nnto
    1185          163 :                   sume = sume + ia_eval(i)
    1186              :                   WRITE (iounit, "(T6,A,i2,T30,A,i1,T42,A,F8.5,T63,A,F8.5)") &
    1187          163 :                      "Particle-Hole state:", i, " Spin:", ia_index(2, i), &
    1188          461 :                      "Eigenvalue:", ia_eval(i), " Sum Eigv:", sume
    1189              :                END DO
    1190              :             END IF
    1191              :             ! Cube and Molden files
    1192          270 :             nto_section => section_vals_get_subs_vals(print_section, "NTO_ANALYSIS")
    1193          270 :             CALL section_vals_val_get(nto_section, "CUBE_FILES", l_val=cube_file)
    1194          270 :             CALL section_vals_val_get(nto_section, "STRIDE", i_vals=stride)
    1195          270 :             CALL section_vals_val_get(nto_section, "APPEND", l_val=append_cube)
    1196          270 :             IF (cube_file) THEN
    1197            8 :                CALL print_nto_cubes(qs_env, nto_set, istate, stride, append_cube, nto_section)
    1198              :             END IF
    1199          270 :             CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, particle_set=particle_set, cell=cell)
    1200          270 :             molden_section => section_vals_get_subs_vals(print_section, "MOS_MOLDEN")
    1201          270 :             CALL write_mos_molden(nto_set, qs_kind_set, particle_set, molden_section, cell=cell, qs_env=qs_env)
    1202              :             !
    1203          270 :             DEALLOCATE (eigenvalues)
    1204          270 :             CALL cp_fm_release(teig)
    1205              :             !
    1206          810 :             DO i = 1, 2
    1207          810 :                CALL deallocate_mo_set(nto_set(i))
    1208              :             END DO
    1209         1034 :             DEALLOCATE (nto_set)
    1210              :          END DO
    1211              : 
    1212          224 :          IF (iounit > 0) THEN
    1213              :             WRITE (iounit, "(1X,A)") &
    1214          112 :                "-------------------------------------------------------------------------------"
    1215              :          END IF
    1216              : 
    1217              :       END IF
    1218              : 
    1219         1426 :       CALL timestop(handle)
    1220              : 
    1221         2852 :    END SUBROUTINE tddfpt_print_nto_analysis
    1222              : 
    1223              : ! **************************************************************************************************
    1224              : !> \brief Print exciton descriptors, cf. Mewes et al., JCTC 14, 710-725 (2018)
    1225              : !> \param log_unit                              output unit
    1226              : !> \param evects                                TDDFPT trial vectors (SIZE(evects,1) -- number of spins;
    1227              : !>                                              SIZE(evects,2) -- number of excited states to print)
    1228              : !> \param gs_mos                                molecular orbitals optimised for the ground state
    1229              : !> \param matrix_s                              overlap matrix
    1230              : !> \param do_directional_exciton_descriptors    flag for computing descriptors for each (cartesian) direction
    1231              : !> \param qs_env                                Information on particles/geometry
    1232              : !> \par History
    1233              : !>    * 12.2024 created as 'tddfpt_print_exciton_descriptors' [Maximilian Graml]
    1234              : ! **************************************************************************************************
    1235            2 :    SUBROUTINE tddfpt_print_exciton_descriptors(log_unit, evects, gs_mos, matrix_s, &
    1236              :                                                do_directional_exciton_descriptors, qs_env)
    1237              :       INTEGER, INTENT(in)                                :: log_unit
    1238              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in)      :: evects
    1239              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
    1240              :          INTENT(in)                                      :: gs_mos
    1241              :       TYPE(dbcsr_type), POINTER                          :: matrix_s
    1242              :       LOGICAL, INTENT(IN) :: do_directional_exciton_descriptors
    1243              :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
    1244              : 
    1245              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_print_exciton_descriptors'
    1246              : 
    1247              :       CHARACTER(LEN=4)                                   :: prefix_output
    1248              :       INTEGER                                            :: handle, ispin, istate, n_moments_quad, &
    1249              :                                                             nactive, nao, nspins, nstates
    1250              :       INTEGER, DIMENSION(maxspins)                       :: nmo_occ, nmo_virt
    1251              :       LOGICAL                                            :: print_checkvalue
    1252            2 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: ref_point_multipole
    1253              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1254              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct_mo_coeff, &
    1255              :                                                             fm_struct_S_mos_virt, fm_struct_X_ia_n
    1256            2 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: eigvec_X_ia_n, fm_multipole_ab, &
    1257            2 :                                                             fm_multipole_ai, fm_multipole_ij, &
    1258            2 :                                                             S_mos_virt
    1259            2 :       TYPE(cp_fm_type), DIMENSION(:), POINTER            :: mo_coeff
    1260              :       TYPE(exciton_descr_type), ALLOCATABLE, &
    1261            2 :          DIMENSION(:)                                    :: exc_descr
    1262              : 
    1263            2 :       CALL timeset(routineN, handle)
    1264              : 
    1265            2 :       nspins = SIZE(evects, 1)
    1266            2 :       nstates = SIZE(evects, 2)
    1267              : 
    1268            2 :       CPASSERT(nspins == 1) ! Other spins are not yet implemented for exciton descriptors
    1269              : 
    1270            2 :       CALL cp_fm_get_info(gs_mos(1)%mos_occ, context=blacs_env)
    1271            2 :       CALL dbcsr_get_info(matrix_s, nfullrows_total=nao)
    1272              : 
    1273            4 :       DO ispin = 1, nspins
    1274            2 :          nmo_occ(ispin) = SIZE(gs_mos(ispin)%evals_occ)
    1275            4 :          nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
    1276              :       END DO
    1277              : 
    1278              :       ! Prepare fm with all MO coefficents, i.e. nao x nao
    1279            8 :       ALLOCATE (mo_coeff(nspins))
    1280              :       CALL cp_fm_struct_create(fm_struct_mo_coeff, nrow_global=nao, ncol_global=nao, &
    1281            2 :                                context=blacs_env)
    1282            4 :       DO ispin = 1, nspins
    1283            2 :          CALL cp_fm_create(mo_coeff(ispin), fm_struct_mo_coeff)
    1284              :          CALL cp_fm_to_fm_submat_general(gs_mos(ispin)%mos_occ, &
    1285              :                                          mo_coeff(ispin), &
    1286              :                                          nao, &
    1287              :                                          nmo_occ(ispin), &
    1288              :                                          1, &
    1289              :                                          1, &
    1290              :                                          1, &
    1291              :                                          1, &
    1292            2 :                                          blacs_env)
    1293              :          CALL cp_fm_to_fm_submat_general(gs_mos(ispin)%mos_virt, &
    1294              :                                          mo_coeff(ispin), &
    1295              :                                          nao, &
    1296              :                                          nmo_virt(ispin), &
    1297              :                                          1, &
    1298              :                                          1, &
    1299              :                                          1, &
    1300              :                                          nmo_occ(ispin) + 1, &
    1301            4 :                                          blacs_env)
    1302              :       END DO
    1303            2 :       CALL cp_fm_struct_release(fm_struct_mo_coeff)
    1304              : 
    1305              :       ! Compute multipole moments
    1306              :       ! fm_multipole_XY have structure inherited by libint, i.e. x, y, z, xx, xy, xz, yy, yz, zz
    1307            2 :       n_moments_quad = 9
    1308            2 :       ALLOCATE (ref_point_multipole(3))
    1309           20 :       ALLOCATE (fm_multipole_ij(n_moments_quad))
    1310           20 :       ALLOCATE (fm_multipole_ab(n_moments_quad))
    1311           20 :       ALLOCATE (fm_multipole_ai(n_moments_quad))
    1312              : 
    1313              :       CALL get_multipoles_mo(fm_multipole_ai, fm_multipole_ij, fm_multipole_ab, &
    1314              :                              qs_env, mo_coeff, ref_point_multipole, 2, &
    1315            2 :                              nmo_occ(1), nmo_virt(1), blacs_env)
    1316              : 
    1317            2 :       CALL cp_fm_release(mo_coeff)
    1318              : 
    1319              :       ! Compute eigenvector X of the Casida equation from trial vectors
    1320           10 :       ALLOCATE (S_mos_virt(nspins), eigvec_X_ia_n(nspins))
    1321            4 :       DO ispin = 1, nspins
    1322            2 :          CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct_S_mos_virt)
    1323            2 :          CALL cp_fm_create(S_mos_virt(ispin), fm_struct_S_mos_virt)
    1324            2 :          NULLIFY (fm_struct_S_mos_virt)
    1325              :          CALL cp_dbcsr_sm_fm_multiply(matrix_s, &
    1326              :                                       gs_mos(ispin)%mos_virt, &
    1327              :                                       S_mos_virt(ispin), &
    1328            2 :                                       ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
    1329              : 
    1330              :          CALL cp_fm_struct_create(fm_struct_X_ia_n, nrow_global=nmo_occ(ispin), ncol_global=nmo_virt(ispin), &
    1331            2 :                                   context=blacs_env)
    1332            2 :          CALL cp_fm_create(eigvec_X_ia_n(ispin), fm_struct_X_ia_n)
    1333            4 :          CALL cp_fm_struct_release(fm_struct_X_ia_n)
    1334              :       END DO
    1335          172 :       ALLOCATE (exc_descr(nstates))
    1336           12 :       DO istate = 1, nstates
    1337           22 :          DO ispin = 1, nspins
    1338           10 :             CALL cp_fm_set_all(eigvec_X_ia_n(ispin), 0.0_dp)
    1339              :             ! compute eigenvectors X of the TDA equation
    1340              :             ! Reshuffle multiplication from
    1341              :             ! X_ai = S_ma ^T * C_mi
    1342              :             ! to
    1343              :             ! X_ia = C_mi ^T * S_ma
    1344              :             ! for compatibility with the structure needed for get_exciton_descriptors of bse_properties.F
    1345           10 :             CALL cp_fm_get_info(evects(ispin, istate), ncol_global=nactive)
    1346           10 :             IF (nactive /= nmo_occ(ispin)) THEN
    1347              :                CALL cp_abort(__LOCATION__, &
    1348            0 :                              "Reduced active space excitations not implemented")
    1349              :             END IF
    1350              :             CALL parallel_gemm('T', 'N', nmo_occ(ispin), nmo_virt(ispin), nao, 1.0_dp, &
    1351           10 :                                evects(ispin, istate), S_mos_virt(ispin), 0.0_dp, eigvec_X_ia_n(ispin))
    1352              : 
    1353              :             CALL get_exciton_descriptors(exc_descr, eigvec_X_ia_n(ispin), &
    1354              :                                          fm_multipole_ij, fm_multipole_ab, &
    1355              :                                          fm_multipole_ai, &
    1356           30 :                                          istate, nmo_occ(ispin), nmo_virt(ispin))
    1357              :          END DO
    1358              :       END DO
    1359            2 :       CALL cp_fm_release(eigvec_X_ia_n)
    1360            2 :       CALL cp_fm_release(S_mos_virt)
    1361            2 :       CALL cp_fm_release(fm_multipole_ai)
    1362            2 :       CALL cp_fm_release(fm_multipole_ij)
    1363            2 :       CALL cp_fm_release(fm_multipole_ab)
    1364              : 
    1365              :       ! Actual printing
    1366            2 :       print_checkvalue = .TRUE.
    1367            2 :       prefix_output = ' '
    1368              :       CALL print_exciton_descriptors(exc_descr, ref_point_multipole, log_unit, &
    1369              :                                      nstates, print_checkvalue, do_directional_exciton_descriptors, &
    1370            2 :                                      prefix_output, qs_env)
    1371              : 
    1372            2 :       DEALLOCATE (ref_point_multipole)
    1373            2 :       DEALLOCATE (exc_descr)
    1374              : 
    1375            2 :       CALL timestop(handle)
    1376              : 
    1377            6 :    END SUBROUTINE tddfpt_print_exciton_descriptors
    1378              : 
    1379              : ! **************************************************************************************************
    1380              : !> \brief ...
    1381              : !> \param vin ...
    1382              : !> \param vout ...
    1383              : !> \param mos_occ ...
    1384              : !> \param matrix_s ...
    1385              : ! **************************************************************************************************
    1386            0 :    SUBROUTINE project_vector(vin, vout, mos_occ, matrix_s)
    1387              :       TYPE(dbcsr_type)                                   :: vin, vout
    1388              :       TYPE(cp_fm_type), INTENT(IN)                       :: mos_occ
    1389              :       TYPE(dbcsr_type), POINTER                          :: matrix_s
    1390              : 
    1391              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'project_vector'
    1392              : 
    1393              :       INTEGER                                            :: handle, nao, nmo
    1394              :       REAL(KIND=dp)                                      :: norm(1)
    1395              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct, fm_vec_struct
    1396              :       TYPE(cp_fm_type)                                   :: csvec, svec, vec
    1397              : 
    1398            0 :       CALL timeset(routineN, handle)
    1399              : 
    1400            0 :       CALL cp_fm_get_info(mos_occ, matrix_struct=fm_struct, nrow_global=nao, ncol_global=nmo)
    1401              :       CALL cp_fm_struct_create(fmstruct=fm_vec_struct, template_fmstruct=fm_struct, &
    1402            0 :                                nrow_global=nao, ncol_global=1)
    1403            0 :       CALL cp_fm_create(vec, fm_vec_struct)
    1404            0 :       CALL cp_fm_create(svec, fm_vec_struct)
    1405            0 :       CALL cp_fm_struct_release(fm_vec_struct)
    1406              :       CALL cp_fm_struct_create(fmstruct=fm_vec_struct, template_fmstruct=fm_struct, &
    1407            0 :                                nrow_global=nmo, ncol_global=1)
    1408            0 :       CALL cp_fm_create(csvec, fm_vec_struct)
    1409            0 :       CALL cp_fm_struct_release(fm_vec_struct)
    1410              : 
    1411            0 :       CALL copy_dbcsr_to_fm(vin, vec)
    1412            0 :       CALL cp_dbcsr_sm_fm_multiply(matrix_s, vec, svec, ncol=1, alpha=1.0_dp, beta=0.0_dp)
    1413            0 :       CALL parallel_gemm('T', 'N', nmo, 1, nao, 1.0_dp, mos_occ, svec, 0.0_dp, csvec)
    1414            0 :       CALL parallel_gemm('N', 'N', nao, 1, nmo, -1.0_dp, mos_occ, csvec, 1.0_dp, vec)
    1415            0 :       CALL cp_fm_vectorsnorm(vec, norm)
    1416            0 :       CPASSERT(norm(1) > 1.e-14_dp)
    1417            0 :       norm(1) = SQRT(1._dp/norm(1))
    1418            0 :       CALL cp_fm_scale(norm(1), vec)
    1419            0 :       CALL copy_fm_to_dbcsr(vec, vout, keep_sparsity=.FALSE.)
    1420              : 
    1421            0 :       CALL cp_fm_release(csvec)
    1422            0 :       CALL cp_fm_release(svec)
    1423            0 :       CALL cp_fm_release(vec)
    1424              : 
    1425            0 :       CALL timestop(handle)
    1426              : 
    1427            0 :    END SUBROUTINE project_vector
    1428              : 
    1429              : ! **************************************************************************************************
    1430              : !> \brief ...
    1431              : !> \param va ...
    1432              : !> \param vb ...
    1433              : !> \param res ...
    1434              : ! **************************************************************************************************
    1435            0 :    SUBROUTINE vec_product(va, vb, res)
    1436              :       TYPE(dbcsr_type)                                   :: va, vb
    1437              :       REAL(KIND=dp), INTENT(OUT)                         :: res
    1438              : 
    1439              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'vec_product'
    1440              : 
    1441              :       INTEGER                                            :: handle, icol, irow
    1442              :       LOGICAL                                            :: found
    1443            0 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: vba, vbb
    1444              :       TYPE(dbcsr_iterator_type)                          :: iter
    1445              :       TYPE(mp_comm_type)                                 :: group
    1446              : 
    1447            0 :       CALL timeset(routineN, handle)
    1448              : 
    1449            0 :       res = 0.0_dp
    1450              : 
    1451            0 :       CALL dbcsr_get_info(va, group=group)
    1452            0 :       CALL dbcsr_iterator_start(iter, va)
    1453            0 :       DO WHILE (dbcsr_iterator_blocks_left(iter))
    1454            0 :          CALL dbcsr_iterator_next_block(iter, irow, icol, vba)
    1455            0 :          CALL dbcsr_get_block_p(vb, row=irow, col=icol, block=vbb, found=found)
    1456            0 :          res = res + SUM(vba*vbb)
    1457            0 :          CPASSERT(found)
    1458              :       END DO
    1459            0 :       CALL dbcsr_iterator_stop(iter)
    1460            0 :       CALL group%sum(res)
    1461              : 
    1462            0 :       CALL timestop(handle)
    1463              : 
    1464            0 :    END SUBROUTINE vec_product
    1465              : 
    1466              : ! **************************************************************************************************
    1467              : !> \brief ...
    1468              : !> \param qs_env ...
    1469              : !> \param mos ...
    1470              : !> \param istate ...
    1471              : !> \param stride ...
    1472              : !> \param append_cube ...
    1473              : !> \param print_section ...
    1474              : ! **************************************************************************************************
    1475            8 :    SUBROUTINE print_nto_cubes(qs_env, mos, istate, stride, append_cube, print_section)
    1476              : 
    1477              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1478              :       TYPE(mo_set_type), DIMENSION(:), INTENT(IN)        :: mos
    1479              :       INTEGER, INTENT(IN)                                :: istate
    1480              :       INTEGER, DIMENSION(:), POINTER                     :: stride
    1481              :       LOGICAL, INTENT(IN)                                :: append_cube
    1482              :       TYPE(section_vals_type), POINTER                   :: print_section
    1483              : 
    1484              :       CHARACTER(LEN=default_path_length)                 :: filename, my_pos_cube, title
    1485              :       INTEGER                                            :: i, iset, nmo, unit_nr
    1486              :       LOGICAL                                            :: mpi_io
    1487            8 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
    1488              :       TYPE(cell_type), POINTER                           :: cell
    1489              :       TYPE(cp_fm_type), POINTER                          :: mo_coeff
    1490              :       TYPE(cp_logger_type), POINTER                      :: logger
    1491              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1492              :       TYPE(particle_list_type), POINTER                  :: particles
    1493            8 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1494              :       TYPE(pw_c1d_gs_type)                               :: wf_g
    1495              :       TYPE(pw_env_type), POINTER                         :: pw_env
    1496            8 :       TYPE(pw_pool_p_type), DIMENSION(:), POINTER        :: pw_pools
    1497              :       TYPE(pw_pool_type), POINTER                        :: auxbas_pw_pool
    1498              :       TYPE(pw_r3d_rs_type)                               :: wf_r
    1499            8 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1500              :       TYPE(qs_subsys_type), POINTER                      :: subsys
    1501              : 
    1502           16 :       logger => cp_get_default_logger()
    1503              : 
    1504            8 :       CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, pw_env=pw_env)
    1505            8 :       CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, pw_pools=pw_pools)
    1506            8 :       CALL auxbas_pw_pool%create_pw(wf_r)
    1507            8 :       CALL auxbas_pw_pool%create_pw(wf_g)
    1508              : 
    1509            8 :       CALL get_qs_env(qs_env, subsys=subsys)
    1510            8 :       CALL qs_subsys_get(subsys, particles=particles)
    1511              : 
    1512            8 :       my_pos_cube = "REWIND"
    1513            8 :       IF (append_cube) THEN
    1514            0 :          my_pos_cube = "APPEND"
    1515              :       END IF
    1516              : 
    1517              :       CALL get_qs_env(qs_env=qs_env, &
    1518              :                       atomic_kind_set=atomic_kind_set, &
    1519              :                       qs_kind_set=qs_kind_set, &
    1520              :                       cell=cell, &
    1521            8 :                       particle_set=particle_set)
    1522              : 
    1523           24 :       DO iset = 1, 2
    1524           16 :          CALL get_mo_set(mo_set=mos(iset), mo_coeff=mo_coeff, nmo=nmo)
    1525           44 :          DO i = 1, nmo
    1526              :             CALL calculate_wavefunction(mo_coeff, i, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
    1527           20 :                                         cell, dft_control, particle_set, pw_env)
    1528           20 :             IF (iset == 1) THEN
    1529           10 :                WRITE (filename, '(a4,I3.3,I2.2,a11)') "NTO_STATE", istate, i, "_Hole_State"
    1530           10 :             ELSE IF (iset == 2) THEN
    1531           10 :                WRITE (filename, '(a4,I3.3,I2.2,a15)') "NTO_STATE", istate, i, "_Particle_State"
    1532              :             END IF
    1533           20 :             mpi_io = .TRUE.
    1534              :             unit_nr = cp_print_key_unit_nr(logger, print_section, '', extension=".cube", &
    1535              :                                            middle_name=TRIM(filename), file_position=my_pos_cube, &
    1536           20 :                                            log_filename=.FALSE., ignore_should_output=.TRUE., mpi_io=mpi_io)
    1537           20 :             IF (iset == 1) THEN
    1538           10 :                WRITE (title, *) "Natural Transition Orbital Hole State", i
    1539           10 :             ELSE IF (iset == 2) THEN
    1540           10 :                WRITE (title, *) "Natural Transition Orbital Particle State", i
    1541              :             END IF
    1542           20 :             CALL cp_pw_to_cube(wf_r, unit_nr, title, particles=particles, stride=stride, mpi_io=mpi_io)
    1543              :             CALL cp_print_key_finished_output(unit_nr, logger, print_section, '', &
    1544           36 :                                               ignore_should_output=.TRUE., mpi_io=mpi_io)
    1545              :          END DO
    1546              :       END DO
    1547              : 
    1548            8 :       CALL auxbas_pw_pool%give_back_pw(wf_g)
    1549            8 :       CALL auxbas_pw_pool%give_back_pw(wf_r)
    1550              : 
    1551            8 :    END SUBROUTINE print_nto_cubes
    1552              : 
    1553              : END MODULE qs_tddfpt2_properties
        

Generated by: LCOV version 2.0-1