LCOV - code coverage report
Current view: top level - src - qs_tddfpt2_soc_utils.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:fd1133a) Lines: 94.2 % 207 195
Test Date: 2025-12-07 06:28:01 Functions: 87.5 % 8 7

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2025 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       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_neighbor_list_types,          ONLY: neighbor_list_set_p_type
      53              :    USE qs_operators_ao,                 ONLY: p_xyz_ao,&
      54              :                                               rRc_xyz_ao
      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              :                    !!This routine is analog to qs_tddfpt_prperties but only until the rRc_xyz_ao routine
     130              :                    !! This will lead to an operator within the nao x nao basis
     131              :                    !! qs_tddpft_properies uses nvirt x nocc
     132              :          CALL get_reference_point(reference_point, qs_env=qs_env, &
     133              :                                   reference=tddfpt_control%dipole_reference, &
     134            8 :                                   ref_point=tddfpt_control%dipole_ref_point)
     135              : 
     136              :          CALL rRc_xyz_ao(op=soc_env%dipmat_ao, qs_env=qs_env, rc=reference_point, order=1, &
     137            8 :                          minimum_image=.FALSE., soft=.FALSE.)
     138              :          !! This will lead to S C^virt C^virt,T Q_q (vgl Strand et al., J. Chem Phys. 150, 044702, 2019)
     139            8 :          CALL length_rep(qs_env, gs_mos, soc_env)
     140              :       CASE (tddfpt_dipole_velocity)
     141              :          !!This Routine calcluates the dipole Operator within the velocity-form within the ao basis
     142              :          !!This Operation is only used in xas_tdp and qs_tddfpt_soc, lines uses rmc_x_p_xyz_ao
     143            2 :          CALL p_xyz_ao(soc_env%dipmat_ao, qs_env, minimum_image=.FALSE.)
     144              :          !! This will precomute SC^virt, (omega^a-omega^i)^-1 and C^virt dS/dq
     145            2 :          CALL velocity_rep(qs_env, gs_mos, soc_env)
     146              :       CASE DEFAULT
     147           10 :          CPABORT("Unimplemented form of the dipole operator")
     148              :       END SELECT
     149              : 
     150           10 :       CALL timestop(handle)
     151              : 
     152           20 :    END SUBROUTINE soc_dipole_operator
     153              : 
     154              : ! **************************************************************************************************
     155              : !> \brief ...
     156              : !> \param qs_env ...
     157              : !> \param gs_mos ...
     158              : !> \param soc_env ...
     159              : ! **************************************************************************************************
     160            8 :    SUBROUTINE length_rep(qs_env, gs_mos, soc_env)
     161              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     162              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     163              :          INTENT(in)                                      :: gs_mos
     164              :       TYPE(soc_env_type), TARGET                         :: soc_env
     165              : 
     166              :       INTEGER                                            :: ideriv, ispin, nao, nderivs, nspins
     167            8 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: nmo_virt
     168              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     169              :       TYPE(cp_fm_struct_type), POINTER                   :: dip_struct, fm_struct
     170            8 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:)        :: S_mos_virt
     171            8 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: dipole_op_mos_occ
     172              :       TYPE(cp_fm_type), POINTER                          :: dipmat_tmp, wfm_ao_ao
     173            8 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s
     174              :       TYPE(dbcsr_type), POINTER                          :: symm_tmp
     175              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     176              : 
     177            8 :       CALL get_qs_env(qs_env, matrix_s=matrix_s, blacs_env=blacs_env, para_env=para_env)
     178              : 
     179            8 :       nderivs = 3
     180            8 :       nspins = 1  !!We only account for rcs, will be changed in the future
     181            8 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
     182              :       ALLOCATE (S_mos_virt(nspins), dipole_op_mos_occ(3, nspins), &
     183           48 :                 wfm_ao_ao, nmo_virt(nspins), symm_tmp, dipmat_tmp)
     184              : 
     185            8 :       CALL cp_fm_struct_create(dip_struct, context=blacs_env, ncol_global=nao, nrow_global=nao, para_env=para_env)
     186              : 
     187            8 :       CALL dbcsr_allocate_matrix_set(soc_env%dipmat, nderivs)
     188            8 :       CALL dbcsr_desymmetrize(matrix_s(1)%matrix, symm_tmp)
     189           32 :       DO ideriv = 1, nderivs
     190           24 :          ALLOCATE (soc_env%dipmat(ideriv)%matrix)
     191              :          CALL dbcsr_create(soc_env%dipmat(ideriv)%matrix, template=symm_tmp, &
     192           24 :                            name="contracted operator", matrix_type="N")
     193           56 :          DO ispin = 1, nspins
     194           48 :             CALL cp_fm_create(dipole_op_mos_occ(ideriv, ispin), matrix_struct=dip_struct)
     195              :          END DO
     196              :       END DO
     197              : 
     198            8 :       CALL dbcsr_release(symm_tmp)
     199            8 :       DEALLOCATE (symm_tmp)
     200              : 
     201           16 :       DO ispin = 1, nspins
     202            8 :          nmo_virt(ispin) = SIZE(gs_mos(ispin)%evals_virt)
     203            8 :          CALL cp_fm_get_info(gs_mos(ispin)%mos_virt, matrix_struct=fm_struct)
     204            8 :          CALL cp_fm_create(wfm_ao_ao, dip_struct)
     205            8 :          CALL cp_fm_create(S_mos_virt(ispin), fm_struct)
     206              : 
     207              :          CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
     208              :                                       gs_mos(ispin)%mos_virt, &
     209              :                                       S_mos_virt(ispin), &
     210            8 :                                       ncol=nmo_virt(ispin), alpha=1.0_dp, beta=0.0_dp)
     211              :          CALL parallel_gemm('N', 'T', nao, nao, nmo_virt(ispin), &
     212              :                             1.0_dp, S_mos_virt(ispin), gs_mos(ispin)%mos_virt, &
     213            8 :                             0.0_dp, wfm_ao_ao)
     214              : 
     215           32 :          DO ideriv = 1, nderivs
     216           24 :             CALL cp_fm_create(dipmat_tmp, dip_struct)
     217           24 :             CALL copy_dbcsr_to_fm(soc_env%dipmat_ao(ideriv)%matrix, dipmat_tmp)
     218              :             CALL parallel_gemm('N', 'T', nao, nao, nao, &
     219              :                                1.0_dp, wfm_ao_ao, dipmat_tmp, &
     220           24 :                                0.0_dp, dipole_op_mos_occ(ideriv, ispin))
     221           24 :             CALL copy_fm_to_dbcsr(dipole_op_mos_occ(ideriv, ispin), soc_env%dipmat(ideriv)%matrix)
     222           56 :             CALL cp_fm_release(dipmat_tmp)
     223              :          END DO
     224            8 :          CALL cp_fm_release(wfm_ao_ao)
     225           24 :          DEALLOCATE (wfm_ao_ao)
     226              :       END DO
     227              : 
     228            8 :       CALL cp_fm_struct_release(dip_struct)
     229           16 :       DO ispin = 1, nspins
     230            8 :          CALL cp_fm_release(S_mos_virt(ispin))
     231           40 :          DO ideriv = 1, nderivs
     232           32 :             CALL cp_fm_release(dipole_op_mos_occ(ideriv, ispin))
     233              :          END DO
     234              :       END DO
     235            8 :       DEALLOCATE (S_mos_virt, dipole_op_mos_occ, nmo_virt, dipmat_tmp)
     236              : 
     237            8 :    END SUBROUTINE length_rep
     238              : 
     239              : ! **************************************************************************************************
     240              : !> \brief ...
     241              : !> \param qs_env ...
     242              : !> \param gs_mos ...
     243              : !> \param soc_env ...
     244              : ! **************************************************************************************************
     245            2 :    SUBROUTINE velocity_rep(qs_env, gs_mos, soc_env)
     246              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     247              :       TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
     248              :          INTENT(in)                                      :: gs_mos
     249              :       TYPE(soc_env_type), TARGET                         :: soc_env
     250              : 
     251              :       INTEGER                                            :: ici, icol, ideriv, irow, ispin, n_act, &
     252              :                                                             n_virt, nao, ncols_local, nderivs, &
     253              :                                                             nrows_local, nspins
     254            2 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     255              :       REAL(kind=dp)                                      :: eval_occ
     256              :       REAL(kind=dp), CONTIGUOUS, DIMENSION(:, :), &
     257            2 :          POINTER                                         :: local_data_ediff
     258              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     259              :       TYPE(cp_fm_struct_type), POINTER                   :: ao_cvirt_struct, cvirt_ao_struct, &
     260              :                                                             fm_struct, scrm_struct
     261              :       TYPE(cp_fm_type)                                   :: scrm_fm
     262            2 :       TYPE(dbcsr_p_type), DIMENSION(:), POINTER          :: matrix_s, scrm
     263              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
     264            2 :          POINTER                                         :: sab_orb
     265              :       TYPE(qs_ks_env_type), POINTER                      :: ks_env
     266              : 
     267            2 :       NULLIFY (scrm, scrm_struct, blacs_env, matrix_s, ao_cvirt_struct, cvirt_ao_struct)
     268            2 :       nspins = 1
     269            2 :       nderivs = 3
     270           18 :       ALLOCATE (soc_env%SC(nspins), soc_env%CdS(nspins, nderivs), soc_env%ediff(nspins))
     271              : 
     272            2 :       CALL get_qs_env(qs_env, ks_env=ks_env, sab_orb=sab_orb, blacs_env=blacs_env, matrix_s=matrix_s)
     273            2 :       CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
     274              :       CALL cp_fm_struct_create(scrm_struct, nrow_global=nao, ncol_global=nao, &
     275            2 :                                context=blacs_env)
     276            2 :       CALL cp_fm_get_info(gs_mos(1)%mos_virt, matrix_struct=ao_cvirt_struct)
     277              : 
     278              :       CALL build_overlap_matrix(ks_env, matrix_s=scrm, nderivative=1, &
     279              :                                 basis_type_a="ORB", basis_type_b="ORB", &
     280            2 :                                 sab_nl=sab_orb)
     281              : 
     282            4 :       DO ispin = 1, nspins
     283            2 :          NULLIFY (fm_struct)
     284              : !deb     n_occ = SIZE(gs_mos(ispin)%evals_occ)
     285            2 :          n_act = gs_mos(ispin)%nmo_active
     286            2 :          n_virt = SIZE(gs_mos(ispin)%evals_virt)
     287              :          CALL cp_fm_struct_create(fm_struct, nrow_global=n_virt, &
     288            2 :                                   ncol_global=n_act, context=blacs_env)
     289              :          CALL cp_fm_struct_create(cvirt_ao_struct, nrow_global=n_virt, &
     290            2 :                                   ncol_global=nao, context=blacs_env)
     291            2 :          CALL cp_fm_create(soc_env%ediff(ispin), fm_struct)
     292            2 :          CALL cp_fm_create(soc_env%SC(ispin), ao_cvirt_struct)
     293              : 
     294              :          CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, &
     295              :                                       gs_mos(ispin)%mos_virt, &
     296              :                                       soc_env%SC(ispin), &
     297            2 :                                       ncol=n_virt, alpha=1.0_dp, beta=0.0_dp)
     298              : 
     299              :          CALL cp_fm_get_info(soc_env%ediff(ispin), nrow_local=nrows_local, ncol_local=ncols_local, &
     300            2 :                              row_indices=row_indices, col_indices=col_indices, local_data=local_data_ediff)
     301              : 
     302              : !$OMP       PARALLEL DO DEFAULT(NONE), &
     303              : !$OMP                PRIVATE(eval_occ, ici, icol, irow), &
     304            2 : !$OMP                SHARED(col_indices, gs_mos, ispin, local_data_ediff, ncols_local, nrows_local, row_indices)
     305              :          DO icol = 1, ncols_local
     306              :             ! E_occ_i ; imo_occ = col_indices(icol)
     307              :             ici = gs_mos(ispin)%index_active(col_indices(icol))
     308              :             eval_occ = gs_mos(ispin)%evals_occ(ici)
     309              : 
     310              :             DO irow = 1, nrows_local
     311              :                ! ediff_inv_weights(a, i) = 1.0 / (E_virt_a - E_occ_i)
     312              :                ! imo_virt = row_indices(irow)
     313              :                local_data_ediff(irow, icol) = 1.0_dp/(gs_mos(ispin)%evals_virt(row_indices(irow)) - eval_occ)
     314              :             END DO
     315              :          END DO
     316              : !$OMP       END PARALLEL DO
     317              : 
     318            8 :          DO ideriv = 1, nderivs
     319            6 :             CALL cp_fm_create(soc_env%CdS(ispin, ideriv), cvirt_ao_struct)
     320            6 :             CALL cp_fm_create(scrm_fm, scrm_struct)
     321            6 :             CALL copy_dbcsr_to_fm(scrm(ideriv + 1)%matrix, scrm_fm)
     322              :             CALL parallel_gemm('T', 'N', n_virt, nao, nao, 1.0_dp, gs_mos(ispin)%mos_virt, &
     323            6 :                                scrm_fm, 0.0_dp, soc_env%CdS(ispin, ideriv))
     324           14 :             CALL cp_fm_release(scrm_fm)
     325              : 
     326              :          END DO
     327              : 
     328            6 :          CALL cp_fm_struct_release(fm_struct)
     329              :       END DO
     330            2 :       CALL dbcsr_deallocate_matrix_set(scrm)
     331            2 :       CALL cp_fm_struct_release(scrm_struct)
     332            2 :       CALL cp_fm_struct_release(cvirt_ao_struct)
     333              : 
     334            4 :    END SUBROUTINE velocity_rep
     335              : 
     336              : ! **************************************************************************************************
     337              : !> \brief This routine will construct the dipol operator within velocity representation
     338              : !> \param soc_env ..
     339              : !> \param qs_env ...
     340              : !> \param evec_fm ...
     341              : !> \param op ...
     342              : !> \param ideriv ...
     343              : !> \param tp ...
     344              : !> \param gs_coeffs ...
     345              : !> \param sggs_fm ...
     346              : ! **************************************************************************************************
     347           18 :    SUBROUTINE dip_vel_op(soc_env, qs_env, evec_fm, op, ideriv, tp, gs_coeffs, sggs_fm)
     348              :       TYPE(soc_env_type), TARGET                         :: soc_env
     349              :       TYPE(qs_environment_type), POINTER                 :: qs_env
     350              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN)      :: evec_fm
     351              :       TYPE(dbcsr_type), INTENT(INOUT)                    :: op
     352              :       INTEGER, INTENT(IN)                                :: ideriv
     353              :       LOGICAL, INTENT(IN)                                :: tp
     354              :       TYPE(cp_fm_type), OPTIONAL, POINTER                :: gs_coeffs
     355              :       TYPE(cp_fm_type), INTENT(INOUT), OPTIONAL          :: sggs_fm
     356              : 
     357              :       INTEGER                                            :: iex, ispin, n_act, n_virt, nao, nex
     358              :       LOGICAL                                            :: sggs
     359              :       TYPE(cp_blacs_env_type), POINTER                   :: blacs_env
     360              :       TYPE(cp_fm_struct_type), POINTER                   :: op_struct, virt_occ_struct
     361              :       TYPE(cp_fm_type)                                   :: CdSC, op_fm, SCWCdSC, WCdSC
     362           18 :       TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :)     :: WCdSC_tmp
     363              :       TYPE(cp_fm_type), POINTER                          :: coeff
     364              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     365              : 
     366           18 :       NULLIFY (virt_occ_struct, virt_occ_struct, op_struct, blacs_env, para_env, coeff)
     367              : 
     368           18 :       IF (tp) THEN
     369            6 :          coeff => soc_env%b_coeff
     370              :       ELSE
     371           12 :          coeff => soc_env%a_coeff
     372              :       END IF
     373              : 
     374           18 :       sggs = .FALSE.
     375           18 :       IF (PRESENT(gs_coeffs)) sggs = .TRUE.
     376              : 
     377           18 :       ispin = 1 !! only rcs availble
     378           18 :       nex = SIZE(evec_fm, 2)
     379           90 :       IF (.NOT. sggs) ALLOCATE (WCdSC_tmp(ispin, nex))
     380           18 :       CALL get_qs_env(qs_env, blacs_env=blacs_env, para_env=para_env)
     381           18 :       CALL cp_fm_get_info(soc_env%CdS(ispin, ideriv), ncol_global=nao, nrow_global=n_virt)
     382           18 :       CALL cp_fm_get_info(evec_fm(1, 1), ncol_global=n_act)
     383              : 
     384           18 :       IF (sggs) THEN
     385              :          CALL cp_fm_struct_create(virt_occ_struct, context=blacs_env, para_env=para_env, nrow_global=n_virt, &
     386            6 :                                   ncol_global=n_act)
     387              :          CALL cp_fm_struct_create(op_struct, context=blacs_env, para_env=para_env, nrow_global=n_act*nex, &
     388            6 :                                   ncol_global=n_act)
     389              :       ELSE
     390              :          CALL cp_fm_struct_create(virt_occ_struct, context=blacs_env, para_env=para_env, nrow_global=n_virt, &
     391           12 :                                   ncol_global=n_act*nex)
     392              :          CALL cp_fm_struct_create(op_struct, context=blacs_env, para_env=para_env, nrow_global=n_act*nex, &
     393           12 :                                   ncol_global=n_act*nex)
     394              :       END IF
     395              : 
     396           18 :       CALL cp_fm_create(CdSC, soc_env%ediff(ispin)%matrix_struct)
     397           18 :       CALL cp_fm_create(op_fm, op_struct)
     398              : 
     399           18 :       IF (sggs) THEN
     400            6 :          CALL cp_fm_create(SCWCdSC, gs_coeffs%matrix_struct)
     401            6 :          CALL cp_fm_create(WCdSC, soc_env%ediff(ispin)%matrix_struct)
     402              :          CALL parallel_gemm('N', 'N', n_virt, n_act, nao, 1.0_dp, soc_env%CdS(ispin, ideriv), &
     403            6 :                             gs_coeffs, 0.0_dp, CdSC)
     404            6 :          CALL cp_fm_schur_product(CdSC, soc_env%ediff(ispin), WCdSC)
     405              :       ELSE
     406           12 :          CALL cp_fm_create(SCWCdSC, coeff%matrix_struct)
     407           36 :          DO iex = 1, nex
     408           24 :             CALL cp_fm_create(WCdSC_tmp(ispin, iex), soc_env%ediff(ispin)%matrix_struct)
     409              :             CALL parallel_gemm('N', 'N', n_virt, n_act, nao, 1.0_dp, soc_env%CdS(ispin, ideriv), &
     410           24 :                                evec_fm(ispin, iex), 0.0_dp, CdSC)
     411           36 :             CALL cp_fm_schur_product(CdSC, soc_env%ediff(ispin), WCdSC_tmp(ispin, iex))
     412              :          END DO
     413           12 :          CALL cp_fm_create(WCdSC, virt_occ_struct)
     414           12 :          CALL soc_contract_evect(WCdSC_tmp, WCdSC)
     415           36 :          DO iex = 1, nex
     416           36 :             CALL cp_fm_release(WCdSC_tmp(ispin, iex))
     417              :          END DO
     418           12 :          DEALLOCATE (WCdSC_tmp)
     419              :       END IF
     420              : 
     421           18 :       IF (sggs) THEN
     422            6 :          CALL parallel_gemm('N', 'N', nao, n_act, n_virt, 1.0_dp, soc_env%SC(ispin), WCdSC, 0.0_dp, SCWCdSC)
     423            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)
     424              :       ELSE
     425           12 :          CALL parallel_gemm('N', 'N', nao, n_act*nex, n_virt, 1.0_dp, soc_env%SC(ispin), WCdSC, 0.0_dp, SCWCdSC)
     426           12 :          CALL parallel_gemm('T', 'N', n_act*nex, n_act*nex, nao, 1.0_dp, coeff, SCWCdSC, 0.0_dp, op_fm)
     427              :       END IF
     428              : 
     429           18 :       IF (sggs) THEN
     430            6 :          CALL cp_fm_to_fm(op_fm, sggs_fm)
     431              :       ELSE
     432           12 :          CALL copy_fm_to_dbcsr(op_fm, op)
     433              :       END IF
     434              : 
     435           18 :       CALL cp_fm_release(op_fm)
     436           18 :       CALL cp_fm_release(WCdSC)
     437           18 :       CALL cp_fm_release(SCWCdSC)
     438           18 :       CALL cp_fm_release(CdSC)
     439           18 :       CALL cp_fm_struct_release(virt_occ_struct)
     440           18 :       CALL cp_fm_struct_release(op_struct)
     441              : 
     442           36 :    END SUBROUTINE dip_vel_op
     443              : 
     444              : ! **************************************************************************************************
     445              : !> \brief ...
     446              : !> \param fm_start ...
     447              : !> \param fm_res ...
     448              : ! **************************************************************************************************
     449           32 :    SUBROUTINE soc_contract_evect(fm_start, fm_res)
     450              : 
     451              :       TYPE(cp_fm_type), DIMENSION(:, :), INTENT(in)      :: fm_start
     452              :       TYPE(cp_fm_type), INTENT(inout)                    :: fm_res
     453              : 
     454              :       CHARACTER(len=*), PARAMETER :: routineN = 'soc_contract_evect'
     455              : 
     456              :       INTEGER                                            :: handle, ii, jj, nactive, nao, nspins, &
     457              :                                                             nstates, ntmp1, ntmp2
     458              : 
     459           32 :       CALL timeset(routineN, handle)
     460              : 
     461           32 :       nstates = SIZE(fm_start, 2)
     462           32 :       nspins = SIZE(fm_start, 1)
     463              : 
     464           32 :       CALL cp_fm_set_all(fm_res, 0.0_dp)
     465              :          !! Evects are written into one matrix.
     466          112 :       DO ii = 1, nstates
     467          192 :          DO jj = 1, nspins
     468           80 :             CALL cp_fm_get_info(fm_start(jj, ii), nrow_global=nao, ncol_global=nactive)
     469           80 :             CALL cp_fm_get_info(fm_res, nrow_global=ntmp1, ncol_global=ntmp2)
     470              :             CALL cp_fm_to_fm_submat(fm_start(jj, ii), &
     471              :                                     fm_res, &
     472              :                                     nao, nactive, &
     473              :                                     1, 1, 1, &
     474          160 :                                     1 + nactive*(ii - 1) + (jj - 1)*nao*nstates)
     475              :          END DO !nspins
     476              :       END DO !nsstates
     477              : 
     478           32 :       CALL timestop(handle)
     479              : 
     480           32 :    END SUBROUTINE soc_contract_evect
     481              : 
     482              : ! **************************************************************************************************
     483              : !> \brief ...
     484              : !> \param vec ...
     485              : !> \param new_entry ...
     486              : !> \param res ...
     487              : !> \param res_int ...
     488              : ! **************************************************************************************************
     489          462 :    SUBROUTINE test_repetition(vec, new_entry, res, res_int)
     490              :       INTEGER, DIMENSION(:), INTENT(IN)                  :: vec
     491              :       INTEGER, INTENT(IN)                                :: new_entry
     492              :       LOGICAL, INTENT(OUT)                               :: res
     493              :       INTEGER, INTENT(OUT), OPTIONAL                     :: res_int
     494              : 
     495              :       INTEGER                                            :: i
     496              : 
     497          462 :       res = .TRUE.
     498          462 :       IF (PRESENT(res_int)) res_int = -1
     499              : 
     500         4262 :       DO i = 1, SIZE(vec)
     501         4262 :          IF (vec(i) == new_entry) THEN
     502          198 :             res = .FALSE.
     503          198 :             IF (PRESENT(res_int)) res_int = i
     504              :             EXIT
     505              :          END IF
     506              :       END DO
     507              : 
     508          462 :    END SUBROUTINE test_repetition
     509              : 
     510              : ! **************************************************************************************************
     511              : !> \brief Used to find out, which state has which spin-multiplicity
     512              : !> \param evects_cfm ...
     513              : !> \param sort ...
     514              : ! **************************************************************************************************
     515            8 :    SUBROUTINE resort_evects(evects_cfm, sort)
     516              :       TYPE(cp_cfm_type), INTENT(INOUT)                   :: evects_cfm
     517              :       INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(OUT)    :: sort
     518              : 
     519              :       COMPLEX(dp), ALLOCATABLE, DIMENSION(:, :)          :: cpl_tmp
     520              :       INTEGER                                            :: i_rep, ii, jj, ntot, tmp
     521            8 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: rep_int
     522              :       LOGICAL                                            :: rep
     523              :       REAL(dp)                                           :: max_dev, max_wfn, wfn_sq
     524              : 
     525            8 :       CALL cp_cfm_get_info(evects_cfm, nrow_global=ntot)
     526           32 :       ALLOCATE (cpl_tmp(ntot, ntot))
     527           32 :       ALLOCATE (sort(ntot), rep_int(ntot))
     528         1280 :       cpl_tmp = 0_dp
     529          104 :       sort = 0
     530            8 :       max_dev = 0.5
     531            8 :       CALL cp_cfm_get_submatrix(evects_cfm, cpl_tmp)
     532              : 
     533          104 :       DO jj = 1, ntot
     534         1272 :          rep_int = 0
     535           96 :          tmp = 0
     536           96 :          max_wfn = 0_dp
     537         1272 :          DO ii = 1, ntot
     538         1176 :             wfn_sq = ABS(REAL(cpl_tmp(ii, jj)**2 - AIMAG(cpl_tmp(ii, jj)**2)))
     539         1272 :             IF (max_wfn <= wfn_sq) THEN
     540          462 :                CALL test_repetition(sort, ii, rep, rep_int(ii))
     541          462 :                IF (rep) THEN
     542          264 :                   max_wfn = wfn_sq
     543          264 :                   tmp = ii
     544              :                END IF
     545              :             END IF
     546              :          END DO
     547          104 :          IF (tmp > 0) THEN
     548           96 :             sort(jj) = tmp
     549              :          ELSE
     550            0 :             DO i_rep = 1, ntot
     551            0 :                IF (rep_int(i_rep) > 0) THEN
     552            0 :                   max_wfn = ABS(REAL(cpl_tmp(sort(i_rep), jj)**2 - AIMAG(cpl_tmp(sort(i_rep), jj)**2))) - max_dev
     553            0 :                   DO ii = 1, ntot
     554            0 :                      wfn_sq = ABS(REAL(cpl_tmp(ii, jj)**2 - AIMAG(cpl_tmp(ii, jj)**2)))
     555            0 :                      IF ((max_wfn - wfn_sq)/max_wfn <= max_dev) THEN
     556            0 :                         CALL test_repetition(sort, ii, rep)
     557            0 :                         IF (rep .AND. ii /= i_rep) THEN
     558            0 :                            sort(jj) = sort(i_rep)
     559            0 :                            sort(i_rep) = ii
     560              :                         END IF
     561              :                      END IF
     562              :                   END DO
     563              :                END IF
     564              :             END DO
     565              :          END IF
     566              :       END DO
     567              : 
     568            8 :       DEALLOCATE (cpl_tmp, rep_int)
     569              : 
     570            8 :    END SUBROUTINE resort_evects
     571              : 
     572            0 : END MODULE qs_tddfpt2_soc_utils
        

Generated by: LCOV version 2.0-1