Line data Source code
1 : !!****m* ABINIT/m_cgtk
2 : !! NAME
3 : !! m_cgtk
4 : !!
5 : !! FUNCTION
6 : !!
7 : !!
8 : !! COPYRIGHT
9 : !! Copyright (C) 2008-2026 ABINIT group (MG)
10 : !! This file is distributed under the terms of the
11 : !! GNU General Public License, see ~abinit/COPYING
12 : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : !!
14 : !! SOURCE
15 :
16 : #if defined HAVE_CONFIG_H
17 : #include "config.h"
18 : #endif
19 :
20 : #include "abi_common.h"
21 :
22 : module m_cgtk
23 :
24 : use defs_basis
25 : use m_errors
26 : use m_abicore
27 : use m_xmpi
28 : use m_time
29 :
30 : use m_fstrings, only : itoa, sjoin
31 : use defs_abitypes, only : MPI_type
32 : use m_matrix, only : mati3inv
33 : use m_geometry, only : getspinrot
34 : use m_crystal, only : crystal_t
35 : use m_fftcore, only : sphere
36 : use m_kg, only : ph1d3d, getph
37 : use m_pawcprj, only : pawcprj_type, pawcprj_zaxpby
38 :
39 : implicit none
40 :
41 : private
42 : !!***
43 :
44 : !interface cgtk_rotate
45 : ! module procedure cgtk_rotate_dp
46 : ! module procedure cgtk_rotate_sp
47 : !end interface cgtk_rotate
48 :
49 : public :: cgtk_rotate ! Recostruct wfs in the BZ from IBZ using symmetry tables generated
50 : ! with the the symrel^T conventions.
51 : public :: cgtk_rotate_symrec ! Similar to cgtk_rotate but assumes symrec conventions.
52 : public :: cgtk_change_gsphere
53 : public :: cgtk_fixphase
54 : !!***
55 :
56 : integer,private,parameter :: to_box = 1, to_sph = -1, me_g0 = 1, ndat1 = 1
57 : integer,private,parameter :: no_shift(3) = 0
58 :
59 : contains
60 : !!***
61 :
62 : !!****f* ABINIT/cgtk_rotate
63 : !! NAME
64 : !! cgtk_rotate
65 : !!
66 : !! FUNCTION
67 : !! Reconstruct wavefunction cg2 in the BZ from the symmetrical image cg1 by applying a symmetry operation.
68 : !! Note that there are two possible conventions for mapping k-points:
69 : !!
70 : !! 1) k2 = T symrel(:,:, isym)^t k1 + g0 (note transpose of symrel)
71 : !!
72 : !! 2) k2 = T symrec(:,:, isym) k1 + g0
73 : !!
74 : !! where T is for time-reversal (itimrev)
75 : !!
76 : !! This routine assumes the FIRST convention that, unfortunately, is not very handy.
77 : !! The second convention, indeed, is the most natural one when mapping k-points.
78 : !!
79 : !! INPUTS
80 : !! cryst=crystalline structure
81 : !! kpt1(3)=k-point in cg1.
82 : !! isym=Index of symmetry operation (symrel^T convention)
83 : !! itimrev=1 if time-reversal is needed else 0.
84 : !! g0(3)=g0 vector
85 : !! nspinor=Number of spinor components.
86 : !! ndat=Number of wavefunctions
87 : !! npw1, npw2=Number of G-vectors in kg1 and kg2.
88 : !! kg1(3,npw1), kg2(3,npw2) = G vectors in cg1, and cg2.
89 : !! istwf1, istwf2= Storage mode for cg1 and cg2
90 : !! work_ngfft(18)= Specifies the size of the workspace array work.
91 : !! IMPORTANT: must be large enough to account for all possible shifts of the g-sphere.
92 : !! The caller is responsible for computing the max size needed to handle all the possible symmetrization.
93 : !! cg1(2, npw1, nspinor, ndat)=Wavefunctions in the IBZ
94 : !!
95 : !! OUTPUT
96 : !! cg2(2, npw2, nspinor, ndat)= symmetrized wavefunctions.
97 : !! work(2, work_ngfft(4), work_ngfft(5), work_ngfft(6))) = workspace array. See comments in INPUTS section.
98 : !!
99 : !! NOTES
100 : !! Inspired to wfconv.
101 : !!
102 : !! SOURCE
103 :
104 481355 : subroutine cgtk_rotate(cryst, kpt1, isym, itimrev, g0, nspinor, ndat, &
105 481355 : npw1, kg1, npw2, kg2, istwf1, istwf2, cg1, cg2, work_ngfft, work)
106 :
107 : !Arguments ------------------------------------
108 : !scalars
109 : integer,intent(in) :: isym, itimrev, nspinor, ndat, npw1, npw2, istwf1, istwf2
110 : type(crystal_t),intent(in) :: cryst
111 : !arrays
112 : integer,intent(in) :: g0(3), kg1(3,npw1), kg2(3,npw2), work_ngfft(18)
113 : real(dp),intent(in) :: kpt1(3), cg1(2,npw1,nspinor,ndat)
114 : real(dp),intent(out) :: cg2(2,npw2,nspinor,ndat)
115 : real(dp),intent(out) :: work(2,work_ngfft(4),work_ngfft(5),work_ngfft(6)) !*ndat) for threads?
116 :
117 : !Local variables ------------------------------
118 : !scalars
119 : integer :: n1,n2,n3,n4,n5,n6,ipw,idat,isp
120 : real(dp) :: arg,ar,ai,bi,br,spinrots,spinrotx,spinroty,spinrotz
121 : logical :: have_phase
122 : !arrays
123 : integer,parameter :: atindx(1) = 1
124 : integer :: symrec(3,3), symrel(3,3)
125 : real(dp) :: phktnons(2,1), tau(3), spinrot(4), tsec(2)
126 481355 : real(dp),allocatable :: phase1d(:,:), phase3d(:,:), wavef1(:,:)
127 : !************************************************************************
128 :
129 : ! Keep track of total time spent.
130 481355 : call timab(1780, 1, tsec)
131 :
132 481355 : ABI_CHECK_IRANGE(itimrev, 0, 1, "itimrev should be in [0, 1]")
133 :
134 481355 : n1 = work_ngfft(1); n2 = work_ngfft(2); n3 = work_ngfft(3)
135 481355 : n4 = work_ngfft(4); n5 = work_ngfft(5); n6 = work_ngfft(6)
136 :
137 6257615 : symrel = cryst%symrel(:,:,isym)
138 481355 : call mati3inv(symrel, symrec) ! symrec = symrel^{-1t}
139 1925420 : tau = cryst%tnons(:,isym)
140 1925420 : have_phase = sum(tau ** 2) > tol8
141 :
142 : ! Compute rotation in spinor space
143 481355 : if (nspinor == 2) call getspinrot(cryst%rprimd, spinrot, symrel)
144 963923 : if (itimrev == 1) symrec = -symrec
145 :
146 : ! Need to compute phase factors associated with nonsymmorphic translations?
147 481355 : if (have_phase) then
148 : ! Although the routine getph is originally written for atomic phase factors, it does precisely what we want
149 40353 : ABI_MALLOC(phase1d, (2, (2*n1+1)+(2*n2+1)+(2*n3+1)))
150 13451 : call getph(atindx, 1, n1, n2, n3, phase1d, tau)
151 :
152 13451 : arg = two_pi * (kpt1(1)*tau(1) + kpt1(2)*tau(2) + kpt1(3)*tau(3))
153 13451 : phktnons(1, 1) = cos(arg)
154 13451 : phktnons(2, 1) = sin(arg)
155 : ! Convert 1D phase factors to 3D phase factors exp(i 2 pi (k1 + G).tnons )
156 40353 : ABI_MALLOC(phase3d, (2, npw1))
157 13451 : call ph1d3d(1, 1, kg1, 1, 1, npw1, n1, n2, n3, phktnons, phase1d, phase3d)
158 13451 : ABI_FREE(phase1d)
159 : end if
160 :
161 1444065 : ABI_MALLOC(wavef1, (2, npw1))
162 :
163 1553713 : do idat=1,ndat
164 2153726 : do isp=1,nspinor
165 1358679450 : wavef1 = cg1(:,:,isp,idat)
166 :
167 1081368 : if (have_phase) then
168 : ! Multiply by phase factors due to nonsymmorphic translations.
169 25635223 : do ipw=1,npw1
170 25573785 : ar = phase3d(1,ipw) * wavef1(1,ipw) - phase3d(2,ipw) * wavef1(2,ipw)
171 25573785 : ai = phase3d(2,ipw) * wavef1(1,ipw) + phase3d(1,ipw) * wavef1(2,ipw)
172 25573785 : wavef1(1, ipw) = ar
173 25635223 : wavef1(2, ipw) = ai
174 : end do
175 : end if
176 :
177 : ! Take into account time-reversal symmetry for SCALAR wavefunctions, if needed.
178 18960484 : if (itimrev == 1 .and. nspinor == 1) wavef1(2, :npw1) = -wavef1(2, :npw1)
179 :
180 : ! Insert wavef1 in work array.
181 1081368 : call sphere(wavef1,ndat1,npw1,work,n1,n2,n3,n4,n5,n6,kg1,istwf1,to_box,me_g0,no_shift,identity_3d,one)
182 :
183 : ! Apply rotation + g0 and extract data on the kg2 sphere: cg2(g) = work(S(g + g0))
184 2153726 : call sphere(cg2(:,:,isp,idat),ndat1,npw2,work,n1,n2,n3,n4,n5,n6,kg2,istwf2,to_sph,me_g0,g0,symrec,one)
185 : end do ! isp
186 :
187 1553713 : if (nspinor == 2) then
188 9010 : if (itimrev == 1) then
189 : ! Take care of time-reversal symmetry, if needed
190 : ! 1) Exchange spin-up and spin-down.
191 : ! 2) Make complex conjugate of one component, and change sign of other component
192 9384 : do ipw=1,npw2
193 : ! Here, change sign of real part
194 9216 : ar = -cg2(1,ipw,1,idat)
195 9216 : ai = cg2(2,ipw,1,idat)
196 : ! Here, change sign of imaginary part
197 9216 : cg2(1,ipw,1,idat) = cg2(1,ipw,2,idat)
198 9216 : cg2(2,ipw,1,idat) = -cg2(2,ipw,2,idat)
199 9216 : cg2(1,ipw,2,idat) = ar
200 9384 : cg2(2,ipw,2,idat) = ai
201 : end do
202 : end if ! itimrev==1
203 :
204 : ! Rotation in spinor space (see also wfconv)
205 9010 : spinrots = spinrot(1); spinrotx = spinrot(2); spinroty = spinrot(3); spinrotz = spinrot(4)
206 2290124 : do ipw=1,npw2
207 2281114 : ar = cg2(1,ipw,1,idat)
208 2281114 : ai = cg2(2,ipw,1,idat)
209 2281114 : br = cg2(1,ipw,2,idat)
210 2281114 : bi = cg2(2,ipw,2,idat)
211 2281114 : cg2(1,ipw,1,idat) = spinrots*ar - spinrotz*ai + spinroty*br - spinrotx*bi
212 2281114 : cg2(2,ipw,1,idat) = spinrots*ai + spinrotz*ar + spinroty*bi + spinrotx*br
213 2281114 : cg2(1,ipw,2,idat) = -spinroty*ar - spinrotx*ai + spinrots*br + spinrotz*bi
214 2290124 : cg2(2,ipw,2,idat) = -spinroty*ai + spinrotx*ar + spinrots*bi - spinrotz*br
215 : end do
216 : end if
217 : end do ! idat
218 :
219 481355 : ABI_FREE(wavef1)
220 481355 : ABI_SFREE(phase3d)
221 :
222 481355 : call timab(1780, 2, tsec)
223 :
224 481355 : end subroutine cgtk_rotate
225 : !!***
226 :
227 : !!****f* ABINIT/cgtk_rotate_symrec
228 : !! NAME
229 : !! cgtk_rotate_symrec
230 : !!
231 : !! FUNCTION
232 : !! Reconstruct wavefunction cg2 in the BZ from the symmetrical image cg1 by applying a symmetry operation.
233 : !! Note that there are two possible conventions for mapping k-points:
234 : !!
235 : !! 1) k2 = T symrel(:,:, isym)^t k1 + g0 (note transpose of symrel)
236 : !!
237 : !! 2) k2 = T symrec(:,:, isym) k1 + g0
238 : !!
239 : !! where T is for time-reversal (itimrev)
240 : !!
241 : !! This routine assumes the SECOND convention.
242 : !!
243 : !! For scalar wavefunctions, we have (with S being a symrec operation)
244 : !!
245 : !! 1) u_{Sk}(g) = e^{-i(Sk + g).tau)} u_k(S^{-1} g) if g0 = 0 and no TR
246 : !!
247 : !! 2) u_{-k}(g) = u_{k}(-g)^* for TR
248 : !!
249 : !! 3) u_{k+g0}(g) = u_{k}(g+g0) if g0 != 0
250 : !!
251 :
252 0 : subroutine cgtk_rotate_symrec(cryst, kpt1, isym, itimrev, g0, nspinor, ndat, &
253 0 : npw1, kg1, npw2, kg2, istwf1, istwf2, cg1, cg2, work_ngfft, work)
254 :
255 : !Arguments ------------------------------------
256 : !scalars
257 : integer,intent(in) :: isym, itimrev, nspinor, ndat, npw1, npw2, istwf1, istwf2
258 : type(crystal_t),intent(in) :: cryst
259 : !arrays
260 : integer,intent(in) :: g0(3), kg1(3,npw1), kg2(3,npw2), work_ngfft(18)
261 : real(dp),intent(in) :: kpt1(3), cg1(2,npw1,nspinor,ndat)
262 : real(dp),intent(out) :: cg2(2,npw2,nspinor,ndat)
263 : real(dp),intent(out) :: work(2,work_ngfft(4),work_ngfft(5),work_ngfft(6)) !*ndat) for threads?
264 :
265 : !Local variables ------------------------------
266 : !scalars
267 : integer :: n1,n2,n3,n4,n5,n6,ipw,idat,isp
268 : real(dp) :: arg,ar,ai,bi,br,spinrots,spinrotx,spinroty,spinrotz
269 : logical :: have_phase
270 : !arrays
271 : integer,parameter :: atindx(1) = 1
272 : integer :: symrec(3,3), symrec_inv(3,3), symrel(3,3), symrel_inv(3,3)
273 : real(dp) :: phktnons(2,1), tau(3), spinrot(4), tsec(2), kpt2(3)
274 0 : real(dp),allocatable :: phase1d(:,:), phase3d(:,:), wavef1(:,:)
275 : !************************************************************************
276 :
277 : ! Keep track of total time spent.
278 0 : call timab(1780, 1, tsec)
279 :
280 0 : ABI_CHECK_IRANGE(itimrev, 0, 1, "itimrev should be in [0, 1]")
281 :
282 0 : n1 = work_ngfft(1); n2 = work_ngfft(2); n3 = work_ngfft(3)
283 0 : n4 = work_ngfft(4); n5 = work_ngfft(5); n6 = work_ngfft(6)
284 :
285 0 : symrec = cryst%symrec(:,:,isym)
286 0 : symrel = cryst%symrel(:,:,isym) ! symrel = symrec^{-1t}
287 : symrec_inv = transpose(symrel)
288 : symrel_inv = transpose(symrec)
289 0 : tau = cryst%tnons(:,isym)
290 0 : have_phase = sum(tau ** 2) > tol8
291 0 : kpt2 = (merge(1, -1, itimrev == 0) * matmul(symrec, kpt1)) + g0
292 :
293 : ! Compute rotation in spinor space
294 0 : if (nspinor == 2) call getspinrot(cryst%rprimd, spinrot, symrel)
295 0 : if (itimrev == 1) symrec = -symrec
296 :
297 : ! Need to compute phase factors associated with nonsymmorphic translations?
298 0 : if (have_phase) then
299 :
300 : ! Although the routine getph is originally written for atomic phase factors, it does precisely what we want
301 0 : ABI_MALLOC(phase1d, (2, (2*n1+1)+(2*n2+1)+(2*n3+1)))
302 0 : call getph(atindx, 1, n1, n2, n3, phase1d, tau)
303 :
304 : ! Note kpt2 instead of kpt1 (difference wrt cgtk_rotate).
305 0 : arg = two_pi * (kpt2(1)*tau(1) + kpt2(2)*tau(2) + kpt2(3)*tau(3))
306 0 : phktnons(1, 1) = cos(arg)
307 0 : phktnons(2, 1) = sin(arg)
308 : ! Convert 1D phase factors to 3D phase factors exp(i 2 pi (k2+G).tnons )
309 0 : ABI_MALLOC(phase3d, (2, npw1))
310 0 : call ph1d3d(1, 1, kg1, 1, 1, npw1, n1, n2, n3, phktnons, phase1d, phase3d)
311 0 : ABI_FREE(phase1d)
312 : end if
313 :
314 0 : ABI_MALLOC(wavef1, (2, npw1))
315 :
316 0 : do idat=1,ndat
317 0 : do isp=1,nspinor
318 0 : wavef1 = cg1(:,:,isp,idat)
319 :
320 0 : if (have_phase) then
321 : ! Multiply by phase factors due to nonsymmorphic translations.
322 : ! Here take complex conjugate of phased3d (note the difference wrt cgtk_rotate).
323 0 : do ipw=1,npw1
324 0 : ar = phase3d(1,ipw) * wavef1(1,ipw) + phase3d(2,ipw) * wavef1(2,ipw)
325 0 : ai = -phase3d(2,ipw) * wavef1(1,ipw) + phase3d(1,ipw) * wavef1(2,ipw)
326 0 : wavef1(1, ipw) = ar
327 0 : wavef1(2, ipw) = ai
328 : end do
329 : end if
330 :
331 : ! Take into account time-reversal symmetry for SCALAR wavefunctions, if needed.
332 0 : if (itimrev == 1 .and. nspinor == 1) wavef1(2, :npw1) = -wavef1(2, :npw1)
333 :
334 : ! Insert wavef1 in work array.
335 0 : call sphere(wavef1,ndat1,npw1,work,n1,n2,n3,n4,n5,n6,kg1,istwf1,to_box,me_g0,no_shift,identity_3d,one)
336 :
337 0 : ABI_ERROR("sphere is not yet compatible with the symrec convention!!")
338 : ! Apply rotation + g0 and extract data on the kg2 sphere: cg2(g) = work(S(g + g0))
339 0 : call sphere(cg2(:,:,isp,idat),ndat1,npw2,work,n1,n2,n3,n4,n5,n6,kg2,istwf2,to_sph,me_g0,g0,symrec,one)
340 : end do ! isp
341 :
342 0 : if (nspinor == 2) then
343 0 : ABI_ERROR("nspinor 2 in cgtk_rotate_symrec is not coded!")
344 0 : if (itimrev == 1) then
345 : ! Take care of time-reversal symmetry, if needed
346 : ! 1) Exchange spin-up and spin-down.
347 : ! 2) Make complex conjugate of one component, and change sign of other component
348 0 : do ipw=1,npw2
349 : ! Here, change sign of real part
350 0 : ar = -cg2(1,ipw,1,idat)
351 0 : ai = cg2(2,ipw,1,idat)
352 : ! Here, change sign of imaginary part
353 0 : cg2(1,ipw,1,idat) = cg2(1,ipw,2,idat)
354 0 : cg2(2,ipw,1,idat) = -cg2(2,ipw,2,idat)
355 0 : cg2(1,ipw,2,idat) = ar
356 0 : cg2(2,ipw,2,idat) = ai
357 : end do
358 : end if ! itimrev==1
359 :
360 : ! Rotation in spinor space (see also wfconv)
361 0 : spinrots = spinrot(1); spinrotx = spinrot(2); spinroty = spinrot(3); spinrotz = spinrot(4)
362 0 : do ipw=1,npw2
363 0 : ar = cg2(1,ipw,1,idat)
364 0 : ai = cg2(2,ipw,1,idat)
365 0 : br = cg2(1,ipw,2,idat)
366 0 : bi = cg2(2,ipw,2,idat)
367 0 : cg2(1,ipw,1,idat) = spinrots*ar - spinrotz*ai + spinroty*br - spinrotx*bi
368 0 : cg2(2,ipw,1,idat) = spinrots*ai + spinrotz*ar + spinroty*bi + spinrotx*br
369 0 : cg2(1,ipw,2,idat) = -spinroty*ar - spinrotx*ai + spinrots*br + spinrotz*bi
370 0 : cg2(2,ipw,2,idat) = -spinroty*ai + spinrotx*ar + spinrots*bi - spinrotz*br
371 : end do
372 : end if
373 : end do ! idat
374 :
375 0 : ABI_FREE(wavef1)
376 0 : ABI_SFREE(phase3d)
377 :
378 0 : call timab(1780, 2, tsec)
379 :
380 0 : end subroutine cgtk_rotate_symrec
381 : !!***
382 :
383 : !!****f* ABINIT/cgtk_change_gsphere
384 : !! NAME
385 : !! cgtk_change_gsphere
386 : !!
387 : !! FUNCTION
388 : !! Transfer the G components of ndat wavefunctions from one sphere to another one.
389 : !! Can also be used to change the value of istwfk e.g. 2 --> 1
390 : !!
391 : !! INPUTS
392 : !! ndat = Number of wavefunctions to transform.
393 : !! npw1, npw2 = Number of plane-waves in the (input, output) G-sphere
394 : !! istwf1, istwf2 = Storage mode of (input, output) wavefunctions.
395 : !! kg1(3,npw1), kg2(3,npw2) = Input/Output G-sphere
396 : !! cg1(2,npw1,ndat) = Input wavefunctions on kg1 sphere with istwf1 mode.
397 : !! work_ngfft(18)=Specify work dimensions. Must be large enough to accommodate kg1 and kg2
398 : !!
399 : !! OUTPUT
400 : !! cg2(2,npw2,ndat) = Output wavefunctions on kg2 sphere with istwf2 mode.
401 : !! work(2,work_ngfft(4),work_ngfft(5),work_ngfft(6)) = Workspace array
402 : !!
403 : !! SOURCE
404 :
405 16946 : subroutine cgtk_change_gsphere(ndat, npw1, istwf1, kg1, cg1, npw2, istwf2, kg2, cg2, work_ngfft, work, &
406 : shiftg1) ! optional
407 :
408 : !Arguments ------------------------------------
409 : !scalars
410 : integer,intent(in) :: ndat,npw1,npw2,istwf1,istwf2
411 : !arrays
412 : integer,intent(in) :: kg1(3,npw1),kg2(3,npw2)
413 : integer,intent(in) :: work_ngfft(18)
414 : real(dp),intent(inout) :: cg1(2,npw1,ndat) ! TODO: Should be intent(in) but need to change sphere
415 : real(dp),intent(out) :: cg2(2,npw2,ndat)
416 : real(dp),intent(out) :: work(2,work_ngfft(4),work_ngfft(5),work_ngfft(6))
417 : integer,optional,intent(in) :: shiftg1(3)
418 :
419 : !Local variables ------------------------------
420 : integer :: n1,n2,n3,n4,n5,n6,idat
421 : integer :: shiftg1__(3)
422 : !************************************************************************
423 :
424 16946 : n1 = work_ngfft(1); n2 = work_ngfft(2); n3 = work_ngfft(3)
425 16946 : n4 = work_ngfft(4); n5 = work_ngfft(5); n6 = work_ngfft(6)
426 :
427 16946 : shiftg1__ = no_shift; if (present(shiftg1)) shiftg1__ = shiftg1
428 :
429 : !print *, "npw1", npw1, "npw2", npw2
430 :
431 35286 : do idat=1,ndat
432 : ! Insert cg1 in work array taking into account istwf1 (intent in)
433 : ! Note: shiftg is only used by sphere when iflag=-1 (extraction).
434 18340 : call sphere(cg1(:,:,idat),1,npw1,work,n1,n2,n3,n4,n5,n6,kg1,istwf1,to_box,me_g0,no_shift,identity_3d,one)
435 :
436 : ! Extract cg2 from work array taking into account istwf2
437 35286 : call sphere(cg2(:,:,idat),1,npw2,work,n1,n2,n3,n4,n5,n6,kg2,istwf2,to_sph,me_g0,shiftg1__,identity_3d,one)
438 : end do
439 :
440 16946 : end subroutine cgtk_change_gsphere
441 : !!***
442 :
443 : !!****f* ABINIT/cgtk_fixphase
444 : !! NAME
445 : !! cgtk_fixphase
446 : !!
447 : !! FUNCTION
448 : !! Fix phase of all bands. Keep normalization but maximize real part
449 : !! (minimize imag part). Also fix the sign of real part
450 : !! by setting the first non-zero element to be positive.
451 : !! See also fxphas_seq in m_cgtools
452 : !!
453 : !! INPUTS
454 : !! cg(2,mcg)= contains the wavefunction |c> coefficients.
455 : !! gsc(2,mgsc)= if useoverlap==1, contains the S|c> coefficients, where S is an overlap matrix.
456 : !! icg=shift to be applied on the location of data in the array cg
457 : !! igsc=shift to be applied on the location of data in the array gsc
458 : !! istwfk=input option parameter that describes the storage of wfs (set to 1 if usual complex vectors)
459 : !! mcg=size of second dimension of cg
460 : !! mgsc=size of second dimension of gsc
461 : !! mpi_enreg=information about MPI parallelization
462 : !! nband_k=number of bands
463 : !! npw_k=number of planewaves
464 : !! useoverlap=describe the overlap of wavefunctions:
465 : !! 0: no overlap (S=Identi0,ty_matrix)
466 : !! 1: wavefunctions are overlapping
467 : !!
468 : !! OUTPUT
469 : !! cg(2,mcg)=same array with altered phase.
470 : !! gsc(2,mgsc)= same array with altered phase.
471 : !!
472 : !! SOURCE
473 :
474 453586 : subroutine cgtk_fixphase(cg, gsc, icg, igsc, istwfk, mcg, mgsc, mpi_enreg, nband_k, npw_k, useoverlap, cprj, nspinor)
475 :
476 : !Arguments ------------------------------------
477 : !scalars
478 : integer,intent(in) :: icg,igsc,istwfk,mcg,mgsc,nband_k,npw_k,useoverlap
479 : type(MPI_type),intent(in) :: mpi_enreg
480 : !arrays
481 : real(dp),intent(inout) :: cg(2,mcg),gsc(2,mgsc*useoverlap)
482 : type(pawcprj_type),intent(inout),optional,target :: cprj(:,:)
483 : integer,intent(in),optional :: nspinor
484 :
485 : !Local variables-------------------------------
486 : !scalars
487 : logical :: do_cprj
488 : integer :: iband,ierr,ii,indx,ncprj
489 : real(dp) :: cim,cre,gscim,gscre,quotient,root1,root2,saa,sab,sbb,theta,thppi,xx,yy
490 : character(len=500) :: msg
491 : !arrays
492 907172 : real(dp) :: buffer2(nband_k,2),buffer3(nband_k,3),tsec(2)
493 453586 : real(dp),allocatable :: cimb(:),creb(:),saab(:),sabb(:),sbbb(:) !,sarr(:,:)
494 : ! *************************************************************************
495 :
496 453586 : do_cprj=.false.
497 453586 : if (present(cprj)) then
498 0 : do_cprj=.true.
499 0 : ncprj = size(cprj,2)
500 0 : if (ncprj/=nband_k*nspinor) then
501 0 : ABI_ERROR('bad size for cprj')
502 : end if
503 : end if
504 :
505 : !The general case, where a complex phase indeterminacy is present
506 453586 : if(istwfk==1)then
507 :
508 1272225 : ABI_MALLOC(cimb,(nband_k))
509 848150 : ABI_MALLOC(creb,(nband_k))
510 848150 : ABI_MALLOC(saab,(nband_k))
511 848150 : ABI_MALLOC(sabb,(nband_k))
512 848150 : ABI_MALLOC(sbbb,(nband_k))
513 6419201 : cimb(:)=zero ; creb(:)=zero
514 :
515 : ! Loop over bands
516 : ! TODO: MG store saa arrays in sarr(3,nband_k) to reduce false sharing.
517 : !$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(nband_k,icg,npw_k,cg,saab,sbbb,sabb)
518 3421638 : do iband=1,nband_k
519 2997563 : indx=icg+(iband-1)*npw_k
520 :
521 : ! Compute several sums over Re, Im parts of c
522 2997563 : saa=zero; sbb=zero; sab=zero
523 913877405 : do ii=1+indx,npw_k+indx
524 910879842 : saa=saa+cg(1,ii)*cg(1,ii)
525 910879842 : sbb=sbb+cg(2,ii)*cg(2,ii)
526 913877405 : sab=sab+cg(1,ii)*cg(2,ii)
527 : end do
528 2997563 : saab(iband)=saa
529 2997563 : sbbb(iband)=sbb
530 3421638 : sabb(iband)=sab
531 : end do
532 :
533 : ! XG030513 : MPIWF : should transmit saab,sbbb,sabb from the procs
534 : ! of the WF group to the master processor of the WF group
535 424075 : if (mpi_enreg%paral_kgb == 1) then
536 0 : buffer3(:,1)=saab(:)
537 0 : buffer3(:,2)=sbbb(:)
538 0 : buffer3(:,3)=sabb(:)
539 0 : call timab(48,1,tsec)
540 0 : call xmpi_sum(buffer3,mpi_enreg%comm_fft,ierr)
541 0 : if (mpi_enreg%paral_spinor==1) then
542 0 : call xmpi_sum(buffer3,mpi_enreg%comm_spinor,ierr)
543 : end if
544 0 : call timab(48,2,tsec)
545 0 : saab(:)=buffer3(:,1)
546 0 : sbbb(:)=buffer3(:,2)
547 0 : sabb(:)=buffer3(:,3)
548 : end if
549 :
550 : ! XG030513 : MPIWF this loop should only be executed by the master of the WF group
551 :
552 424075 : if (mpi_enreg%paral_kgb==0.or.mpi_enreg%me_fft==0) then
553 3421638 : do iband=1,nband_k
554 2997563 : indx=icg+(iband-1)*npw_k
555 :
556 2997563 : saa=saab(iband)
557 2997563 : sbb=sbbb(iband)
558 2997563 : sab=sabb(iband)
559 :
560 : ! Get phase angle theta
561 2997563 : if (sbb+saa>tol8)then
562 2997563 : if(abs(sbb-saa)>tol8*(sbb+saa) .or. 2*abs(sab)>tol8*(sbb+saa))then
563 2992730 : if (abs(sbb-saa)>tol8*abs(sab)) then
564 2992621 : quotient=sab/(sbb-saa)
565 2992621 : theta=0.5_dp*atan(2.0_dp*quotient)
566 : else
567 : ! Taylor expansion of the atan in terms of inverse of its argument. Correct up to 1/x2, included.
568 109 : theta=0.25_dp*(pi-(sbb-saa)/sab)
569 : end if
570 : ! Check roots to get theta for max Re part
571 2992730 : root1=cos(theta)**2*saa+sin(theta)**2*sbb-2.0_dp*cos(theta)*sin(theta)*sab
572 2992730 : thppi=theta+0.5_dp*pi
573 2992730 : root2=cos(thppi)**2*saa+sin(thppi)**2*sbb-2.0_dp*cos(thppi)*sin(thppi)*sab
574 2992730 : if (root2>root1) theta=thppi
575 : else
576 : ! The real part vector and the imaginary part vector are orthogonal, and of same norm. Strong indeterminacy.
577 : ! Will determine the first non-zero coefficient, and fix its phase
578 : ! Hypothesis : there is at least one non-zero element on the master node ...
579 397414 : do ii=1+indx,npw_k+indx
580 397414 : cre=cg(1,ii)
581 397414 : cim=cg(2,ii)
582 397414 : if(cre**2+cim**2>tol8**2*(saa+sbb))then
583 4833 : if(cre**2>tol8**2**cim**2)then
584 3941 : theta=atan(cim/cre)
585 : else
586 : ! Taylor expansion of the atan in terms of inverse of its argument. Correct up to 1/x2, included.
587 892 : theta=pi/2-cre/cim
588 : end if
589 : exit
590 : end if
591 : end do
592 : end if
593 : else
594 : write(msg,'(a,i0,5a)')&
595 0 : & 'The eigenvector with band ',iband,' has zero norm.',ch10,&
596 0 : & 'This usually happens when the number of bands (nband) is comparable to the number of planewaves (mpw)',ch10,&
597 0 : & 'Action: Check the parameters of the calculation. If nband ~ mpw, then decrease nband or, alternatively, increase ecut'
598 0 : ABI_ERROR(msg)
599 : end if
600 :
601 2997563 : xx=cos(theta)
602 2997563 : yy=sin(theta)
603 :
604 : ! Here, set the first non-zero element to be positive
605 : ! Comment the next nine lines to recover the behaviour of pre v3.1.3g
606 : ! Hypothesis : there is at least one non-zero element on the master node ...
607 7088078 : do ii=1+indx,npw_k+indx
608 7088078 : cre=cg(1,ii)
609 7088078 : cim=cg(2,ii)
610 7088078 : cre=xx*cre-yy*cim
611 7088078 : if(abs(cre)>tol8)exit
612 : end do
613 2997563 : if(cre<zero)then
614 411836 : xx=-xx ; yy=-yy
615 : end if
616 :
617 2997563 : creb(iband)=xx
618 3421638 : cimb(iband)=yy
619 :
620 : end do
621 : end if
622 :
623 : ! XG030513 : MPIWF : should transmit creb(:),cimb(:) of the master
624 : ! processor of the WF group to the others procs of the WF group
625 424075 : if (mpi_enreg%paral_kgb == 1) then
626 0 : call timab(48,1,tsec)
627 0 : buffer2(:,1)=creb(:)
628 0 : buffer2(:,2)=cimb(:)
629 0 : call xmpi_sum(buffer2,mpi_enreg%comm_fft,ierr)
630 0 : if (mpi_enreg%paral_spinor==1) then
631 0 : call xmpi_sum(buffer2,mpi_enreg%comm_spinor,ierr)
632 : end if
633 0 : call timab(48,2,tsec)
634 0 : creb(:)=buffer2(:,1)
635 0 : cimb(:)=buffer2(:,2)
636 : end if
637 :
638 : ! MG TODO: Scaling can be done with zscal
639 : !$OMP PARALLEL DO PRIVATE(indx,xx,yy,cre,cim,gscre,gscim)
640 3421638 : do iband=1,nband_k
641 2997563 : indx=icg+(iband-1)*npw_k
642 :
643 2997563 : xx=creb(iband)
644 2997563 : yy=cimb(iband)
645 : ! Alter phase of array |cg>
646 913877405 : do ii=1+indx,npw_k+indx
647 910879842 : cre=cg(1,ii)
648 910879842 : cim=cg(2,ii)
649 910879842 : cg(1,ii)=xx*cre-yy*cim
650 913877405 : cg(2,ii)=xx*cim+yy*cre
651 : end do
652 2997563 : if (do_cprj) call pawcprj_zaxpby((/zero,zero/),(/xx,yy/),cprj(:,nspinor*(iband-1)+1:nspinor*iband),&
653 0 : & cprj(:,nspinor*(iband-1)+1:nspinor*iband))
654 :
655 : ! Alter phase of array S|cg>
656 3421638 : if (useoverlap==1) then
657 1172917 : indx=igsc+(iband-1)*npw_k
658 370101406 : do ii=1+indx,npw_k+indx
659 368928489 : gscre=gsc(1,ii)
660 368928489 : gscim=gsc(2,ii)
661 368928489 : gsc(1,ii)=xx*gscre-yy*gscim
662 370101406 : gsc(2,ii)=xx*gscim+yy*gscre
663 : end do
664 : end if
665 : end do ! iband
666 :
667 424075 : ABI_FREE(cimb)
668 424075 : ABI_FREE(creb)
669 424075 : ABI_FREE(saab)
670 424075 : ABI_FREE(sabb)
671 424075 : ABI_FREE(sbbb)
672 :
673 : else ! if istwfk/=1. Storages that take into account the time-reversal symmetry : the freedom is only a sign freedom
674 :
675 88533 : ABI_MALLOC(creb,(nband_k))
676 294231 : creb(:)=zero
677 : ! XG030513 : MPIWF : this loop should be done only by the master processor of the WF group
678 :
679 29511 : if (mpi_enreg%paral_kgb==0.or.mpi_enreg%me_fft==0) then
680 :
681 : ! Loop over bands
682 294231 : do iband=1,nband_k
683 :
684 264720 : indx=icg+(iband-1)*npw_k
685 :
686 : ! Here, set the first non-zero real element to be positive
687 10769542 : do ii=1+indx,npw_k+indx
688 10749844 : cre=cg(1,ii)
689 10769542 : if(abs(cre)>tol8)exit
690 : end do
691 294231 : creb(iband)=cre
692 :
693 : end do ! iband
694 :
695 : end if
696 : ! XG030513 : MPIWF : should transmit cre(:) of the master processor of the WF group to the others
697 29511 : if (mpi_enreg%paral_kgb == 1) then
698 0 : call timab(48,1,tsec)
699 0 : call xmpi_sum(creb,mpi_enreg%comm_fft,ierr)
700 0 : if (mpi_enreg%paral_spinor==1) then
701 0 : call xmpi_sum(creb,mpi_enreg%comm_spinor,ierr)
702 : end if
703 0 : call timab(48,2,tsec)
704 : end if
705 :
706 294231 : do iband=1,nband_k
707 264720 : cre=creb(iband)
708 294231 : if(cre<zero)then
709 51269 : indx=icg+(iband-1)*npw_k
710 25275750 : do ii=1+indx,npw_k+indx
711 25224481 : cg(1,ii)=-cg(1,ii)
712 25275750 : cg(2,ii)=-cg(2,ii)
713 : end do
714 51269 : if (do_cprj) call pawcprj_zaxpby((/zero,zero/),(/-one,zero/),cprj(:,iband:iband),cprj(:,iband:iband))
715 51269 : if(useoverlap==1)then
716 14417 : indx=igsc+(iband-1)*npw_k
717 11239482 : do ii=1+indx,npw_k+indx
718 11225065 : gsc(1,ii)=-gsc(1,ii)
719 11239482 : gsc(2,ii)=-gsc(2,ii)
720 : end do
721 : end if
722 : end if
723 : end do ! iband
724 :
725 29511 : ABI_FREE(creb)
726 : end if ! istwfk
727 :
728 453586 : end subroutine cgtk_fixphase
729 : !!***
730 :
731 : end module m_cgtk
732 : !!***
|