LCOV - code coverage report
Current view: top level - src - qs_tddfpt2_soc.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:42dac4a) Lines: 97.7 % 620 606
Test Date: 2025-07-25 12:55:17 Functions: 85.7 % 7 6

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : MODULE qs_tddfpt2_soc
       8              :    USE basis_set_types,                 ONLY: get_gto_basis_set,&
       9              :                                               gto_basis_set_type
      10              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      11              :    USE cp_cfm_diag,                     ONLY: cp_cfm_heevd
      12              :    USE cp_cfm_types,                    ONLY: cp_cfm_create,&
      13              :                                               cp_cfm_get_info,&
      14              :                                               cp_cfm_get_submatrix,&
      15              :                                               cp_cfm_release,&
      16              :                                               cp_cfm_type,&
      17              :                                               cp_fm_to_cfm
      18              :    USE cp_control_types,                ONLY: dft_control_type,&
      19              :                                               qs_control_type,&
      20              :                                               tddfpt2_control_type
      21              :    USE cp_dbcsr_api,                    ONLY: &
      22              :         dbcsr_copy, dbcsr_create, dbcsr_distribution_get, dbcsr_distribution_new, &
      23              :         dbcsr_distribution_release, dbcsr_distribution_type, dbcsr_get_info, dbcsr_multiply, &
      24              :         dbcsr_p_type, dbcsr_release, dbcsr_scale, dbcsr_type, dbcsr_type_no_symmetry
      25              :    USE cp_dbcsr_contrib,                ONLY: dbcsr_print,&
      26              :                                               dbcsr_reserve_all_blocks
      27              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      28              :                                               copy_fm_to_dbcsr,&
      29              :                                               cp_dbcsr_sm_fm_multiply
      30              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_scale,&
      31              :                                               cp_fm_transpose,&
      32              :                                               cp_fm_uplo_to_full
      33              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      34              :                                               cp_fm_struct_release,&
      35              :                                               cp_fm_struct_type
      36              :    USE cp_fm_types,                     ONLY: &
      37              :         cp_fm_create, cp_fm_get_diag, cp_fm_get_info, cp_fm_get_submatrix, cp_fm_release, &
      38              :         cp_fm_set_all, cp_fm_set_element, cp_fm_to_fm_submat, cp_fm_type
      39              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      40              :                                               cp_logger_get_default_unit_nr,&
      41              :                                               cp_logger_type
      42              :    USE cp_output_handling,              ONLY: cp_print_key_unit_nr
      43              :    USE input_constants,                 ONLY: tddfpt_dipole_length
      44              :    USE input_section_types,             ONLY: section_vals_get_subs_vals,&
      45              :                                               section_vals_type,&
      46              :                                               section_vals_val_get
      47              :    USE kinds,                           ONLY: default_string_length,&
      48              :                                               dp
      49              :    USE lebedev,                         ONLY: deallocate_lebedev_grids,&
      50              :                                               get_number_of_lebedev_grid,&
      51              :                                               init_lebedev_grids,&
      52              :                                               lebedev_grid
      53              :    USE mathlib,                         ONLY: get_diag
      54              :    USE memory_utilities,                ONLY: reallocate
      55              :    USE message_passing,                 ONLY: mp_para_env_type
      56              :    USE orbital_pointers,                ONLY: indso,&
      57              :                                               nsoset
      58              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      59              :    USE particle_types,                  ONLY: particle_type
      60              :    USE physcon,                         ONLY: evolt,&
      61              :                                               wavenumbers
      62              :    USE qs_environment_types,            ONLY: get_qs_env,&
      63              :                                               qs_environment_type
      64              :    USE qs_grid_atom,                    ONLY: allocate_grid_atom,&
      65              :                                               create_grid_atom,&
      66              :                                               grid_atom_type
      67              :    USE qs_harmonics_atom,               ONLY: allocate_harmonics_atom,&
      68              :                                               create_harmonics_atom,&
      69              :                                               get_maxl_CG,&
      70              :                                               harmonics_atom_type
      71              :    USE qs_kind_types,                   ONLY: get_qs_kind,&
      72              :                                               get_qs_kind_set,&
      73              :                                               qs_kind_type
      74              :    USE qs_mo_types,                     ONLY: get_mo_set,&
      75              :                                               mo_set_type
      76              :    USE qs_tddfpt2_soc_types,            ONLY: soc_atom_create,&
      77              :                                               soc_atom_env_type,&
      78              :                                               soc_atom_release,&
      79              :                                               soc_env_create,&
      80              :                                               soc_env_release,&
      81              :                                               soc_env_type
      82              :    USE qs_tddfpt2_soc_utils,            ONLY: dip_vel_op,&
      83              :                                               resort_evects,&
      84              :                                               soc_contract_evect,&
      85              :                                               soc_dipole_operator
      86              :    USE qs_tddfpt2_types,                ONLY: tddfpt_ground_state_mos
      87              :    USE soc_pseudopotential_methods,     ONLY: V_SOC_xyz_from_pseudopotential
      88              :    USE spherical_harmonics,             ONLY: clebsch_gordon,&
      89              :                                               clebsch_gordon_deallocate,&
      90              :                                               clebsch_gordon_init
      91              :    USE xas_tdp_atom,                    ONLY: compute_sphi_so,&
      92              :                                               integrate_soc_atoms,&
      93              :                                               truncate_radial_grid
      94              :    USE xas_tdp_utils,                   ONLY: rcs_amew_soc_elements
      95              : #include "./base/base_uses.f90"
      96              : 
      97              :    IMPLICIT NONE
      98              : 
      99              :    PRIVATE
     100              : 
     101              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_soc'
     102              : 
     103              :    LOGICAL, PARAMETER, PRIVATE          :: debug_this_module = .FALSE.
     104              : 
     105              :    INTEGER, PARAMETER, PRIVATE          :: nderivs = 3
     106              :    INTEGER, PARAMETER, PRIVATE          :: maxspins = 2
     107              : 
     108              :    !A helper type for SOC
     109              :    TYPE dbcsr_soc_package_type
     110              :       TYPE(dbcsr_type), POINTER     :: dbcsr_sg => Null()
     111              :       TYPE(dbcsr_type), POINTER     :: dbcsr_tp => Null()
     112              :       TYPE(dbcsr_type), POINTER     :: dbcsr_sc => Null()
     113              :       TYPE(dbcsr_type), POINTER     :: dbcsr_sf => Null()
     114              :       TYPE(dbcsr_type), POINTER     :: dbcsr_prod => Null()
     115              :       TYPE(dbcsr_type), POINTER     :: dbcsr_ovlp => Null()
     116              :       TYPE(dbcsr_type), POINTER     :: dbcsr_tmp => Null()
     117              :       TYPE(dbcsr_type), POINTER     :: dbcsr_work => Null()
     118              :    END TYPE dbcsr_soc_package_type
     119              : 
     120              :    PUBLIC :: tddfpt_soc
     121              : 
     122              : ! **************************************************************************************************
     123              : 
     124              : CONTAINS
     125              : 
     126              : ! **************************************************************************************************
     127              : !> \brief Perform TDDFPT-SOC calculation.
     128              : !> \param qs_env  Quickstep environment
     129              : !> \param evals_a eigenvalues for the singlet states
     130              : !> \param evals_b eigenvalues for the triplet states
     131              : !> \param evects_a eigenvectors for the singlet states
     132              : !> \param evects_b eigenvectors for the triplet states
     133              : !> \param gs_mos ground state orbitlas from the TDDFPT calculation
     134              : !> \par History
     135              : !>    * 02.2023 created [Jan-Robert Vogt]
     136              : !> \note Based on tddfpt2_methods and xas_tdp_utils.
     137              : !> \note Only rcs for now, but written with the addition of os in mind
     138              : ! **************************************************************************************************
     139              : 
     140            8 :    SUBROUTINE tddfpt_soc(qs_env, evals_a, evals_b, evects_a, evects_b, gs_mos)
     141              : 
     142              :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
     143              :       REAL(kind=dp), DIMENSION(:), INTENT(IN)            :: evals_a, evals_b
     144              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evects_a, evects_b
     145              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     146              :          POINTER                                         :: gs_mos
     147              : 
     148              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'tddfpt_soc'
     149              : 
     150              :       INTEGER                                            :: handle, istate, log_unit
     151              :       LOGICAL                                            :: do_os
     152              :       TYPE(cp_logger_type), POINTER                      :: logger
     153              :       TYPE(dft_control_type), POINTER                    :: dft_control
     154              : 
     155            8 :       CALL timeset(routineN, handle)
     156              : 
     157            8 :       logger => cp_get_default_logger()
     158            8 :       IF (logger%para_env%is_source()) THEN
     159            4 :          log_unit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     160              :       ELSE
     161            4 :          log_unit = -1
     162              :       END IF
     163              : 
     164            8 :       IF (log_unit > 0) THEN
     165            4 :          WRITE (log_unit, "(1X,A)") "", &
     166            4 :             "-------------------------------------------------------------------------------", &
     167            4 :             "-                         START SOC CALCULATIONS                              -", &
     168            8 :             "-------------------------------------------------------------------------------"
     169              :       END IF
     170              : 
     171            8 :       NULLIFY (dft_control)
     172            8 :       CALL get_qs_env(qs_env, dft_control=dft_control)
     173            8 :       do_os = dft_control%uks .OR. dft_control%roks
     174            0 :       IF (do_os) CPABORT("SOC only implemented for closed shell.")
     175              : 
     176            8 :       IF (log_unit > 0) THEN
     177            4 :          WRITE (log_unit, '(A)') "Starting from TDDFPT Excited States:"
     178            4 :          WRITE (log_unit, '(A)') "      STATE          SINGLET/eV         TRIPLET/eV"
     179           15 :          DO istate = 1, SIZE(evals_a)
     180           15 :             WRITE (log_unit, '(6X,I3,11X,F10.5,6X,F10.5)') istate, evals_a(istate)*evolt, evals_b(istate)*evolt
     181              :          END DO
     182              :       END IF
     183              : 
     184            8 :       IF (log_unit > 0) WRITE (log_unit, '(A)') "Starting restricted closed shell:"
     185            8 :       CALL tddfpt_soc_rcs(qs_env, evals_a, evals_b, evects_a, evects_b, log_unit, gs_mos)
     186              : 
     187            8 :       IF (log_unit > 0) THEN
     188            4 :          WRITE (log_unit, '(A,/,A)') "SOC Calculation terminated", &
     189            8 :             "Returning to TDDFPT for Force calculation and deallocations"
     190              :       END IF
     191              : 
     192            8 :       CALL timestop(handle)
     193              : 
     194            8 :    END SUBROUTINE
     195              : 
     196              : ! **************************************************************************************************
     197              : !> \brief Will perform the soc-calculation for restricted-closed-shell systems
     198              : !> \param qs_env Quickstep Enviroment
     199              : !> \param evals_sing eigenvalues singlet states
     200              : !> \param evals_trip eigenvalues triplet states
     201              : !> \param evects_sing eigenvector singlet states
     202              : !> \param evects_trip eigenvectors triplet states
     203              : !> \param log_unit default log_unit for convinients
     204              : !> \param gs_mos ground state MOs from TDDFPT
     205              : !> \par History
     206              : !>      * created 02.2023 [Jan-Robert Vogt]
     207              : !> \note Mostly copied and modified from xas_tdp_utils include_rcs_soc
     208              : ! **************************************************************************************************
     209            8 :    SUBROUTINE tddfpt_soc_rcs(qs_env, evals_sing, evals_trip, evects_sing, evects_trip, log_unit, gs_mos)
     210              : 
     211              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     212              :       REAL(kind=dp), DIMENSION(:), INTENT(IN), TARGET    :: evals_sing, evals_trip
     213              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evects_sing, evects_trip
     214              :       INTEGER                                            :: log_unit
     215              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     216              :          POINTER                                         :: gs_mos
     217              : 
     218              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'tddfpt_soc_rcs'
     219              : 
     220              :       CHARACTER(len=3)                                   :: mult
     221              :       INTEGER                                            :: dipole_form, group, handle, iex, ii, &
     222              :                                                             isg, istate, itp, jj, nactive, nao, &
     223              :                                                             nex, npcols, nprows, nsg, ntot, ntp
     224            8 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: evects_sort
     225            8 :       INTEGER, DIMENSION(:), POINTER                     :: col_blk_size, col_dist, row_blk_size, &
     226            8 :                                                             row_dist, row_dist_new
     227            8 :       INTEGER, DIMENSION(:, :), POINTER                  :: pgrid
     228              :       LOGICAL                                            :: print_ev, print_some, print_splitting, &
     229              :                                                             print_wn
     230              :       REAL(dp)                                           :: eps_filter, soc_gst, sqrt2, unit_scale
     231            8 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: diag, tmp_evals
     232            8 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: img_tmp, real_tmp
     233            8 :       REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :)        :: gstp_block, mo_soc_x, mo_soc_y, mo_soc_z
     234              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     235              :       TYPE(cp_cfm_type)                                  :: evecs_cfm, hami_cfm
     236              :       TYPE(cp_fm_struct_type), POINTER                   :: full_struct, gstp_struct, prod_struct, &
     237              :                                                             vec_struct, work_struct
     238              :       TYPE(cp_fm_type)                                   :: gstp_fm, img_fm, prod_fm, real_fm, &
     239              :                                                             tmp_fm, vec_soc_x, vec_soc_y, &
     240              :                                                             vec_soc_z, work_fm
     241              :       TYPE(cp_fm_type), POINTER                          :: gs_coeffs, tp_coeffs
     242              :       TYPE(cp_logger_type), POINTER                      :: logger
     243              :       TYPE(dbcsr_distribution_type), POINTER             :: coeffs_dist, dbcsr_dist, prod_dist
     244            8 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     245              :       TYPE(dbcsr_soc_package_type)                       :: dbcsr_soc_package
     246              :       TYPE(dbcsr_type), POINTER                          :: dbcsr_dummy, dbcsr_ovlp, dbcsr_prod, &
     247              :                                                             dbcsr_sg, dbcsr_tmp, dbcsr_tp, &
     248              :                                                             dbcsr_work, orb_soc_x, orb_soc_y, &
     249              :                                                             orb_soc_z
     250            8 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
     251              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     252              :       TYPE(section_vals_type), POINTER                   :: soc_print_section, soc_section, &
     253              :                                                             tddfpt_print_section
     254              :       TYPE(soc_atom_env_type), POINTER                   :: soc_atom_env
     255            8 :       TYPE(soc_env_type), TARGET                         :: soc_env
     256              : 
     257            8 :       CALL timeset(routineN, handle)
     258              : 
     259            8 :       NULLIFY (logger, pgrid, row_dist, row_dist_new)
     260            8 :       NULLIFY (col_dist, col_blk_size, row_blk_size, matrix_s)
     261            8 :       NULLIFY (gstp_struct, tddfpt_print_section, soc_print_section, soc_section)
     262              : 
     263            8 :       logger => cp_get_default_logger()
     264            8 :       tddfpt_print_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%PRINT")
     265            8 :       soc_print_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%PRINT%SOC_PRINT")
     266            8 :       soc_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%SOC")
     267              : 
     268            8 :       CALL section_vals_val_get(soc_section, "EPS_FILTER", r_val=eps_filter)
     269              : 
     270            8 :       nsg = SIZE(evals_sing)   ! Number of excited singlet states
     271            8 :       ntp = SIZE(evals_trip)   ! Number of excited triplet states
     272            8 :       nex = nsg                ! Number of excited states of each multiplicity
     273            8 :       ntot = 1 + nsg + 3*ntp ! Number of (GS + S + T^-1 + T^0 + T^1)
     274              : 
     275              :       ! Initzialize Working environment
     276              :       CALL inititialize_soc(qs_env, soc_atom_env, soc_env, &
     277            8 :                             evects_sing, evects_trip, dipole_form, gs_mos)
     278              : 
     279            8 :       NULLIFY (mos)
     280            8 :       CALL get_qs_env(qs_env, mos=mos, para_env=para_env, blacs_env=blacs_env)
     281            8 :       CALL get_mo_set(mos(1), nao=nao, homo=nactive)
     282              : 
     283              :       ! this will create the H^SOC in an atomic basis
     284            8 :       CALL integrate_soc_atoms(soc_env%orb_soc, qs_env=qs_env, soc_atom_env=soc_atom_env)
     285            8 :       CALL soc_atom_release(soc_atom_env)
     286              : 
     287              :       !! Point at H^SOC and MOs for better readablity
     288            8 :       NULLIFY (tp_coeffs, orb_soc_x, orb_soc_y, orb_soc_z)
     289            8 :       tp_coeffs => soc_env%b_coeff
     290            8 :       soc_env%evals_a => evals_sing
     291            8 :       soc_env%evals_b => evals_trip
     292            8 :       orb_soc_x => soc_env%orb_soc(1)%matrix
     293            8 :       orb_soc_y => soc_env%orb_soc(2)%matrix
     294            8 :       orb_soc_z => soc_env%orb_soc(3)%matrix
     295              : 
     296              :       !! Create a matrix-structure, which links all states in this calculation
     297            8 :       NULLIFY (full_struct)
     298            8 :       CALL cp_fm_struct_create(full_struct, context=blacs_env, para_env=para_env, nrow_global=ntot, ncol_global=ntot)
     299            8 :       CALL cp_fm_create(real_fm, full_struct)
     300            8 :       CALL cp_fm_create(img_fm, full_struct)
     301            8 :       CALL cp_fm_set_all(real_fm, 0.0_dp)
     302            8 :       CALL cp_fm_set_all(img_fm, 0.0_dp)
     303              : 
     304              :       !  Put the excitation energies on the diagonal of the real matrix
     305           30 :       DO isg = 1, nsg
     306           30 :          CALL cp_fm_set_element(real_fm, 1 + isg, 1 + isg, evals_sing(isg))
     307              :       END DO
     308           30 :       DO itp = 1, ntp
     309              :          ! first T^-1, then T^0, then T^+1
     310           22 :          CALL cp_fm_set_element(real_fm, 1 + itp + nsg, 1 + itp + nsg, evals_trip(itp))
     311           22 :          CALL cp_fm_set_element(real_fm, 1 + itp + ntp + nsg, 1 + itp + ntp + nsg, evals_trip(itp))
     312           30 :          CALL cp_fm_set_element(real_fm, 1 + itp + 2*ntp + nsg, 1 + itp + 2*ntp + nsg, evals_trip(itp))
     313              :       END DO
     314              : 
     315              :       !!Create the dbcsr structures for this calculations
     316            8 :       CALL get_qs_env(qs_env, dbcsr_dist=dbcsr_dist)
     317              :       CALL dbcsr_distribution_get(dbcsr_dist, group=group, row_dist=row_dist, pgrid=pgrid, &
     318            8 :                                   npcols=npcols, nprows=nprows)
     319           32 :       ALLOCATE (col_dist(nex), row_dist_new(nex))                   ! Split for each excitation
     320           30 :       DO iex = 1, nex
     321           22 :          col_dist(iex) = MODULO(npcols - iex, npcols)
     322           30 :          row_dist_new(iex) = MODULO(nprows - iex, nprows)
     323              :       END DO
     324            8 :       ALLOCATE (coeffs_dist, prod_dist)
     325              :       CALL dbcsr_distribution_new(coeffs_dist, group=group, pgrid=pgrid, row_dist=row_dist, &
     326            8 :                                   col_dist=col_dist)
     327              :       CALL dbcsr_distribution_new(prod_dist, group=group, pgrid=pgrid, row_dist=row_dist_new, &
     328            8 :                                   col_dist=col_dist)
     329              : 
     330              :       !! Create the matrices
     331           16 :       ALLOCATE (col_blk_size(nex))
     332           30 :       col_blk_size = nactive
     333              : 
     334            8 :       CALL get_qs_env(qs_env, matrix_s=matrix_s)
     335            8 :       CALL dbcsr_get_info(matrix_s(1)%matrix, row_blk_size=row_blk_size)
     336              : 
     337              :       !! The Eigenvectors for Sg und Tp will be dived into their diffrent components again
     338            8 :       ALLOCATE (dbcsr_sg, dbcsr_tp, dbcsr_work, dbcsr_ovlp, dbcsr_tmp, dbcsr_prod)
     339              :       CALL dbcsr_create(matrix=dbcsr_sg, name="SINGLETS", matrix_type=dbcsr_type_no_symmetry, &
     340            8 :                         dist=coeffs_dist, row_blk_size=row_blk_size, col_blk_size=col_blk_size)
     341              :       CALL dbcsr_create(matrix=dbcsr_tp, name="TRIPLETS", matrix_type=dbcsr_type_no_symmetry, &
     342            8 :                         dist=coeffs_dist, row_blk_size=row_blk_size, col_blk_size=col_blk_size)
     343              :       CALL dbcsr_create(matrix=dbcsr_work, name="WORK", matrix_type=dbcsr_type_no_symmetry, &
     344            8 :                         dist=coeffs_dist, row_blk_size=row_blk_size, col_blk_size=col_blk_size)
     345              :       CALL dbcsr_create(matrix=dbcsr_prod, name="PROD", matrix_type=dbcsr_type_no_symmetry, &
     346            8 :                         dist=prod_dist, row_blk_size=col_blk_size, col_blk_size=col_blk_size)
     347              :       CALL dbcsr_create(matrix=dbcsr_ovlp, name="OVLP", matrix_type=dbcsr_type_no_symmetry, &
     348            8 :                         dist=prod_dist, row_blk_size=col_blk_size, col_blk_size=col_blk_size)
     349              : 
     350           30 :       col_blk_size = 1
     351              :       CALL dbcsr_create(matrix=dbcsr_tmp, name="TMP", matrix_type=dbcsr_type_no_symmetry, &
     352            8 :                         dist=prod_dist, row_blk_size=col_blk_size, col_blk_size=col_blk_size)
     353            8 :       CALL dbcsr_reserve_all_blocks(dbcsr_tmp)
     354              : 
     355              :       IF (debug_this_module) THEN
     356              :          ALLOCATE (dbcsr_dummy)
     357              :          CALL dbcsr_create(matrix=dbcsr_dummy, name="DUMMY", matrix_type=dbcsr_type_no_symmetry, &
     358              :                            dist=prod_dist, row_blk_size=col_blk_size, col_blk_size=col_blk_size)
     359              :          CALL dbcsr_reserve_all_blocks(dbcsr_dummy)
     360              :       END IF
     361              : 
     362              :       !! This work dbcsr matrix will be packed together for easy transfer to other subroutines
     363            8 :       dbcsr_soc_package%dbcsr_sg => dbcsr_sg
     364            8 :       dbcsr_soc_package%dbcsr_tp => dbcsr_tp
     365            8 :       dbcsr_soc_package%dbcsr_work => dbcsr_work
     366            8 :       dbcsr_soc_package%dbcsr_ovlp => dbcsr_ovlp
     367            8 :       dbcsr_soc_package%dbcsr_prod => dbcsr_prod
     368            8 :       dbcsr_soc_package%dbcsr_tmp => dbcsr_tmp
     369              : 
     370              :       !Filling the coeffs matrices by copying from the stored fms
     371            8 :       CALL copy_fm_to_dbcsr(soc_env%a_coeff, dbcsr_sg)
     372            8 :       CALL copy_fm_to_dbcsr(soc_env%b_coeff, dbcsr_tp)
     373              : 
     374              :       !Create the work and helper fms
     375              :       !CALL get_mo_set(mos(1),mo_coeff=gs_coeffs)
     376            8 :       gs_coeffs => gs_mos(1)%mos_occ
     377            8 :       CALL cp_fm_get_info(gs_coeffs, matrix_struct=vec_struct)
     378            8 :       CALL cp_fm_create(vec_soc_x, vec_struct)
     379            8 :       CALL cp_fm_create(vec_soc_y, vec_struct)
     380            8 :       CALL cp_fm_create(vec_soc_z, vec_struct)
     381              : 
     382              :       CALL cp_fm_struct_create(prod_struct, context=blacs_env, para_env=para_env, &
     383            8 :                                nrow_global=nactive, ncol_global=nactive)
     384            8 :       CALL cp_fm_create(prod_fm, prod_struct)
     385              : 
     386              :       CALL cp_fm_struct_create(work_struct, context=blacs_env, para_env=para_env, &
     387            8 :                                nrow_global=nex, ncol_global=nex)
     388            8 :       CALL cp_fm_create(work_fm, work_struct)
     389            8 :       CALL cp_fm_create(tmp_fm, work_struct)
     390              : 
     391              :       IF (log_unit > 0 .AND. debug_this_module) THEN
     392              :          WRITE (log_unit, '(A)') "Starting Precomputations"
     393              :       END IF
     394              : 
     395              :       !! Begin with the precomputation
     396              :       !! Prefactor due to rcs.
     397              :       !! The excitation is presented as a linear combination of
     398              :       !! alpha and beta, where dalpha=-dbeta for triplet exc.
     399              :       !! and dalpha=dbeta for the singlet case
     400            8 :       sqrt2 = SQRT(2.0_dp)
     401              : 
     402              :       !! Precompute the <phi_i^0|H^SOC|phi_j^0> matrix elements
     403           24 :       ALLOCATE (diag(nactive))
     404           64 :       ALLOCATE (mo_soc_x(nactive, nactive), mo_soc_y(nactive, nactive), mo_soc_z(nactive, nactive))
     405              : 
     406              :       !! This will be the GS|H|GS contribution needed for all couplings
     407            8 :       CALL cp_dbcsr_sm_fm_multiply(orb_soc_x, gs_coeffs, vec_soc_x, ncol=nactive)
     408              :       CALL parallel_gemm('T', 'N', nactive, &
     409              :                          nactive, nao, 1.0_dp, &
     410              :                          gs_coeffs, vec_soc_x, &
     411            8 :                          0.0_dp, prod_fm)
     412            8 :       CALL cp_fm_get_submatrix(prod_fm, mo_soc_x)
     413              : 
     414            8 :       CALL cp_dbcsr_sm_fm_multiply(orb_soc_y, gs_coeffs, vec_soc_y, ncol=nactive)
     415              :       CALL parallel_gemm('T', 'N', nactive, &
     416              :                          nactive, nao, 1.0_dp, &
     417              :                          gs_coeffs, vec_soc_y, &
     418            8 :                          0.0_dp, prod_fm)
     419            8 :       CALL cp_fm_get_submatrix(prod_fm, mo_soc_y)
     420              : 
     421            8 :       CALL cp_dbcsr_sm_fm_multiply(orb_soc_z, gs_coeffs, vec_soc_z, ncol=nactive)
     422              :       CALL parallel_gemm('T', 'N', nactive, &
     423              :                          nactive, nao, 1.0_dp, &
     424              :                          gs_coeffs, vec_soc_z, &
     425            8 :                          0.0_dp, prod_fm)
     426            8 :       CALL cp_fm_get_submatrix(prod_fm, mo_soc_z)
     427              : 
     428              :       !  Only have SOC between singlet-triplet triplet-triplet and ground_state-triplet, the resulting
     429              :       !  matrix is Hermitian i.e. the real part is symmetric and the imaginary part is anti-symmetric.
     430              :       !  Can only fill upper half
     431              :       IF (log_unit > 0 .AND. debug_this_module) THEN
     432              :          WRITE (log_unit, '(A)') "Starting Ground-State contributions..."
     433              :       END IF
     434              :       !Start with the ground state/triplet SOC, SOC*gs_coeffs already computed above
     435              :       !note: we are computing <0|H|T>, but have SOC*gs_coeffs instead of gs_coeffs*SOC in store.
     436              :       !Since the SOC Hamiltonian is anti-symmetric, a - signs pops up in the gemms below
     437              :       CALL cp_fm_struct_create(gstp_struct, context=blacs_env, para_env=para_env, &
     438            8 :                                nrow_global=ntp*nactive, ncol_global=nactive)
     439            8 :       CALL cp_fm_create(gstp_fm, gstp_struct)
     440           24 :       ALLOCATE (gstp_block(nactive, nactive))
     441              : 
     442              :       !gs-triplet with Ms=+-1, imaginary part
     443              :       ! <T+-1|H_x|GS>
     444              :       ! -1 to change to <GS|H|T+-1>
     445              :       CALL parallel_gemm('T', 'N', nactive*ntp, &
     446              :                          nactive, nao, -1.0_dp, &
     447              :                          tp_coeffs, vec_soc_x, &
     448            8 :                          0.0_dp, gstp_fm)
     449              : 
     450              :       !! Seperate them into the different states again (nactive x nactive)
     451           30 :       DO itp = 1, ntp
     452              :          CALL cp_fm_get_submatrix(fm=gstp_fm, target_m=gstp_block, &
     453              :                                   start_row=(itp - 1)*nactive + 1, start_col=1, &
     454           22 :                                   n_rows=nactive, n_cols=nactive)
     455           22 :          diag(:) = get_diag(gstp_block)
     456          176 :          soc_gst = SUM(diag)
     457              :          !!  <0|H_x|T^-1>
     458           22 :          CALL cp_fm_set_element(img_fm, 1, 1 + nsg + itp, -1_dp*soc_gst)
     459              :          !! <0|H_x|T^+1>
     460           30 :          CALL cp_fm_set_element(img_fm, 1, 1 + nsg + 2*ntp + itp, soc_gst)
     461              :       END DO
     462              : 
     463              :       IF (debug_this_module .AND. (log_unit > 0)) THEN
     464              :          WRITE (log_unit, "(A,2F18.6)") "<0|H_x|T^-1> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
     465              :          WRITE (log_unit, "(A,2F18.6)") "<0|H_x|T^+1> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
     466              :       END IF
     467              : 
     468              :       !gs-triplet with Ms=+-1, real part
     469              :       ! <T+-1|H_y|GS>
     470              :       CALL parallel_gemm('T', 'N', nactive*ntp, &
     471              :                          nactive, nao, -1.0_dp, &
     472              :                          tp_coeffs, vec_soc_y, &
     473            8 :                          0.0_dp, gstp_fm)
     474              : 
     475           30 :       DO itp = 1, ntp
     476              :          CALL cp_fm_get_submatrix(fm=gstp_fm, target_m=gstp_block, start_row=(itp - 1)*nactive + 1, &
     477           22 :                                   start_col=1, n_rows=nactive, n_cols=nactive)
     478           22 :          diag(:) = get_diag(gstp_block)
     479          176 :          soc_gst = SUM(diag)
     480              :          ! <0|H_y|T^-1>
     481           22 :          CALL cp_fm_set_element(real_fm, 1, 1 + nsg + itp, -1.0_dp*soc_gst)
     482              :          ! <0|H_y|T^+1>
     483           30 :          CALL cp_fm_set_element(real_fm, 1, 1 + nsg + 2*ntp + itp, -1.0_dp*soc_gst)
     484              :       END DO
     485              : 
     486              :       IF (debug_this_module .AND. (log_unit > 0)) THEN
     487              :          WRITE (log_unit, "(A,2F18.6)") "<0|H_y|T^-1> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
     488              :          WRITE (log_unit, "(A,2F18.6)") "<0|H_y|T^+1> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
     489              :       END IF
     490              : 
     491              :       !gs-triplet with Ms=0, purely imaginary
     492              :       !< T0|H_z|GS>
     493              :       CALL parallel_gemm('T', 'N', nactive*ntp, &
     494              :                          nactive, nao, -1.0_dp, &
     495              :                          tp_coeffs, vec_soc_z, &
     496            8 :                          0.0_dp, gstp_fm)
     497              : 
     498           30 :       DO itp = 1, ntp
     499              :          CALL cp_fm_get_submatrix(fm=gstp_fm, &
     500              :                                   target_m=gstp_block, &
     501              :                                   start_row=(itp - 1)*nactive + 1, &
     502              :                                   start_col=1, &
     503              :                                   n_rows=nactive, &
     504           22 :                                   n_cols=nactive)
     505           22 :          diag(:) = get_diag(gstp_block)
     506          176 :          soc_gst = sqrt2*SUM(diag)
     507           30 :          CALL cp_fm_set_element(img_fm, 1, 1 + nsg + ntp + itp, soc_gst)
     508              :       END DO
     509              : 
     510              :       IF (debug_this_module .AND. (log_unit > 0)) THEN
     511              :          WRITE (log_unit, "(A,2F18.6)") "<0|H_z|T> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
     512              :       END IF
     513              : 
     514              :       !! After all::
     515              :       !! T-1 :: -<0|H_x|T^-1> - <0|H_y|T^-1> at 1+nsg+itp
     516              :       !! T+1 :: <0|H_x|T^-1> - <0|H_y|T^-1> at 1+nsp+2tnp+itp
     517              :       !! T0  :: < T0|H_z|GS>                at 1+nsg+ntp+itp
     518              : 
     519              :       !gs clean-up
     520            8 :       CALL cp_fm_release(prod_fm)
     521            8 :       CALL cp_fm_release(vec_soc_x)
     522            8 :       CALL cp_fm_release(vec_soc_y)
     523            8 :       CALL cp_fm_release(vec_soc_z)
     524            8 :       CALL cp_fm_release(gstp_fm)
     525            8 :       CALL cp_fm_struct_release(gstp_struct)
     526            8 :       CALL cp_fm_struct_release(prod_struct)
     527            8 :       DEALLOCATE (gstp_block)
     528              : 
     529              :       IF (log_unit > 0 .AND. debug_this_module) THEN
     530              :          WRITE (log_unit, '(A)') "Starting Singlet-Triplet contributions..."
     531              :       END IF
     532              : 
     533              :       !Now do the singlet-triplet SOC
     534              :       !start by computing the singlet-triplet overlap
     535              :       ! <S|T>
     536              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, &
     537              :                           matrix_s(1)%matrix, &
     538              :                           dbcsr_tp, 0.0_dp, &
     539              :                           dbcsr_work, &
     540            8 :                           filter_eps=eps_filter)
     541              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, &
     542              :                           dbcsr_sg, &
     543              :                           dbcsr_work, &
     544              :                           0.0_dp, dbcsr_ovlp, &
     545            8 :                           filter_eps=eps_filter)
     546              : 
     547              :       !singlet-triplet with Ms=+-1, imaginary part
     548              :       ! First precalculate <S|H_x|T+-1>
     549              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, &
     550              :                           orb_soc_x, &
     551              :                           dbcsr_tp, 0.0_dp, &
     552              :                           dbcsr_work, &
     553            8 :                           filter_eps=eps_filter)
     554              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, &
     555              :                           dbcsr_sg, &
     556              :                           dbcsr_work, 0.0_dp, &
     557              :                           dbcsr_prod, &
     558            8 :                           filter_eps=eps_filter)
     559              : 
     560              :       !! This will lead to:
     561              :       !! -1/sqrt(2)(<S|H_x|T> - <S|T> <GS|H_x|GS>)
     562              :       CALL rcs_amew_soc_elements(dbcsr_tmp, &
     563              :                                  dbcsr_prod, &
     564              :                                  dbcsr_ovlp, &
     565              :                                  mo_soc_x, &
     566              :                                  pref_trace=-1.0_dp, &
     567            8 :                                  pref_overall=-0.5_dp*sqrt2)
     568              : 
     569              :       !<S|H_x|T^-1>
     570              :       !! Convert to fm for transfer to img_fm
     571            8 :       CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
     572              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     573              :                               mtarget=img_fm, &
     574              :                               nrow=nex, &
     575              :                               ncol=nex, &
     576              :                               s_firstrow=1, &
     577              :                               s_firstcol=1, &
     578              :                               t_firstrow=2, &
     579            8 :                               t_firstcol=1 + nsg + 1)
     580              : 
     581              :       IF (debug_this_module) THEN
     582              :          WRITE (log_unit, "(/,A)") "<S|H_x|T^-1> in Hartree / cm^-1"
     583              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     584              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     585              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     586              :       END IF
     587              : 
     588              :       !<S|H_x|T^+1> takes a minus sign
     589            8 :       CALL cp_fm_scale(-1.0_dp, tmp_fm)
     590              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     591              :                               mtarget=img_fm, &
     592              :                               nrow=nex, &
     593              :                               ncol=nex, &
     594              :                               s_firstrow=1, &
     595              :                               s_firstcol=1, &
     596              :                               t_firstrow=2, &
     597            8 :                               t_firstcol=1 + nsg + 2*ntp + 1)
     598              : 
     599              :       IF (debug_this_module) THEN
     600              :          WRITE (log_unit, "(/,A)") "<S|H_x|T^+1> in Hartree / cm^-1"
     601              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     602              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     603              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     604              :       END IF
     605              : 
     606              :        !!singlet-triplet with Ms=+-1, real part
     607              :        !! Precompute <S|H_y|T>
     608              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, &
     609              :                           orb_soc_y, dbcsr_tp, &
     610              :                           0.0_dp, dbcsr_work, &
     611            8 :                           filter_eps=eps_filter)
     612              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, &
     613              :                           dbcsr_sg, dbcsr_work, &
     614              :                           0.0_dp, dbcsr_prod, &
     615            8 :                           filter_eps=eps_filter)
     616              : 
     617              :       !! This will lead to -1/sqrt(2)(<S|H_y|T> - <S|T> <GS|H_y|GS>)
     618              :       CALL rcs_amew_soc_elements(dbcsr_tmp, &
     619              :                                  dbcsr_prod, &
     620              :                                  dbcsr_ovlp, &
     621              :                                  mo_soc_y, &
     622              :                                  pref_trace=-1.0_dp, &
     623            8 :                                  pref_overall=-0.5_dp*sqrt2)
     624              : 
     625              :       !<S|H_y|T^-1>
     626            8 :       CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
     627              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     628              :                               mtarget=real_fm, &
     629              :                               nrow=nex, &
     630              :                               ncol=nex, &
     631              :                               s_firstrow=1, &
     632              :                               s_firstcol=1, &
     633              :                               t_firstrow=2, &
     634            8 :                               t_firstcol=1 + nsg + 1)
     635              : 
     636              :       IF (debug_this_module) THEN
     637              :          WRITE (log_unit, "(/,A)") "<S|H_y|T^-1> in Hartree / cm^-1"
     638              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     639              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     640              :          CALL dbcsr_print(dbcsr_tmp, unit_nr=log_unit)
     641              :       END IF
     642              : 
     643              :       !<S|H_y|T^+1>
     644              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     645              :                               mtarget=real_fm, &
     646              :                               nrow=nex, &
     647              :                               ncol=nex, &
     648              :                               s_firstrow=1, &
     649              :                               s_firstcol=1, &
     650              :                               t_firstrow=2, &
     651            8 :                               t_firstcol=1 + nsg + 2*ntp + 1)
     652              : 
     653              :       IF (debug_this_module) THEN
     654              :          WRITE (log_unit, "(/,A)") "<S|H_y|T^+1> in Hartree / cm^-1"
     655              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     656              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     657              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     658              :       END IF
     659              : 
     660              :       !singlet-triplet with Ms=0, purely imaginary
     661              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, &
     662              :                           orb_soc_z, dbcsr_tp, &
     663              :                           0.0_dp, dbcsr_work, &
     664            8 :                           filter_eps=eps_filter)
     665              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, &
     666              :                           dbcsr_sg, dbcsr_work, &
     667              :                           0.0_dp, dbcsr_prod, &
     668            8 :                           filter_eps=eps_filter)
     669              : 
     670              :       CALL rcs_amew_soc_elements(dbcsr_tmp, &
     671              :                                  dbcsr_prod, &
     672              :                                  dbcsr_ovlp, &
     673              :                                  mo_soc_z, &
     674              :                                  pref_trace=-1.0_dp, &
     675            8 :                                  pref_overall=1.0_dp)
     676              : 
     677              :       !<S|H_z|T^0>
     678            8 :       CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
     679              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     680              :                               mtarget=img_fm, &
     681              :                               nrow=nex, &
     682              :                               ncol=nex, &
     683              :                               s_firstrow=1, &
     684              :                               s_firstcol=1, &
     685              :                               t_firstrow=2, &
     686            8 :                               t_firstcol=1 + nsg + ntp + 1)
     687              : 
     688              :       IF (debug_this_module) THEN
     689              :          WRITE (log_unit, "(/,A)") "<S|H_z|T^0> in Hartree / cm^-1"
     690              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     691              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     692              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     693              :       END IF
     694              : 
     695              :       IF (log_unit > 0 .AND. debug_this_module) THEN
     696              :          WRITE (log_unit, '(A)') "Starting Triplet-Triplet contributions..."
     697              :       END IF
     698              : 
     699              :       !Now the triplet-triplet SOC
     700              :       !start by computing the overlap
     701              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, &
     702              :                           matrix_s(1)%matrix, &
     703              :                           dbcsr_tp, 0.0_dp, &
     704              :                           dbcsr_work, &
     705            8 :                           filter_eps=eps_filter)
     706              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, &
     707              :                           dbcsr_tp, dbcsr_work, &
     708              :                           0.0_dp, dbcsr_ovlp, &
     709            8 :                           filter_eps=eps_filter)
     710              : 
     711              :       !Ms=0 to Ms=+-1 SOC, imaginary part
     712              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, &
     713              :                           orb_soc_x, dbcsr_tp, &
     714              :                           0.0_dp, dbcsr_work, &
     715            8 :                           filter_eps=eps_filter)
     716              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, &
     717              :                           dbcsr_tp, dbcsr_work, &
     718              :                           0.0_dp, dbcsr_prod, &
     719            8 :                           filter_eps=eps_filter)
     720              : 
     721              :       CALL rcs_amew_soc_elements(dbcsr_tmp, &
     722              :                                  dbcsr_prod, &
     723              :                                  dbcsr_ovlp, &
     724              :                                  mo_soc_x, &
     725              :                                  pref_trace=1.0_dp, &
     726            8 :                                  pref_overall=-0.5_dp*sqrt2)
     727              : 
     728              :       !<T^0|H_x|T^+1>
     729            8 :       CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
     730              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     731              :                               mtarget=img_fm, &
     732              :                               nrow=nex, &
     733              :                               ncol=nex, &
     734              :                               s_firstrow=1, &
     735              :                               s_firstcol=1, &
     736              :                               t_firstrow=1 + nsg + ntp + 1, &
     737            8 :                               t_firstcol=1 + nsg + 2*ntp + 1)
     738              : 
     739              :       IF (debug_this_module) THEN
     740              :          WRITE (log_unit, "(/,A)") "<T^0|H_x|T^+1> in Hartree / cm^-1"
     741              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     742              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     743              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     744              :       END IF
     745              : 
     746              :       !<T^-1|H_x|T^0>, takes a minus sign and a transpose (because computed <T^0|H_x|T^-1>)
     747            8 :       CALL cp_fm_transpose(tmp_fm, work_fm)
     748            8 :       CALL cp_fm_scale(-1.0_dp, work_fm)
     749              :       CALL cp_fm_to_fm_submat(msource=work_fm, &
     750              :                               mtarget=img_fm, &
     751              :                               nrow=nex, &
     752              :                               ncol=nex, &
     753              :                               s_firstrow=1, &
     754              :                               s_firstcol=1, &
     755              :                               t_firstrow=1 + nsg + 1, &
     756            8 :                               t_firstcol=1 + nsg + ntp + 1)
     757              : 
     758              :       IF (debug_this_module) THEN
     759              :          WRITE (log_unit, "(/,A)") "<T^-1|H_x|T^0> in Hartree / cm^-1"
     760              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     761              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     762              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     763              :       END IF
     764              : 
     765              :       !Ms=0 to Ms=+-1 SOC, real part
     766              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, &
     767              :                           orb_soc_y, dbcsr_tp, &
     768              :                           0.0_dp, dbcsr_work, &
     769            8 :                           filter_eps=eps_filter)
     770              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, &
     771              :                           dbcsr_tp, dbcsr_work, &
     772              :                           0.0_dp, dbcsr_prod, &
     773            8 :                           filter_eps=eps_filter)
     774              : 
     775              :       CALL rcs_amew_soc_elements(dbcsr_tmp, &
     776              :                                  dbcsr_prod, &
     777              :                                  dbcsr_ovlp, &
     778              :                                  mo_soc_y, &
     779              :                                  pref_trace=1.0_dp, &
     780            8 :                                  pref_overall=0.5_dp*sqrt2)
     781              : 
     782              :       !<T^0|H_y|T^+1>
     783            8 :       CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
     784              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     785              :                               mtarget=real_fm, &
     786              :                               nrow=nex, &
     787              :                               ncol=nex, &
     788              :                               s_firstrow=1, &
     789              :                               s_firstcol=1, t_firstrow=1 + nsg + ntp + 1, &
     790            8 :                               t_firstcol=1 + nsg + 2*ntp + 1)
     791              : 
     792              :       IF (debug_this_module) THEN
     793              :          WRITE (log_unit, "(/,A)") "<T^0|H_y|T^+1> in Hartree / cm^-1"
     794              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     795              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     796              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     797              :       END IF
     798              : 
     799              :       !<T^-1|H_y|T^0>, takes a minus sign and a transpose
     800            8 :       CALL cp_fm_transpose(tmp_fm, work_fm)
     801            8 :       CALL cp_fm_scale(-1.0_dp, work_fm)
     802              :       CALL cp_fm_to_fm_submat(msource=work_fm, &
     803              :                               mtarget=real_fm, &
     804              :                               nrow=nex, &
     805              :                               ncol=nex, &
     806              :                               s_firstrow=1, &
     807              :                               s_firstcol=1, t_firstrow=1 + nsg + 1, &
     808            8 :                               t_firstcol=1 + nsg + ntp + 1)
     809              : 
     810              :       IF (debug_this_module) THEN
     811              :          WRITE (log_unit, "(/,A)") "<T^0|H_y|T^+1> in Hartree / cm^-1"
     812              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     813              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     814              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     815              :       END IF
     816              : 
     817              :       !Ms=1 to Ms=1 and Ms=-1 to Ms=-1 SOC, purely imaginary
     818              :       CALL dbcsr_multiply('N', 'N', 1.0_dp, &
     819              :                           orb_soc_z, dbcsr_tp, &
     820              :                           0.0_dp, dbcsr_work, &
     821            8 :                           filter_eps=eps_filter)
     822              :       CALL dbcsr_multiply('T', 'N', 1.0_dp, &
     823              :                           dbcsr_tp, dbcsr_work, &
     824              :                           0.0_dp, dbcsr_prod, &
     825            8 :                           filter_eps=eps_filter)
     826              : 
     827              :       CALL rcs_amew_soc_elements(dbcsr_tmp, &
     828              :                                  dbcsr_prod, &
     829              :                                  dbcsr_ovlp, &
     830              :                                  mo_soc_z, &
     831              :                                  pref_trace=1.0_dp, &
     832            8 :                                  pref_overall=1.0_dp)
     833              : 
     834              :       !<T^+1|H_z|T^+1>
     835            8 :       CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
     836              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     837              :                               mtarget=img_fm, &
     838              :                               nrow=nex, &
     839              :                               ncol=nex, &
     840              :                               s_firstrow=1, &
     841              :                               s_firstcol=1, &
     842              :                               t_firstrow=1 + nsg + 2*ntp + 1, &
     843            8 :                               t_firstcol=1 + nsg + 2*ntp + 1)
     844              : 
     845              :       IF (debug_this_module) THEN
     846              :          WRITE (log_unit, "(/,A)") "<T^+1|H_z|T^+1> in Hartree / cm^-1"
     847              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     848              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     849              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     850              :       END IF
     851              : 
     852              :       !<T^-1|H_z|T^-1>, takes a minus sign
     853            8 :       CALL cp_fm_scale(-1.0_dp, tmp_fm)
     854              :       CALL cp_fm_to_fm_submat(msource=tmp_fm, &
     855              :                               mtarget=img_fm, &
     856              :                               nrow=nex, &
     857              :                               ncol=nex, &
     858              :                               s_firstrow=1, &
     859              :                               s_firstcol=1, &
     860              :                               t_firstrow=1 + nsg + 1, &
     861            8 :                               t_firstcol=1 + nsg + 1)
     862              : 
     863              :       IF (debug_this_module) THEN
     864              :          WRITE (log_unit, "(/,A)") "<T^-1|H_z|T^-1> in Hartree / cm^-1"
     865              :          CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
     866              :          CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
     867              :          CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
     868              :       END IF
     869              : 
     870              :       !Intermediate clean-up
     871            8 :       CALL cp_fm_struct_release(work_struct)
     872            8 :       CALL cp_fm_release(work_fm)
     873            8 :       CALL cp_fm_release(tmp_fm)
     874            8 :       DEALLOCATE (diag, mo_soc_x, mo_soc_y, mo_soc_z)
     875              : 
     876            8 :       IF (log_unit > 0) THEN
     877            4 :          WRITE (log_unit, '(A)') "Diagonlzing SOC-Matrix"
     878              :       END IF
     879              : 
     880              :       !Set-up the complex hermitian perturbation matrix
     881            8 :       CALL cp_cfm_create(hami_cfm, full_struct)
     882            8 :       CALL cp_fm_to_cfm(real_fm, img_fm, hami_cfm)
     883              : 
     884              :       !!Optinal Output: SOC-Matrix
     885            8 :       IF (logger%para_env%is_source()) THEN
     886              :          log_unit = cp_print_key_unit_nr(logger, &
     887              :                                          tddfpt_print_section, &
     888              :                                          "SOC_PRINT", &
     889              :                                          extension=".socme", &
     890              :                                          file_form="FORMATTED", &
     891              :                                          file_action="WRITE", &
     892            4 :                                          file_status="UNKNOWN")
     893              :       ELSE
     894            4 :          log_unit = -1
     895              :       END IF
     896              : 
     897              :       !! Get the requested energy unit and optional outputs
     898            8 :       CALL section_vals_val_get(soc_print_section, "UNIT_eV", l_val=print_ev)
     899            8 :       CALL section_vals_val_get(soc_print_section, "UNIT_wn", l_val=print_wn)
     900            8 :       CALL section_vals_val_get(soc_print_section, "SPLITTING", l_val=print_splitting)
     901            8 :       CALL section_vals_val_get(soc_print_section, "SOME", l_val=print_some)
     902              : 
     903              :       !! save convertion unit into different varible for cleaner code
     904            8 :       IF (print_wn) THEN
     905            2 :          print_ev = .FALSE.
     906            2 :          unit_scale = wavenumbers
     907            6 :       ELSE IF (print_ev) THEN
     908              :          unit_scale = evolt
     909              :       ELSE
     910            0 :          CPWARN("No output unit was selected, printout will be in Hartree!")
     911            0 :          unit_scale = 1
     912              :       END IF
     913              : 
     914              :       !! This needs something to deal with a parallel run
     915              :       !! This output will be needed for NEWTONX for ISC!!
     916            8 :       IF (print_some) THEN
     917            2 :          IF (log_unit > 0) THEN
     918            1 :             WRITE (log_unit, '(A)') "____________________________________________________"
     919            1 :             WRITE (log_unit, '(A)') "                   FULL SOC-Matrix                  "
     920            1 :             IF (print_ev) THEN
     921            0 :                WRITE (log_unit, '(A)') "STATE   STATE   REAL-PART[eV]       IMG-PART[eV]    "
     922            1 :             ELSE IF (print_wn) THEN
     923            1 :                WRITE (log_unit, '(A)') "STATE   STATE   REAL-PART[cm-1]       IMG-PART[cm-1]"
     924              :             ELSE
     925            0 :                WRITE (log_unit, '(A)') "STATE   STATE   REAL-PART[Hartree] IMG-PART[Hartree]"
     926              :             END IF
     927            1 :             WRITE (log_unit, '(A)') "____________________________________________________"
     928              :          END IF
     929           12 :          ALLOCATE (real_tmp(ntot, ntot), img_tmp(ntot, ntot))
     930          182 :          real_tmp = 0_dp
     931          182 :          img_tmp = 0_dp
     932              : 
     933            2 :          CALL cp_fm_get_submatrix(real_fm, real_tmp, 1, 1, ntot, ntot)
     934            2 :          CALL cp_fm_get_submatrix(img_fm, img_tmp, 1, 1, ntot, ntot)
     935              : 
     936            2 :          IF (log_unit > 0) THEN
     937           10 :             DO jj = 1, ntot
     938           91 :                DO ii = 1, ntot
     939           81 :                   WRITE (unit=log_unit, fmt="(I3,5X,I3,5X,f16.8,5X,f16.8)") ii, jj, &
     940           81 :                      real_tmp(ii, jj)*unit_scale, &
     941          171 :                      img_tmp(ii, jj)*unit_scale
     942              :                END DO !! jj
     943              :             END DO        !! ii
     944            1 :             WRITE (log_unit, '(A)') "                   END SOC-MATRIX                   "
     945            1 :             WRITE (log_unit, '(A)') "____________________________________________________"
     946            1 :             WRITE (log_unit, '(A)') "____________________________________________________"
     947              :          END IF !(log_unit)
     948            2 :          DEALLOCATE (real_tmp, img_tmp)
     949              :       END IF !print_some
     950              : 
     951            8 :       CALL cp_fm_release(real_fm)
     952            8 :       CALL cp_fm_release(img_fm)
     953              : 
     954              :       ! Diagonalize the Hamiltonian
     955           24 :       ALLOCATE (tmp_evals(ntot))
     956            8 :       CALL cp_cfm_create(evecs_cfm, full_struct)
     957            8 :       CALL cp_cfm_heevd(hami_cfm, evecs_cfm, tmp_evals)
     958              : 
     959              :       !  Adjust the energies so the GS has zero, and store in the donor_state (without the GS)
     960           24 :       ALLOCATE (soc_env%soc_evals(ntot - 1))
     961           96 :       soc_env%soc_evals(:) = tmp_evals(2:ntot) - tmp_evals(1)
     962              : 
     963              :       !! We may be interested in the ground state stabilisation energy
     964            8 :       IF (logger%para_env%is_source()) THEN
     965            4 :          log_unit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     966              :       ELSE
     967            4 :          log_unit = -1
     968              :       END IF
     969              : 
     970            8 :       IF (log_unit > 0) THEN
     971            4 :          WRITE (log_unit, '(A27,6X,F18.10)') "Ground state stabilisation:", (soc_env%soc_evals(1)*unit_scale)
     972              :          IF (debug_this_module) THEN
     973              :             WRITE (log_unit, '(A)') "Calculation Dipole Moments"
     974              :          END IF
     975              :       END IF
     976              : 
     977              :       !Compute the dipole oscillator strengths
     978            8 :       soc_env%evals_a => evals_sing
     979            8 :       soc_env%evals_b => evals_trip
     980              :       CALL soc_dipol(qs_env, dbcsr_soc_package, soc_env, &
     981              :                      evecs_cfm, eps_filter, dipole_form, gs_mos, &
     982            8 :                      evects_sing, evects_trip)
     983              : 
     984              :       !Create final output
     985              :       !! Output unit is choosen by the keyword "UNIT_eV" and "UNIT_wn" in "SOC_PRINT" section
     986            8 :       IF (logger%para_env%is_source()) THEN
     987            4 :          log_unit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
     988              :       ELSE
     989            4 :          log_unit = -1
     990              :       END IF
     991              : 
     992            8 :       IF (log_unit > 0) THEN
     993            4 :          WRITE (log_unit, '(A)') "------------------------------------------------------------------------------"
     994            4 :          WRITE (log_unit, '(A)') "-                         SOC CORRECTED SPECTRUM                             -"
     995            4 :          WRITE (log_unit, '(A)') "------------------------------------------------------------------------------"
     996            4 :          IF (print_ev) THEN
     997            3 :             WRITE (log_unit, '(A)') "-     STATE   SOC-corrected exc. energies [eV]  Oscillator strengths [a.u.]  -"
     998            1 :          ELSE IF (print_wn) THEN
     999            1 :             WRITE (log_unit, '(A)') "-     STATE   SOC-corrected exc. energies [cm-1] Oscillator strengths [a.u.]-"
    1000              :          ELSE
    1001            0 :             WRITE (log_unit, '(A)') "-     STATE SOC-corrected exc.energies [Hartree] Oscillator strengths [a.u.]-"
    1002              :          END IF
    1003            4 :          WRITE (log_unit, '(A)') "------------------------------------------------------------------------------"
    1004           48 :          DO istate = 1, SIZE(soc_env%soc_evals)
    1005           44 :             WRITE (log_unit, '(6X,I5,11X,2F16.5)') istate, soc_env%soc_evals(istate)*unit_scale, &
    1006           92 :                soc_env%soc_osc(istate)
    1007              :          END DO
    1008              :          !! This is used for regtesting
    1009           48 :          WRITE (log_unit, '(A,F18.8)') "TDDFT+SOC : CheckSum (eV) ", SUM(soc_env%soc_evals)*evolt
    1010              :       END IF
    1011              : 
    1012              :       !! We may be interested in the differenz between the SOC and
    1013              :       !! TDDFPT Eigenvalues
    1014              :       !! Activated with the "SPLITTING" keyword in "SOC_PRINT" section
    1015           16 :       IF (print_splitting .OR. debug_this_module) THEN
    1016            8 :          CALL resort_evects(evecs_cfm, evects_sort)
    1017            8 :          IF (log_unit > 0) THEN
    1018            4 :             WRITE (log_unit, '(A)') "-----------------------------------------------------------------------------"
    1019            4 :             WRITE (log_unit, '(A)') "-                              Splittings                                   -"
    1020            4 :             WRITE (log_unit, '(A)') "-----------------------------------------------------------------------------"
    1021            4 :             IF (print_ev) THEN
    1022            3 :                WRITE (log_unit, '(A)') "-     STATE          exc.energies[eV]          splittings[eV]               -"
    1023            1 :             ELSE IF (print_wn) THEN
    1024            1 :                WRITE (log_unit, '(A)') "-     STATE          exc.energies[cm-1]        splittings[cm-1]             -"
    1025              :             ELSE
    1026            0 :                WRITE (log_unit, '(A)') "-     STATE          exc.energies[Hartree]     splittings[Hartree]          -"
    1027              :             END IF
    1028            4 :             WRITE (log_unit, '(A)') "-----------------------------------------------------------------------------"
    1029            4 :             mult = "   "
    1030           48 :             DO iex = 1, SIZE(soc_env%soc_evals)
    1031           44 :                IF (evects_sort(iex + 1) .GT. nsg + ntp*2 + 1) THEN
    1032           11 :                   mult = "T+1"
    1033           33 :                ELSE IF (evects_sort(iex + 1) .GT. nsg + ntp + 1) THEN
    1034           11 :                   mult = "T0"
    1035           22 :                ELSE IF (evects_sort(iex + 1) .GT. nsg + 1) THEN
    1036           11 :                   mult = "T-1"
    1037              :                ELSE
    1038           11 :                   mult = "S  "
    1039              :                END IF
    1040           48 :                IF (mult == "T-1") THEN
    1041           11 :                   WRITE (log_unit, "(5X,A,I5,6X,F18.10,6X,F18.10)") mult, &
    1042           11 :                      evects_sort(iex + 1) - (1 + nsg), soc_env%soc_evals(iex)*unit_scale, &
    1043           22 :                      (soc_env%soc_evals(iex) - evals_trip(evects_sort(iex + 1) - (1 + nsg)))*unit_scale
    1044           33 :                ELSE IF (mult == "T0") THEN
    1045           11 :                   WRITE (log_unit, "(5X,A,I5,6X,F18.10,6X,F18.10)") mult, &
    1046           11 :                      evects_sort(iex + 1) - (1 + nsg + ntp), soc_env%soc_evals(iex)*unit_scale, &
    1047           22 :                      (soc_env%soc_evals(iex) - evals_trip(evects_sort(iex + 1) - (1 + nsg + ntp)))*unit_scale
    1048           22 :                ELSE IF (mult == "T+1") THEN
    1049           11 :                   WRITE (log_unit, "(5X,A,I5,6X,F18.10,6X,F18.10)") mult, &
    1050           11 :                      evects_sort(iex + 1) - (1 + nsg + ntp*2), soc_env%soc_evals(iex)*unit_scale, &
    1051           22 :                      (soc_env%soc_evals(iex) - evals_trip(evects_sort(iex + 1) - (1 + nsg + ntp*2)))*unit_scale
    1052           11 :                ELSE IF (mult == "S  ") THEN
    1053           11 :                   WRITE (log_unit, "(5X,A,I5,6X,F18.10,6X,F18.10)") mult, &
    1054           11 :                      evects_sort(iex + 1), soc_env%soc_evals(iex)*unit_scale, &
    1055           22 :                      (soc_env%soc_evals(iex) - evals_sing(evects_sort(iex + 1) - 1))*unit_scale
    1056              :                END IF
    1057              :             END DO
    1058            4 :             WRITE (log_unit, '(A)') "----------------------------------------------------------------------------"
    1059            4 :             DEALLOCATE (evects_sort)
    1060              :          END IF
    1061              :       END IF
    1062              : 
    1063              :       !! clean up
    1064            8 :       CALL soc_env_release(soc_env)
    1065            8 :       CALL cp_fm_struct_release(full_struct)
    1066            8 :       CALL cp_cfm_release(hami_cfm)
    1067            8 :       CALL cp_cfm_release(evecs_cfm)
    1068            8 :       CALL dbcsr_distribution_release(coeffs_dist)
    1069            8 :       CALL dbcsr_distribution_release(prod_dist)
    1070            8 :       CALL dbcsr_release(dbcsr_sg)
    1071            8 :       CALL dbcsr_release(dbcsr_tp)
    1072            8 :       CALL dbcsr_release(dbcsr_prod)
    1073            8 :       CALL dbcsr_release(dbcsr_ovlp)
    1074            8 :       CALL dbcsr_release(dbcsr_tmp)
    1075            8 :       CALL dbcsr_release(dbcsr_work)
    1076              :       IF (debug_this_module) THEN
    1077              :          CALL dbcsr_release(dbcsr_dummy)
    1078              :          DEALLOCATE (dbcsr_dummy)
    1079              :       END IF
    1080              : 
    1081            8 :       DEALLOCATE (dbcsr_work, dbcsr_prod, dbcsr_ovlp, dbcsr_tmp)
    1082            8 :       DEALLOCATE (coeffs_dist, prod_dist, col_dist, col_blk_size, row_dist_new)
    1083            8 :       DEALLOCATE (dbcsr_sg, dbcsr_tp, tmp_evals)
    1084              : 
    1085            8 :       CALL timestop(handle)
    1086              : 
    1087          112 :    END SUBROUTINE tddfpt_soc_rcs
    1088              : 
    1089              : ! **************************************************************************************************
    1090              : !> \brief Some additional initalizations
    1091              : !> \param qs_env Quickstep environment
    1092              : !> \param soc_atom_env contains information to build the ZORA-Hamiltionian
    1093              : !> \param soc_env contails details and outputs for SOC Correction
    1094              : !> \param evects_a singlet Eigenvectors
    1095              : !> \param evects_b triplet eigenvectors
    1096              : !> \param dipole_form choosen dipole-form from TDDFPT-Section
    1097              : !> \param gs_mos ...
    1098              : ! **************************************************************************************************
    1099            8 :    SUBROUTINE inititialize_soc(qs_env, soc_atom_env, soc_env, &
    1100            8 :                                evects_a, evects_b, &
    1101            8 :                                dipole_form, gs_mos)
    1102              :       !! Different Types
    1103              :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
    1104              :       TYPE(soc_atom_env_type), INTENT(OUT), POINTER      :: soc_atom_env
    1105              :       TYPE(soc_env_type), INTENT(OUT), TARGET            :: soc_env
    1106              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evects_a, evects_b
    1107              :       INTEGER                                            :: dipole_form
    1108              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
    1109              :          INTENT(in)                                      :: gs_mos
    1110              : 
    1111              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'inititialize_soc'
    1112              : 
    1113              :       CHARACTER(len=default_string_length), &
    1114              :          ALLOCATABLE, DIMENSION(:, :)                    :: grid_info
    1115              :       CHARACTER(len=default_string_length), &
    1116            8 :          DIMENSION(:), POINTER                           :: k_list
    1117              :       INTEGER                                            :: handle, i, ikind, irep, ispin, nactive, &
    1118              :                                                             nao, natom, nkind, nrep, nspins, &
    1119              :                                                             nstates
    1120              :       LOGICAL                                            :: all_potential_present, do_os
    1121              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1122              :       TYPE(cp_fm_struct_type), POINTER                   :: fm_struct
    1123              :       TYPE(cp_fm_type), POINTER                          :: a_coeff, b_coeff
    1124            8 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
    1125              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1126            8 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1127              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1128            8 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
    1129            8 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1130              :       TYPE(section_vals_type), POINTER                   :: soc_section
    1131              :       TYPE(tddfpt2_control_type), POINTER                :: tddfpt_control
    1132              : 
    1133            8 :       CALL timeset(routineN, handle)
    1134              : 
    1135            8 :       NULLIFY (qs_kind_set, particle_set, blacs_env, para_env, &
    1136            8 :                a_coeff, b_coeff, tddfpt_control, soc_section)
    1137              : 
    1138              :       !! Open_shell is not implemented yet
    1139            8 :       do_os = .FALSE.
    1140              : 
    1141              :       !! soc_env will pass most of the larger matrices to the different modules
    1142            8 :       CALL soc_env_create(soc_env)
    1143              :       CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, &
    1144              :                       mos=mos, natom=natom, &
    1145              :                       particle_set=particle_set, blacs_env=blacs_env, &
    1146              :                       para_env=para_env, matrix_s=matrix_s, &
    1147            8 :                       dft_control=dft_control)
    1148              : 
    1149              :       !! The Dipole form shall be consistent with the tddfpt-module!
    1150            8 :       tddfpt_control => dft_control%tddfpt2_control
    1151            8 :       dipole_form = tddfpt_control%dipole_form
    1152              : 
    1153            8 :       soc_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%SOC")
    1154              : 
    1155              :       !! We may want to use a bigger grid then default
    1156            8 :       CALL section_vals_val_get(soc_section, "GRID", n_rep_val=nrep)
    1157           16 :       ALLOCATE (grid_info(nrep, 3))
    1158            8 :       DO irep = 1, nrep
    1159              :          CALL section_vals_val_get(soc_section, &
    1160              :                                    "GRID", &
    1161              :                                    i_rep_val=irep, &
    1162            0 :                                    c_vals=k_list)
    1163            8 :          grid_info(irep, :) = k_list
    1164              :       END DO
    1165              : 
    1166            8 :       CALL soc_dipole_operator(soc_env, tddfpt_control, qs_env, gs_mos)
    1167              : 
    1168            8 :       nspins = SIZE(evects_a, 1)
    1169           16 :       DO ispin = 1, nspins
    1170           16 :          CALL cp_fm_get_info(evects_a(ispin, 1), nrow_global=nao, ncol_global=nactive)
    1171              :       END DO
    1172              : 
    1173              :       !! We need to change and create structures for the exitation vectors.
    1174              :       !! All excited states shall be written in one matrix, oneafter the other
    1175            8 :       nstates = SIZE(evects_a, 2)
    1176              : 
    1177            8 :       a_coeff => soc_env%a_coeff
    1178            8 :       b_coeff => soc_env%b_coeff
    1179              : 
    1180            8 :       NULLIFY (fm_struct)
    1181              :       CALL cp_fm_struct_create(fm_struct, context=blacs_env, para_env=para_env, &
    1182            8 :                                nrow_global=nao, ncol_global=nspins*nactive*nstates)
    1183            8 :       CALL cp_fm_create(a_coeff, fm_struct)
    1184            8 :       CALL cp_fm_create(b_coeff, fm_struct)
    1185            8 :       CALL cp_fm_struct_release(fm_struct)
    1186              : 
    1187            8 :       CALL soc_contract_evect(evects_a, a_coeff)
    1188            8 :       CALL soc_contract_evect(evects_b, b_coeff)
    1189              : 
    1190           32 :       ALLOCATE (soc_env%orb_soc(3))
    1191           32 :       DO i = 1, 3
    1192           32 :          ALLOCATE (soc_env%orb_soc(i)%matrix)
    1193              :       END DO
    1194              : 
    1195              :       ! Make soc_atom_env for H^SOC calculations
    1196              :       ! Compute the contraction coefficients for spherical orbitals
    1197            8 :       CALL soc_atom_create(soc_atom_env)
    1198              :       IF (do_os) THEN
    1199              :          soc_atom_env%nspins = 2
    1200              :       ELSE
    1201            8 :          soc_atom_env%nspins = 1
    1202              :       END IF
    1203              : 
    1204            8 :       nkind = SIZE(qs_kind_set)
    1205           32 :       ALLOCATE (soc_atom_env%grid_atom_set(nkind))
    1206           32 :       ALLOCATE (soc_atom_env%harmonics_atom_set(nkind))
    1207           32 :       ALLOCATE (soc_atom_env%orb_sphi_so(nkind))
    1208              : 
    1209            8 :       CALL get_qs_kind_set(qs_kind_set, all_potential_present=all_potential_present)
    1210            8 :       IF (.NOT. all_potential_present) THEN
    1211            2 :          CALL V_SOC_xyz_from_pseudopotential(qs_env, soc_atom_env%soc_pp)
    1212              :       END IF
    1213              : 
    1214              :       !! Prepare the atomic grid we need to calculate the SOC Operator in an Atomic basis
    1215              :       !! copied from init_xas_atom_grid_harmo for convenience
    1216            8 :       CALL init_atom_grid(soc_atom_env, grid_info, qs_env)
    1217              : 
    1218           16 :       DO ikind = 1, nkind
    1219            8 :          NULLIFY (soc_atom_env%orb_sphi_so(ikind)%array)
    1220           16 :          CALL compute_sphi_so(ikind, "ORB", soc_atom_env%orb_sphi_so(ikind)%array, qs_env)
    1221              :       END DO !ikind
    1222              : 
    1223            8 :       DEALLOCATE (grid_info)
    1224              : 
    1225            8 :       CALL timestop(handle)
    1226              : 
    1227           40 :    END SUBROUTINE inititialize_soc
    1228              : 
    1229              : ! **************************************************************************************************
    1230              : !> \brief Initializes the atomic grids and harmonics for the atomic calculations
    1231              : !> \param soc_atom_env ...
    1232              : !> \param grid_info ...
    1233              : !> \param qs_env ...
    1234              : !> \note Copied and modified from init_xas_atom_grid_harmo
    1235              : ! **************************************************************************************************
    1236            8 :    SUBROUTINE init_atom_grid(soc_atom_env, grid_info, qs_env)
    1237              : 
    1238              :       TYPE(soc_atom_env_type)                            :: soc_atom_env
    1239              :       CHARACTER(len=default_string_length), &
    1240              :          ALLOCATABLE, DIMENSION(:, :)                    :: grid_info
    1241              :       TYPE(qs_environment_type)                          :: qs_env
    1242              : 
    1243              :       CHARACTER(LEN=*), PARAMETER                        :: routineN = 'init_atom_grid'
    1244              : 
    1245              :       CHARACTER(LEN=default_string_length)               :: kind_name
    1246              :       INTEGER :: handle, igrid, ikind, il, iso, iso1, iso2, l1, l1l2, l2, la, lc1, lc2, lcleb, ll, &
    1247              :          llmax, lp, m1, m2, max_s_harm, max_s_set, maxl, maxlgto, maxs, mm, mp, na, nr, &
    1248              :          quadrature, stat
    1249              :       REAL(dp)                                           :: kind_radius
    1250              :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: rga
    1251            8 :       REAL(dp), DIMENSION(:, :, :), POINTER              :: my_CG
    1252              :       TYPE(dft_control_type), POINTER                    :: dft_control
    1253              :       TYPE(grid_atom_type), POINTER                      :: grid_atom
    1254              :       TYPE(gto_basis_set_type), POINTER                  :: tmp_basis
    1255              :       TYPE(harmonics_atom_type), POINTER                 :: harmonics
    1256              :       TYPE(qs_control_type), POINTER                     :: qs_control
    1257            8 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
    1258              : 
    1259            8 :       CALL timeset(routineN, handle)
    1260              : 
    1261            8 :       NULLIFY (my_CG, qs_kind_set, dft_control, qs_control)
    1262            8 :       NULLIFY (grid_atom, harmonics, tmp_basis)
    1263              : 
    1264              :       !!  Initialization of some integer for the CG coeff generation
    1265              :       CALL get_qs_env(qs_env, &
    1266              :                       qs_kind_set=qs_kind_set, &
    1267            8 :                       dft_control=dft_control)
    1268              : 
    1269            8 :       CALL get_qs_kind_set(qs_kind_set, maxlgto=maxlgto, basis_type="ORB")
    1270            8 :       qs_control => dft_control%qs_control
    1271              : 
    1272              :       !!To be sure:: Is the basis grid present?
    1273            8 :       IF (maxlgto < 0) THEN
    1274            0 :          CPABORT("tmp_basis is not Present!")
    1275              :       END IF
    1276              : 
    1277              :       !maximum expansion
    1278            8 :       llmax = 2*maxlgto
    1279            8 :       max_s_harm = nsoset(llmax)
    1280            8 :       max_s_set = nsoset(maxlgto)
    1281            8 :       lcleb = llmax
    1282              : 
    1283              :       !  Allocate and compute the CG coeffs (copied from init_rho_atom)
    1284            8 :       CALL clebsch_gordon_init(lcleb)
    1285            8 :       CALL reallocate(my_CG, 1, max_s_set, 1, max_s_set, 1, max_s_harm)
    1286              : 
    1287           24 :       ALLOCATE (rga(lcleb, 2))
    1288           32 :       DO lc1 = 0, maxlgto
    1289          104 :          DO iso1 = nsoset(lc1 - 1) + 1, nsoset(lc1)
    1290           72 :             l1 = indso(1, iso1)
    1291           72 :             m1 = indso(2, iso1)
    1292          312 :             DO lc2 = 0, maxlgto
    1293          936 :                DO iso2 = nsoset(lc2 - 1) + 1, nsoset(lc2)
    1294          648 :                   l2 = indso(1, iso2)
    1295          648 :                   m2 = indso(2, iso2)
    1296          648 :                   CALL clebsch_gordon(l1, m1, l2, m2, rga)
    1297          648 :                   IF (l1 + l2 > llmax) THEN
    1298              :                      l1l2 = llmax
    1299              :                   ELSE
    1300              :                      l1l2 = l1 + l2
    1301              :                   END IF
    1302          648 :                   mp = m1 + m2
    1303          648 :                   mm = m1 - m2
    1304          648 :                   IF (m1*m2 < 0 .OR. (m1*m2 == 0 .AND. (m1 < 0 .OR. m2 < 0))) THEN
    1305          288 :                      mp = -ABS(mp)
    1306          288 :                      mm = -ABS(mm)
    1307              :                   ELSE
    1308          360 :                      mp = ABS(mp)
    1309          360 :                      mm = ABS(mm)
    1310              :                   END IF
    1311         2304 :                   DO lp = MOD(l1 + l2, 2), l1l2, 2
    1312         1440 :                      il = lp/2 + 1
    1313         1440 :                      IF (ABS(mp) <= lp) THEN
    1314         1024 :                      IF (mp >= 0) THEN
    1315          688 :                         iso = nsoset(lp - 1) + lp + 1 + mp
    1316              :                      ELSE
    1317          336 :                         iso = nsoset(lp - 1) + lp + 1 - ABS(mp)
    1318              :                      END IF
    1319         1024 :                      my_CG(iso1, iso2, iso) = rga(il, 1)
    1320              :                      END IF
    1321         2088 :                      IF (mp /= mm .AND. ABS(mm) <= lp) THEN
    1322          480 :                      IF (mm >= 0) THEN
    1323          320 :                         iso = nsoset(lp - 1) + lp + 1 + mm
    1324              :                      ELSE
    1325          160 :                         iso = nsoset(lp - 1) + lp + 1 - ABS(mm)
    1326              :                      END IF
    1327          480 :                      my_CG(iso1, iso2, iso) = rga(il, 2)
    1328              :                      END IF
    1329              :                   END DO
    1330              :                END DO ! iso2
    1331              :             END DO ! lc2
    1332              :          END DO ! iso1
    1333              :       END DO ! lc1
    1334            8 :       DEALLOCATE (rga)
    1335            8 :       CALL clebsch_gordon_deallocate()
    1336              : 
    1337              :       !  Create the Lebedev grids and compute the spherical harmonics
    1338            8 :       CALL init_lebedev_grids()
    1339            8 :       quadrature = qs_control%gapw_control%quadrature
    1340              : 
    1341           16 :       DO ikind = 1, SIZE(soc_atom_env%grid_atom_set)
    1342              : 
    1343              :          ! Allocate the grid and the harmonics for this kind
    1344            8 :          NULLIFY (soc_atom_env%grid_atom_set(ikind)%grid_atom)
    1345            8 :          NULLIFY (soc_atom_env%harmonics_atom_set(ikind)%harmonics_atom)
    1346            8 :          CALL allocate_grid_atom(soc_atom_env%grid_atom_set(ikind)%grid_atom)
    1347              :          CALL allocate_harmonics_atom( &
    1348            8 :             soc_atom_env%harmonics_atom_set(ikind)%harmonics_atom)
    1349              : 
    1350              :          NULLIFY (grid_atom, harmonics)
    1351            8 :          grid_atom => soc_atom_env%grid_atom_set(ikind)%grid_atom
    1352            8 :          harmonics => soc_atom_env%harmonics_atom_set(ikind)%harmonics_atom
    1353              : 
    1354              :          ! Initialize some integers
    1355              :          CALL get_qs_kind(qs_kind_set(ikind), &
    1356              :                           ngrid_rad=nr, &
    1357              :                           ngrid_ang=na, &
    1358            8 :                           name=kind_name)
    1359              : 
    1360              :          ! take the grid dimension given as input, if none, take the GAPW ones above
    1361            8 :          DO igrid = 1, SIZE(grid_info, 1)
    1362            8 :             IF (grid_info(igrid, 1) == kind_name) THEN
    1363            0 :                READ (grid_info(igrid, 2), *, iostat=stat) na
    1364            0 :                IF (stat .NE. 0) CPABORT("The 'na' value for the GRID keyword must be an integer")
    1365            0 :                READ (grid_info(igrid, 3), *, iostat=stat) nr
    1366            0 :                IF (stat .NE. 0) CPABORT("The 'nr' value for the GRID keyword must be an integer")
    1367              :                EXIT
    1368              :             END IF
    1369              :          END DO !igrid
    1370              : 
    1371            8 :          ll = get_number_of_lebedev_grid(n=na)
    1372            8 :          na = lebedev_grid(ll)%n
    1373            8 :          la = lebedev_grid(ll)%l
    1374            8 :          grid_atom%ng_sphere = na
    1375            8 :          grid_atom%nr = nr
    1376              : 
    1377              :          !Create the harmonics with the ORB-Basis
    1378              :          CALL get_qs_kind(qs_kind_set(ikind), &
    1379              :                           basis_set=tmp_basis, &
    1380            8 :                           basis_type="ORB")
    1381              :          CALL get_gto_basis_set(gto_basis_set=tmp_basis, &
    1382              :                                 maxl=maxl, &
    1383            8 :                                 kind_radius=kind_radius)
    1384              : 
    1385            8 :          CALL create_grid_atom(grid_atom, nr, na, llmax, ll, quadrature)
    1386            8 :          CALL truncate_radial_grid(grid_atom, kind_radius)
    1387              : 
    1388            8 :          maxs = nsoset(maxl)
    1389              :          CALL create_harmonics_atom(harmonics, &
    1390              :                                     my_CG, na, &
    1391              :                                     llmax, maxs, &
    1392              :                                     max_s_harm, ll, &
    1393              :                                     grid_atom%wa, &
    1394              :                                     grid_atom%azi, &
    1395            8 :                                     grid_atom%pol)
    1396           32 :          CALL get_maxl_CG(harmonics, tmp_basis, llmax, max_s_harm)
    1397              :       END DO !ikind
    1398              : 
    1399            8 :       CALL deallocate_lebedev_grids()
    1400            8 :       DEALLOCATE (my_CG)
    1401              : 
    1402            8 :       CALL timestop(handle)
    1403              : 
    1404           16 :    END SUBROUTINE init_atom_grid
    1405              : 
    1406              : ! **************************************************************************************************
    1407              : !> \brief ...
    1408              : !> \param qs_env ...
    1409              : !> \param dbcsr_soc_package ...
    1410              : !> \param soc_env ...
    1411              : !> \param soc_evecs_cfm ...
    1412              : !> \param eps_filter ...
    1413              : !> \param dipole_form ...
    1414              : !> \param gs_mos ...
    1415              : !> \param evects_sing ...
    1416              : !> \param evects_trip ...
    1417              : ! **************************************************************************************************
    1418            8 :    SUBROUTINE soc_dipol(qs_env, dbcsr_soc_package, soc_env, &
    1419              :                         soc_evecs_cfm, eps_filter, dipole_form, gs_mos, &
    1420            8 :                         evects_sing, evects_trip)
    1421              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1422              :       TYPE(dbcsr_soc_package_type)                       :: dbcsr_soc_package
    1423              :       TYPE(soc_env_type), TARGET                         :: soc_env
    1424              :       TYPE(cp_cfm_type), INTENT(in)                      :: soc_evecs_cfm
    1425              :       REAL(dp), INTENT(IN)                               :: eps_filter
    1426              :       INTEGER                                            :: dipole_form
    1427              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
    1428              :          POINTER                                         :: gs_mos
    1429              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evects_sing, evects_trip
    1430              : 
    1431              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'soc_dipol'
    1432              : 
    1433              :       COMPLEX(dp), ALLOCATABLE, DIMENSION(:, :)          :: transdip
    1434              :       INTEGER                                            :: handle, i, nosc, ntot
    1435            8 :       REAL(dp), DIMENSION(:), POINTER                    :: osc_str, soc_evals
    1436              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1437              :       TYPE(cp_cfm_type)                                  :: dip_cfm, work1_cfm, work2_cfm
    1438              :       TYPE(cp_fm_struct_type), POINTER                   :: dip_struct, full_struct
    1439            8 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: amew_dip
    1440              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1441              : 
    1442            8 :       CALL timeset(routineN, handle)
    1443              : 
    1444            8 :       NULLIFY (para_env, blacs_env, dip_struct, full_struct, osc_str)
    1445            8 :       NULLIFY (soc_evals)
    1446              : 
    1447            8 :       CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
    1448              : 
    1449            8 :       soc_evals => soc_env%soc_evals
    1450            8 :       nosc = SIZE(soc_evals)
    1451            8 :       ntot = nosc + 1
    1452           24 :       ALLOCATE (soc_env%soc_osc(nosc))
    1453            8 :       osc_str => soc_env%soc_osc
    1454           96 :       osc_str(:) = 0.0_dp
    1455              : 
    1456              :       !get some work arrays/matrix
    1457              :       CALL cp_fm_struct_create(dip_struct, &
    1458              :                                context=blacs_env, para_env=para_env, &
    1459            8 :                                nrow_global=ntot, ncol_global=1)
    1460              : 
    1461            8 :       CALL cp_cfm_get_info(soc_evecs_cfm, matrix_struct=full_struct)
    1462            8 :       CALL cp_cfm_create(dip_cfm, dip_struct)
    1463            8 :       CALL cp_cfm_create(work1_cfm, full_struct)
    1464            8 :       CALL cp_cfm_create(work2_cfm, full_struct)
    1465              : 
    1466           24 :       ALLOCATE (transdip(ntot, 1))
    1467              : 
    1468              :       CALL get_rcs_amew_op(amew_dip, soc_env, dbcsr_soc_package, &
    1469              :                            eps_filter, qs_env, gs_mos, &
    1470            8 :                            evects_sing, evects_trip)
    1471              : 
    1472           32 :       DO i = 1, 3 !cartesian coord x, y, z
    1473              : 
    1474              :          !Convert the real dipole into the cfm format for calculations
    1475           24 :          CALL cp_fm_to_cfm(msourcer=amew_dip(i), mtarget=work1_cfm)
    1476              : 
    1477              :          !compute amew_coeffs^dagger * amew_dip * amew_gs to get the transition moments
    1478              :          CALL parallel_gemm('C', 'N', ntot, &
    1479              :                             ntot, ntot, &
    1480              :                             (1.0_dp, 0.0_dp), &
    1481              :                             soc_evecs_cfm, &
    1482              :                             work1_cfm, &
    1483              :                             (0.0_dp, 0.0_dp), &
    1484           24 :                             work2_cfm)
    1485              :          CALL parallel_gemm('N', 'N', ntot, &
    1486              :                             1, ntot, &
    1487              :                             (1.0_dp, 0.0_dp), &
    1488              :                             work2_cfm, &
    1489              :                             soc_evecs_cfm, &
    1490              :                             (0.0_dp, 0.0_dp), &
    1491           24 :                             dip_cfm)
    1492              : 
    1493           24 :          CALL cp_cfm_get_submatrix(dip_cfm, transdip)
    1494              : 
    1495              :          !transition dipoles are real numbers
    1496          296 :          osc_str(:) = osc_str(:) + REAL(transdip(2:ntot, 1))**2 + AIMAG(transdip(2:ntot, 1))**2
    1497              : 
    1498              :       END DO !i
    1499              : 
    1500              :       !multiply with appropriate prefac depending in the rep
    1501            8 :       IF (dipole_form == tddfpt_dipole_length) THEN
    1502          156 :          osc_str(:) = 2.0_dp/3.0_dp*soc_evals(:)*osc_str(:)
    1503              :       ELSE
    1504           36 :          osc_str(:) = 2.0_dp/3.0_dp*soc_evals(:)*osc_str(:)
    1505              :       END IF
    1506              : 
    1507              :       !clean-up
    1508            8 :       CALL cp_fm_struct_release(dip_struct)
    1509            8 :       CALL cp_cfm_release(work1_cfm)
    1510            8 :       CALL cp_cfm_release(work2_cfm)
    1511            8 :       CALL cp_cfm_release(dip_cfm)
    1512           32 :       DO i = 1, 3
    1513           32 :          CALL cp_fm_release(amew_dip(i))
    1514              :       END DO
    1515            8 :       DEALLOCATE (amew_dip, transdip)
    1516              : 
    1517            8 :       CALL timestop(handle)
    1518              : 
    1519           16 :    END SUBROUTINE soc_dipol
    1520              : 
    1521              : !**********************************************************************************
    1522              : !> \brief: This will create the Dipole operator within the amew basis
    1523              : !> \param amew_op Output dipole operator
    1524              : !> \param soc_env ...
    1525              : !> \param dbcsr_soc_package Some work matrices
    1526              : !> \param eps_filter ...
    1527              : !> \param qs_env ...
    1528              : !> \param gs_mos ...
    1529              : !> \param evects_sing ...
    1530              : !> \param evects_trip ...
    1531              : ! **************************************************************************************************
    1532            8 :    SUBROUTINE get_rcs_amew_op(amew_op, soc_env, dbcsr_soc_package, eps_filter, qs_env, gs_mos, &
    1533            8 :                               evects_sing, evects_trip)
    1534              : 
    1535              :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
    1536              :          INTENT(OUT)                                     :: amew_op
    1537              :       TYPE(soc_env_type), TARGET                         :: soc_env
    1538              :       TYPE(dbcsr_soc_package_type)                       :: dbcsr_soc_package
    1539              :       REAL(dp), INTENT(IN)                               :: eps_filter
    1540              :       TYPE(qs_environment_type), POINTER                 :: qs_env
    1541              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
    1542              :          POINTER                                         :: gs_mos
    1543              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evects_sing, evects_trip
    1544              : 
    1545              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'get_rcs_amew_op'
    1546              : 
    1547              :       INTEGER                                            :: dim_op, handle, i, isg, nactive, nao, &
    1548              :                                                             nex, nsg, ntot, ntp
    1549              :       LOGICAL                                            :: vel_rep
    1550              :       REAL(dp)                                           :: op, sqrt2
    1551            8 :       REAL(dp), ALLOCATABLE, DIMENSION(:)                :: diag, gs_diag, gsgs_op
    1552            8 :       REAL(dp), ALLOCATABLE, DIMENSION(:, :)             :: mo_op, sggs_block
    1553              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
    1554              :       TYPE(cp_fm_struct_type), POINTER                   :: full_struct, gsgs_struct, sggs_struct, &
    1555              :                                                             std_struct, tmp_struct
    1556              :       TYPE(cp_fm_type)                                   :: gs_fm, sggs_fm, tmp_fm, vec_op, work_fm
    1557              :       TYPE(cp_fm_type), POINTER                          :: gs_coeffs
    1558            8 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: ao_op, matrix_s
    1559              :       TYPE(dbcsr_type), POINTER                          :: ao_op_i, dbcsr_ovlp, dbcsr_prod, &
    1560              :                                                             dbcsr_sg, dbcsr_tmp, dbcsr_tp, &
    1561              :                                                             dbcsr_work
    1562            8 :       TYPE(mo_set_type), DIMENSION(:), POINTER           :: mos
    1563              :       TYPE(mp_para_env_type), POINTER                    :: para_env
    1564              : 
    1565            8 :       CALL timeset(routineN, handle)
    1566              : 
    1567            8 :       NULLIFY (mos, gs_coeffs)
    1568            8 :       NULLIFY (matrix_s)
    1569            8 :       NULLIFY (para_env, blacs_env)
    1570            8 :       NULLIFY (full_struct, gsgs_struct, std_struct, tmp_struct, sggs_struct)
    1571            8 :       NULLIFY (ao_op_i, ao_op)
    1572            8 :       NULLIFY (dbcsr_tp, dbcsr_sg, dbcsr_ovlp, dbcsr_work, dbcsr_tmp, dbcsr_prod)
    1573              : 
    1574              :       ! Initialization
    1575              :       !! Fist case for length, secound for velocity-representation
    1576            8 :       IF (ASSOCIATED(soc_env%dipmat)) THEN
    1577            6 :          ao_op => soc_env%dipmat
    1578            6 :          vel_rep = .FALSE.
    1579              :       ELSE
    1580            2 :          ao_op => soc_env%dipmat_ao
    1581            2 :          vel_rep = .TRUE.
    1582              :       END IF
    1583            8 :       nsg = SIZE(soc_env%evals_a)
    1584            8 :       ntp = nsg; nex = nsg !all the same by construction, keep them separate for clarity
    1585            8 :       ntot = 1 + nsg + 3*ntp
    1586              : 
    1587            8 :       CALL get_qs_env(qs_env, matrix_s=matrix_s, mos=mos, para_env=para_env, blacs_env=blacs_env)
    1588            8 :       sqrt2 = SQRT(2.0_dp)
    1589            8 :       dim_op = SIZE(ao_op)
    1590              : 
    1591            8 :       dbcsr_sg => dbcsr_soc_package%dbcsr_sg
    1592            8 :       dbcsr_tp => dbcsr_soc_package%dbcsr_tp
    1593            8 :       dbcsr_work => dbcsr_soc_package%dbcsr_work
    1594            8 :       dbcsr_prod => dbcsr_soc_package%dbcsr_prod
    1595            8 :       dbcsr_ovlp => dbcsr_soc_package%dbcsr_ovlp
    1596            8 :       dbcsr_tmp => dbcsr_soc_package%dbcsr_tmp
    1597              : 
    1598              :       !  Create the amew_op matrix
    1599              :       CALL cp_fm_struct_create(full_struct, &
    1600              :                                context=blacs_env, para_env=para_env, &
    1601            8 :                                nrow_global=ntot, ncol_global=ntot)
    1602           48 :       ALLOCATE (amew_op(dim_op))
    1603           32 :       DO i = 1, dim_op
    1604           32 :          CALL cp_fm_create(amew_op(i), full_struct)
    1605              :       END DO !i
    1606              : 
    1607              :       !  Deal with the GS-GS contribution <0|0> = 2*sum_j <phi_j|op|phi_j>
    1608            8 :       CALL get_mo_set(mos(1), nao=nao, homo=nactive)
    1609            8 :       gs_coeffs => gs_mos(1)%mos_occ
    1610            8 :       CALL cp_fm_get_info(gs_coeffs, matrix_struct=std_struct)
    1611              : 
    1612              :       CALL cp_fm_struct_create(gsgs_struct, &
    1613              :                                context=blacs_env, para_env=para_env, &
    1614            8 :                                nrow_global=nactive, ncol_global=nactive)
    1615              : 
    1616            8 :       CALL cp_fm_create(gs_fm, gsgs_struct) !nactive nactive
    1617            8 :       CALL cp_fm_create(work_fm, std_struct) !nao nactive
    1618              : 
    1619           24 :       ALLOCATE (gsgs_op(dim_op))
    1620           24 :       ALLOCATE (gs_diag(nactive))
    1621              : 
    1622           32 :       DO i = 1, dim_op
    1623              : 
    1624           24 :          ao_op_i => ao_op(i)%matrix
    1625           24 :          CALL cp_dbcsr_sm_fm_multiply(ao_op_i, gs_coeffs, work_fm, ncol=nactive)
    1626              :          CALL parallel_gemm('T', 'N', nactive, nactive, nao, &
    1627           24 :                             1.0_dp, gs_coeffs, work_fm, 0.0_dp, gs_fm)
    1628           24 :          CALL cp_fm_get_diag(gs_fm, gs_diag)
    1629          194 :          gsgs_op(i) = 2.0_dp*SUM(gs_diag)
    1630              : 
    1631              :       END DO !i
    1632            8 :       DEALLOCATE (gs_diag)
    1633              : 
    1634            8 :       CALL cp_fm_release(work_fm)
    1635              : 
    1636              :       !  Create the work and helper fms
    1637            8 :       CALL cp_fm_create(vec_op, std_struct) !nao nactive
    1638            8 :       CALL cp_fm_struct_release(gsgs_struct)
    1639              : 
    1640              :       CALL cp_fm_struct_create(tmp_struct, &
    1641              :                                context=blacs_env, para_env=para_env, &
    1642            8 :                                nrow_global=nex, ncol_global=nex)
    1643              :       CALL cp_fm_struct_create(sggs_struct, &
    1644              :                                context=blacs_env, para_env=para_env, &
    1645            8 :                                nrow_global=nactive*nsg, ncol_global=nactive)
    1646              : 
    1647            8 :       CALL cp_fm_create(tmp_fm, tmp_struct)
    1648            8 :       CALL cp_fm_create(work_fm, full_struct)
    1649            8 :       CALL cp_fm_create(sggs_fm, sggs_struct)
    1650              : 
    1651           16 :       ALLOCATE (diag(nactive))
    1652           32 :       ALLOCATE (mo_op(nactive, nactive))
    1653           24 :       ALLOCATE (sggs_block(nactive, nactive))
    1654              : 
    1655              :       ! Iterate over the dimensions of the operator
    1656              :       ! Note: operator matrices are asusmed symmetric, can only do upper half
    1657           32 :       DO i = 1, dim_op
    1658              : 
    1659           24 :          ao_op_i => ao_op(i)%matrix
    1660              : 
    1661              :          ! The GS-GS contribution
    1662           24 :          CALL cp_fm_set_element(amew_op(i), 1, 1, gsgs_op(i))
    1663              : 
    1664              :          ! Compute the operator in the MO basis
    1665           24 :          CALL cp_dbcsr_sm_fm_multiply(ao_op_i, gs_coeffs, vec_op, ncol=nactive)
    1666           24 :          CALL cp_fm_get_submatrix(gs_fm, mo_op)  ! instead of prod_fm
    1667              : 
    1668              :          ! Compute the ground-state/singlet components. ao_op*gs_coeffs already stored in vec_op
    1669           24 :          IF (vel_rep) THEN
    1670              :             CALL dip_vel_op(soc_env, qs_env, evects_sing, dbcsr_prod, i, .FALSE., &
    1671            6 :                             gs_coeffs, sggs_fm)
    1672              :          ELSE
    1673              :             CALL parallel_gemm('T', 'N', nactive*nsg, nactive, nao, &
    1674           18 :                                1.0_dp, soc_env%a_coeff, vec_op, 0.0_dp, sggs_fm)
    1675              :          END IF
    1676              : 
    1677           90 :          DO isg = 1, nsg
    1678              :             CALL cp_fm_get_submatrix(fm=sggs_fm, &
    1679              :                                      target_m=sggs_block, &
    1680              :                                      start_row=(isg - 1)*nactive + 1, &
    1681              :                                      start_col=1, &
    1682              :                                      n_rows=nactive, &
    1683           66 :                                      n_cols=nactive)
    1684           66 :             diag(:) = get_diag(sggs_block)
    1685          528 :             op = sqrt2*SUM(diag)
    1686           90 :             CALL cp_fm_set_element(amew_op(i), 1, 1 + isg, op)
    1687              :          END DO !isg
    1688              : 
    1689              :          ! do the singlet-singlet components
    1690              :          !start with the overlap
    1691              :          CALL dbcsr_multiply('N', 'N', 1.0_dp, &
    1692              :                              matrix_s(1)%matrix, dbcsr_sg, &
    1693              :                              0.0_dp, dbcsr_work, &
    1694           24 :                              filter_eps=eps_filter)
    1695              :          CALL dbcsr_multiply('T', 'N', 1.0_dp, &
    1696              :                              dbcsr_sg, dbcsr_work, &
    1697              :                              0.0_dp, dbcsr_ovlp, &
    1698           24 :                              filter_eps=eps_filter)
    1699              : 
    1700           24 :          IF (vel_rep) THEN
    1701            6 :             CALL dip_vel_op(soc_env, qs_env, evects_sing, dbcsr_prod, i, .FALSE.)
    1702              :          ELSE
    1703              :             !then the operator in the LR orbital basis
    1704              :             CALL dbcsr_multiply('N', 'N', 1.0_dp, &
    1705              :                                 ao_op_i, dbcsr_sg, &
    1706              :                                 0.0_dp, dbcsr_work, &
    1707           18 :                                 filter_eps=eps_filter)
    1708              :             CALL dbcsr_multiply('T', 'N', 1.0_dp, &
    1709              :                                 dbcsr_sg, dbcsr_work, &
    1710              :                                 0.0_dp, dbcsr_prod, &
    1711           18 :                                 filter_eps=eps_filter)
    1712              :          END IF
    1713              : 
    1714              :          !use the soc routine, it is compatible
    1715              :          CALL rcs_amew_soc_elements(dbcsr_tmp, &
    1716              :                                     dbcsr_prod, &
    1717              :                                     dbcsr_ovlp, &
    1718              :                                     mo_op, &
    1719              :                                     pref_trace=-1.0_dp, &
    1720              :                                     pref_overall=1.0_dp, &
    1721              :                                     pref_diags=gsgs_op(i), &
    1722           24 :                                     symmetric=.TRUE.)
    1723              : 
    1724           24 :          CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
    1725              :          CALL cp_fm_to_fm_submat(msource=tmp_fm, &
    1726              :                                  mtarget=amew_op(i), &
    1727              :                                  nrow=nex, &
    1728              :                                  ncol=nex, &
    1729              :                                  s_firstrow=1, &
    1730              :                                  s_firstcol=1, &
    1731              :                                  t_firstrow=2, &
    1732           24 :                                  t_firstcol=2)
    1733              : 
    1734              :          ! compute the triplet-triplet components
    1735              :          !the overlap
    1736              :          CALL dbcsr_multiply('N', 'N', 1.0_dp, &
    1737              :                              matrix_s(1)%matrix, &
    1738              :                              dbcsr_tp, 0.0_dp, &
    1739              :                              dbcsr_work, &
    1740           24 :                              filter_eps=eps_filter)
    1741              :          CALL dbcsr_multiply('T', 'N', 1.0_dp, &
    1742              :                              dbcsr_tp, dbcsr_work, &
    1743              :                              0.0_dp, dbcsr_ovlp, &
    1744           24 :                              filter_eps=eps_filter)
    1745              : 
    1746              :          !the operator in the LR orbital basis
    1747           24 :          IF (vel_rep) THEN
    1748            6 :             CALL dip_vel_op(soc_env, qs_env, evects_trip, dbcsr_prod, i, .TRUE.)
    1749              :          ELSE
    1750              :             CALL dbcsr_multiply('N', 'N', 1.0_dp, &
    1751              :                                 ao_op_i, dbcsr_tp, &
    1752              :                                 0.0_dp, dbcsr_work, &
    1753           18 :                                 filter_eps=eps_filter)
    1754              :             CALL dbcsr_multiply('T', 'N', 1.0_dp, &
    1755              :                                 dbcsr_tp, dbcsr_work, &
    1756              :                                 0.0_dp, dbcsr_prod, &
    1757           18 :                                 filter_eps=eps_filter)
    1758              :          END IF
    1759              : 
    1760              :          CALL rcs_amew_soc_elements(dbcsr_tmp, &
    1761              :                                     dbcsr_prod, &
    1762              :                                     dbcsr_ovlp, &
    1763              :                                     mo_op, &
    1764              :                                     pref_trace=-1.0_dp, &
    1765              :                                     pref_overall=1.0_dp, &
    1766              :                                     pref_diags=gsgs_op(i), &
    1767           24 :                                     symmetric=.TRUE.)
    1768              : 
    1769           24 :          CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
    1770              :          !<T^-1|op|T^-1>
    1771              :          CALL cp_fm_to_fm_submat(msource=tmp_fm, &
    1772              :                                  mtarget=amew_op(i), &
    1773              :                                  nrow=nex, &
    1774              :                                  ncol=nex, &
    1775              :                                  s_firstrow=1, &
    1776              :                                  s_firstcol=1, &
    1777              :                                  t_firstrow=1 + nsg + 1, &
    1778           24 :                                  t_firstcol=1 + nsg + 1)
    1779              : 
    1780              :          !<T^0|op|T^0>
    1781              :          CALL cp_fm_to_fm_submat(msource=tmp_fm, &
    1782              :                                  mtarget=amew_op(i), &
    1783              :                                  nrow=nex, &
    1784              :                                  ncol=nex, &
    1785              :                                  s_firstrow=1, &
    1786              :                                  s_firstcol=1, &
    1787              :                                  t_firstrow=1 + nsg + ntp + 1, &
    1788           24 :                                  t_firstcol=1 + nsg + ntp + 1)
    1789              :          !<T^+1|op|T^+1>
    1790              :          CALL cp_fm_to_fm_submat(msource=tmp_fm, &
    1791              :                                  mtarget=amew_op(i), &
    1792              :                                  nrow=nex, &
    1793              :                                  ncol=nex, &
    1794              :                                  s_firstrow=1, &
    1795              :                                  s_firstcol=1, &
    1796              :                                  t_firstrow=1 + nsg + 2*ntp + 1, &
    1797           24 :                                  t_firstcol=1 + nsg + 2*ntp + 1)
    1798              : 
    1799              :          ! Symmetrize the matrix (only upper triangle built)
    1800           32 :          CALL cp_fm_uplo_to_full(amew_op(i), work_fm)
    1801              : 
    1802              :       END DO !i
    1803              : 
    1804              :       ! Clean-up
    1805            8 :       CALL cp_fm_release(gs_fm)
    1806            8 :       CALL cp_fm_release(work_fm)
    1807            8 :       CALL cp_fm_release(tmp_fm)
    1808            8 :       CALL cp_fm_release(vec_op)
    1809            8 :       CALL cp_fm_release(sggs_fm)
    1810            8 :       CALL cp_fm_struct_release(full_struct)
    1811            8 :       CALL cp_fm_struct_release(tmp_struct)
    1812            8 :       CALL cp_fm_struct_release(sggs_struct)
    1813              : 
    1814            8 :       DEALLOCATE (sggs_block)
    1815            8 :       DEALLOCATE (diag, gsgs_op, mo_op)
    1816            8 :       CALL timestop(handle)
    1817              : 
    1818           40 :    END SUBROUTINE get_rcs_amew_op
    1819              : 
    1820            0 : END MODULE qs_tddfpt2_soc
        

Generated by: LCOV version 2.0-1