LCOV - code coverage report
Current view: top level - src - qs_tddfpt2_soc.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:62906da) Lines: 97.6 % 584 570
Test Date: 2026-10-24 01:17:15 Functions: 85.7 % 7 6

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

Generated by: LCOV version 2.0-1