(git:fdbe441)
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! **************************************************************************************************
17 USE kinds, ONLY: dp
21 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_real real part of source MO coefficients
55!> \param src_imag imaginary part of source MO coefficients
56!> \param dst_real real part of transformed MO coefficients
57!> \param dst_imag imaginary part of transformed MO coefficients
58!> \param qs_kpoint SCF k-point object containing symmetry operations
59!> \param ikred representative k-point index
60!> \param isym symmetry operation index; 0 direct copy, -1 time reversal
61!> \param para_env global parallel environment
62!> \param success true if the transformation was performed
63!> \param reason diagnostic message
64! **************************************************************************************************
65 SUBROUTINE kpoint_transform_scf_mo(src_real, src_imag, dst_real, dst_imag, qs_kpoint, ikred, &
66 isym, para_env, success, reason)
67 TYPE(cp_fm_type), INTENT(IN) :: src_real, src_imag, dst_real, dst_imag
68 TYPE(kpoint_type), POINTER :: qs_kpoint
69 INTEGER, INTENT(IN) :: ikred, isym
70 TYPE(mp_para_env_type), POINTER :: para_env
71 LOGICAL, INTENT(OUT) :: success
72 CHARACTER(LEN=*), INTENT(OUT) :: reason
73
74 INTEGER :: iao, iatom, ikind, imo, irow, irow_source, irow_target, irow_work, nao, natom, &
75 nmo, rot_slot, source_atom, source_dim, target_atom, target_dim
76 INTEGER, ALLOCATABLE, DIMENSION(:) :: ao_size, ao_start
77 LOGICAL :: reverse_phase, time_reversal
78 REAL(kind=dp) :: arg, coeff_imag, coeff_real, coskl, &
79 phase_imag, phase_real, sinkl
80 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: dst_i, dst_r, src_i, src_r
81 REAL(kind=dp), DIMENSION(3) :: xkp_phase
82 REAL(kind=dp), DIMENSION(:, :), POINTER :: rotmat
83 TYPE(kind_rotmat_type), DIMENSION(:), POINTER :: kind_rot
84 TYPE(kpoint_sym_type), POINTER :: kpsym
85
86 success = .false.
87 reason = ""
88 IF (isym == 0) THEN
89 CALL cp_fm_copy_general(src_real, dst_real, para_env)
90 CALL cp_fm_copy_general(src_imag, dst_imag, para_env)
91 success = .true.
92 RETURN
93 END IF
94
95 CALL cp_fm_get_info(src_real, nrow_global=nao, ncol_global=nmo)
96 ALLOCATE (src_r(nao, nmo), src_i(nao, nmo), dst_r(nao, nmo), dst_i(nao, nmo))
97 CALL cp_fm_get_submatrix(src_real, src_r)
98 CALL cp_fm_get_submatrix(src_imag, src_i)
99 dst_r(:, :) = 0.0_dp
100 dst_i(:, :) = 0.0_dp
101
102 IF (isym == -1) THEN
103 dst_r(1:nao, 1:nmo) = src_r(1:nao, 1:nmo)
104 dst_i(1:nao, 1:nmo) = -src_i(1:nao, 1:nmo)
105 CALL cp_fm_set_submatrix(dst_real, dst_r)
106 CALL cp_fm_set_submatrix(dst_imag, dst_i)
107 DEALLOCATE (src_r, src_i, dst_r, dst_i)
108 success = .true.
109 RETURN
110 END IF
111
112 IF (.NOT. ASSOCIATED(qs_kpoint%kp_sym)) THEN
113 reason = "SCF symmetry operation data are not available"
114 DEALLOCATE (src_r, src_i, dst_r, dst_i)
115 RETURN
116 END IF
117 kpsym => qs_kpoint%kp_sym(ikred)%kpoint_sym
118 IF (.NOT. ASSOCIATED(kpsym)) THEN
119 reason = "SCF k-point symmetry operation is not available"
120 DEALLOCATE (src_r, src_i, dst_r, dst_i)
121 RETURN
122 END IF
123 IF (isym > kpsym%nwred) THEN
124 reason = "SCF k-point symmetry operation index is out of range"
125 DEALLOCATE (src_r, src_i, dst_r, dst_i)
126 RETURN
127 END IF
128 IF (.NOT. ASSOCIATED(qs_kpoint%atype) .OR. .NOT. ASSOCIATED(qs_kpoint%kind_rotmat)) THEN
129 reason = "SCF atom mappings or basis rotation matrices are not available"
130 DEALLOCATE (src_r, src_i, dst_r, dst_i)
131 RETURN
132 END IF
133
134 rot_slot = find_kpoint_rotation_slot(qs_kpoint, kpsym%rotp(isym))
135 IF (rot_slot == 0) THEN
136 reason = "could not match the SCF symmetry operation to a basis rotation"
137 DEALLOCATE (src_r, src_i, dst_r, dst_i)
138 RETURN
139 END IF
140 kind_rot => qs_kpoint%kind_rotmat(rot_slot, :)
141 natom = SIZE(qs_kpoint%atype)
142 ALLOCATE (ao_start(natom), ao_size(natom))
143 irow = 1
144 DO iatom = 1, natom
145 ikind = qs_kpoint%atype(iatom)
146 IF (.NOT. ASSOCIATED(kind_rot(ikind)%rmat)) THEN
147 reason = "a required basis rotation matrix is not available"
148 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)
149 RETURN
150 END IF
151 ao_start(iatom) = irow
152 ao_size(iatom) = SIZE(kind_rot(ikind)%rmat, 2)
153 irow = irow + ao_size(iatom)
154 END DO
155 IF (irow - 1 /= nao) THEN
156 reason = "atom-resolved AO dimensions do not match the MO coefficient matrix"
157 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)
158 RETURN
159 END IF
160
161 time_reversal = kpsym%rotp(isym) < 0
162 reverse_phase = qs_kpoint%gamma_centered .AND. any(mod(qs_kpoint%nkp_grid, 2) == 0)
163 IF (ASSOCIATED(kpsym%phase_mode)) THEN
164 IF (kpsym%phase_mode(isym) > 0) reverse_phase = kpsym%phase_mode(isym) == 2
165 END IF
166 xkp_phase(1:3) = kpsym%xkp(1:3, isym)
167 DO iatom = 1, natom
168 source_atom = iatom
169 target_atom = kpsym%f0(iatom, isym)
170 ikind = qs_kpoint%atype(source_atom)
171 rotmat => kind_rot(ikind)%rmat
172 source_dim = ao_size(source_atom)
173 target_dim = ao_size(target_atom)
174 IF (SIZE(rotmat, 1) /= target_dim .OR. SIZE(rotmat, 2) /= source_dim) THEN
175 reason = "basis rotation dimensions do not match the atom/AO symmetry transform"
176 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)
177 RETURN
178 END IF
179 arg = real(kpsym%fcell_gauge(1, source_atom, isym), kind=dp)*xkp_phase(1) + &
180 REAL(kpsym%fcell_gauge(2, source_atom, isym), kind=dp)*xkp_phase(2) + &
181 REAL(kpsym%fcell_gauge(3, source_atom, isym), kind=dp)*xkp_phase(3)
182 IF (ASSOCIATED(kpsym%kgphase)) THEN
183 arg = arg + kpsym%kgphase(source_atom, isym)
184 END IF
185 IF (reverse_phase) arg = -arg
186 coskl = cos(twopi*arg)
187 sinkl = sin(twopi*arg)
188 DO imo = 1, nmo
189 DO irow_work = 1, source_dim
190 irow_source = ao_start(source_atom) + irow_work - 1
191 coeff_real = src_r(irow_source, imo)
192 coeff_imag = src_i(irow_source, imo)
193 IF (time_reversal) coeff_imag = -coeff_imag
194 phase_real = coskl*coeff_real - sinkl*coeff_imag
195 phase_imag = sinkl*coeff_real + coskl*coeff_imag
196 DO iao = 1, target_dim
197 irow_target = ao_start(target_atom) + iao - 1
198 dst_r(irow_target, imo) = dst_r(irow_target, imo) + &
199 rotmat(iao, irow_work)*phase_real
200 dst_i(irow_target, imo) = dst_i(irow_target, imo) + &
201 rotmat(iao, irow_work)*phase_imag
202 END DO
203 END DO
204 END DO
205 END DO
206
207 CALL cp_fm_set_submatrix(dst_real, dst_r)
208 CALL cp_fm_set_submatrix(dst_imag, dst_i)
209 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)
210 success = .true.
211
212 END SUBROUTINE kpoint_transform_scf_mo
213
214! **************************************************************************************************
215!> \brief Locate the basis-rotation slot corresponding to a signed k-point symmetry operation.
216!> \param qs_kpoint SCF k-point object
217!> \param rotp signed operation identifier
218!> \return rotation slot, or zero when no slot matches
219! **************************************************************************************************
220 INTEGER FUNCTION find_kpoint_rotation_slot(qs_kpoint, rotp) RESULT(rot_slot)
221 TYPE(kpoint_type), POINTER :: qs_kpoint
222 INTEGER, INTENT(IN) :: rotp
223
224 INTEGER :: irot, rot_abs
225
226 rot_slot = 0
227 rot_abs = abs(rotp)
228 IF (.NOT. ASSOCIATED(qs_kpoint%ibrot)) RETURN
229 DO irot = 1, SIZE(qs_kpoint%ibrot)
230 IF (rot_abs == qs_kpoint%ibrot(irot)) THEN
231 rot_slot = irot
232 RETURN
233 END IF
234 END DO
235
236 END FUNCTION find_kpoint_rotation_slot
237
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_copy_general(source, destination, para_env)
General copy of a fm matrix to another fm matrix. Uses non-blocking MPI rather than ScaLAPACK.
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_set_submatrix(fm, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
sets a submatrix of a full matrix fm(start_row:start_row+n_rows,start_col:start_col+n_cols) = alpha*o...
subroutine, public cp_fm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
gets a submatrix of a full matrix op(target_m)(1:n_rows,1:n_cols) =fm(start_row:start_row+n_rows,...
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_real, src_imag, dst_real, dst_imag, qs_kpoint, ikred, isym, para_env, success, reason)
Transform one SCF MO coefficient matrix to an equivalent full-mesh k-point.
Types and basic routines needed for a kpoint calculation.
K-points and crystal symmetry routines based on.
Definition kpsym.F:28
Definition of mathematical constants and functions.
real(kind=dp), parameter, public twopi
Interface to the message passing library MPI.
represent a full matrix
Rotation matrices for basis sets.
Keeps symmetry information about a specific k-point.
Contains information about kpoints.
stores all the informations relevant to an mpi environment