66 isym, para_env, success, reason)
67 TYPE(
cp_fm_type),
INTENT(IN) :: src_real, src_imag, dst_real, dst_imag
69 INTEGER,
INTENT(IN) :: ikred, isym
71 LOGICAL,
INTENT(OUT) :: success
72 CHARACTER(LEN=*),
INTENT(OUT) :: reason
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
96 ALLOCATE (src_r(nao, nmo), src_i(nao, nmo), dst_r(nao, nmo), dst_i(nao, nmo))
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)
107 DEALLOCATE (src_r, src_i, dst_r, dst_i)
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)
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)
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)
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)
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)
140 kind_rot => qs_kpoint%kind_rotmat(rot_slot, :)
141 natom =
SIZE(qs_kpoint%atype)
142 ALLOCATE (ao_start(natom), ao_size(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)
151 ao_start(iatom) = irow
152 ao_size(iatom) =
SIZE(kind_rot(ikind)%rmat, 2)
153 irow = irow + ao_size(iatom)
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)
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
166 xkp_phase(1:3) =
kpsym%xkp(1:3, isym)
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)
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)
185 IF (reverse_phase) arg = -arg
186 coskl = cos(
twopi*arg)
187 sinkl = sin(
twopi*arg)
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
209 DEALLOCATE (src_r, src_i, dst_r, dst_i, ao_start, ao_size)