LCOV - code coverage report
Current view: top level - src - soc_pseudopotential_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:8ebf9ad) Lines: 100.0 % 79 79
Test Date: 2026-01-22 06:43:13 Functions: 100.0 % 2 2

            Line data    Source code
       1              : !--------------------------------------------------------------------------------------------------!
       2              : !   CP2K: A general program to perform molecular dynamics simulations                              !
       3              : !   Copyright 2000-2026 CP2K developers group <https://cp2k.org>                                   !
       4              : !                                                                                                  !
       5              : !   SPDX-License-Identifier: GPL-2.0-or-later                                                      !
       6              : !--------------------------------------------------------------------------------------------------!
       7              : 
       8              : MODULE soc_pseudopotential_methods
       9              :    USE atomic_kind_types,               ONLY: atomic_kind_type
      10              :    USE core_ppnl,                       ONLY: build_core_ppnl
      11              :    USE cp_cfm_types,                    ONLY: cp_cfm_get_info,&
      12              :                                               cp_cfm_type
      13              :    USE cp_control_types,                ONLY: dft_control_type
      14              :    USE cp_dbcsr_api,                    ONLY: dbcsr_add,&
      15              :                                               dbcsr_copy,&
      16              :                                               dbcsr_create,&
      17              :                                               dbcsr_desymmetrize,&
      18              :                                               dbcsr_p_type,&
      19              :                                               dbcsr_set,&
      20              :                                               dbcsr_type_antisymmetric,&
      21              :                                               dbcsr_type_no_symmetry
      22              :    USE cp_dbcsr_cp2k_link,              ONLY: cp_dbcsr_alloc_block_from_nbl
      23              :    USE cp_dbcsr_operations,             ONLY: dbcsr_allocate_matrix_set,&
      24              :                                               dbcsr_deallocate_matrix_set
      25              :    USE kinds,                           ONLY: dp
      26              :    USE kpoint_types,                    ONLY: get_kpoint_info,&
      27              :                                               kpoint_type
      28              :    USE particle_types,                  ONLY: particle_type
      29              :    USE qs_environment_types,            ONLY: get_qs_env,&
      30              :                                               qs_environment_type
      31              :    USE qs_force_types,                  ONLY: qs_force_type
      32              :    USE qs_kind_types,                   ONLY: qs_kind_type
      33              :    USE qs_neighbor_list_types,          ONLY: get_neighbor_list_set_p,&
      34              :                                               neighbor_list_set_p_type
      35              :    USE virial_types,                    ONLY: virial_type
      36              : #include "./base/base_uses.f90"
      37              : 
      38              :    IMPLICIT NONE
      39              : 
      40              :    PRIVATE
      41              : 
      42              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'soc_pseudopotential_methods'
      43              : 
      44              :    PUBLIC :: V_SOC_xyz_from_pseudopotential, &
      45              :              remove_soc_outside_energy_window_mo
      46              : 
      47              : CONTAINS
      48              : 
      49              : ! **************************************************************************************************
      50              : !> \brief V^SOC_µν^(α),R = ħ/2 < ϕ_µ cell O | sum_ℓ ΔV_ℓ^SO(r,r') L^(α) | ϕ_ν cell R>, α = x,y,z
      51              : !>        see Hartwigsen, Goedecker, Hutter, Eq.(18), (19) (doi.org/10.1103/PhysRevB.58.3641)
      52              : !>        Caution: V^SOC_µν^(α) is purely imaginary and Hermitian; V^SOC_µν^(α) is stored as real
      53              : !>                 dbcsr matrix mat_V_SOC_xyz without symmetry; V^SOC_µν^(α) is stored without
      54              : !>                 the imaginary unit, i.e. mat_V_SOC_xyz is real and antisymmetric
      55              : !> \param qs_env ...
      56              : !> \param mat_V_SOC_xyz ...
      57              : !> \par History
      58              : !>    * 09.2023 created
      59              : !> \author Jan Wilhelm
      60              : ! **************************************************************************************************
      61           28 :    SUBROUTINE V_SOC_xyz_from_pseudopotential(qs_env, mat_V_SOC_xyz)
      62              :       TYPE(qs_environment_type), POINTER                 :: qs_env
      63              :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_V_SOC_xyz
      64              : 
      65              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'V_SOC_xyz_from_pseudopotential'
      66              : 
      67              :       INTEGER                                            :: handle, img, nder, nimages, xyz
      68           14 :       INTEGER, DIMENSION(:, :, :), POINTER               :: cell_to_index
      69              :       LOGICAL                                            :: calculate_forces, do_kp, do_symmetric, &
      70              :                                                             use_virial
      71              :       REAL(KIND=dp)                                      :: eps_ppnl
      72           14 :       TYPE(atomic_kind_type), DIMENSION(:), POINTER      :: atomic_kind_set
      73           14 :       TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER       :: mat_l, mat_l_nosym, mat_pot_dummy, &
      74           14 :                                                             matrix_dummy, matrix_s
      75              :       TYPE(dft_control_type), POINTER                    :: dft_control
      76              :       TYPE(kpoint_type), POINTER                         :: kpoints
      77              :       TYPE(neighbor_list_set_p_type), DIMENSION(:), &
      78           14 :          POINTER                                         :: sab_orb, sap_ppnl
      79           14 :       TYPE(particle_type), DIMENSION(:), POINTER         :: particle_set
      80           14 :       TYPE(qs_force_type), DIMENSION(:), POINTER         :: force
      81           14 :       TYPE(qs_kind_type), DIMENSION(:), POINTER          :: qs_kind_set
      82              :       TYPE(virial_type), POINTER                         :: virial
      83              : 
      84           14 :       CALL timeset(routineN, handle)
      85              : 
      86           14 :       NULLIFY (qs_kind_set, dft_control, sab_orb, sap_ppnl, particle_set, atomic_kind_set, &
      87           14 :                cell_to_index)
      88              :       CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, dft_control=dft_control, &
      89              :                       matrix_s_kp=matrix_s, kpoints=kpoints, atomic_kind_set=atomic_kind_set, &
      90           14 :                       particle_set=particle_set, sab_orb=sab_orb, sap_ppnl=sap_ppnl)
      91              : 
      92           14 :       eps_ppnl = dft_control%qs_control%eps_ppnl
      93           14 :       nimages = dft_control%nimages
      94           14 :       do_kp = (nimages > 1)
      95           14 :       CALL get_neighbor_list_set_p(neighbor_list_sets=sab_orb, symmetric=do_symmetric)
      96           14 :       CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
      97              : 
      98           14 :       NULLIFY (mat_l, mat_pot_dummy)
      99           14 :       CALL dbcsr_allocate_matrix_set(mat_l, 3, nimages)
     100           56 :       DO xyz = 1, 3
     101          614 :          DO img = 1, nimages
     102          558 :             ALLOCATE (mat_l(xyz, img)%matrix)
     103              :             CALL dbcsr_create(mat_l(xyz, img)%matrix, template=matrix_s(1, 1)%matrix, &
     104          558 :                               matrix_type=dbcsr_type_antisymmetric)
     105          558 :             CALL cp_dbcsr_alloc_block_from_nbl(mat_l(xyz, img)%matrix, sab_orb)
     106          600 :             CALL dbcsr_set(mat_l(xyz, img)%matrix, 0.0_dp)
     107              :          END DO
     108              :       END DO
     109              : 
     110              :       ! get mat_l; the next CPASSERT fails if the atoms do not have any SOC parameters, i.e.
     111              :       ! SOC is zero and one should not activate the SOC section
     112           14 :       CPASSERT(ASSOCIATED(sap_ppnl))
     113           14 :       nder = 0
     114           14 :       use_virial = .FALSE.
     115           14 :       calculate_forces = .FALSE.
     116              : 
     117           14 :       NULLIFY (mat_pot_dummy)
     118           14 :       CALL dbcsr_allocate_matrix_set(mat_pot_dummy, 1, nimages)
     119          200 :       DO img = 1, nimages
     120          186 :          ALLOCATE (mat_pot_dummy(1, img)%matrix)
     121          186 :          CALL dbcsr_create(mat_pot_dummy(1, img)%matrix, template=matrix_s(1, 1)%matrix)
     122          186 :          CALL cp_dbcsr_alloc_block_from_nbl(mat_pot_dummy(1, img)%matrix, sab_orb)
     123          200 :          CALL dbcsr_set(mat_pot_dummy(1, img)%matrix, 0.0_dp)
     124              :       END DO
     125              : 
     126              :       CALL build_core_ppnl(mat_pot_dummy, matrix_dummy, force, virial, &
     127              :                            calculate_forces, use_virial, nder, &
     128              :                            qs_kind_set, atomic_kind_set, particle_set, sab_orb, sap_ppnl, &
     129              :                            eps_ppnl, nimages=nimages, cell_to_index=cell_to_index, &
     130           14 :                            basis_type="ORB", matrix_l=mat_l)
     131              : 
     132           14 :       NULLIFY (mat_l_nosym)
     133           14 :       CALL dbcsr_allocate_matrix_set(mat_l_nosym, 3, nimages)
     134           56 :       DO xyz = 1, 3
     135          614 :          DO img = 1, nimages
     136              : 
     137          558 :             ALLOCATE (mat_l_nosym(xyz, img)%matrix)
     138          600 :             IF (do_kp) THEN
     139              :                CALL dbcsr_create(mat_l_nosym(xyz, img)%matrix, template=matrix_s(1, 1)%matrix, &
     140          534 :                                  matrix_type=dbcsr_type_antisymmetric)
     141          534 :                CALL dbcsr_copy(mat_l_nosym(xyz, img)%matrix, mat_l(xyz, img)%matrix)
     142              :             ELSE
     143              :                CALL dbcsr_create(mat_l_nosym(xyz, img)%matrix, template=matrix_s(1, 1)%matrix, &
     144           24 :                                  matrix_type=dbcsr_type_no_symmetry)
     145           24 :                CALL dbcsr_desymmetrize(mat_l(xyz, img)%matrix, mat_l_nosym(xyz, img)%matrix)
     146              :             END IF
     147              : 
     148              :          END DO
     149              :       END DO
     150              : 
     151           14 :       NULLIFY (mat_V_SOC_xyz)
     152           14 :       CALL dbcsr_allocate_matrix_set(mat_V_SOC_xyz, 3, nimages)
     153           56 :       DO xyz = 1, 3
     154          614 :          DO img = 1, nimages
     155          558 :             ALLOCATE (mat_V_SOC_xyz(xyz, img)%matrix)
     156          558 :             IF (do_kp) THEN
     157              :                ! mat_V_SOC_xyz^R with neighbor cell R actually has no symmetry
     158              :                ! mat_V_SOC_xyz^R_µν = mat_V_SOC_xyz^R_νµ* (the actual symmetry is
     159              :                ! mat_V_SOC_xyz^R_µν = mat_V_SOC_xyz^-R_νµ* )  but rskp_transform
     160              :                ! for mat_V_SOC_xyz^R -> mat_V_SOC_xyz(k) requires symmetry...
     161              :                CALL dbcsr_create(mat_V_SOC_xyz(xyz, img)%matrix, template=matrix_s(1, 1)%matrix, &
     162          534 :                                  matrix_type=dbcsr_type_antisymmetric)
     163              :             ELSE
     164              :                CALL dbcsr_create(mat_V_SOC_xyz(xyz, img)%matrix, template=matrix_s(1, 1)%matrix, &
     165           24 :                                  matrix_type=dbcsr_type_no_symmetry)
     166              :             END IF
     167          558 :             CALL cp_dbcsr_alloc_block_from_nbl(mat_V_SOC_xyz(xyz, img)%matrix, sab_orb)
     168              :             ! factor 0.5 from ħ/2 prefactor
     169              :             CALL dbcsr_add(mat_V_SOC_xyz(xyz, img)%matrix, mat_l_nosym(xyz, img)%matrix, &
     170          600 :                            0.0_dp, 0.5_dp)
     171              :          END DO
     172              :       END DO
     173              : 
     174           14 :       CALL dbcsr_deallocate_matrix_set(mat_pot_dummy)
     175           14 :       CALL dbcsr_deallocate_matrix_set(mat_l_nosym)
     176           14 :       CALL dbcsr_deallocate_matrix_set(mat_l)
     177              : 
     178           14 :       CALL timestop(handle)
     179              : 
     180           14 :    END SUBROUTINE V_SOC_xyz_from_pseudopotential
     181              : 
     182              : ! **************************************************************************************************
     183              : !> \brief ...
     184              : !> \param cfm_ks_spinor ...
     185              : !> \param e_win ...
     186              : !> \param eigenval ...
     187              : !> \param E_HOMO ...
     188              : !> \param E_LUMO ...
     189              : ! **************************************************************************************************
     190          336 :    SUBROUTINE remove_soc_outside_energy_window_mo(cfm_ks_spinor, e_win, eigenval, E_HOMO, E_LUMO)
     191              :       TYPE(cp_cfm_type)                                  :: cfm_ks_spinor
     192              :       REAL(KIND=dp)                                      :: e_win
     193              :       REAL(KIND=dp), DIMENSION(:)                        :: eigenval
     194              :       REAL(KIND=dp)                                      :: E_HOMO, E_LUMO
     195              : 
     196              :       CHARACTER(LEN=*), PARAMETER :: routineN = 'remove_soc_outside_energy_window_mo'
     197              : 
     198              :       INTEGER                                            :: handle, i_glob, iiB, j_glob, jjB, &
     199              :                                                             ncol_global, ncol_local, nrow_global, &
     200              :                                                             nrow_local
     201          336 :       INTEGER, DIMENSION(:), POINTER                     :: col_indices, row_indices
     202              :       REAL(KIND=dp)                                      :: E_i, E_j
     203              : 
     204              :       ! Remove SOC outside of energy window (otherwise, numerical problems arise
     205              :       ! because energetically low semicore states and energetically very high
     206              :       ! unbound states couple to the states around the Fermi level).
     207              :       ! This routine is for cfm_ks_spinor being in the molecular-orbital (mo) with
     208              :       ! corresponding eigenvalues "eigenval".
     209              : 
     210          336 :       CALL timeset(routineN, handle)
     211              : 
     212              :       CALL cp_cfm_get_info(matrix=cfm_ks_spinor, &
     213              :                            nrow_global=nrow_global, &
     214              :                            ncol_global=ncol_global, &
     215              :                            nrow_local=nrow_local, &
     216              :                            ncol_local=ncol_local, &
     217              :                            row_indices=row_indices, &
     218          336 :                            col_indices=col_indices)
     219              : 
     220          336 :       CPASSERT(nrow_global == SIZE(eigenval))
     221          336 :       CPASSERT(ncol_global == SIZE(eigenval))
     222              : 
     223         7664 :       DO jjB = 1, ncol_local
     224         7328 :          j_glob = col_indices(jjB)
     225        91536 :          DO iiB = 1, nrow_local
     226        83872 :             i_glob = row_indices(iiB)
     227              : 
     228        83872 :             E_i = eigenval(i_glob)
     229        83872 :             E_j = eigenval(j_glob)
     230              : 
     231              :             IF (E_i < E_HOMO - 0.5_dp*e_win .OR. E_i > E_LUMO + 0.5_dp*e_win .OR. &
     232        91200 :                 E_j < E_HOMO - 0.5_dp*e_win .OR. E_j > E_LUMO + 0.5_dp*e_win) THEN
     233        61340 :                cfm_ks_spinor%local_data(iiB, jjB) = 0.0_dp
     234              :             END IF
     235              : 
     236              :          END DO
     237              :       END DO
     238              : 
     239          336 :       CALL timestop(handle)
     240              : 
     241          336 :    END SUBROUTINE remove_soc_outside_energy_window_mo
     242              : 
     243              : END MODULE soc_pseudopotential_methods
        

Generated by: LCOV version 2.0-1