LCOV - code coverage report
Current view: top level - src - qs_tddfpt2_soc_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:6d276e9) Lines: 94.2 % 207 195
Test Date: 2026-09-10 07:29:18 Functions: 87.5 % 8 7

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : ! **************************************************************************************************
       9              : !> \brief Utilities absorption spectroscopy using TDDFPT with SOC
      10              : !> \author JRVogt (12.2023)
      11              : ! **************************************************************************************************
      12              : 
      13              : MODULE qs_tddfpt2_soc_utils
      14              :    USE cp_blacs_env,                    ONLY: cp_blacs_env_type
      15              :    USE cp_cfm_types,                    ONLY: cp_cfm_get_info,&
      16              :                                               cp_cfm_get_submatrix,&
      17              :                                               cp_cfm_type
      18              :    USE cp_control_types,                ONLY: tddfpt2_control_type
      19              :    USE cp_dbcsr_api,                    ONLY: dbcsr_copy,&
      20              :                                               dbcsr_create,&
      21              :                                               dbcsr_desymmetrize,&
      22              :                                               dbcsr_get_info,&
      23              :                                               dbcsr_p_type,&
      24              :                                               dbcsr_release,&
      25              :                                               dbcsr_type
      26              :    USE cp_dbcsr_operations,             ONLY: copy_dbcsr_to_fm,&
      27              :                                               copy_fm_to_dbcsr,&
      28              :                                               cp_dbcsr_sm_fm_multiply,&
      29              :                                               dbcsr_allocate_matrix_set,&
      30              :                                               dbcsr_deallocate_matrix_set
      31              :    USE cp_fm_basic_linalg,              ONLY: cp_fm_schur_product
      32              :    USE cp_fm_struct,                    ONLY: cp_fm_struct_create,&
      33              :                                               cp_fm_struct_release,&
      34              :                                               cp_fm_struct_type
      35              :    USE cp_fm_types,                     ONLY: cp_fm_create,&
      36              :                                               cp_fm_get_info,&
      37              :                                               cp_fm_release,&
      38              :                                               cp_fm_set_all,&
      39              :                                               cp_fm_to_fm,&
      40              :                                               cp_fm_to_fm_submat,&
      41              :                                               cp_fm_type
      42              :    USE input_constants,                 ONLY: tddfpt_dipole_berry,&
      43              :                                               tddfpt_dipole_length,&
      44              :                                               tddfpt_dipole_velocity
      45              :    USE kinds,                           ONLY: dp
      46              :    USE message_passing,                 ONLY: mp_para_env_type
      47              :    USE moments_utils,                   ONLY: get_reference_point
      48              :    USE parallel_gemm_api,               ONLY: parallel_gemm
      49              :    USE qs_environment_types,            ONLY: get_qs_env,&
      50              :                                               qs_environment_type
      51              :    USE qs_ks_types,                     ONLY: qs_ks_env_type
      52              :    USE qs_moments,                      ONLY: build_local_moment_matrix
      53              :    USE qs_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      54              :    USE qs_operators_ao,                 ONLY: build_lin_mom_matrix
      55              :    USE qs_overlap,                      ONLY: build_overlap_matrix
      56              :    USE qs_tddfpt2_soc_types,            ONLY: soc_env_type
      57              :    USE qs_tddfpt2_types,                ONLY: tddfpt_ground_state_mos
      58              : 
      59              : !$ USE OMP_LIB, ONLY: omp_get_max_threads, omp_get_thread_num
      60              : #include "./base/base_uses.f90"
      61              : 
      62              :    IMPLICIT NONE
      63              :    PRIVATE
      64              : 
      65              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_soc_utils'
      66              : 
      67              :    PUBLIC :: soc_dipole_operator, soc_contract_evect, resort_evects, dip_vel_op
      68              : 
      69              :    !A helper type for SOC
      70              :    TYPE dbcsr_soc_package_type
      71              :       TYPE(dbcsr_type), POINTER     :: dbcsr_sg => Null()
      72              :       TYPE(dbcsr_type), POINTER     :: dbcsr_tp => Null()
      73              :       TYPE(dbcsr_type), POINTER     :: dbcsr_sc => Null()
      74              :       TYPE(dbcsr_type), POINTER     :: dbcsr_sf => Null()
      75              :       TYPE(dbcsr_type), POINTER     :: dbcsr_prod => Null()
      76              :       TYPE(dbcsr_type), POINTER     :: dbcsr_ovlp => Null()
      77              :       TYPE(dbcsr_type), POINTER     :: dbcsr_tmp => Null()
      78              :       TYPE(dbcsr_type), POINTER     :: dbcsr_work => Null()
      79              :    END TYPE dbcsr_soc_package_type
      80              : 
      81              : CONTAINS
      82              : 
      83              : ! **************************************************************************************************
      84              : !> \brief Build the atomic dipole operator
      85              : !> \param soc_env ...
      86              : !> \param tddfpt_control informations on how to build the operaot
      87              : !> \param qs_env Qucikstep environment
      88              : !> \param gs_mos ...
      89              : ! **************************************************************************************************
      90           10 :    SUBROUTINE soc_dipole_operator(soc_env, tddfpt_control, qs_env, gs_mos)
      91              :       TYPE(soc_env_type), TARGET                         :: soc_env
      92              :       TYPE(tddfpt2_control_type), POINTER                :: tddfpt_control
      93              :       TYPE(qs_environment_type), INTENT(IN), POINTER     :: qs_env
      94              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
      95              :          INTENT(in)                                      :: gs_mos
      96              : 
      97              :       CHARACTER(len=*), PARAMETER :: routineN = 'soc_dipole_operator'
      98              : 
      99              :       INTEGER                                            :: dim_op, handle, i_dim, nao, nspin
     100              :       REAL(kind=dp), DIMENSION(3)                        :: reference_point
     101           10 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     102              : 
     103           10 :       CALL timeset(routineN, handle)
     104              : 
     105           10 :       NULLIFY (matrix_s)
     106              : 
     107           10 :       IF (tddfpt_control%dipole_form == tddfpt_dipole_berry) THEN
     108            0 :          CPABORT("BERRY DIPOLE FORM NOT IMPLEMENTED FOR SOC")
     109              :       END IF
     110              :            !! ONLY RCS have been implemented, Therefore, nspin sould always be 1!
     111           10 :       nspin = 1
     112              :            !! Number of dimensions should be 3, unless multipole is implemented in the future
     113           10 :       dim_op = 3
     114              : 
     115              :            !! Initzilize the dipmat structure
     116           10 :       CALL get_qs_env(qs_env, matrix_s=matrix_s)
     117           10 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
     118              : 
     119           40 :       ALLOCATE (soc_env%dipmat_ao(dim_op))
     120           40 :       DO i_dim = 1, dim_op
     121           30 :          ALLOCATE (soc_env%dipmat_ao(i_dim)%matrix)
     122              :          CALL dbcsr_copy(soc_env%dipmat_ao(i_dim)%matrix, &
     123              :                          matrix_s(1)%matrix, &
     124           40 :                          name="dipole operator matrix")
     125              :       END DO
     126              : 
     127           18 :       SELECT CASE (tddfpt_control%dipole_form)
     128              :       CASE (tddfpt_dipole_length)
     129              :          CALL get_reference_point(reference_point, qs_env=qs_env, &
     130              :                                   reference=tddfpt_control%dipole_reference, &
     131            8 :                                   ref_point=tddfpt_control%dipole_ref_point)
     132              : 
     133              :          CALL build_local_moment_matrix(qs_env, soc_env%dipmat_ao, 1, &
     134            8 :                                         ref_point=reference_point, all_images=.TRUE.)
     135              :          !! This will lead to S C^virt C^virt,T Q_q (vgl Strand et al., J. Chem Phys. 150, 044702, 2019)
     136            8 :          CALL length_rep(qs_env, gs_mos, soc_env)
     137              :       CASE (tddfpt_dipole_velocity)
     138              :          !!This Routine calcluates the dipole Operator within the velocity-form within the ao basis
     139              :          !!This operation is only used in xas_tdp and qs_tddfpt_soc.
     140            2 :          CALL build_lin_mom_matrix(qs_env, soc_env%dipmat_ao, minimum_image=.FALSE.)
     141              :          !! This will precomute SC^virt, (omega^a-omega^i)^-1 and C^virt dS/dq
     142            2 :          CALL velocity_rep(qs_env, gs_mos, soc_env)
     143              :       CASE DEFAULT
     144           10 :          CPABORT("Unimplemented form of the dipole operator")
     145              :       END SELECT
     146              : 
     147           10 :       CALL timestop(handle)
     148              : 
     149           20 :    END SUBROUTINE soc_dipole_operator
     150              : 
     151              : ! **************************************************************************************************
     152              : !> \brief ...
     153              : !> \param qs_env ...
     154              : !> \param gs_mos ...
     155              : !> \param soc_env ...
     156              : ! **************************************************************************************************
     157            8 :    SUBROUTINE length_rep(qs_env, gs_mos, soc_env)
     158              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     159              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     160              :          INTENT(in)                                      :: gs_mos
     161              :       TYPE(soc_env_type), TARGET                         :: soc_env
     162              : 
     163              :       INTEGER                                            :: ideriv, ispin, nao, nderivs, nspins
     164            8 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nmo_virt
     165              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     166              :       TYPE(cp_fm_struct_type), POINTER                   :: dip_struct, fm_struct
     167            8 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: S_mos_virt
     168            8 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: dipole_op_mos_occ
     169              :       TYPE(cp_fm_type), POINTER                          :: dipmat_tmp, wfm_ao_ao
     170            8 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     171              :       TYPE(dbcsr_type), POINTER                          :: symm_tmp
     172              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     173              : 
     174            8 :       CALL get_qs_env(qs_env, matrix_s=matrix_s, blacs_env=blacs_env, para_env=para_env)
     175              : 
     176            8 :       nderivs = 3
     177            8 :       nspins = 1  !!We only account for rcs, will be changed in the future
     178            8 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
     179              :       ALLOCATE (S_mos_virt(nspins), dipole_op_mos_occ(3, nspins), &
     180           48 :                 wfm_ao_ao, nmo_virt(nspins), symm_tmp, dipmat_tmp)
     181              : 
     182            8 :       CALL cp_fm_struct_create(dip_struct, context=blacs_env, ncol_global=nao, nrow_global=nao, para_env=para_env)
     183              : 
     184            8 :       CALL dbcsr_allocate_matrix_set(soc_env%dipmat, nderivs)
     185            8 :       CALL dbcsr_desymmetrize(matrix_s(1)%matrix, symm_tmp)
     186           32 :       DO ideriv = 1, nderivs
     187           24 :          ALLOCATE (soc_env%dipmat(ideriv)%matrix)
     188              :          CALL dbcsr_create(soc_env%dipmat(ideriv)%matrix, template=symm_tmp, &
     189           24 :                            name="contracted operator", matrix_type="N")
     190           56 :          DO ispin = 1, nspins
     191           48 :             CALL cp_fm_create(dipole_op_mos_occ(ideriv, ispin), matrix_struct=dip_struct)
     192              :          END DO
     193              :       END DO
     194              : 
     195            8 :       CALL dbcsr_release(symm_tmp)
     196            8 :       DEALLOCATE (symm_tmp)
     197              : 
     198           16 :       DO ispin = 1, nspins
     199            8 :          nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
     200            8 :          CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct)
     201            8 :          CALL cp_fm_create(wfm_ao_ao, dip_struct)
     202            8 :          CALL cp_fm_create(S_mos_virt(ispin), fm_struct)
     203              : 
     204              :          CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
     205              :                                       gs_mos(ispin)%mos_virt, &
     206              :                                       S_mos_virt(ispin), &
     207            8 :                                       ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
     208              :          CALL parallel_gemm('N', 'T', nao, nao, nmo_virt(ispin), &
     209              :                             1.0_dp, S_mos_virt(ispin), gs_mos(ispin)%mos_virt, &
     210            8 :                             0.0_dp, wfm_ao_ao)
     211              : 
     212           32 :          DO ideriv = 1, nderivs
     213           24 :             CALL cp_fm_create(dipmat_tmp, dip_struct)
     214           24 :             CALL copy_dbcsr_to_fm(soc_env%dipmat_ao(ideriv)%matrix, dipmat_tmp)
     215              :             CALL parallel_gemm('N', 'T', nao, nao, nao, &
     216              :                                1.0_dp, wfm_ao_ao, dipmat_tmp, &
     217           24 :                                0.0_dp, dipole_op_mos_occ(ideriv, ispin))
     218           24 :             CALL copy_fm_to_dbcsr(dipole_op_mos_occ(ideriv, ispin), soc_env%dipmat(ideriv)%matrix)
     219           56 :             CALL cp_fm_release(dipmat_tmp)
     220              :          END DO
     221            8 :          CALL cp_fm_release(wfm_ao_ao)
     222           24 :          DEALLOCATE (wfm_ao_ao)
     223              :       END DO
     224              : 
     225            8 :       CALL cp_fm_struct_release(dip_struct)
     226           16 :       DO ispin = 1, nspins
     227            8 :          CALL cp_fm_release(S_mos_virt(ispin))
     228           40 :          DO ideriv = 1, nderivs
     229           32 :             CALL cp_fm_release(dipole_op_mos_occ(ideriv, ispin))
     230              :          END DO
     231              :       END DO
     232            8 :       DEALLOCATE (S_mos_virt, dipole_op_mos_occ, nmo_virt, dipmat_tmp)
     233              : 
     234            8 :    END SUBROUTINE length_rep
     235              : 
     236              : ! **************************************************************************************************
     237              : !> \brief ...
     238              : !> \param qs_env ...
     239              : !> \param gs_mos ...
     240              : !> \param soc_env ...
     241              : ! **************************************************************************************************
     242            2 :    SUBROUTINE velocity_rep(qs_env, gs_mos, soc_env)
     243              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     244              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     245              :          INTENT(in)                                      :: gs_mos
     246              :       TYPE(soc_env_type), TARGET                         :: soc_env
     247              : 
     248              :       INTEGER                                            :: ici, icol, ideriv, irow, ispin, n_act, &
     249              :                                                             n_virt, nao, ncols_local, nderivs, &
     250              :                                                             nrows_local, nspins
     251            2 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     252              :       REAL(kind=dp)                                      :: eval_occ
     253              :       REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
     254            2 :          POINTER                                         :: local_data_ediff
     255              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     256              :       TYPE(cp_fm_struct_type), POINTER                   :: ao_cvirt_struct, cvirt_ao_struct, &
     257              :                                                             fm_struct, scrm_struct
     258              :       TYPE(cp_fm_type)                                   :: scrm_fm
     259            2 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, scrm
     260              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     261            2 :          POINTER                                         :: sab_orb
     262              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     263              : 
     264            2 :       NULLIFY (scrm, scrm_struct, blacs_env, matrix_s, ao_cvirt_struct, cvirt_ao_struct)
     265            2 :       nspins = 1
     266            2 :       nderivs = 3
     267           18 :       ALLOCATE (soc_env%SC(nspins), soc_env%CdS(nspins, nderivs), soc_env%ediff(nspins))
     268              : 
     269            2 :       CALL get_qs_env(qs_env, ks_env=ks_env, sab_orb=sab_orb, blacs_env=blacs_env, matrix_s=matrix_s)
     270            2 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
     271              :       CALL cp_fm_struct_create(scrm_struct, nrow_global=nao, ncol_global=nao, &
     272            2 :                                context=blacs_env)
     273            2 :       CALL cp_fm_get_info(gs_mos(1)%mos_virt, matrix_struct=ao_cvirt_struct)
     274              : 
     275              :       CALL build_overlap_matrix(ks_env, matrix_s=scrm, nderivative=1, &
     276              :                                 basis_type_a="ORB", basis_type_b="ORB", &
     277            2 :                                 sab_nl=sab_orb)
     278              : 
     279            4 :       DO ispin = 1, nspins
     280            2 :          NULLIFY (fm_struct)
     281              : !deb     n_occ = SIZE(gs_mos(ispin)%evals_occ)
     282            2 :          n_act = gs_mos(ispin)%nmo_active
     283            2 :          n_virt = SIZE(gs_mos(ispin)%evals_virt)
     284              :          CALL cp_fm_struct_create(fm_struct, nrow_global=n_virt, &
     285            2 :                                   ncol_global=n_act, context=blacs_env)
     286              :          CALL cp_fm_struct_create(cvirt_ao_struct, nrow_global=n_virt, &
     287            2 :                                   ncol_global=nao, context=blacs_env)
     288            2 :          CALL cp_fm_create(soc_env%ediff(ispin), fm_struct)
     289            2 :          CALL cp_fm_create(soc_env%SC(ispin), ao_cvirt_struct)
     290              : 
     291              :          CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
     292              :                                       gs_mos(ispin)%mos_virt, &
     293              :                                       soc_env%SC(ispin), &
     294            2 :                                       ncol=n_virt, alpha=1.0_dp, beta=0.0_dp)
     295              : 
     296              :          CALL cp_fm_get_info(soc_env%ediff(ispin), nrow_local=nrows_local, ncol_local=ncols_local, &
     297            2 :                              row_indices=row_indices, col_indices=col_indices, local_data=local_data_ediff)
     298              : 
     299              : !$OMP       PARALLEL DO DEFAULT(NONE), &
     300              : !$OMP                PRIVATE(eval_occ, ici, icol, irow), &
     301            2 : !$OMP                SHARED(col_indices, gs_mos, ispin, local_data_ediff, ncols_local, nrows_local, row_indices)
     302              :          DO icol = 1, ncols_local
     303              :             ! E_occ_i ; imo_occ = col_indices(icol)
     304              :             ici = gs_mos(ispin)%index_active(col_indices(icol))
     305              :             eval_occ = gs_mos(ispin)%evals_occ(ici)
     306              : 
     307              :             DO irow = 1, nrows_local
     308              :                ! ediff_inv_weights(a, i) = 1.0 / (E_virt_a - E_occ_i)
     309              :                ! imo_virt = row_indices(irow)
     310              :                local_data_ediff(irow, icol) = 1.0_dp/(gs_mos(ispin)%evals_virt(row_indices(irow)) - eval_occ)
     311              :             END DO
     312              :          END DO
     313              : !$OMP       END PARALLEL DO
     314              : 
     315            8 :          DO ideriv = 1, nderivs
     316            6 :             CALL cp_fm_create(soc_env%CdS(ispin, ideriv), cvirt_ao_struct)
     317            6 :             CALL cp_fm_create(scrm_fm, scrm_struct)
     318            6 :             CALL copy_dbcsr_to_fm(scrm(ideriv + 1)%matrix, scrm_fm)
     319              :             CALL parallel_gemm('T', 'N', n_virt, nao, nao, 1.0_dp, gs_mos(ispin)%mos_virt, &
     320            6 :                                scrm_fm, 0.0_dp, soc_env%CdS(ispin, ideriv))
     321           14 :             CALL cp_fm_release(scrm_fm)
     322              : 
     323              :          END DO
     324              : 
     325            6 :          CALL cp_fm_struct_release(fm_struct)
     326              :       END DO
     327            2 :       CALL dbcsr_deallocate_matrix_set(scrm)
     328            2 :       CALL cp_fm_struct_release(scrm_struct)
     329            2 :       CALL cp_fm_struct_release(cvirt_ao_struct)
     330              : 
     331            4 :    END SUBROUTINE velocity_rep
     332              : 
     333              : ! **************************************************************************************************
     334              : !> \brief This routine will construct the dipol operator within velocity representation
     335              : !> \param soc_env ..
     336              : !> \param qs_env ...
     337              : !> \param evec_fm ...
     338              : !> \param op ...
     339              : !> \param ideriv ...
     340              : !> \param tp ...
     341              : !> \param gs_coeffs ...
     342              : !> \param sggs_fm ...
     343              : ! **************************************************************************************************
     344           18 :    SUBROUTINE dip_vel_op(soc_env, qs_env, evec_fm, op, ideriv, tp, gs_coeffs, sggs_fm)
     345              :       TYPE(soc_env_type), TARGET                         :: soc_env
     346              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     347              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evec_fm
     348              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: op
     349              :       INTEGER, INTENT(IN)                                :: ideriv
     350              :       LOGICAL, INTENT(IN)                                :: tp
     351              :       TYPE(cp_fm_type), OPTIONAL, POINTER                :: gs_coeffs
     352              :       TYPE(cp_fm_type), INTENT(INOUT), OPTIONAL          :: sggs_fm
     353              : 
     354              :       INTEGER                                            :: iex, ispin, n_act, n_virt, nao, nex
     355              :       LOGICAL                                            :: sggs
     356              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     357              :       TYPE(cp_fm_struct_type), POINTER                   :: op_struct, virt_occ_struct
     358              :       TYPE(cp_fm_type)                                   :: CdSC, op_fm, SCWCdSC, WCdSC
     359           18 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: WCdSC_tmp
     360              :       TYPE(cp_fm_type), POINTER                          :: coeff
     361              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     362              : 
     363           18 :       NULLIFY (virt_occ_struct, virt_occ_struct, op_struct, blacs_env, para_env, coeff)
     364              : 
     365           18 :       IF (tp) THEN
     366            6 :          coeff => soc_env%b_coeff
     367              :       ELSE
     368           12 :          coeff => soc_env%a_coeff
     369              :       END IF
     370              : 
     371           18 :       sggs = .FALSE.
     372           18 :       IF (PRESENT(gs_coeffs)) sggs = .TRUE.
     373              : 
     374           18 :       ispin = 1 !! only rcs availble
     375           18 :       nex = SIZE(evec_fm, 2)
     376           90 :       IF (.NOT. sggs) ALLOCATE (WCdSC_tmp(ispin, nex))
     377           18 :       CALL get_qs_env(qs_env, blacs_env=blacs_env, para_env=para_env)
     378           18 :       CALL cp_fm_get_info(soc_env%CdS(ispin, ideriv), ncol_global=nao, nrow_global=n_virt)
     379           18 :       CALL cp_fm_get_info(evec_fm(1, 1), ncol_global=n_act)
     380              : 
     381           18 :       IF (sggs) THEN
     382              :          CALL cp_fm_struct_create(virt_occ_struct, context=blacs_env, para_env=para_env, nrow_global=n_virt, &
     383            6 :                                   ncol_global=n_act)
     384              :          CALL cp_fm_struct_create(op_struct, context=blacs_env, para_env=para_env, nrow_global=n_act*nex, &
     385            6 :                                   ncol_global=n_act)
     386              :       ELSE
     387              :          CALL cp_fm_struct_create(virt_occ_struct, context=blacs_env, para_env=para_env, nrow_global=n_virt, &
     388           12 :                                   ncol_global=n_act*nex)
     389              :          CALL cp_fm_struct_create(op_struct, context=blacs_env, para_env=para_env, nrow_global=n_act*nex, &
     390           12 :                                   ncol_global=n_act*nex)
     391              :       END IF
     392              : 
     393           18 :       CALL cp_fm_create(CdSC, soc_env%ediff(ispin)%matrix_struct)
     394           18 :       CALL cp_fm_create(op_fm, op_struct)
     395              : 
     396           18 :       IF (sggs) THEN
     397            6 :          CALL cp_fm_create(SCWCdSC, gs_coeffs%matrix_struct)
     398            6 :          CALL cp_fm_create(WCdSC, soc_env%ediff(ispin)%matrix_struct)
     399              :          CALL parallel_gemm('N', 'N', n_virt, n_act, nao, 1.0_dp, soc_env%CdS(ispin, ideriv), &
     400            6 :                             gs_coeffs, 0.0_dp, CdSC)
     401            6 :          CALL cp_fm_schur_product(CdSC, soc_env%ediff(ispin), WCdSC)
     402              :       ELSE
     403           12 :          CALL cp_fm_create(SCWCdSC, coeff%matrix_struct)
     404           36 :          DO iex = 1, nex
     405           24 :             CALL cp_fm_create(WCdSC_tmp(ispin, iex), soc_env%ediff(ispin)%matrix_struct)
     406              :             CALL parallel_gemm('N', 'N', n_virt, n_act, nao, 1.0_dp, soc_env%CdS(ispin, ideriv), &
     407           24 :                                evec_fm(ispin, iex), 0.0_dp, CdSC)
     408           36 :             CALL cp_fm_schur_product(CdSC, soc_env%ediff(ispin), WCdSC_tmp(ispin, iex))
     409              :          END DO
     410           12 :          CALL cp_fm_create(WCdSC, virt_occ_struct)
     411           12 :          CALL soc_contract_evect(WCdSC_tmp, WCdSC)
     412           36 :          DO iex = 1, nex
     413           36 :             CALL cp_fm_release(WCdSC_tmp(ispin, iex))
     414              :          END DO
     415           12 :          DEALLOCATE (WCdSC_tmp)
     416              :       END IF
     417              : 
     418           18 :       IF (sggs) THEN
     419            6 :          CALL parallel_gemm('N', 'N', nao, n_act, n_virt, 1.0_dp, soc_env%SC(ispin), WCdSC, 0.0_dp, SCWCdSC)
     420            6 :          CALL parallel_gemm('T', 'N', n_act*nex, n_act, nao, 1.0_dp, soc_env%a_coeff, SCWCdSC, 0.0_dp, op_fm)
     421              :       ELSE
     422           12 :          CALL parallel_gemm('N', 'N', nao, n_act*nex, n_virt, 1.0_dp, soc_env%SC(ispin), WCdSC, 0.0_dp, SCWCdSC)
     423           12 :          CALL parallel_gemm('T', 'N', n_act*nex, n_act*nex, nao, 1.0_dp, coeff, SCWCdSC, 0.0_dp, op_fm)
     424              :       END IF
     425              : 
     426           18 :       IF (sggs) THEN
     427            6 :          CALL cp_fm_to_fm(op_fm, sggs_fm)
     428              :       ELSE
     429           12 :          CALL copy_fm_to_dbcsr(op_fm, op)
     430              :       END IF
     431              : 
     432           18 :       CALL cp_fm_release(op_fm)
     433           18 :       CALL cp_fm_release(WCdSC)
     434           18 :       CALL cp_fm_release(SCWCdSC)
     435           18 :       CALL cp_fm_release(CdSC)
     436           18 :       CALL cp_fm_struct_release(virt_occ_struct)
     437           18 :       CALL cp_fm_struct_release(op_struct)
     438              : 
     439           36 :    END SUBROUTINE dip_vel_op
     440              : 
     441              : ! **************************************************************************************************
     442              : !> \brief ...
     443              : !> \param fm_start ...
     444              : !> \param fm_res ...
     445              : ! **************************************************************************************************
     446           32 :    SUBROUTINE soc_contract_evect(fm_start, fm_res)
     447              : 
     448              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in)      :: fm_start
     449              :       TYPE(cp_fm_type), INTENT(inout)                    :: fm_res
     450              : 
     451              :       CHARACTER(len=*), PARAMETER :: routineN = 'soc_contract_evect'
     452              : 
     453              :       INTEGER                                            :: handle, ii, jj, nactive, nao, nspins, &
     454              :                                                             nstates, ntmp1, ntmp2
     455              : 
     456           32 :       CALL timeset(routineN, handle)
     457              : 
     458           32 :       nstates = SIZE(fm_start, 2)
     459           32 :       nspins = SIZE(fm_start, 1)
     460              : 
     461           32 :       CALL cp_fm_set_all(fm_res, 0.0_dp)
     462              :          !! Evects are written into one matrix.
     463          112 :       DO ii = 1, nstates
     464          192 :          DO jj = 1, nspins
     465           80 :             CALL cp_fm_get_info(fm_start(jj, ii), nrow_global=nao, ncol_global=nactive)
     466           80 :             CALL cp_fm_get_info(fm_res, nrow_global=ntmp1, ncol_global=ntmp2)
     467              :             CALL cp_fm_to_fm_submat(fm_start(jj, ii), &
     468              :                                     fm_res, &
     469              :                                     nao, nactive, &
     470              :                                     1, 1, 1, &
     471          160 :                                     1 + nactive*(ii - 1) + (jj - 1)*nao*nstates)
     472              :          END DO !nspins
     473              :       END DO !nsstates
     474              : 
     475           32 :       CALL timestop(handle)
     476              : 
     477           32 :    END SUBROUTINE soc_contract_evect
     478              : 
     479              : ! **************************************************************************************************
     480              : !> \brief ...
     481              : !> \param vec ...
     482              : !> \param new_entry ...
     483              : !> \param res ...
     484              : !> \param res_int ...
     485              : ! **************************************************************************************************
     486          466 :    SUBROUTINE test_repetition(vec, new_entry, res, res_int)
     487              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: vec
     488              :       INTEGER, INTENT(IN)                                :: new_entry
     489              :       LOGICAL, INTENT(OUT)                               :: res
     490              :       INTEGER, INTENT(OUT), OPTIONAL                     :: res_int
     491              : 
     492              :       INTEGER                                            :: i
     493              : 
     494          466 :       res = .TRUE.
     495          466 :       IF (PRESENT(res_int)) res_int = -1
     496              : 
     497         4266 :       DO i = 1, SIZE(vec)
     498         4266 :          IF (vec(i) == new_entry) THEN
     499          204 :             res = .FALSE.
     500          204 :             IF (PRESENT(res_int)) res_int = i
     501              :             EXIT
     502              :          END IF
     503              :       END DO
     504              : 
     505          466 :    END SUBROUTINE test_repetition
     506              : 
     507              : ! **************************************************************************************************
     508              : !> \brief Used to find out, which state has which spin-multiplicity
     509              : !> \param evects_cfm ...
     510              : !> \param sort ...
     511              : ! **************************************************************************************************
     512            8 :    SUBROUTINE resort_evects(evects_cfm, sort)
     513              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: evects_cfm
     514              :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT)    :: sort
     515              : 
     516              :       COMPLEX(dp), ALLOCATABLE, DIMENSION(:, :)          :: cpl_tmp
     517              :       INTEGER                                            :: i_rep, ii, jj, ntot, tmp
     518            8 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: rep_int
     519              :       LOGICAL                                            :: rep
     520              :       REAL(dp)                                           :: max_dev, max_wfn, wfn_sq
     521              : 
     522            8 :       CALL cp_cfm_get_info(evects_cfm, nrow_global=ntot)
     523           32 :       ALLOCATE (cpl_tmp(ntot, ntot))
     524           32 :       ALLOCATE (sort(ntot), rep_int(ntot))
     525            8 :       cpl_tmp = 0_dp
     526            8 :       sort = 0
     527            8 :       max_dev = 0.5
     528            8 :       CALL cp_cfm_get_submatrix(evects_cfm, cpl_tmp)
     529              : 
     530          104 :       DO jj = 1, ntot
     531           96 :          rep_int = 0
     532           96 :          tmp = 0
     533           96 :          max_wfn = 0_dp
     534         1272 :          DO ii = 1, ntot
     535         1176 :             wfn_sq = ABS(REAL(cpl_tmp(ii, jj)**2 - AIMAG(cpl_tmp(ii, jj)**2)))
     536         1272 :             IF (max_wfn <= wfn_sq) THEN
     537          466 :                CALL test_repetition(sort, ii, rep, rep_int(ii))
     538          466 :                IF (rep) THEN
     539          262 :                   max_wfn = wfn_sq
     540          262 :                   tmp = ii
     541              :                END IF
     542              :             END IF
     543              :          END DO
     544          104 :          IF (tmp > 0) THEN
     545           96 :             sort(jj) = tmp
     546              :          ELSE
     547            0 :             DO i_rep = 1, ntot
     548            0 :                IF (rep_int(i_rep) > 0) THEN
     549            0 :                   max_wfn = ABS(REAL(cpl_tmp(sort(i_rep), jj)**2 - AIMAG(cpl_tmp(sort(i_rep), jj)**2))) - max_dev
     550            0 :                   DO ii = 1, ntot
     551            0 :                      wfn_sq = ABS(REAL(cpl_tmp(ii, jj)**2 - AIMAG(cpl_tmp(ii, jj)**2)))
     552            0 :                      IF ((max_wfn - wfn_sq)/max_wfn <= max_dev) THEN
     553            0 :                         CALL test_repetition(sort, ii, rep)
     554            0 :                         IF (rep .AND. ii /= i_rep) THEN
     555            0 :                            sort(jj) = sort(i_rep)
     556            0 :                            sort(i_rep) = ii
     557              :                         END IF
     558              :                      END IF
     559              :                   END DO
     560              :                END IF
     561              :             END DO
     562              :          END IF
     563              :       END DO
     564              : 
     565            8 :       DEALLOCATE (cpl_tmp, rep_int)
     566              : 
     567            8 :    END SUBROUTINE resort_evects
     568              : 
     569            0 : END MODULE qs_tddfpt2_soc_utils
        

Generated by: LCOV version 2.0-1