(git:f2099e5)
Loading...
Searching...
No Matches
kpoint_mo_symmetry_methods.F
Go to the documentation of this file.
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 for transforming k-point MO coefficients under symmetry operations
10! **************************************************************************************************
12 USE cp_cfm_types, ONLY: cp_cfm_get_info,&
17 USE kinds, ONLY: dp
22 USE mathconstants, ONLY: twopi
23#include "./base/base_uses.f90"
24
25 IMPLICIT NONE
26 PRIVATE
27
28 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'kpoint_mo_symmetry_methods'
29
30 PUBLIC :: kpoint_same_periodic, &
32
33CONTAINS
34
35! **************************************************************************************************
36!> \brief Compare two fractional k-points modulo reciprocal lattice vectors.
37!> \param xkp_a first k-point
38!> \param xkp_b second k-point
39!> \return true if the k-points are equivalent
40! **************************************************************************************************
41 LOGICAL FUNCTION kpoint_same_periodic(xkp_a, xkp_b) RESULT(same)
42 REAL(kind=dp), DIMENSION(3), INTENT(IN) :: xkp_a, xkp_b
43
44 REAL(kind=dp), DIMENSION(3) :: diff
45
46 diff(1:3) = xkp_a(1:3) - xkp_b(1:3)
47 diff(1:3) = diff(1:3) - real(nint(diff(1:3)), kind=dp)
48 same = sum(abs(diff(1:3))) < 1.0e-8_dp
49
50 END FUNCTION kpoint_same_periodic
51
52! **************************************************************************************************
53!> \brief Transform one SCF MO coefficient matrix to an equivalent full-mesh k-point.
54!> \param src source MO coefficients
55!> \param dst transformed MO coefficients
56!> \param qs_kpoint SCF k-point object containing symmetry operations
57!> \param ikred representative k-point index
58!> \param isym symmetry operation index; 0 direct copy, -1 time reversal
59!> \param success true if the transformation was performed
60!> \param reason diagnostic message
61! **************************************************************************************************
62 SUBROUTINE kpoint_transform_scf_mo(src, dst, qs_kpoint, ikred, &
63 isym, success, reason)
64 TYPE(cp_cfm_type), INTENT(IN) :: src, dst
65 TYPE(kpoint_type), POINTER :: qs_kpoint
66 INTEGER, INTENT(IN) :: ikred, isym
67 LOGICAL, INTENT(OUT) :: success
68 CHARACTER(LEN=*), INTENT(OUT) :: reason
69
70 COMPLEX(KIND=dp) :: coeff, phase
71 COMPLEX(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: dst_coeff, src_coeff
72 INTEGER :: iao, iatom, ikind, imo, irow, irow_source, irow_target, irow_work, nao, natom, &
73 nmo, rot_slot, source_atom, source_dim, target_atom, target_dim
74 INTEGER, ALLOCATABLE, DIMENSION(:) :: ao_size, ao_start
75 LOGICAL :: reverse_phase, time_reversal
76 REAL(kind=dp) :: arg, coskl, sinkl
77 REAL(kind=dp), DIMENSION(3) :: xkp_phase
78 REAL(kind=dp), DIMENSION(:, :), POINTER :: rotmat
79 TYPE(kind_rotmat_type), DIMENSION(:), POINTER :: kind_rot
80 TYPE(kpoint_sym_type), POINTER :: kpsym
81
82 success = .false.
83 reason = ""
84 IF (isym == 0) THEN
85 CALL cp_cfm_to_cfm(src, dst)
86 success = .true.
87 RETURN
88 END IF
89
90 CALL cp_cfm_get_info(src, nrow_global=nao, ncol_global=nmo)
91 ALLOCATE (src_coeff(nao, nmo), dst_coeff(nao, nmo))
92 CALL cp_cfm_get_submatrix(src, src_coeff)
93 dst_coeff(:, :) = cmplx(0.0_dp, 0.0_dp, kind=dp)
94
95 IF (isym == -1) THEN
96 dst_coeff(:, :) = conjg(src_coeff)
97 CALL cp_cfm_set_submatrix(dst, dst_coeff)
98 success = .true.
99 RETURN
100 END IF
101
102 IF (.NOT. ASSOCIATED(qs_kpoint%kp_sym)) THEN
103 reason = "SCF symmetry operation data are not available"
104 RETURN
105 END IF
106 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
107 IF (.NOT. ASSOCIATED(kpsym)) THEN
108 reason = "SCF k-point symmetry operation is not available"
109 RETURN
110 END IF
111 IF (isym > kpsym%nwred) THEN
112 reason = "SCF k-point symmetry operation index is out of range"
113 RETURN
114 END IF
115 IF (.NOT. ASSOCIATED(qs_kpoint%atype) .OR. .NOT. ASSOCIATED(qs_kpoint%kind_rotmat)) THEN
116 reason = "SCF atom mappings or basis rotation matrices are not available"
117 RETURN
118 END IF
119
120 rot_slot = find_kpoint_rotation_slot(qs_kpoint, kpsym%rotp(isym))
121 IF (rot_slot == 0) THEN
122 reason = "could not match the SCF symmetry operation to a basis rotation"
123 RETURN
124 END IF
125 kind_rot => qs_kpoint%kind_rotmat(rot_slot, :)
126 natom = SIZE(qs_kpoint%atype)
127 ALLOCATE (ao_start(natom), ao_size(natom))
128 irow = 1
129 DO iatom = 1, natom
130 ikind = qs_kpoint%atype(iatom)
131 IF (.NOT. ASSOCIATED(kind_rot(ikind)%rmat)) THEN
132 reason = "a required basis rotation matrix is not available"
133 RETURN
134 END IF
135 ao_start(iatom) = irow
136 ao_size(iatom) = SIZE(kind_rot(ikind)%rmat, 2)
137 irow = irow + ao_size(iatom)
138 END DO
139 IF (irow - 1 /= nao) THEN
140 reason = "atom-resolved AO dimensions do not match the MO coefficient matrix"
141 RETURN
142 END IF
143
144 time_reversal = kpsym%rotp(isym) < 0
145 reverse_phase = qs_kpoint%gamma_centered .AND. any(mod(qs_kpoint%nkp_grid, 2) == 0)
146 IF (ASSOCIATED(kpsym%phase_mode)) THEN
147 IF (kpsym%phase_mode(isym) > 0) reverse_phase = kpsym%phase_mode(isym) == 2
148 END IF
149 xkp_phase(1:3) = kpsym%xkp(1:3, isym)
150 DO iatom = 1, natom
151 source_atom = iatom
152 target_atom = kpsym%f0(iatom, isym)
153 ikind = qs_kpoint%atype(source_atom)
154 rotmat => kind_rot(ikind)%rmat
155 source_dim = ao_size(source_atom)
156 target_dim = ao_size(target_atom)
157 IF (SIZE(rotmat, 1) /= target_dim .OR. SIZE(rotmat, 2) /= source_dim) THEN
158 reason = "basis rotation dimensions do not match the atom/AO symmetry transform"
159 RETURN
160 END IF
161 arg = real(kpsym%fcell_gauge(1, source_atom, isym), kind=dp)*xkp_phase(1) + &
162 REAL(kpsym%fcell_gauge(2, source_atom, isym), kind=dp)*xkp_phase(2) + &
163 REAL(kpsym%fcell_gauge(3, source_atom, isym), kind=dp)*xkp_phase(3)
164 IF (ASSOCIATED(kpsym%kgphase)) THEN
165 arg = arg + kpsym%kgphase(source_atom, isym)
166 END IF
167 IF (reverse_phase) arg = -arg
168 coskl = cos(twopi*arg)
169 sinkl = sin(twopi*arg)
170 DO imo = 1, nmo
171 DO irow_work = 1, source_dim
172 irow_source = ao_start(source_atom) + irow_work - 1
173 coeff = src_coeff(irow_source, imo)
174 IF (time_reversal) coeff = conjg(coeff)
175 phase = cmplx(coskl, sinkl, kind=dp)*coeff
176 DO iao = 1, target_dim
177 irow_target = ao_start(target_atom) + iao - 1
178 dst_coeff(irow_target, imo) = dst_coeff(irow_target, imo) + &
179 rotmat(iao, irow_work)*phase
180 END DO
181 END DO
182 END DO
183 END DO
184
185 CALL cp_cfm_set_submatrix(dst, dst_coeff)
186 success = .true.
187
188 END SUBROUTINE kpoint_transform_scf_mo
189
Represents a complex full matrix distributed on many processors.
subroutine, public cp_cfm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
Extract a sub-matrix from the full matrix: op(target_m)(1:n_rows,1:n_cols) = fm(start_row:start_row+n...
subroutine, public cp_cfm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, matrix_struct, para_env)
Returns information about a full matrix.
subroutine, public cp_cfm_set_submatrix(matrix, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
Set a sub-matrix of the full matrix: matrix(start_row:start_row+n_rows,start_col:start_col+n_cols) = ...
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Utilities for transforming k-point MO coefficients under symmetry operations.
logical function, public kpoint_same_periodic(xkp_a, xkp_b)
Compare two fractional k-points modulo reciprocal lattice vectors.
subroutine, public kpoint_transform_scf_mo(src, dst, qs_kpoint, ikred, isym, success, reason)
Transform one SCF MO coefficient matrix to an equivalent full-mesh k-point.
Types and basic routines needed for a kpoint calculation.
integer function, public find_kpoint_rotation_slot(qs_kpoint, rotp)
Locate the basis-rotation slot corresponding to a signed k-point symmetry operation.
Crystal-symmetry routines originating from the K290/ACMI code.
Definition kpsym.F:14
Definition of mathematical constants and functions.
real(kind=dp), parameter, public twopi
Represent a complex full matrix.
Rotation matrices for basis sets.
Keeps symmetry information about a specific k-point.
Contains information about kpoints.