Line data Source code
1 : !!****m* ABINIT/m_cgtools
2 : !! NAME
3 : !! m_cgtools
4 : !!
5 : !! FUNCTION
6 : !! This module defines wrappers for BLAS routines. The arguments are stored
7 : !! using the "cg" convention, namely real array of shape cg(2,...)
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 1992-2026 ABINIT group (MG, MT, XG, DCA, GZ, FB, MVer, DCA, GMR, FF)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
15 : !!
16 : !! NOTES
17 : !! 1) The convention about names of interfaced routine is: cg_<name>,
18 : !! where <name> is equal to the name of the standard BLAS routine
19 : !!
20 : !! 2) Blas routines are called without an explicit interface on purpose since
21 : !!
22 : !! a) The compiler should pass the base address of the array to the F77 BLAS
23 : !!
24 : !! b) Any compiler would complain about type mismatch (REAL,COMPLEX)
25 : !! if an explicit interface is given.
26 : !!
27 : !! 3) The use of mpi_type is not allowed here. MPI parallelism should be handled in a generic
28 : !! way by passing the MPI communicator so that the caller can decide how to handle MPI.
29 : !!
30 :
31 : #if defined HAVE_CONFIG_H
32 : #include "config.h"
33 : #endif
34 :
35 : #include "abi_common.h"
36 :
37 : module m_cgtools
38 :
39 : use, intrinsic :: iso_c_binding, only: c_size_t, c_loc
40 : use defs_basis
41 : use m_abicore
42 : use m_errors
43 : use m_xmpi
44 : use m_xomp
45 : use m_gputk
46 : use m_abi_linalg
47 : use m_linalg_interfaces
48 :
49 : use m_fstrings, only : toupper, itoa, sjoin
50 : use m_time, only : timab, cwtime, cwtime_report
51 : use m_numeric_tools, only : hermit, rhophi
52 : use m_pawcprj, only : pawcprj_type,pawcprj_axpby,pawcprj_zaxpby
53 :
54 : implicit none
55 :
56 : private
57 :
58 : real(dp),public,parameter :: cg_czero(2) = (/0._dp,0._dp/)
59 : real(dp),public,parameter :: cg_cone(2) = (/1._dp,0._dp/)
60 :
61 : ! Helper functions.
62 : public :: cg_tocplx
63 : public :: cg_fromcplx
64 : public :: cg_kfilter
65 : public :: cg_setaug_zero
66 : public :: cg_to_reim
67 : public :: cg_from_reim
68 :
69 : ! Blas1
70 : public :: cg_zcopy
71 : public :: cg_zscal
72 : public :: cg_dznrm2
73 : public :: cg_zdotc
74 : public :: cg_real_zdotc
75 : public :: cg_zdotu
76 : public :: cg_zaxpy
77 : public :: cg_zaxpby
78 :
79 : ! Blas2
80 : public :: cg_zgemv ! alpha*A*x + beta*y,
81 :
82 : ! Blas3
83 : public :: cg_zgemm
84 :
85 : ! Helper functions for DFT calculations.
86 : public :: set_istwfk ! Returns the value of istwfk associated to the input k-point.
87 : public :: sqnorm_g ! Square of the norm in reciprocal space.
88 : public :: dotprod_g ! Scalar product <vec1|vect2> of complex vectors vect1 and vect2 (can be the same)
89 : public :: dotprod_g_batch_half ! Scalar product <vec1|vect2> of complex vectors vect1 and vect2 (can be the same)
90 : public :: dotprod_g_batch_full ! Scalar product <vec1|vect2> of complex vectors vect1 and vect2 (can be the same)
91 : public :: matrixelmt_g ! matrix element <wf1|O|wf2> of two wavefunctions, in reciprocal space,
92 : ! for an operator diagonal in G-space.
93 : public :: dotprod_v ! Dot product of two potentials (integral over FFT grid).
94 : public :: dotprod_vn
95 : public :: sqnorm_v ! Compute square of the norm of a potential (integral over FFT grid).
96 : public :: mean_fftr ! Compute the mean of an arraysp(nfft,nspden), over the FFT grid.
97 : public :: cg_getspin ! Sandwich a single wave function on the Pauli matrices
98 : public :: cg_gsph2box ! Transfer data from the G-sphere to the FFT box.
99 : public :: cg_box2gsph ! Transfer data from the FFT box to the G-sphere
100 : public :: cg_addtorho ! Add |ur|**2 to the ground-states density rho.
101 : public :: cg_vlocpsi ! Apply the local part of the potential to the wavefunction in real space.
102 : public :: cgnc_cholesky ! Cholesky orthonormalization (version optimized for NC wavefunctions).
103 : public :: cgpaw_cholesky ! Cholesky orthonormalization of PAW wavefunctions.
104 : public :: cgnc_normalize ! Normalize NC wavefunctions.
105 : public :: cgnc_gramschmidt ! Gram-Schmidt orthogonalization for NC wavefunctions.
106 : public :: cgpaw_normalize ! Normalize PAW wavefunctions.
107 : public :: cgpaw_gramschmidt ! Gram-Schmidt orthogonalization for PAW wavefuncion
108 : public :: projbd ! Project out vector "direc" onto the bands i.e.
109 : ! direc=direc-$sum_{j/=i} { <cg_{j}|direc>.|cg_{j}> }$
110 : public :: cg_envlop ! Multiply random number values in cg by envelope function to lower initial kinetic energy.
111 : public :: cg_normev ! Normalize a set of num eigenvectors of complex length ndim
112 : public :: cg_precon ! precondition $<G|(H-e_{n,k})|C_{n,k}>$
113 : public :: cg_precon_block ! precondition $<G|(H-e_{n,k})|C_{n,k}>$ for a block of band
114 : ! in the case of real WFs (istwfk/=1)
115 : public :: cg_zprecon_block ! precondition $<G|(H-e_{n,k})|C_{n,k}>$ for a block of band
116 : public :: fxphas_seq ! Fix phase of all bands. Keep normalization but maximize real part
117 : public :: fxphas_and_cmp ! Fix phase and compare two set of wavefunctions
118 : public :: overlap_g ! Compute the scalar product between WF at two different k-points
119 : public :: subdiago ! Diagonalizes the Hamiltonian in the eigenfunction subspace
120 : public :: subdiago_low_memory ! Diagonalizes the Hamiltonian in the eigenfunction subspace
121 : ! G components are updated block by block to save memory.
122 : public :: pw_orthon ! Normalize nvec complex vectors each of length nelem and then
123 : ! orthogonalize by modified Gram-Schmidt.
124 : public :: pw_orthon_cprj ! Normalize nvec complex vectors each of length nelem and then
125 : ! orthogonalize by modified Gram-Schmidt. Also update cprj coeffs.
126 : public :: cg_hprotate_and_get_diag
127 : public :: cg_hrotate_and_get_diag
128 : public :: cg_get_eigens ! Compute <i|H|i> / <i|S|i> for ndat states.
129 : public :: cg_get_residvecs ! Compute (H - eS) |psi> for ndat states.
130 : public :: cg_norm2g ! Compute <psi|psi> for ndat states distributed inside communicator comm.
131 : public :: cg_zdotg_zip ! Compute <cg1|cg2> for ndat states
132 : public :: cg_precon_many
133 : public :: cg_zaxpy_many_areal
134 : public :: cg_set_imag0_to_zero
135 : public :: cg_randomize ! Initialize cg_k with random numbers.
136 : public :: cg_copy_spin
137 : public :: cg_put_spin
138 : public :: cg_p_psi ! Compute <g|-i\Nabla|psi_nk>.
139 : !***
140 :
141 : CONTAINS !========================================================================================
142 : !!***
143 :
144 : !----------------------------------------------------------------------
145 :
146 : !!****f* m_cgtools/cg_tocplx
147 : !! NAME
148 : !! cg_tocplx
149 : !!
150 : !! FUNCTION
151 : !! Convert a real array with (real,imag) part to complex.
152 : !!
153 : !! INPUTS
154 : !! n = Specifies the number of elements in cg and ocplx
155 : !! cg(2*n)=Input array with real and imaginary part.
156 : !!
157 : !! OUTPUT
158 : !! ocplx(n)=Output complex array.
159 : !!
160 : !! SOURCE
161 :
162 0 : subroutine cg_tocplx(n, cg, ocplx)
163 :
164 : !Arguments ------------------------------------
165 : !scalars
166 : integer,intent(in) :: n
167 : !arrays
168 : real(dp),intent(in) :: cg(2*n)
169 : complex(dp),intent(out) :: ocplx(n)
170 :
171 : !Local variables ------------------------------
172 : !scalars
173 : integer :: ii,idx
174 : ! *************************************************************************
175 :
176 : !$OMP PARALLEL DO PRIVATE(idx)
177 0 : do ii=1,n
178 0 : idx = 2*ii-1
179 0 : ocplx(ii) = DCMPLX(cg(idx),cg(idx+1))
180 : end do
181 :
182 0 : end subroutine cg_tocplx
183 : !!***
184 :
185 : !----------------------------------------------------------------------
186 :
187 : !!****f* m_cgtools/cg_fromcplx
188 : !! NAME
189 : !! cg_fromcplx
190 : !!
191 : !! FUNCTION
192 : !! Convert a complex array to a real array with (real,imag) part
193 : !!
194 : !! INPUTS
195 : !! n = Specifies the number of elements in icplx and ocg.
196 : !! icplx(n)=Input complex array.
197 : !!
198 : !! OUTPUT
199 : !! ocg(2*n)=Output array with real and imaginary part.
200 : !!
201 : !! SOURCE
202 :
203 0 : subroutine cg_fromcplx(n, icplx, ocg)
204 :
205 : !Arguments ------------------------------------
206 : !scalars
207 : integer,intent(in) :: n
208 : !arrays
209 : real(dp),intent(out) :: ocg(2*n)
210 : complex(dp),intent(in) :: icplx(n)
211 :
212 : !Local variables ------------------------------
213 : !scalars
214 : integer :: ii,idx
215 : ! *************************************************************************
216 :
217 : !$OMP PARALLEL DO PRIVATE(idx)
218 0 : do ii=1,n
219 0 : idx = 2*ii-1
220 0 : ocg(idx ) = DBLE (icplx(ii))
221 0 : ocg(idx+1) = AIMAG(icplx(ii))
222 : end do
223 :
224 0 : end subroutine cg_fromcplx
225 : !!***
226 :
227 : !----------------------------------------------------------------------
228 :
229 : !!****f* m_cgtools/cg_kfilter
230 : !! NAME
231 : !! cg_kfilter
232 : !!
233 : !! FUNCTION
234 : !!
235 : !! INPUTS
236 : !! nband=Number of vectors in icg1
237 : !!
238 : !! SOURCE
239 :
240 0 : pure subroutine cg_kfilter(npw_k, my_nspinor, nband_k, kinpw, cg)
241 :
242 : !Arguments ------------------------------------
243 : !scalars
244 : integer,intent(in) :: npw_k, my_nspinor, nband_k
245 : !arrays
246 : real(dp), intent(in) :: kinpw(npw_k)
247 : real(dp),intent(inout) :: cg(2,npw_k*my_nspinor*nband_k)
248 :
249 : !Local variables-------------------------------
250 : integer :: ispinor, iband, igs, iwavef, ipw
251 : ! *************************************************************************
252 :
253 : ! Filter the WFs when modified kinetic energy is too large (see routine mkkin.f)
254 : ! !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(igs, iwavef)
255 0 : do ispinor=1,my_nspinor
256 0 : igs=(ispinor-1)*npw_k
257 0 : do iband=1,nband_k
258 0 : iwavef=(iband-1)*npw_k*my_nspinor
259 0 : do ipw=1+igs,npw_k+igs
260 0 : if (kinpw(ipw-igs)>huge(zero)*1.d-11) cg(:,ipw+iwavef)=zero
261 : end do
262 : end do
263 : end do
264 :
265 0 : end subroutine cg_kfilter
266 : !!***
267 :
268 : !----------------------------------------------------------------------
269 :
270 : !!****f* m_cgtools/cg_setaug_zero
271 : !! NAME
272 : !! cg_setaug_zero
273 : !!
274 : !! FUNCTION
275 : !! Set to zero all elements of the array that are not in the FFT box.
276 : !!
277 : !! INPUTS
278 : !! nx,ny,nz=physical dimensions of the FFT box
279 : !! ldx,ldy,ldx=memory dimension of arr
280 : !! ndat=number of FFTs
281 : !!
282 : !! SIDE EFFECT
283 : !! arr(2,ldx,ldy,ldz*ndat)= all entries in the augmented region are set to zero
284 : !!
285 : !! SOURCE
286 :
287 96 : pure subroutine cg_setaug_zero(cplex,nx,ny,nz,ldx,ldy,ldz,ndat,arr)
288 :
289 : !Arguments ------------------------------------
290 : !scalars
291 : integer,intent(in) :: cplex,nx,ny,nz,ldx,ldy,ldz,ndat
292 : !arrays
293 : real(dp),intent(inout) :: arr(cplex,ldx,ldy,ldz*ndat)
294 :
295 : !Local variables-------------------------------
296 : integer :: iy,iz,dat,padat
297 : ! *************************************************************************
298 :
299 96 : if (nx /= ldx) then
300 1312 : do iz=1,ldz*ndat
301 26052 : do iy=1,ldy
302 125670 : arr(:,nx+1:ldx,iy,iz) = zero
303 : end do
304 : end do
305 : end if
306 :
307 96 : if (ny /= ldy) then
308 1004 : do iz=1,ldz*ndat
309 63354 : arr(:,:,ny+1:ldy,iz) = zero
310 : end do
311 : end if
312 :
313 96 : if (nz /= ldz) then
314 84 : do dat=1,ndat
315 60 : padat = ldz*(dat-1)
316 184 : do iz=nz+1,ldz
317 72560 : arr(:,:,:,iz+padat) = zero
318 : end do
319 : end do
320 : end if
321 :
322 96 : end subroutine cg_setaug_zero
323 : !!***
324 :
325 : !----------------------------------------------------------------------
326 :
327 : !!****f* m_cgtools/cg_to_reim
328 : !! NAME
329 : !! cg_to_reim
330 : !!
331 : !! FUNCTION
332 : !!
333 : !! INPUTS
334 : !!
335 : !! SOURCE
336 :
337 0 : subroutine cg_to_reim(npw, ndat, cg, factor, reim)
338 :
339 : !Arguments ------------------------------------
340 : !scalars
341 : integer,intent(in) :: npw,ndat
342 : real(dp),intent(in) :: factor
343 : !arrays
344 : real(dp),intent(in) :: cg(2*npw,ndat)
345 : real(dp),intent(out) :: reim(npw*2,ndat)
346 :
347 : !Local variables-------------------------------
348 : integer :: idat
349 : ! *************************************************************************
350 :
351 : ! Pack real and imaginary part of the wavefunctions.
352 : ! and multiply by scale factor if factor /= one.
353 0 : do idat=1,ndat
354 0 : call dcopy(npw, cg(1, idat), 2, reim(1, idat), 1)
355 0 : call dcopy(npw, cg(2, idat), 2, reim(npw+1, idat), 1)
356 0 : if (factor /= one) call dscal(2*npw, factor, reim(1, idat), 1)
357 : end do
358 :
359 0 : end subroutine cg_to_reim
360 : !!***
361 :
362 : !----------------------------------------------------------------------
363 :
364 : !!****f* m_cgtools/cg_from_reim
365 : !! NAME
366 : !! cg_from_reim
367 : !!
368 : !! FUNCTION
369 : !!
370 : !! INPUTS
371 : !!
372 : !! SOURCE
373 :
374 0 : subroutine cg_from_reim(npw, ndat, reim, factor, cg)
375 :
376 : !Arguments ------------------------------------
377 : !scalars
378 : integer,intent(in) :: npw,ndat
379 : real(dp),intent(in) :: factor
380 : !arrays
381 : real(dp),intent(in) :: reim(npw*2, ndat)
382 : real(dp),intent(out) :: cg(2*npw, ndat)
383 :
384 : !Local variables-------------------------------
385 : integer :: idat
386 : ! *************************************************************************
387 :
388 : ! UnPack real and imaginary part and multiply by scale factor if /= one.
389 0 : do idat=1,ndat
390 0 : call dcopy(npw, reim(1, idat), 1, cg(1, idat), 2)
391 0 : call dcopy(npw, reim(npw+1, idat), 1, cg(2, idat), 2)
392 0 : if (factor /= one) call dscal(2*npw, factor, cg(1, idat), 1)
393 : end do
394 :
395 0 : end subroutine cg_from_reim
396 : !!***
397 :
398 : !----------------------------------------------------------------------
399 :
400 : !!****f* m_cgtools/cg_zcopy
401 : !! NAME
402 : !! cg_zcopy
403 : !!
404 : !! FUNCTION
405 : !! Perform y = x, where x and y are vectors.
406 : !!
407 : !! INPUTS
408 : !! n = Specifies the number of elements in vectors x and y.
409 : !! x = Input Array
410 : !!
411 : !! OUTPUT
412 : !! y = In output, y contains a copy of the values of x.
413 : !!
414 : !! SOURCE
415 :
416 73115982 : subroutine cg_zcopy(n, x, y)
417 :
418 : !Arguments ------------------------------------
419 : !scalars
420 : integer,intent(in) :: n
421 : !arrays
422 : real(dp),intent(in) :: x(2*n)
423 : real(dp),intent(out) :: y(2*n)
424 : ! *************************************************************************
425 :
426 73115982 : call zcopy(n, x, 1, y, 1)
427 :
428 73115982 : end subroutine cg_zcopy
429 : !!***
430 :
431 : !----------------------------------------------------------------------
432 :
433 : !!****f* m_cgtools/cg_zscal
434 : !! NAME
435 : !! cg_zscal
436 : !!
437 : !! FUNCTION
438 : !! Perform x = a*x
439 : !!
440 : !! INPUTS
441 : !! n = Specifies the number of elements in vector x.
442 : !! a(2)= The scalar a. If a(2) is zero, x = a*x is computed via zdscal
443 : !!
444 : !! OUTPUT
445 : !! x = Updated vector.
446 : !!
447 : !! SOURCE
448 :
449 10400309 : subroutine cg_zscal(n, a, x)
450 :
451 : !Arguments ------------------------------------
452 : !scalars
453 : integer,intent(in) :: n
454 : real(dp),intent(in) :: a(2)
455 : !arrays
456 : real(dp),intent(inout) :: x(2*n)
457 : ! *************************************************************************
458 :
459 10400309 : if (a(2) == zero) then
460 10400309 : call dscal(2*n, a(1), x, 1)
461 : else
462 0 : call zscal(n, a, x, 1)
463 : end if
464 :
465 10400309 : end subroutine cg_zscal
466 : !!***
467 :
468 : !----------------------------------------------------------------------
469 :
470 : !!****f* m_cgtools/cg_dznrm2
471 : !! NAME
472 : !! cg_dznrm2
473 : !!
474 : !! FUNCTION
475 : !! returns the euclidean norm of a vector via the function name, so that
476 : !! DZNRM2 := sqrt( x**H*x )
477 : !!
478 : !! INPUTS
479 : !! n = Specifies the number of elements in vector x.
480 : !! x(2*x) = Input array.
481 : !!
482 : !! OUTPUT
483 : !!
484 : !! SOURCE
485 :
486 35204279 : function cg_dznrm2(n, x) result(res)
487 :
488 : !Arguments ------------------------------------
489 : !scalars
490 : integer,intent(in) :: n
491 : real(dp) :: res
492 : !arrays
493 : real(dp),intent(in) :: x(2*n)
494 : real(dp),external :: dznrm2
495 : ! *************************************************************************
496 :
497 35174271 : res = dznrm2(n, x, 1)
498 :
499 1320 : end function cg_dznrm2
500 : !!***
501 : !----------------------------------------------------------------------
502 :
503 : !!****f* m_cgtools/cg_zdotc
504 : !! NAME
505 : !! cg_zdotc
506 : !!
507 : !! FUNCTION
508 : !! Perform a vector-vector operation defined as res = \Sigma (conjg(x)*y) where x and y are n-element vectors.
509 : !!
510 : !! INPUTS
511 : !! n = Specifies the number of elements in vector x and y
512 : !! x,y = Input arrays.
513 : !!
514 : !! OUTPUT
515 : !! res(2)=Real and Imaginary part of the scalar product.
516 : !!
517 : !! SOURCE
518 :
519 31633028 : function cg_zdotc(n, x, y) result(res)
520 :
521 : !Arguments ------------------------------------
522 : !scalars
523 : integer,intent(in) :: n
524 : !arrays
525 : real(dp),intent(in) :: x(2,n), y(2,n)
526 : real(dp) :: res(2)
527 :
528 : !Local variables-------------------------------
529 : #ifdef HAVE_LINALG_ZDOTC_BUG
530 : integer :: ii
531 : #else
532 : complex(dp) :: cres
533 : complex(dp),external :: zdotc
534 : #endif
535 : ! *************************************************************************
536 :
537 : #ifdef HAVE_LINALG_ZDOTC_BUG
538 : ! Workaround for veclib on MacOSx
539 : res = zero
540 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:res)
541 : do ii=1,n
542 : res(1) = res(1) + x(1,ii)*y(1,ii) + x(2,ii)*y(2,ii)
543 : res(2) = res(2) + x(1,ii)*y(2,ii) - x(2,ii)*y(1,ii)
544 : end do
545 :
546 : #else
547 31633028 : cres = zdotc(n, x, 1, y, 1)
548 31633028 : res(1) = REAL(cres)
549 31633028 : res(2) = AIMAG(cres)
550 : #endif
551 :
552 31633028 : end function cg_zdotc
553 : !!***
554 :
555 : !----------------------------------------------------------------------
556 :
557 : !!****f* m_cgtools/cg_real_zdotc
558 : !! NAME
559 : !! cg_real_zdotc
560 : !!
561 : !! FUNCTION
562 : !! Perform a vector-vector operation defined as res = REAL (\Sigma (conjg(x)*y)) where x and y are n-element vectors.
563 : !!
564 : !! INPUTS
565 : !! n = Specifies the number of elements in vector x and y
566 : !! x,y = Input arrays.
567 : !!
568 : !! OUTPUT
569 : !! res=Real part of the scalar product.
570 : !!
571 : !! SOURCE
572 :
573 134806871 : function cg_real_zdotc(n,x,y) result(res)
574 :
575 : !Arguments ------------------------------------
576 : !scalars
577 : integer,intent(in) :: n
578 : !arrays
579 : real(dp),intent(in) :: x(2,n)
580 : real(dp),intent(in) :: y(2,n)
581 : real(dp) :: res
582 :
583 : !Local variables-------------------------------
584 : real(dp),external :: ddot
585 : ! *************************************************************************
586 :
587 134806871 : res = ddot(2*n, x, 1, y, 1)
588 :
589 134806871 : end function cg_real_zdotc
590 : !!***
591 :
592 : !----------------------------------------------------------------------
593 :
594 : !!****f* m_cgtools/cg_zdotu
595 : !! NAME
596 : !! cg_zdotu
597 : !!
598 : !! FUNCTION
599 : !! Perform a vector-vector operation defined as res = \Sigma (x*y) where x and y are n-element vectors.
600 : !! Note that x is unconjugated.
601 : !!
602 : !! INPUTS
603 : !! n = Specifies the number of elements in vector x and y
604 : !! x,y = Input arrays.
605 : !!
606 : !! OUTPUT
607 : !! res(2)=Real and Imaginary part of the scalar product.
608 : !!
609 : !! SOURCE
610 :
611 0 : function cg_zdotu(n, x, y) result(res)
612 :
613 : !Arguments ------------------------------------
614 : !scalars
615 : integer,intent(in) :: n
616 : !arrays
617 : real(dp),intent(in) :: x(2,n)
618 : real(dp),intent(in) :: y(2,n)
619 : real(dp) :: res(2)
620 :
621 : !Local variables-------------------------------
622 : #ifdef HAVE_LINALG_ZDOTU_BUG
623 : integer :: ii
624 : #else
625 : complex(dp) :: cres
626 : complex(dp),external :: zdotu
627 : #endif
628 : ! *************************************************************************
629 :
630 : #ifdef HAVE_LINALG_ZDOTU_BUG
631 : ! Workaround for veclib on MacOSx
632 : res = zero
633 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:res)
634 : do ii=1,n
635 : res(1) = res(1) + x(1,ii)*y(1,ii) - x(2,ii)*y(2,ii)
636 : res(2) = res(2) + x(1,ii)*y(2,ii) + x(2,ii)*y(1,ii)
637 : end do
638 : #else
639 0 : cres = zdotu(n, x, 1, y, 1)
640 0 : res(1) = REAL(cres)
641 0 : res(2) = AIMAG(cres)
642 : #endif
643 :
644 0 : end function cg_zdotu
645 : !!***
646 :
647 : !----------------------------------------------------------------------
648 :
649 : !!****f* m_cgtools/cg_zaxpy
650 : !! NAME
651 : !! cg_zaxpy
652 : !!
653 : !! FUNCTION
654 : !! Computes y = alpha*x + y
655 : !!
656 : !! INPUTS
657 : !! n = Specifies the number of elements in vectors x and y.
658 : !! alpha = Specifies the scalar alpha.
659 : !! x = Array
660 : !!
661 : !! SIDE EFFECTS
662 : !! y = Array. In output, y contains the updated vector.
663 : !!
664 : !! SOURCE
665 :
666 55365521 : subroutine cg_zaxpy(n, alpha, x, y)
667 :
668 : !Arguments ------------------------------------
669 : !scalars
670 : integer,intent(in) :: n
671 : real(dp),intent(in) :: alpha(2)
672 : !arrays
673 : real(dp),intent(in) :: x(2*n)
674 : real(dp),intent(inout) :: y(2*n)
675 : ! *************************************************************************
676 :
677 55365521 : if (alpha(2) == zero) then
678 54763886 : call daxpy(2*n, alpha(1), x, 1, y, 1)
679 : else
680 601635 : call zaxpy(n, alpha, x, 1, y, 1)
681 : end if
682 :
683 55365521 : end subroutine cg_zaxpy
684 : !!***
685 :
686 : !----------------------------------------------------------------------
687 :
688 : !!****f* m_cgtools/cg_zaxpby
689 : !! NAME
690 : !! cg_zaxpby
691 : !!
692 : !! FUNCTION
693 : !! Scales two vectors, adds them to one another and stores result in the vector.
694 : !! y := a*x + b*y
695 : !!
696 : !! INPUTS
697 : !! n = the number of elements in vectors x and y.
698 : !! a = Specifies the scalar a.
699 : !! x = Array.
700 : !! b = Specifies the scalar b.
701 : !! y = Array
702 : !!
703 : !! OUTPUT
704 : !! y Contains the updated vector y.
705 : !!
706 : !! SOURCE
707 :
708 0 : subroutine cg_zaxpby(n, a, x, b, y)
709 :
710 : !Arguments ------------------------------------
711 : !scalars
712 : integer,intent(in) :: n
713 : real(dp),intent(in) :: a(2),b(2)
714 : !arrays
715 : real(dp),intent(in) :: x(2*n)
716 : real(dp),intent(inout) :: y(2*n)
717 : ! *************************************************************************
718 :
719 : #ifdef HAVE_LINALG_AXPBY
720 0 : call zaxpby(n, a, x, 1, b, y, 1)
721 : #else
722 : call zscal(n, b, y, 1)
723 : call zaxpy(n, a, x, 1, y,1)
724 : #endif
725 :
726 0 : end subroutine cg_zaxpby
727 : !!***
728 :
729 : !----------------------------------------------------------------------
730 :
731 : !!****f* m_cgtools/cg_zgemv
732 : !! NAME
733 : !! cg_zgemv
734 : !!
735 : !! FUNCTION
736 : !! The cg_zgemv routines perform a **complex** matrix-vector operation defined as:
737 : !!
738 : !! y := alpha*A*x + beta*y,
739 : !! or
740 : !! y := alpha*A'*x + beta*y,
741 : !! or
742 : !! y := alpha*conjg(A')*x + beta*y,
743 : !!
744 : !! where: alpha and beta are COMPLEX scalars, x and y are COMPLEX vectors, A is a m-by-n COMPLEX matrix.
745 : !! Default is: alpha = 1 and beta = 0.
746 : !!
747 : !! INPUTS
748 : !!
749 : !! OUTPUT
750 : !!
751 : !! SOURCE
752 :
753 115860950 : subroutine cg_zgemv(trans, nrows, ncols, cgmat, vec, matvec, alpha, beta, gpu_option)
754 :
755 : !Arguments ------------------------------------
756 : !scalars
757 : integer,intent(in) :: nrows, ncols
758 : real(dp),optional,intent(in) :: alpha(2), beta(2)
759 : character(len=1),intent(in) :: trans
760 : integer,optional,intent(in) :: gpu_option
761 : !arrays
762 : real(dp),intent(in), target :: cgmat(2,nrows*ncols), vec(2,*)
763 : real(dp),intent(inout), target :: matvec(2,*)
764 :
765 : !Local variables-------------------------------
766 : !scalars
767 : integer :: mm, nn, kk, lda, ldb, ldc, my_gpu_option
768 : real(dp) :: my_alpha(2), my_beta(2)
769 : complex(dp) :: my_calpha, my_cbeta
770 : ! *************************************************************************
771 :
772 115860950 : my_alpha = cg_cone; if (present(alpha)) my_alpha = alpha
773 115860950 : my_beta = cg_czero; if (present(beta)) my_beta = beta
774 115860950 : my_gpu_option = ABI_GPU_DISABLED; if (present(gpu_option)) my_gpu_option = gpu_option
775 :
776 115860950 : lda = nrows; mm = nrows; nn = 1; kk = ncols
777 115860950 : if (toupper(trans) /= 'N') then
778 173616877 : mm = ncols; kk = nrows
779 : end if
780 115860950 : ldb = kk; ldc = mm
781 :
782 : ! ZGEMM(TRANSA,TRANSB,M,N,K,ALPHA,A,LDA,B,LDB,BETA,C,LDC)
783 :
784 115860950 : my_calpha = DCMPLX(my_alpha(1), my_alpha(2))
785 115860950 : my_cbeta = DCMPLX(my_beta(1), my_beta(2))
786 : call abi_xgemm(trans, "N", mm, nn, kk, my_calpha,&
787 : & cgmat, lda, &
788 : & vec, ldb, my_cbeta, &
789 : & matvec, ldc, &
790 115860950 : & x_cplx=2, gpu_option=my_gpu_option)
791 :
792 115860950 : end subroutine cg_zgemv
793 : !!***
794 :
795 : !----------------------------------------------------------------------
796 :
797 : !!****f* m_cgtools/cg_zgemm
798 : !! NAME
799 : !! cg_zgemm
800 : !!
801 : !! FUNCTION
802 : !! The cg_zgemm routines perform a matrix-matrix operation with general matrices.
803 : !! The operation is defined as C := alpha*op(A)*op(B) + beta*C, where:
804 : !!
805 : !! op(x) is one of op(x) = x, or op(x) = x', or op(x) = conjg(x'),
806 : !!
807 : !! alpha and beta are scalars,
808 : !! A, B and C are matrices:
809 : !! op(A) is an m-by-k matrix,
810 : !! op(B) is a k-by-n matrix,
811 : !! C is an m-by-n matrix.
812 : !!
813 : !! INPUTS
814 : !!
815 : !! OUTPUT
816 : !!
817 : !! SOURCE
818 :
819 38852 : subroutine cg_zgemm(transa, transb, npwsp, ncola, ncolb, cg_a, cg_b, cg_c, &
820 : alpha, beta) ! optional
821 :
822 : !Arguments ------------------------------------
823 : !scalars
824 : integer,intent(in) :: npwsp,ncola,ncolb
825 : character(len=1),intent(in) :: transa, transb
826 : real(dp),optional,intent(in) :: alpha(2), beta(2)
827 : !arrays
828 : real(dp),intent(in) :: cg_a(2,npwsp*ncola), cg_b(2,npwsp*ncolb)
829 : real(dp),intent(inout) :: cg_c(2,*)
830 :
831 : !Local variables-------------------------------
832 : !scalars
833 : integer :: mm,nn,kk,lda,ldb,ldc
834 : !real(dp) :: my_alpha(2),my_beta(2)
835 : complex(dp) :: my_calpha, my_cbeta
836 : ! *************************************************************************
837 :
838 38852 : lda = npwsp
839 38852 : ldb = npwsp
840 :
841 38852 : mm = npwsp
842 38852 : nn = ncolb
843 38852 : kk = ncola
844 :
845 38852 : if (toupper(transa) /= 'N') then
846 5745 : mm = ncola
847 44597 : kk = npwsp
848 : end if
849 38852 : if (toupper(transb) /= 'N') nn = npwsp
850 :
851 38852 : ldc = mm
852 :
853 : !my_alpha = cg_cone; if (PRESENT(alpha)) my_alpha = alpha
854 : !my_beta = cg_czero; if (PRESENT(beta)) my_beta = beta
855 : !call ZGEMM(transa, transb, mm, nn, kk, my_alpha, cg_a, lda, cg_b, ldb, my_beta, cg_c, ldc)
856 : !call ZGEMM3M(transa, transb, mm, nn, kk, my_alpha, cg_a, lda, cg_b, ldb, my_beta, cg_c, ldc)
857 :
858 38852 : my_calpha = cone; if (PRESENT(alpha)) my_calpha = DCMPLX(alpha(1), alpha(2))
859 38852 : my_cbeta = czero; if (PRESENT(beta)) my_cbeta = DCMPLX(beta(1), beta(2))
860 :
861 38852 : call abi_zgemm_2r(transa, transb, mm, nn, kk, my_calpha, cg_a, lda, cg_b, ldb, my_cbeta, cg_c, ldc)
862 :
863 38852 : end subroutine cg_zgemm
864 : !!***
865 :
866 : !!****f* m_cgtools/set_istwfk
867 : !! NAME
868 : !! set_istwfk
869 : !!
870 : !! FUNCTION
871 : !! Returns the value of istwfk associated to the input k-point.
872 : !!
873 : !! INPUTS
874 : !! kpoint(3)=The k-point in reduced coordinates.
875 : !!
876 : !! OUTPUT
877 : !! istwfk= Integer flag internally used in the code to define the storage mode of the wavefunctions.
878 : !! It also define the algorithm used to apply an operator in reciprocal space as well as the FFT
879 : !! algorithm used to go from G- to r-space and vice versa.
880 : !!
881 : !! 1 => time-reversal cannot be used
882 : !! 2 => use time-reversal at the Gamma point.
883 : !! 3 => use time-reversal symmetry for k=(1/2, 0 , 0 )
884 : !! 4 => use time-reversal symmetry for k=( 0 , 0 ,1/2)
885 : !! 5 => use time-reversal symmetry for k=(1/2, 0 ,1/2)
886 : !! 6 => use time-reversal symmetry for k=( 0 ,1/2, 0 )
887 : !! 7 => use time-reversal symmetry for k=(1/2,1/2, 0 )
888 : !! 8 => use time-reversal symmetry for k=( 0 ,1/2,1/2)
889 : !! 9 => use time-reversal symmetry for k=(1/2,1/2,1/2)
890 : !!
891 : !! Useful relations:
892 : !! u_k(G) = u_{k+G0}(G-G0); u_{-k}(-G) = u_k(G)^*
893 : !! and therefore:
894 : !! u_{G0/2}(G) = u_{G0/2}(-G-G0)^*.
895 : !!
896 : !! SOURCE
897 :
898 48638 : integer pure function set_istwfk(kpoint) result(istwfk)
899 :
900 : !Arguments ------------------------------------
901 : real(dp),intent(in) :: kpoint(3)
902 :
903 : !Local variables-------------------------------
904 : !scalars
905 : integer :: bit0,ii
906 : !arrays
907 : integer :: bit(3)
908 : ! *************************************************************************
909 :
910 48638 : bit0=1
911 :
912 194552 : do ii=1,3
913 194552 : if (DABS(kpoint(ii))<tol10) then
914 36698 : bit(ii)=0
915 109216 : else if (DABS(kpoint(ii)-half)<tol10 ) then
916 14409 : bit(ii)=1
917 : else
918 : bit0=0
919 : end if
920 : end do
921 :
922 48638 : if (bit0==0) then
923 : istwfk=1
924 : else
925 7674 : istwfk=2+bit(1)+4*bit(2)+2*bit(3) ! Note the inversion between bit(2) and bit(3)
926 : end if
927 :
928 48638 : end function set_istwfk
929 : !!***
930 :
931 : !!****f* m_cgtools/sqnorm_g
932 : !! NAME
933 : !! sqnorm_g
934 : !!
935 : !! FUNCTION
936 : !! Compute the square of the norm of one complex vector vecti, in reciprocal space
937 : !! Take into account the storage mode of the vector (istwf_k)
938 : !!
939 : !! INPUTS
940 : !! istwf_k=option parameter that describes the storage of wfs
941 : !! npwsp= (effective) number of planewaves at this k point.
942 : !! vect(2,npwsp)=the vector in reciprocal space (npw*nspinor, usually)
943 : !! me_g0=1 if this processors treats G=0, 0 otherwise.
944 : !! comm=MPI communicator for MPI sum.
945 : !!
946 : !! OUTPUT
947 : !! dotr= <vect|vect>
948 : !!
949 : !! SOURCE
950 :
951 36635488 : subroutine sqnorm_g(dotr, istwf_k, npwsp, vect, me_g0, comm)
952 :
953 : !Arguments ------------------------------------
954 : !scalars
955 : integer,intent(in) :: istwf_k,npwsp,me_g0,comm
956 : real(dp),intent(out) :: dotr
957 : !arrays
958 : real(dp),intent(in) :: vect(2,npwsp)
959 :
960 : !Local variables-------------------------------
961 : !scalars
962 : integer :: ierr
963 : ! *************************************************************************
964 :
965 36635488 : if (istwf_k==1) then ! General k-point
966 : !dotr = cg_real_zdotc(npwsp,vect,vect)
967 35172951 : dotr = cg_dznrm2(npwsp, vect)
968 35172951 : dotr = dotr * dotr
969 :
970 : else
971 1462537 : if (istwf_k == 2 .and. me_g0 == 1) then
972 : ! Gamma k-point and I have G=0
973 705476 : dotr=half*vect(1,1)**2
974 705476 : dotr = dotr + cg_real_zdotc(npwsp-1, vect(1,2), vect(1,2))
975 : else
976 : ! Other TR k-points
977 757061 : dotr = cg_real_zdotc(npwsp, vect, vect)
978 : end if
979 1462537 : dotr=two*dotr
980 : end if
981 :
982 36635488 : if (xmpi_comm_size(comm)>1) call xmpi_sum(dotr,comm,ierr)
983 :
984 36635488 : end subroutine sqnorm_g
985 : !!***
986 :
987 : !----------------------------------------------------------------------
988 :
989 : !!****f* m_cgtools/dotprod_g
990 : !! NAME
991 : !! dotprod_g
992 : !!
993 : !! FUNCTION
994 : !! Compute scalar product <vec1|vect2> of complex vectors vect1 and vect2 (can be the same)
995 : !! Take into account the storage mode of the vectors (istwf_k)
996 : !! If option=1, compute only real part, if option=2 compute also imaginary part.
997 : !! If the number of calls to the dot product scales quadratically
998 : !! with the volume of the system, it is preferable not to
999 : !! call the present routine, but but to write a specially
1000 : !! optimized routine, that will avoid many branches related to
1001 : !! the existence of 'option' and 'istwf_k'.
1002 : !!
1003 : !! INPUTS
1004 : !! istwf_k=option parameter that describes the storage of wfs
1005 : !! vect1(2,npw)=first vector (one should take its complex conjugate)
1006 : !! vect2(2,npw)=second vector
1007 : !! npw= (effective) number of planewaves at this k point (including spinorial level)
1008 : !! option= 1 if only real part to be computed,
1009 : !! 2 if both real and imaginary.
1010 : !! 3 if in case istwf_k==1 must compute real and imaginary parts,
1011 : !! but if istwf_k >1 must compute only real part
1012 : !! me_g0=1 if this processor treats G=0, 0 otherwise
1013 : !! comm=MPI communicator used to reduce the results.
1014 : !!
1015 : !! OUTPUT
1016 : !! $doti=\Im ( <vect1|vect2> )$ , output only if option=2 and eventually option=3.
1017 : !! $dotr=\Re ( <vect1|vect2> )$
1018 : !!
1019 : !! SOURCE
1020 :
1021 158437632 : subroutine dotprod_g(dotr, doti, istwf_k, npw, option, vect1, vect2, me_g0, comm)
1022 :
1023 : !Arguments ------------------------------------
1024 : !scalars
1025 : integer,intent(in) :: istwf_k,npw,option,me_g0,comm
1026 : real(dp),intent(out) :: doti,dotr
1027 : !arrays
1028 : real(dp),intent(in) :: vect1(2,npw),vect2(2,npw)
1029 :
1030 : !Local variables-------------------------------
1031 : integer :: ierr
1032 : real(dp) :: dotarr(2)
1033 : ! *************************************************************************
1034 :
1035 : ! Init results independently of option.
1036 158437632 : dotr = zero
1037 158437632 : doti = zero
1038 :
1039 158437632 : if (istwf_k==1) then
1040 : ! General k-point
1041 :
1042 154197038 : if(option==1)then
1043 127979561 : dotr = cg_real_zdotc(npw,vect1,vect2)
1044 : else
1045 26217477 : dotarr = cg_zdotc(npw,vect1,vect2)
1046 26217477 : dotr = dotarr(1)
1047 26217477 : doti = dotarr(2)
1048 : end if
1049 :
1050 4240594 : else if (istwf_k==2 .and. me_g0==1) then
1051 : ! Gamma k-point and I have G=0
1052 1969296 : dotr=half*vect1(1,1)*vect2(1,1)
1053 1969296 : dotr = dotr + cg_real_zdotc(npw-1,vect1(1,2),vect2(1,2))
1054 1969296 : dotr = two*dotr
1055 1969296 : if (option==2) doti=zero
1056 :
1057 : else
1058 : ! Other TR k-points
1059 2271298 : dotr = cg_real_zdotc(npw,vect1,vect2)
1060 2271298 : dotr=two*dotr
1061 2271298 : if (option==2) doti=zero
1062 : end if
1063 :
1064 : !Reduction in case of parallelism
1065 158437632 : if (xmpi_comm_size(comm) > 1) then
1066 1152 : if (option==1.or.istwf_k/=1) then
1067 1152 : call xmpi_sum(dotr,comm,ierr)
1068 : else
1069 0 : dotarr(1)=dotr ; dotarr(2)=doti
1070 0 : call xmpi_sum(dotarr,comm,ierr)
1071 0 : dotr=dotarr(1) ; doti=dotarr(2)
1072 : end if
1073 : end if
1074 :
1075 158437632 : end subroutine dotprod_g
1076 : !!***
1077 :
1078 : !----------------------------------------------------------------------
1079 :
1080 : !!****f* m_cgtools/dotprod_g_batch
1081 : !! NAME
1082 : !! dotprod_g_batch
1083 : !!
1084 : !! FUNCTION
1085 : !! Compute scalar product <vec1|vect2> of complex vectors vect1 and vect2 (can be the same)
1086 : !! Take into account the storage mode of the vectors (istwf_k)
1087 : !! If option=1, compute only real part, if option=2 compute also imaginary part.
1088 : !! If the number of calls to the dot product scales quadratically
1089 : !! with the volume of the system, it is preferable not to
1090 : !! call the present routine, but but to write a specially
1091 : !! optimized routine, that will avoid many branches related to
1092 : !! the existence of 'option' and 'istwf_k'.
1093 : !!
1094 : !! INPUTS
1095 : !! istwf_k=option parameter that describes the storage of wfs
1096 : !! vect1(2,npw)=first vector (one should take its complex conjugate)
1097 : !! vect2(2,npw)=second vector
1098 : !! npw= (effective) number of planewaves at this k point (including spinorial level)
1099 : !! option= 1 if only real part to be computed,
1100 : !! 2 if both real and imaginary.
1101 : !! 3 if in case istwf_k==1 must compute real and imaginary parts,
1102 : !! but if istwf_k >1 must compute only real part
1103 : !! me_g0=1 if this processor treats G=0, 0 otherwise
1104 : !! comm=MPI communicator used to reduce the results.
1105 : !!
1106 : !! OUTPUT
1107 : !! $doti=\Im ( <vect1|vect2> )$ , output only if option=2 and eventually option=3.
1108 : !! $dotr=\Re ( <vect1|vect2> )$
1109 : !!
1110 : !! SOURCE
1111 :
1112 250126 : subroutine dotprod_g_batch_half(dotr, doti, istwf_k, npw, ndat, option, vect1, vect2, me_g0, comm, gpu_option)
1113 :
1114 : !Arguments ------------------------------------
1115 : !scalars
1116 : integer,intent(in) :: istwf_k,npw,ndat,option,me_g0,comm
1117 : integer,optional,intent(in) :: gpu_option
1118 : real(dp),target,intent(out) :: doti(ndat),dotr(ndat)
1119 : !arrays
1120 : real(dp),target,intent(in) :: vect1(2,npw),vect2(2,npw,ndat)
1121 :
1122 : !Local variables-------------------------------
1123 : integer :: ierr,idat,ii,l_gpu_option
1124 : real(dp) :: dotarr(2)
1125 : ! *************************************************************************
1126 :
1127 250126 : l_gpu_option=ABI_GPU_DISABLED; if(present(gpu_option)) l_gpu_option = gpu_option
1128 : ! Init results independently of option.
1129 250126 : if(l_gpu_option==ABI_GPU_DISABLED) then
1130 4596124 : dotr = zero; doti = zero
1131 : else if(l_gpu_option==ABI_GPU_OPENMP) then
1132 : #ifdef HAVE_OPENMP_OFFLOAD
1133 : call gpu_set_to_zero(dotr,int(ndat,c_size_t))
1134 : call gpu_set_to_zero(doti,int(ndat,c_size_t))
1135 : #endif
1136 : end if
1137 :
1138 250126 : if (istwf_k==1) then
1139 : ! General k-point
1140 :
1141 249990 : if(option==1)then
1142 : #ifdef HAVE_OPENMP_OFFLOAD
1143 : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(idat,dotarr) MAP(to:vect1,vect2,dotr) &
1144 : !$OMP& IF(l_gpu_option==ABI_GPU_OPENMP)
1145 : #endif
1146 0 : do idat=1,ndat
1147 0 : dotarr = zero
1148 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotarr)
1149 0 : do ii=1,npw
1150 0 : dotarr(1) = dotarr(1) + vect1(1,ii)*vect2(1,ii,idat) + vect1(2,ii)*vect2(2,ii,idat)
1151 : end do
1152 0 : dotr(idat) = dotarr(1)
1153 : end do
1154 : else
1155 : #ifdef HAVE_OPENMP_OFFLOAD
1156 : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(idat,dotarr) MAP(to:vect1,vect2,dotr,doti) &
1157 : !$OMP& IF(l_gpu_option==ABI_GPU_OPENMP)
1158 : #endif
1159 2297790 : do idat=1,ndat
1160 : dotarr = zero
1161 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotarr)
1162 403324894 : do ii=1,npw
1163 401277094 : dotarr(1) = dotarr(1) + vect1(1,ii)*vect2(1,ii,idat) + vect1(2,ii)*vect2(2,ii,idat)
1164 403324894 : dotarr(2) = dotarr(2) + vect1(1,ii)*vect2(2,ii,idat) - vect1(2,ii)*vect2(1,ii,idat)
1165 : end do
1166 2047800 : dotr(idat) = dotarr(1)
1167 2297790 : doti(idat) = dotarr(2)
1168 : end do
1169 : end if
1170 :
1171 136 : else if (istwf_k==2 .and. me_g0==1) then
1172 : ! Gamma k-point and I have G=0
1173 : #ifdef HAVE_OPENMP_OFFLOAD
1174 : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(idat,dotarr) MAP(to:vect1,vect2,dotr) &
1175 : !$OMP& IF(l_gpu_option==ABI_GPU_OPENMP)
1176 : #endif
1177 272 : do idat=1,ndat
1178 136 : dotarr = zero
1179 136 : dotr(idat)=half*vect1(1,1)*vect2(1,1,idat)
1180 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotarr)
1181 410176 : do ii=2,npw
1182 410176 : dotarr(1) = dotarr(1) + vect1(1,ii)*vect2(1,ii,idat) + vect1(2,ii)*vect2(2,ii,idat)
1183 : end do
1184 272 : dotr(idat) = + two * (dotr(idat)+dotarr(1))
1185 : end do
1186 408 : if (option==2) doti=zero
1187 :
1188 : else
1189 : ! Other TR k-points
1190 : #ifdef HAVE_OPENMP_OFFLOAD
1191 : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(idat,dotarr) MAP(to:vect1,vect2,dotr) &
1192 : !$OMP& IF(l_gpu_option==ABI_GPU_OPENMP)
1193 : #endif
1194 0 : do idat=1,ndat
1195 0 : dotarr = zero
1196 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotarr)
1197 0 : do ii=1,npw
1198 0 : dotarr(1) = dotarr(1) + vect1(1,ii)*vect2(1,ii,idat) + vect1(2,ii)*vect2(2,ii,idat)
1199 : end do
1200 0 : dotr(idat) = two * dotarr(1)
1201 : end do
1202 0 : if (option==2) doti=zero
1203 : end if
1204 :
1205 : !Reduction in case of parallelism
1206 250126 : if (xmpi_comm_size(comm) > 1) then
1207 0 : if (option==1.or.istwf_k/=1) then
1208 : #ifdef HAVE_OPENMP_OFFLOAD
1209 : !$OMP TARGET UPDATE FROM(dotr) IF(l_gpu_option==ABI_GPU_OPENMP)
1210 : #endif
1211 0 : call xmpi_sum(dotr,comm,ierr)
1212 : #ifdef HAVE_OPENMP_OFFLOAD
1213 : !$OMP TARGET UPDATE TO(dotr) IF(l_gpu_option==ABI_GPU_OPENMP)
1214 : #endif
1215 : else
1216 : #ifdef HAVE_OPENMP_OFFLOAD
1217 : !$OMP TARGET UPDATE FROM(dotr,doti) IF(l_gpu_option==ABI_GPU_OPENMP)
1218 : #endif
1219 0 : call xmpi_sum(dotr,comm,ierr)
1220 0 : call xmpi_sum(doti,comm,ierr)
1221 : #ifdef HAVE_OPENMP_OFFLOAD
1222 : !$OMP TARGET UPDATE TO(dotr,doti) IF(l_gpu_option==ABI_GPU_OPENMP)
1223 : #endif
1224 : end if
1225 : end if
1226 :
1227 250126 : end subroutine dotprod_g_batch_half
1228 : !!***
1229 :
1230 :
1231 798444 : subroutine dotprod_g_batch_full(dotr, doti, istwf_k, npw, ndat, option, vect1, vect2, me_g0, comm, gpu_option)
1232 :
1233 : !Arguments ------------------------------------
1234 : !scalars
1235 : integer,intent(in) :: istwf_k,npw,ndat,option,me_g0,comm
1236 : integer,optional,intent(in) :: gpu_option
1237 : real(dp),target,intent(out) :: doti(ndat),dotr(ndat)
1238 : !arrays
1239 : real(dp),target,intent(in) :: vect1(2,npw,ndat),vect2(2,npw,ndat)
1240 :
1241 : !Local variables-------------------------------
1242 : integer :: ierr,idat,ii,l_gpu_option
1243 : real(dp) :: dotarr(2)
1244 : ! *************************************************************************
1245 :
1246 798444 : l_gpu_option=ABI_GPU_DISABLED; if(present(gpu_option)) l_gpu_option = gpu_option
1247 : ! Init results independently of option.
1248 798444 : if(l_gpu_option==ABI_GPU_DISABLED) then
1249 3359820 : dotr = zero; doti = zero
1250 : else if(l_gpu_option==ABI_GPU_OPENMP) then
1251 : #ifdef HAVE_OPENMP_OFFLOAD
1252 : call gpu_set_to_zero(dotr,int(ndat,c_size_t))
1253 : call gpu_set_to_zero(doti,int(ndat,c_size_t))
1254 : #endif
1255 : end if
1256 :
1257 798444 : if (istwf_k==1) then
1258 : ! General k-point
1259 :
1260 798006 : if(option==1)then
1261 : #ifdef HAVE_OPENMP_OFFLOAD
1262 : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(idat,dotarr) MAP(to:vect1,vect2,dotr) &
1263 : !$OMP& IF(l_gpu_option==ABI_GPU_OPENMP)
1264 : #endif
1265 2850 : do idat=1,ndat
1266 1284852 : dotarr = zero
1267 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotarr)
1268 1284852 : do ii=1,npw
1269 1284852 : dotarr(1) = dotarr(1) + vect1(1,ii,idat)*vect2(1,ii,idat) + vect1(2,ii,idat)*vect2(2,ii,idat)
1270 : end do
1271 2850 : dotr(idat) = dotarr(1)
1272 : end do
1273 : else
1274 : #ifdef HAVE_OPENMP_OFFLOAD
1275 : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(idat,dotarr) MAP(to:vect1,vect2,dotr,doti) &
1276 : !$OMP& IF(l_gpu_option==ABI_GPU_OPENMP)
1277 : #endif
1278 1675842 : do idat=1,ndat
1279 : dotarr = zero
1280 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotarr)
1281 177579132 : do ii=1,npw
1282 176700162 : dotarr(1) = dotarr(1) + vect1(1,ii,idat)*vect2(1,ii,idat) + vect1(2,ii,idat)*vect2(2,ii,idat)
1283 177579132 : dotarr(2) = dotarr(2) + vect1(1,ii,idat)*vect2(2,ii,idat) - vect1(2,ii,idat)*vect2(1,ii,idat)
1284 : end do
1285 878970 : dotr(idat) = dotarr(1)
1286 1675842 : doti(idat) = dotarr(2)
1287 : end do
1288 : end if
1289 :
1290 438 : else if (istwf_k==2 .and. me_g0==1) then
1291 : ! Gamma k-point and I have G=0
1292 : #ifdef HAVE_OPENMP_OFFLOAD
1293 : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(idat,dotarr) MAP(to:vect1,vect2,dotr) &
1294 : !$OMP& IF(l_gpu_option==ABI_GPU_OPENMP)
1295 : #endif
1296 738 : do idat=1,ndat
1297 540 : dotarr = zero
1298 540 : dotr(idat)=half*vect1(1,1,idat)*vect2(1,1,idat)
1299 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotarr)
1300 466188 : do ii=2,npw
1301 466188 : dotarr(1) = dotarr(1) + vect1(1,ii,idat)*vect2(1,ii,idat) + vect1(2,ii,idat)*vect2(2,ii,idat)
1302 : end do
1303 738 : dotr(idat) = + two * (dotr(idat)+dotarr(1))
1304 : end do
1305 198 : if (option==2) doti=zero
1306 :
1307 : else
1308 : ! Other TR k-points
1309 : #ifdef HAVE_OPENMP_OFFLOAD
1310 : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(idat,dotarr) MAP(to:vect1,vect2,dotr) &
1311 : !$OMP& IF(l_gpu_option==ABI_GPU_OPENMP)
1312 : #endif
1313 480 : do idat=1,ndat
1314 66480 : dotarr = zero
1315 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotarr)
1316 66480 : do ii=1,npw
1317 66480 : dotarr(1) = dotarr(1) + vect1(1,ii,idat)*vect2(1,ii,idat) + vect1(2,ii,idat)*vect2(2,ii,idat)
1318 : end do
1319 480 : dotr(idat) = two * dotarr(1)
1320 : end do
1321 240 : if (option==2) doti=zero
1322 : end if
1323 :
1324 : !Reduction in case of parallelism
1325 798444 : if (xmpi_comm_size(comm) > 1) then
1326 0 : if (option==1.or.istwf_k/=1) then
1327 : #ifdef HAVE_OPENMP_OFFLOAD
1328 : !$OMP TARGET UPDATE FROM(dotr) IF(l_gpu_option==ABI_GPU_OPENMP)
1329 : #endif
1330 0 : call xmpi_sum(dotr,comm,ierr)
1331 : #ifdef HAVE_OPENMP_OFFLOAD
1332 : !$OMP TARGET UPDATE TO(dotr) IF(l_gpu_option==ABI_GPU_OPENMP)
1333 : #endif
1334 : else
1335 : #ifdef HAVE_OPENMP_OFFLOAD
1336 : !$OMP TARGET UPDATE FROM(dotr,doti) IF(l_gpu_option==ABI_GPU_OPENMP)
1337 : #endif
1338 0 : call xmpi_sum(dotr,comm,ierr)
1339 0 : call xmpi_sum(doti,comm,ierr)
1340 : #ifdef HAVE_OPENMP_OFFLOAD
1341 : !$OMP TARGET UPDATE TO(dotr,doti) IF(l_gpu_option==ABI_GPU_OPENMP)
1342 : #endif
1343 : end if
1344 : end if
1345 :
1346 798444 : end subroutine dotprod_g_batch_full
1347 : !!***
1348 :
1349 : !----------------------------------------------------------------------
1350 :
1351 : !!****f* m_cgtools/matrixelmt_g
1352 : !! NAME
1353 : !! matrixelmt_g
1354 : !!
1355 : !! FUNCTION
1356 : !! Compute a matrix element of two wavefunctions, in reciprocal space,
1357 : !! for an operator that is diagonal in reciprocal space: <wf1|op|wf2>
1358 : !! For the time being, only spin-independent operators are treated.
1359 : !!
1360 : !! INPUTS
1361 : !! diag(npw)=diagonal operator (real, spin-independent !)
1362 : !! istwf_k=storage mode of the vectors
1363 : !! needimag=0 if the imaginary part is not needed ; 1 if the imaginary part is needed
1364 : !! npw=number of planewaves of the first vector
1365 : !! nspinor=number of spinor components
1366 : !! vect1(2,npw*nspinor)=first vector
1367 : !! vect2(2,npw*nspinor)=second vector
1368 : !! comm_fft=MPI communicator for the FFT
1369 : !! me_g0=1 if this processors treats the G=0 component.
1370 : !!
1371 : !! OUTPUT
1372 : !! ai=imaginary part of the matrix element
1373 : !! ar=real part of the matrix element
1374 : !!
1375 : !! SOURCE
1376 :
1377 961896 : subroutine matrixelmt_g(ai,ar,diag,istwf_k,needimag,npw,nspinor,vect1,vect2,me_g0,comm_fft)
1378 :
1379 : !Arguments ------------------------------------
1380 : !scalars
1381 : integer,intent(in) :: istwf_k,needimag,npw,nspinor,me_g0,comm_fft
1382 : real(dp),intent(out) :: ai,ar
1383 : !arrays
1384 : real(dp),intent(in) :: diag(npw),vect1(2,npw*nspinor),vect2(2,npw*nspinor)
1385 :
1386 : !Local variables-------------------------------
1387 : !scalars
1388 : integer :: i1,ierr,ipw
1389 : character(len=500) :: msg
1390 : !arrays
1391 : real(dp) :: buffer2(2)
1392 : !real(dp),allocatable :: re_prod(:), im_prod(:)
1393 : ! *************************************************************************
1394 :
1395 961896 : if (nspinor==2 .and. istwf_k/=1) then
1396 : write(msg,'(a,a,a,i6,a,i6)')&
1397 0 : 'When istwf_k/=1, nspinor must be 1,',ch10,&
1398 0 : 'however, nspinor=',nspinor,', and istwf_k=',istwf_k
1399 0 : ABI_BUG(msg)
1400 : end if
1401 :
1402 : #if 0
1403 : !TODO
1404 : ABI_MALLOC(re_prod,(npw*nspinor))
1405 : do ipw=1,npw*nspinor
1406 : re_prod(ipw) = vect1(1,ipw)*vect2(1,ipw) + vect1(2,ipw)*vect2(2,ipw)
1407 : end do
1408 :
1409 : if (needimag == 1) then
1410 : ABI_MALLOC(im_prod,(npw*nspinor))
1411 : do ipw=1,npw*nspinor
1412 : im_prod(ipw) = vect1(1,ipw)*vect2(2,ipw) - vect1(2,ipw)*vect2(1,ipw)
1413 : end do
1414 : end if
1415 : #endif
1416 :
1417 961896 : ar=zero
1418 961896 : if(needimag==1)ai=zero
1419 :
1420 : !Normal storage mode
1421 961896 : if(istwf_k==1)then
1422 :
1423 : ! Need only real part
1424 961896 : if(needimag==0)then
1425 :
1426 136152688 : do ipw=1,npw
1427 136152688 : ar=ar+diag(ipw)*(vect1(1,ipw)*vect2(1,ipw)+vect1(2,ipw)*vect2(2,ipw))
1428 : end do
1429 :
1430 961896 : if(nspinor==2)then
1431 6365472 : do ipw=1+npw,2*npw
1432 6365472 : ar=ar+diag(ipw-npw)*(vect1(1,ipw)*vect2(1,ipw)+vect1(2,ipw)*vect2(2,ipw))
1433 : end do
1434 : end if
1435 :
1436 : else ! Need also the imaginary part
1437 :
1438 0 : do ipw=1,npw
1439 0 : ar=ar+diag(ipw)*(vect1(1,ipw)*vect2(1,ipw)+vect1(2,ipw)*vect2(2,ipw))
1440 0 : ai=ai+diag(ipw)*(vect1(1,ipw)*vect2(2,ipw)-vect1(2,ipw)*vect2(1,ipw))
1441 : end do
1442 :
1443 0 : if(nspinor==2)then
1444 0 : do ipw=1+npw,2*npw
1445 0 : ar=ar+diag(ipw-npw)*(vect1(1,ipw)*vect2(1,ipw)+vect1(2,ipw)*vect2(2,ipw))
1446 0 : ai=ai+diag(ipw-npw)*(vect1(1,ipw)*vect2(2,ipw)-vect1(2,ipw)*vect2(1,ipw))
1447 : end do
1448 : end if
1449 :
1450 : end if ! needimag
1451 :
1452 0 : else if(istwf_k>=2)then
1453 :
1454 : ! XG030513 : MPIWF need to know which proc has G=0
1455 :
1456 0 : i1=1
1457 0 : if(istwf_k==2 .and. me_g0==1)then
1458 0 : ar=half*diag(1)*vect1(1,1)*vect2(1,1) ; i1=2
1459 : end if
1460 :
1461 : ! Need only real part
1462 0 : if(needimag==0)then
1463 :
1464 0 : do ipw=i1,npw
1465 0 : ar=ar+diag(ipw)*(vect1(1,ipw)*vect2(1,ipw)+vect1(2,ipw)*vect2(2,ipw))
1466 : end do
1467 0 : ar=two*ar
1468 :
1469 : else ! Need also the imaginary part
1470 :
1471 0 : do ipw=i1,npw
1472 0 : ar=ar+diag(ipw)*(vect1(1,ipw)*vect2(1,ipw)+vect1(2,ipw)*vect2(2,ipw))
1473 0 : ai=ai+diag(ipw)*(vect1(1,ipw)*vect2(2,ipw)-vect1(2,ipw)*vect2(1,ipw))
1474 : end do
1475 0 : ar=two*ar ; ai=two*ai
1476 :
1477 : end if
1478 :
1479 : end if ! istwf_k
1480 :
1481 : #if 0
1482 : ABI_FREE(re_prod)
1483 : if (needimag == 1) then
1484 : ABI_FREE(im_prod)
1485 : end if
1486 : #endif
1487 :
1488 : !MPIWF need to make reduction on ar and ai .
1489 961896 : if (xmpi_comm_size(comm_fft)>1) then
1490 0 : buffer2(1)=ai
1491 0 : buffer2(2)=ar
1492 0 : call xmpi_sum(buffer2,comm_fft ,ierr)
1493 0 : ai=buffer2(1)
1494 0 : ar=buffer2(2)
1495 : end if
1496 :
1497 961896 : end subroutine matrixelmt_g
1498 : !!***
1499 :
1500 : !----------------------------------------------------------------------
1501 :
1502 : !!****f* m_cgtools/dotprod_v
1503 : !! NAME
1504 : !! dotprod_v
1505 : !!
1506 : !! FUNCTION
1507 : !! Compute dot product of two potentials (integral over FFT grid), to obtain
1508 : !! a square residual-like quantity (so the sum of product of values
1509 : !! is NOT divided by the number of FFT points, and NOT multiplied by the primitive cell volume).
1510 : !! Take into account the spin components of the potentials (nspden), and sum over them.
1511 : !!
1512 : !! INPUTS
1513 : !! cplex=if 1, real space functions on FFT grid are REAL, if 2, COMPLEX
1514 : !! nfft= (effective) number of FFT grid points (for this processor)
1515 : !! nspden=number of spin-density components
1516 : !! opt_storage: 0, if potentials are stored as V^up-up, V^dn-dn, Re[V^up-dn], Im[V^up-dn]
1517 : !! 1, if potentials are stored as V, B_x, B_y, Bz (B=magn. field)
1518 : !! pot1(cplex*nfft,nspden)=first real space potential on FFT grid
1519 : !! pot2(cplex*nfft,nspden)=second real space potential on FFT grid
1520 : !! comm=MPI communicator in which results will be reduced.
1521 : !!
1522 : !! OUTPUT
1523 : !! dotr= value of the dot product
1524 : !!
1525 : !! SOURCE
1526 :
1527 55 : subroutine dotprod_v(cplex,dotr,nfft,nspden,opt_storage,pot1,pot2,comm)
1528 :
1529 : !Arguments ------------------------------------
1530 : !scalars
1531 : integer,intent(in) :: cplex,nfft,nspden,opt_storage,comm
1532 : real(dp),intent(out) :: dotr
1533 : !arrays
1534 : real(dp),intent(in) :: pot1(cplex*nfft,nspden),pot2(cplex*nfft,nspden)
1535 :
1536 : !Local variables-------------------------------
1537 : !scalars
1538 : integer :: ierr,ifft,ispden
1539 : real(dp) :: ar
1540 : !arrays
1541 : ! *************************************************************************
1542 :
1543 : !Real or complex inputs are coded
1544 :
1545 55 : dotr=zero
1546 : !$OMP PARALLEL DO COLLAPSE(2) REDUCTION(+:dotr)
1547 110 : do ispden=1,min(nspden,2)
1548 1085038 : do ifft=1,cplex*nfft
1549 1084983 : dotr =dotr + pot1(ifft,ispden)*pot2(ifft,ispden)
1550 : end do
1551 : end do
1552 :
1553 55 : if (nspden==4) then
1554 : ar=zero
1555 : !$OMP PARALLEL DO COLLAPSE(2) REDUCTION(+:ar)
1556 0 : do ispden=3,4
1557 0 : do ifft=1,cplex*nfft
1558 0 : ar = ar + pot1(ifft,ispden)*pot2(ifft,ispden)
1559 : end do
1560 : end do
1561 :
1562 0 : if (opt_storage==0) then
1563 0 : if (cplex==1) then
1564 0 : dotr = dotr+two*ar
1565 : else
1566 0 : dotr = dotr+ar
1567 : end if
1568 : else
1569 0 : dotr = half*(dotr+ar)
1570 : end if
1571 : end if
1572 :
1573 : !MPIWF reduction (addition) on dotr is needed here
1574 55 : if (xmpi_comm_size(comm)>1) then
1575 0 : call xmpi_sum(dotr,comm,ierr)
1576 : end if
1577 :
1578 55 : end subroutine dotprod_v
1579 : !!***
1580 :
1581 : !!****f* m_cgtools/dotprod_vn
1582 : !! NAME
1583 : !! dotprod_vn
1584 : !!
1585 : !! FUNCTION
1586 : !! Compute dot product of potential and density (integral over FFT grid), to obtain
1587 : !! an energy-like quantity (so the usual dotproduct is divided
1588 : !! by the number of FFT points, and multiplied by the primitive cell volume).
1589 : !! Take into account the spin components of the density and potentials (nspden),
1590 : !! and sum correctly over them. Note that the storage of densities and
1591 : !! potentials is different : for potential, one stores the matrix components,
1592 : !! while for the density, one stores the trace, and then, either the
1593 : !! up component (if nspden=2), or the magnetization vector (if nspden=4).
1594 : !!
1595 : !! INPUTS
1596 : !! cplex=if 1, real space functions on FFT grid are REAL, if 2, COMPLEX
1597 : !! dens(cplex*nfft,nspden)=real space density on FFT grid
1598 : !! mpi_enreg=information about MPI parallelization
1599 : !! nfft= (effective) number of FFT grid points (for this processor)
1600 : !! nfftot= total number of FFT grid points
1601 : !! nspden=number of spin-density components
1602 : !! option= if 1, only the real part is computed
1603 : !! if 2, both real and imaginary parts are computed (not yet coded)
1604 : !! pot(cplex*nfft,nspden)=real space potential on FFT grid
1605 : !! (will be complex conjugated if cplex=2 and option=2)
1606 : !! ucvol=unit cell volume (Bohr**3)
1607 : !!
1608 : !! OUTPUT
1609 : !! doti= imaginary part of the dot product, output only if option=2 (and cplex=2).
1610 : !! dotr= real part
1611 : !!
1612 : !! NOTES
1613 : !! Concerning storage when nspden=4:
1614 : !! cplex=1:
1615 : !! V is stored as : V^11, V^22, Re[V^12], Im[V^12] (complex, hermitian)
1616 : !! N is stored as : n, m_x, m_y, m_z (real)
1617 : !! cplex=2:
1618 : !! V is stored as : V^11, V^22, V^12, i.V^21 (complex)
1619 : !! N is stored as : n, m_x, m_y, mz (complex)
1620 : !!
1621 : !! SOURCE
1622 :
1623 224776 : subroutine dotprod_vn(cplex,dens,dotr,doti,nfft,nfftot,nspden,option,pot,ucvol, &
1624 : mpi_comm_sphgrid) ! Optional
1625 :
1626 : !Arguments ------------------------------------
1627 : !scalars
1628 : integer,intent(in) :: cplex,nfft,nfftot,nspden,option
1629 : integer,intent(in),optional :: mpi_comm_sphgrid
1630 : real(dp),intent(in) :: ucvol
1631 : real(dp),intent(out) :: doti,dotr
1632 : !arrays
1633 : real(dp),intent(in) :: dens(cplex*nfft,nspden),pot(cplex*nfft,nspden)
1634 :
1635 : !Local variables-------------------------------
1636 : !scalars
1637 : integer :: ierr,ifft,jfft
1638 : real(dp) :: dim11,dim12,dim21,dim22,dim_dn,dim_up,dre11,dre12,dre21,dre22
1639 : real(dp) :: dre_dn,dre_up,factor,nproc_sphgrid,pim11,pim12,pim21,pim22,pim_dn,pim_up,pre11
1640 : real(dp) :: pre12,pre21,pre22,pre_dn,pre_up
1641 : real(dp) :: bx_re,bx_im,by_re,by_im,bz_re,bz_im,v0_re,v0_im
1642 : !arrays
1643 : real(dp) :: buffer2(2)
1644 : ! *************************************************************************
1645 :
1646 : !Real or complex inputs are coded
1647 : DBG_CHECK(ANY(cplex==(/1,2/)),"Wrong cplex")
1648 : DBG_CHECK(ANY(nspden==(/1,2,4/)),"Wrong nspden")
1649 :
1650 : !Real or complex output are coded
1651 : DBG_CHECK(ANY(option==(/1,2/)),"Wrong option")
1652 :
1653 224776 : dotr=zero; doti=zero
1654 :
1655 224776 : if(nspden==1)then
1656 :
1657 216070 : if(option==1 .or. cplex==1 )then
1658 : !$OMP PARALLEL DO REDUCTION(+:dotr)
1659 4437007528 : do ifft=1,cplex*nfft
1660 4437007528 : dotr=dotr + pot(ifft,1)*dens(ifft,1)
1661 : end do
1662 : ! dotr = ddot(cplex*nfft,pot,1,dens,1)
1663 :
1664 : else ! option==2 and cplex==2 : one builds the imaginary part, from complex den/pot
1665 :
1666 : !$OMP PARALLEL DO PRIVATE(jfft) REDUCTION(+:dotr,doti)
1667 63849666 : do ifft=1,nfft
1668 63842316 : jfft=2*ifft
1669 63842316 : dotr=dotr + pot(jfft-1,1)*dens(jfft-1,1) + pot(jfft,1)*dens(jfft ,1)
1670 63849666 : doti=doti + pot(jfft-1,1)*dens(jfft ,1) - pot(jfft,1)*dens(jfft-1,1)
1671 : end do
1672 :
1673 : end if
1674 :
1675 8706 : else if(nspden==2)then
1676 :
1677 6672 : if(option==1 .or. cplex==1 )then
1678 : !$OMP PARALLEL DO REDUCTION(+:dotr)
1679 117100369 : do ifft=1,cplex*nfft
1680 : dotr=dotr + pot(ifft,1)* dens(ifft,2) & ! This is the spin up contribution
1681 117100369 : & + pot(ifft,2)*(dens(ifft,1)-dens(ifft,2)) ! This is the spin down contribution
1682 : end do
1683 :
1684 : else ! option==2 and cplex==2 : one builds the imaginary part, from complex den/pot
1685 :
1686 : !$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(nfft,dens,pot) REDUCTION(+:dotr,doti)
1687 289248 : do ifft=1,nfft
1688 :
1689 289188 : jfft=2*ifft
1690 289188 : dre_up=dens(jfft-1,2)
1691 289188 : dim_up=dens(jfft ,2)
1692 289188 : dre_dn=dens(jfft-1,1)-dre_up
1693 289188 : dim_dn=dens(jfft ,1)-dim_up
1694 289188 : pre_up=pot(jfft-1,1)
1695 289188 : pim_up=pot(jfft ,1)
1696 289188 : pre_dn=pot(jfft-1,2)
1697 289188 : pim_dn=pot(jfft ,2)
1698 :
1699 : dotr=dotr + pre_up * dre_up &
1700 : & + pim_up * dim_up &
1701 : & + pre_dn * dre_dn &
1702 289188 : & + pim_dn * dim_dn
1703 : doti=doti + pre_up * dim_up &
1704 : & - pim_up * dre_up &
1705 : & + pre_dn * dim_dn &
1706 289248 : & - pim_dn * dre_dn
1707 :
1708 : end do
1709 : end if
1710 :
1711 2034 : else if(nspden==4)then
1712 : ! \rho{\alpha,\beta} V^{\alpha,\beta} =
1713 : ! rho*(V^{11}+V^{22})/2$
1714 : ! + m_x Re(V^{12})- m_y Im{V^{12}}+ m_z(V^{11}-V^{22})/2
1715 2034 : if (cplex==1) then
1716 : !$OMP PARALLEL DO PRIVATE(ifft) SHARED(nfft,dens,pot) REDUCTION(+:dotr)
1717 16638775 : do ifft=1,nfft
1718 : dotr=dotr + &
1719 : & (pot(ifft,1) + pot(ifft,2))*half*dens(ifft,1) & ! This is the density contrib
1720 : & + pot(ifft,3) *dens(ifft,2) & ! This is the m_x contrib
1721 : & - pot(ifft,4) *dens(ifft,3) & ! This is the m_y contrib
1722 16638775 : & +(pot(ifft,1) - pot(ifft,2))*half*dens(ifft,4) ! This is the m_z contrib
1723 : end do
1724 : else ! cplex=2
1725 : ! Note concerning storage when cplex=2:
1726 : ! V is stored as : v^11, v^22, V^12, i.V^21 (each are complex)
1727 : ! N is stored as : n, m_x, m_y, mZ (each are complex)
1728 528 : if (option==1) then
1729 : !$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(nfft,dens,pot) REDUCTION(+:dotr)
1730 1732830 : do ifft=1,nfft
1731 1732608 : jfft=2*ifft
1732 1732608 : dre11=half*(dens(jfft-1,1)+dens(jfft-1,4))
1733 1732608 : dim11=half*(dens(jfft ,1)+dens(jfft-1,4))
1734 1732608 : dre22=half*(dens(jfft-1,1)-dens(jfft-1,4))
1735 1732608 : dim22=half*(dens(jfft ,1)-dens(jfft-1,4))
1736 1732608 : dre12=half*(dens(jfft-1,2)+dens(jfft ,3))
1737 1732608 : dim12=half*(dens(jfft ,2)-dens(jfft-1,3))
1738 1732608 : dre21=half*(dens(jfft-1,2)-dens(jfft ,3))
1739 1732608 : dim21=half*(dens(jfft ,2)+dens(jfft-1,3))
1740 1732608 : pre11= pot(jfft-1,1)
1741 1732608 : pim11= pot(jfft ,1)
1742 1732608 : pre22= pot(jfft-1,2)
1743 1732608 : pim22= pot(jfft ,2)
1744 1732608 : pre12= pot(jfft-1,3)
1745 1732608 : pim12= pot(jfft ,3)
1746 1732608 : pre21= pot(jfft ,4)
1747 1732608 : pim21=-pot(jfft-1,4)
1748 :
1749 1732608 : v0_re=half*(pre11+pre22)
1750 1732608 : v0_im=half*(pim11+pim22)
1751 1732608 : bx_re=half*(pre12+pre21)
1752 1732608 : bx_im=half*(pim12+pim21)
1753 1732608 : by_re=half*(-pim12+pim21)
1754 1732608 : by_im=half*(pre12-pre21)
1755 1732608 : bz_re=half*(pre11-pre22)
1756 1732608 : bz_im=half*(pim11-pim22)
1757 : dotr=dotr+v0_re * dens(jfft-1,1)&
1758 : & + v0_im * dens(jfft ,1) &
1759 : & + bx_re * dens(jfft-1,2) &
1760 : & + bx_im * dens(jfft ,2) &
1761 : & + by_re * dens(jfft-1,3) &
1762 : & + by_im * dens(jfft ,3) &
1763 : & + bz_re * dens(jfft-1,4) &
1764 1732830 : & + bz_im * dens(jfft ,4)
1765 : ! dotr=dotr + pre11 * dre11 &
1766 : !& + pim11 * dim11 &
1767 : !& + pre22 * dre22 &
1768 : !& + pim22 * dim22 &
1769 : !& + pre12 * dre12 &
1770 : !& + pim12 * dim12 &
1771 : !& + pre21 * dre21 &
1772 : !& + pim21 * dim21
1773 : end do
1774 : else ! option=2
1775 : !$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(nfft,dens,pot) REDUCTION(+:dotr,doti)
1776 1004850 : do ifft=1,nfft
1777 1004544 : jfft=2*ifft
1778 1004544 : dre11=half*(dens(jfft-1,1)+dens(jfft-1,4))
1779 1004544 : dim11=half*(dens(jfft ,1)+dens(jfft-1,4))
1780 1004544 : dre22=half*(dens(jfft-1,1)-dens(jfft-1,4))
1781 1004544 : dim22=half*(dens(jfft ,1)-dens(jfft-1,4))
1782 1004544 : dre12=half*(dens(jfft-1,2)+dens(jfft ,3))
1783 1004544 : dim12=half*(dens(jfft ,2)-dens(jfft-1,3))
1784 1004544 : dre21=half*(dens(jfft-1,2)-dens(jfft ,3))
1785 1004544 : dim21=half*(dens(jfft ,2)+dens(jfft-1,3))
1786 1004544 : pre11= pot(jfft-1,1)
1787 1004544 : pim11= pot(jfft ,1)
1788 1004544 : pre22= pot(jfft-1,2)
1789 1004544 : pim22= pot(jfft ,2)
1790 1004544 : pre12= pot(jfft-1,3)
1791 1004544 : pim12= pot(jfft ,3)
1792 1004544 : pre21= pot(jfft ,4)
1793 1004544 : pim21=-pot(jfft-1,4)
1794 1004544 : v0_re=half*(pre11+pre22)
1795 1004544 : v0_im=half*(pim11+pim22)
1796 1004544 : bx_re=half*(pre12+pre21)
1797 1004544 : bx_im=half*(pim12+pim21)
1798 1004544 : by_re=half*(-pim12+pim21)
1799 1004544 : by_im=half*(pre12-pre21)
1800 1004544 : bz_re=half*(pre11-pre22)
1801 1004544 : bz_im=half*(pim11-pim22)
1802 :
1803 : dotr=dotr+v0_re * dens(jfft-1,1)&
1804 : & + v0_im * dens(jfft ,1) &
1805 : & + bx_re * dens(jfft-1,2) &
1806 : & + bx_im * dens(jfft ,2) &
1807 : & + by_re * dens(jfft-1,3) &
1808 : & + by_im * dens(jfft ,3) &
1809 : & + bz_re * dens(jfft-1,4) &
1810 1004544 : & + bz_im * dens(jfft ,4)
1811 :
1812 : doti=doti+ v0_re * dens(jfft ,1)&
1813 : & - v0_im * dens(jfft-1,1) &
1814 : & + bx_re * dens(jfft ,2) &
1815 : & - bx_im * dens(jfft-1,2) &
1816 : & + by_re * dens(jfft ,3) &
1817 : & - by_im * dens(jfft-1,3) &
1818 : & + bz_re * dens(jfft ,4) &
1819 1004850 : & - bz_im * dens(jfft-1,4)
1820 :
1821 : ! dotr=dotr + pre11 * dre11 &
1822 : !& + pim11 * dim11 &
1823 : !& + pre22 * dre22 &
1824 : !& + pim22 * dim22 &
1825 : !& + pre12 * dre12 &
1826 : !& + pim12 * dim12 &
1827 : !& + pre21 * dre21 &
1828 : !& + pim21 * dim21
1829 : ! doti=doti + pre11 * dim11 &
1830 : !& - pim11 * dre11 &
1831 : !& + pre22 * dim22 &
1832 : !& - pim22 * dre22 &
1833 : !& + pre12 * dim12 &
1834 : !& - pim12 * dre12 &
1835 : !& + pre21 * dim21 &
1836 : !& - pim21 * dre21
1837 : end do
1838 : end if ! option
1839 : end if ! cplex
1840 : end if ! nspden
1841 :
1842 224776 : factor=ucvol/dble(nfftot)
1843 224776 : dotr=factor*dotr
1844 224776 : doti=factor*doti
1845 :
1846 : !MPIWF reduction (addition) on dotr, doti is needed here
1847 224776 : if(present(mpi_comm_sphgrid)) then
1848 118428 : nproc_sphgrid=xmpi_comm_size(mpi_comm_sphgrid)
1849 118428 : if(nproc_sphgrid>1) then
1850 6340 : buffer2(1)=dotr
1851 6340 : buffer2(2)=doti
1852 6340 : call xmpi_sum(buffer2,mpi_comm_sphgrid,ierr)
1853 6340 : dotr=buffer2(1)
1854 6340 : doti=buffer2(2)
1855 : end if
1856 : end if
1857 :
1858 224776 : end subroutine dotprod_vn
1859 : !!***
1860 :
1861 : !----------------------------------------------------------------------
1862 :
1863 : !!****f* m_cgtools/sqnorm_v
1864 : !! NAME
1865 : !! sqnorm_v
1866 : !!
1867 : !! FUNCTION
1868 : !! Compute square of the norm of a potential (integral over FFT grid), to obtain
1869 : !! a square residual-like quantity (so the sum of product of values
1870 : !! is NOT divided by the number of FFT points, and NOT multiplied by the primitive cell volume).
1871 : !! Take into account the spin components of the potentials (nspden),
1872 : !! and sum over them.
1873 : !!
1874 : !! INPUTS
1875 : !! cplex=if 1, real space function on FFT grid is REAL, if 2, COMPLEX
1876 : !! nfft= (effective) number of FFT grid points (for this processor)
1877 : !! nspden=number of spin-density components
1878 : !! opt_storage: 0, if potential is stored as V^up-up, V^dn-dn, Re[V^up-dn], Im[V^up-dn]
1879 : !! 1, if potential is stored as V, B_x, B_y, Bz (B=magn. field)
1880 : !! pot(cplex*nfft,nspden)=real space potential on FFT grid
1881 : !!
1882 : !! OUTPUT
1883 : !! norm2= value of the square of the norm
1884 : !!
1885 : !! SOURCE
1886 :
1887 65193 : subroutine sqnorm_v(cplex,nfft,norm2,nspden,opt_storage,pot,mpi_comm_sphgrid)
1888 :
1889 : !Arguments ------------------------------------
1890 : !scalars
1891 : integer,intent(in) :: cplex,nfft,nspden,opt_storage
1892 : integer,intent(in),optional :: mpi_comm_sphgrid
1893 : real(dp),intent(out) :: norm2
1894 : !arrays
1895 : real(dp),intent(in) :: pot(cplex*nfft,nspden)
1896 :
1897 : !Local variables-------------------------------
1898 : !scalars
1899 : integer :: ierr,ifft,ispden,nproc_sphgrid
1900 : real(dp) :: ar
1901 : ! *************************************************************************
1902 :
1903 : !Real or complex inputs are coded
1904 :
1905 65193 : norm2=zero
1906 139672 : do ispden=1,min(nspden,2)
1907 : !$OMP PARALLEL DO PRIVATE(ifft) SHARED(cplex,ispden,nfft,pot) REDUCTION(+:norm2)
1908 1591062665 : do ifft=1,cplex*nfft
1909 1590997472 : norm2=norm2 + pot(ifft,ispden)**2
1910 : end do
1911 : end do
1912 65193 : if (nspden==4) then
1913 : ar=zero
1914 8034 : do ispden=3,4
1915 : !$OMP PARALLEL DO PRIVATE(ifft) SHARED(cplex,ispden,nfft,pot) REDUCTION(+:ar)
1916 65085984 : do ifft=1,cplex*nfft
1917 65083306 : ar=ar + pot(ifft,ispden)**2
1918 : end do
1919 : end do
1920 2678 : if (opt_storage==0) then
1921 1634 : if (cplex==1) then
1922 1554 : norm2=norm2+two*ar
1923 : else
1924 80 : norm2=norm2+ar
1925 : end if
1926 : else
1927 1044 : norm2=half*(norm2+ar)
1928 : end if
1929 : end if
1930 :
1931 : !MPIWF reduction (addition) on norm2 is needed here
1932 65193 : if(present(mpi_comm_sphgrid)) then
1933 46812 : nproc_sphgrid=xmpi_comm_size(mpi_comm_sphgrid)
1934 46812 : if(nproc_sphgrid>1)then
1935 2580 : call xmpi_sum(norm2,mpi_comm_sphgrid,ierr)
1936 : end if
1937 : end if
1938 :
1939 65193 : end subroutine sqnorm_v
1940 : !!***
1941 :
1942 : !----------------------------------------------------------------------
1943 :
1944 : !!****f* m_cgtools/mean_fftr
1945 : !! NAME
1946 : !! mean_fftr
1947 : !!
1948 : !! FUNCTION
1949 : !! Compute the mean of an arraysp(nfft,nspden), over the FFT grid, for each component nspden,
1950 : !! and return it in meansp(nspden).
1951 : !! Take into account the spread of the array due to parallelism: the actual number of fft
1952 : !! points is nfftot, but the number of points on this proc is nfft only.
1953 : !! So : for ispden from 1 to nspden
1954 : !! meansp(ispden) = sum(ifft=1,nfftot) arraysp(ifft,ispden) / nfftot
1955 : !!
1956 : !! INPUTS
1957 : !! arraysp(nfft,nspden)=the array whose average has to be computed
1958 : !! nfft=number of FFT points stored by one proc
1959 : !! nfftot=total number of FFT points
1960 : !! nspden=number of spin-density components
1961 : !!
1962 : !! OUTPUT
1963 : !! meansp(nspden)=mean value for each nspden component
1964 : !!
1965 : !! SOURCE
1966 :
1967 209439 : subroutine mean_fftr(arraysp,meansp,nfft,nfftot,nspden,mpi_comm_sphgrid,gpu_thread_limit)
1968 :
1969 : !Arguments ------------------------------------
1970 : !scalars
1971 : integer,intent(in) :: nfft,nfftot,nspden
1972 : integer,intent(in),optional:: mpi_comm_sphgrid,gpu_thread_limit
1973 : !arrays
1974 : real(dp),intent(in) :: arraysp(nfft,nspden)
1975 : real(dp),intent(out) :: meansp(nspden)
1976 :
1977 : !Local variables-------------------------------
1978 : !scalars
1979 : integer :: ierr,ifft,ispden,nproc_sphgrid,l_gpu_thread_limit,nthreads_bak
1980 : real(dp) :: invnfftot,tmean
1981 : ! *************************************************************************
1982 :
1983 209439 : l_gpu_thread_limit=0; if(present(gpu_thread_limit)) l_gpu_thread_limit=gpu_thread_limit
1984 209439 : invnfftot=one/(dble(nfftot))
1985 :
1986 209439 : if(l_gpu_thread_limit /= 0) then
1987 0 : nthreads_bak=xomp_get_max_threads()
1988 0 : call xomp_set_num_threads(min(l_gpu_thread_limit,nthreads_bak))
1989 : end if
1990 :
1991 456808 : do ispden=1,nspden
1992 : tmean=zero
1993 : !$OMP PARALLEL DO REDUCTION(+:tmean)
1994 5012354763 : do ifft=1,nfft
1995 5012354763 : tmean=tmean+arraysp(ifft,ispden)
1996 : end do
1997 456808 : meansp(ispden)=tmean*invnfftot
1998 : end do
1999 :
2000 : !XG030514 : MPIWF The values of meansp(ispden) should
2001 : !now be summed across processors in the same WF group, and spread on all procs.
2002 209439 : if(present(mpi_comm_sphgrid)) then
2003 209172 : nproc_sphgrid=xmpi_comm_size(mpi_comm_sphgrid)
2004 209172 : if(nproc_sphgrid>1) then
2005 9884 : call xmpi_sum(meansp,nspden,mpi_comm_sphgrid,ierr)
2006 : end if
2007 : end if
2008 :
2009 209439 : if(l_gpu_thread_limit /= 0) then
2010 0 : call xomp_set_num_threads(nthreads_bak)
2011 : end if
2012 :
2013 209439 : end subroutine mean_fftr
2014 : !!***
2015 :
2016 : !!****f* m_cgtools/cg_getspin
2017 : !! NAME
2018 : !! cg_getspin
2019 : !!
2020 : !! FUNCTION
2021 : !! Sandwich a single wave function on the Pauli matrices
2022 : !!
2023 : !! INPUTS
2024 : !! npw_k = number of plane waves
2025 : !! cgcband = coefficients of spinorial wave function
2026 : !!
2027 : !! OUTPUT
2028 : !! spin = 3-vector of spin components for this state
2029 : !! cgcmat = outer spin product of spinorial wf with itself
2030 : !!
2031 : !! SOURCE
2032 :
2033 300 : subroutine cg_getspin(cgcband, npw_k, spin, cgcmat)
2034 :
2035 : !Arguments ------------------------------------
2036 : !scalars
2037 : integer, intent(in) :: npw_k
2038 : real(dp), intent(in) :: cgcband(2,2*npw_k)
2039 : complex(dp), intent(out),optional :: cgcmat(2,2)
2040 : real(dp), intent(out) :: spin(3)
2041 :
2042 : !Local variables-------------------------------
2043 : !scalars
2044 : complex(dp) :: cspin(0:3), cgcmat_(2,2)
2045 : ! ***********************************************************************
2046 :
2047 : ! cgcmat_ = cgcband * cgcband^T* i.e. 2x2 matrix of spin components (dpcomplex)
2048 300 : cgcmat_ = czero
2049 300 : call zgemm('n','c',2,2,npw_k,cone,cgcband,2,cgcband,2,czero,cgcmat_,2)
2050 :
2051 : ! spin(*) = sum_{si sj pi} cgcband(si,pi)^* pauli_mat*(si,sj) cgcband(sj,pi)
2052 : cspin(0) = cgcmat_(1,1)*pauli_mat(1,1,0) + cgcmat_(2,1)*pauli_mat(2,1,0) &
2053 300 : & + cgcmat_(1,2)*pauli_mat(1,2,0) + cgcmat_(2,2)*pauli_mat(2,2,0)
2054 : cspin(1) = cgcmat_(1,1)*pauli_mat(1,1,1) + cgcmat_(2,1)*pauli_mat(2,1,1) &
2055 300 : & + cgcmat_(1,2)*pauli_mat(1,2,1) + cgcmat_(2,2)*pauli_mat(2,2,1)
2056 : cspin(2) = cgcmat_(1,1)*pauli_mat(1,1,2) + cgcmat_(2,1)*pauli_mat(2,1,2) &
2057 300 : & + cgcmat_(1,2)*pauli_mat(1,2,2) + cgcmat_(2,2)*pauli_mat(2,2,2)
2058 : cspin(3) = cgcmat_(1,1)*pauli_mat(1,1,3) + cgcmat_(2,1)*pauli_mat(2,1,3) &
2059 300 : & + cgcmat_(1,2)*pauli_mat(1,2,3) + cgcmat_(2,2)*pauli_mat(2,2,3)
2060 : !write(std_out,*) 'cgmat: ', cgcmat_
2061 : !write(std_out,*) 'real(spin): ', real(cspin)
2062 : !write(std_out,*) 'aimag(spin): ', aimag(cspin)
2063 :
2064 1200 : spin = real(cspin(1:3))
2065 300 : if (present(cgcmat)) cgcmat = cgcmat_
2066 :
2067 300 : end subroutine cg_getspin
2068 : !!***
2069 :
2070 : !----------------------------------------------------------------------
2071 :
2072 : !!****f* m_cgtools/cg_gsph2box
2073 : !! NAME
2074 : !! cg_gsph2box
2075 : !!
2076 : !! FUNCTION
2077 : !! Array iarrsph is defined in sphere with npw_k points. Insert iarrsph inside box
2078 : !! of nx*ny*nz points to define array oarrbox for fft box. rest of oarrbox is filled with 0 s.
2079 : !!
2080 : !! INPUTS
2081 : !! iarrsph(2,npw_k*ndat)= contains values for npw_k G vectors in basis sphere
2082 : !! ndat=number of FFT to perform.
2083 : !! npw_k=number of G vectors in basis at this k point
2084 : !! oarrbox(2,ldx*ldy*ldz*ndat) = fft box
2085 : !! nx,ny,nz=physical dimension of the box (oarrbox)
2086 : !! ldx,ldy,ldz=memory dimension of oarrbox
2087 : !! kg_k(3,npw_k)=integer coordinates of G vectors in basis sphere
2088 : !! istwf_k=option parameter that describes the storage of wfs
2089 : !!
2090 : !! OUTPUT
2091 : !! oarrbox(ldx*ldy*ldz*ndat)
2092 : !!
2093 : !! NOTES
2094 : !! If istwf_k differs from 1, then special storage modes must be taken
2095 : !! into account, for symmetric wavefunctions coming from k=(0 0 0) or other
2096 : !! special k points.
2097 : !!
2098 : !! SOURCE
2099 :
2100 0 : subroutine cg_gsph2box(nx,ny,nz,ldx,ldy,ldz,ndat,npw_k,istwf_k,kg_k,iarrsph,oarrbox)
2101 :
2102 : !Arguments ------------------------------------
2103 : !scalars
2104 : integer,intent(in) :: istwf_k,nx,ny,nz,ldx,ldy,ldz,ndat,npw_k
2105 : !arrays
2106 : integer,intent(in) :: kg_k(3,npw_k)
2107 : real(dp),intent(in) :: iarrsph(2,npw_k*ndat)
2108 : real(dp),intent(out) :: oarrbox(2,ldx*ldy*ldz*ndat)
2109 :
2110 : !Local variables-------------------------------
2111 : !scalars
2112 : integer,parameter :: me_g0=1
2113 : integer :: ix,ixinv,iy,iyinv,iz,izinv,dat,ipw,npwmin,pad_box,pad_sph,ifft,ifft_inv,ldxyz
2114 : character(len=500) :: msg
2115 : !arrays
2116 0 : integer,allocatable :: ixinver(:),iyinver(:),izinver(:)
2117 : ! *************************************************************************
2118 :
2119 : !In the case of special k-points, invariant under time-reversal,
2120 : !but not Gamma, initialize the inverse coordinates
2121 : !Remember indeed that
2122 : !u_k(G) = u_{k+G0}(G-G0); u_{-k}(-G) = u_k(G)^*
2123 : !and therefore:
2124 : !u_{G0/2}(G) = u_{G0/2}(-G-G0)^*.
2125 0 : if (istwf_k>=2) then
2126 0 : ABI_MALLOC(ixinver,(nx))
2127 0 : ABI_MALLOC(iyinver,(ny))
2128 0 : ABI_MALLOC(izinver,(nz))
2129 0 : if ( ANY(istwf_k==(/2,4,6,8/)) ) then
2130 0 : ixinver(1)=1
2131 0 : do ix=2,nx
2132 0 : ixinver(ix)=nx+2-ix
2133 : end do
2134 : else
2135 0 : do ix=1,nx
2136 0 : ixinver(ix)=nx+1-ix
2137 : end do
2138 : end if
2139 0 : if (istwf_k>=2 .and. istwf_k<=5) then
2140 0 : iyinver(1)=1
2141 0 : do iy=2,ny
2142 0 : iyinver(iy)=ny+2-iy
2143 : end do
2144 : else
2145 0 : do iy=1,ny
2146 0 : iyinver(iy)=ny+1-iy
2147 : end do
2148 : end if
2149 0 : if ( ANY(istwf_k==(/2,3,6,7/)) ) then
2150 0 : izinver(1)=1
2151 0 : do iz=2,nz
2152 0 : izinver(iz)=nz+2-iz
2153 : end do
2154 : else
2155 0 : do iz=1,nz
2156 0 : izinver(iz)=nz+1-iz
2157 : end do
2158 : end if
2159 : end if
2160 :
2161 0 : ldxyz = ldx*ldy*ldz
2162 :
2163 0 : if (istwf_k==1) then
2164 :
2165 : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,iy,iz,ifft)
2166 0 : do dat=1,ndat
2167 0 : pad_sph = (dat-1)*npw_k
2168 0 : pad_box = (dat-1)*ldxyz
2169 0 : oarrbox(:,1+pad_box:ldxyz+pad_box) = zero ! zero the sub-array
2170 0 : do ipw=1,npw_k
2171 0 : ix=kg_k(1,ipw); if (ix<0) ix=ix+nx; ix=ix+1
2172 0 : iy=kg_k(2,ipw); if (iy<0) iy=iy+ny; iy=iy+1
2173 0 : iz=kg_k(3,ipw); if (iz<0) iz=iz+nz; iz=iz+1
2174 0 : ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
2175 : #if (defined FC_NVHPC) || (defined __INTEL_COMPILER && defined HAVE_OPENMP)
2176 : if (ifft<0) stop "prevent from miscompiling this section"
2177 : #endif
2178 0 : oarrbox(1,ifft+pad_box) = iarrsph(1,ipw+pad_sph)
2179 0 : oarrbox(2,ifft+pad_box) = iarrsph(2,ipw+pad_sph)
2180 : end do
2181 : end do
2182 :
2183 0 : else if (istwf_k>=2) then
2184 : !
2185 0 : npwmin=1
2186 0 : if(istwf_k==2 .and. me_g0==1) then ! If gamma point, then oarrbox must be completed
2187 0 : do dat=1,ndat
2188 0 : pad_sph = (dat-1)*npw_k
2189 0 : pad_box = (dat-1)*ldxyz
2190 0 : oarrbox(1,1+pad_box) = iarrsph(1,1+pad_sph)
2191 0 : oarrbox(2,1+pad_box) = zero
2192 : end do
2193 : npwmin=2
2194 : end if
2195 :
2196 : !$OMP PARALLEL DO PRIVATE(pad_sph,pad_box,ix,iy,iz,ixinv,iyinv,izinv,ifft,ifft_inv)
2197 0 : do dat=1,ndat
2198 0 : pad_sph = (dat-1)*npw_k
2199 0 : pad_box = (dat-1)*ldxyz
2200 0 : oarrbox(:,npwmin+pad_box:ldxyz+pad_box) = zero
2201 0 : do ipw=npwmin,npw_k
2202 0 : ix=kg_k(1,ipw); if(ix<0)ix=ix+nx; ix=ix+1
2203 0 : iy=kg_k(2,ipw); if(iy<0)iy=iy+ny; iy=iy+1
2204 0 : iz=kg_k(3,ipw); if(iz<0)iz=iz+nz; iz=iz+1
2205 0 : ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
2206 : #if defined FC_NVHPC
2207 : if (ifft<0) stop "prevent from miscompiling this section"
2208 : #endif
2209 : ! Construct the coordinates of -k-G
2210 0 : ixinv=ixinver(ix); iyinv=iyinver(iy); izinv=izinver(iz)
2211 0 : ifft_inv = ixinv + (iyinv-1)*ldx + (izinv-1)*ldx*ldy
2212 :
2213 0 : oarrbox(:,ifft +pad_box) = iarrsph(:,ipw+pad_sph)
2214 0 : oarrbox(1,ifft_inv+pad_box) = iarrsph(1,ipw+pad_sph)
2215 0 : oarrbox(2,ifft_inv+pad_box) = -iarrsph(2,ipw+pad_sph)
2216 : end do
2217 : end do
2218 : !
2219 : else
2220 0 : write(msg,'(a,i0)')"Wrong istwfk ",istwf_k
2221 0 : ABI_ERROR(msg)
2222 : end if
2223 :
2224 0 : if (istwf_k>=2) then
2225 0 : ABI_FREE(ixinver)
2226 0 : ABI_FREE(iyinver)
2227 0 : ABI_FREE(izinver)
2228 : end if
2229 :
2230 0 : end subroutine cg_gsph2box
2231 : !!***
2232 :
2233 : !----------------------------------------------------------------------
2234 :
2235 : !!****f* m_cgtools/cg_box2gsph
2236 : !! NAME
2237 : !! cg_box2gsph
2238 : !!
2239 : !! FUNCTION
2240 : !!
2241 : !! INPUTS
2242 : !! nx,ny,nz=physical dimension of the FFT box.
2243 : !! ldx,ldy,ldz=Logical dimensions of the arrays.
2244 : !! ndat=number of data in iarrbox
2245 : !! npw_k=Number of planewaves in the G-sphere.
2246 : !! kg_k(3,npw_k)=Reduced coordinates of the G-vectoes.
2247 : !! iarrbox(2,ldx,ldy,ldz*ndat)=Input arrays on the FFT box.
2248 : !! [rscal] = Scaling factor
2249 : !!
2250 : !! OUTPUT
2251 : !! oarrsph(2,npw_k*ndat)=Data defined on the G-sphere.
2252 : !!
2253 : !! SOURCE
2254 :
2255 28521 : subroutine cg_box2gsph(nx,ny,nz,ldx,ldy,ldz,ndat,npw_k,kg_k,iarrbox,oarrsph,rscal)
2256 :
2257 : !Arguments ------------------------------------
2258 : !scalars
2259 : integer,intent(in) :: npw_k,nx,ny,nz,ldx,ldy,ldz,ndat
2260 : real(dp),optional,intent(in) :: rscal
2261 : !arrays
2262 : integer,intent(in) :: kg_k(3,npw_k)
2263 : real(dp),intent(in) :: iarrbox(2,ldx*ldy*ldz*ndat)
2264 : real(dp),intent(out) :: oarrsph(2,npw_k*ndat)
2265 :
2266 : !Local variables-------------------------------
2267 : !scalars
2268 : integer :: ig,ix,iy,iz,idat,sph_pad,box_pad,ifft
2269 : ! *************************************************************************
2270 :
2271 28521 : if (.not. PRESENT(rscal)) then
2272 : !
2273 51 : if (ndat==1) then
2274 : !$OMP PARALLEL DO PRIVATE(ix,iy,iz,ifft)
2275 669787 : do ig=1,npw_k
2276 669736 : ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
2277 669736 : iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
2278 669736 : iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
2279 669736 : ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
2280 : #if defined FC_NVHPC
2281 : if (ifft<0) stop "prevent from miscompiling this section"
2282 : #endif
2283 669736 : oarrsph(1,ig) = iarrbox(1,ifft)
2284 669787 : oarrsph(2,ig) = iarrbox(2,ifft)
2285 : end do
2286 : else
2287 : !$OMP PARALLEL DO PRIVATE(sph_pad,box_pad,ix,iy,iz,ifft)
2288 0 : do idat=1,ndat
2289 0 : sph_pad = (idat-1)*npw_k
2290 0 : box_pad = (idat-1)*ldx*ldy*ldz
2291 0 : do ig=1,npw_k
2292 0 : ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
2293 0 : iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
2294 0 : iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
2295 0 : ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
2296 : #if defined FC_NVHPC
2297 : if (ifft<0) stop "prevent from miscompiling this section"
2298 : #endif
2299 0 : oarrsph(1,ig+sph_pad) = iarrbox(1,ifft+box_pad)
2300 0 : oarrsph(2,ig+sph_pad) = iarrbox(2,ifft+box_pad)
2301 : end do
2302 : end do
2303 : end if
2304 : !
2305 : else
2306 28470 : if (ndat==1) then
2307 : !$OMP PARALLEL DO PRIVATE(ix,iy,iz,ifft)
2308 12097072 : do ig=1,npw_k
2309 12068616 : ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
2310 12068616 : iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
2311 12068616 : iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
2312 12068616 : ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
2313 : #if defined FC_NVHPC
2314 : if (ifft<0) stop "prevent from miscompiling this section"
2315 : #endif
2316 12068616 : oarrsph(1,ig) = iarrbox(1,ifft) * rscal
2317 12097072 : oarrsph(2,ig) = iarrbox(2,ifft) * rscal
2318 : end do
2319 : else
2320 : !$OMP PARALLEL DO PRIVATE(sph_pad,box_pad,ix,iy,iz,ifft)
2321 70 : do idat=1,ndat
2322 56 : sph_pad = (idat-1)*npw_k
2323 56 : box_pad = (idat-1)*ldx*ldy*ldz
2324 3514574 : do ig=1,npw_k
2325 3514504 : ix=kg_k(1,ig); if (ix<0) ix=ix+nx; ix=ix+1
2326 3514504 : iy=kg_k(2,ig); if (iy<0) iy=iy+ny; iy=iy+1
2327 3514504 : iz=kg_k(3,ig); if (iz<0) iz=iz+nz; iz=iz+1
2328 3514504 : ifft = ix + (iy-1)*ldx + (iz-1)*ldx*ldy
2329 : #if defined FC_NVHPC
2330 : if (ifft<0) stop "prevent from miscompiling this section"
2331 : #endif
2332 3514504 : oarrsph(1,ig+sph_pad) = iarrbox(1,ifft+box_pad) * rscal
2333 3514560 : oarrsph(2,ig+sph_pad) = iarrbox(2,ifft+box_pad) * rscal
2334 : end do
2335 : end do
2336 : end if
2337 : end if
2338 :
2339 28521 : end subroutine cg_box2gsph
2340 : !!***
2341 :
2342 : !----------------------------------------------------------------------
2343 :
2344 : !!****f* m_cgtools/cg_addtorho
2345 : !! NAME
2346 : !! cg_addtorho
2347 : !!
2348 : !! FUNCTION
2349 : !! Add |ur|**2 to the ground-states density rho.
2350 : !! rho = rho + weight_r * Re[ur]**2 + weight_i * Im[ur]**2
2351 : !!
2352 : !! INPUTS
2353 : !! nx,ny,nz=physical dimension of the FFT box.
2354 : !! ldx,ldy,ldz=leading dimensions of the arrays.
2355 : !! ndat=number of contributions to accumulate.
2356 : !! weight_r=weight used for the accumulation of the density in real space
2357 : !! weight_i=weight used for the accumulation of the density in real space
2358 : !! ur(2,ldx,ldy,ldz*ndat)=wavefunctions in real space
2359 : !!
2360 : !! SIDE EFFECTS
2361 : !! rho(ldx,ldy,ldz) = contains the input density at input,
2362 : !! modified in input with the contribution given by ur.
2363 : !!
2364 : !! SOURCE
2365 :
2366 234 : subroutine cg_addtorho(nx,ny,nz,ldx,ldy,ldz,ndat,weight_r,weight_i,ur,rho)
2367 :
2368 : !Arguments ------------------------------------
2369 : !scalars
2370 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat
2371 : real(dp),intent(in) :: weight_i,weight_r
2372 : !arrays
2373 : real(dp),intent(in) :: ur(2,ldx,ldy,ldz*ndat)
2374 : real(dp),intent(inout) :: rho(ldx,ldy,ldz)
2375 :
2376 : !Local variables-------------------------------
2377 : !scalars
2378 : integer :: ix,iy,iz,idat,izdat
2379 : ! *************************************************************************
2380 :
2381 234 : if (ndat==1) then
2382 : !$OMP PARALLEL DO
2383 11100 : do iz=1,nz
2384 720162 : do iy=1,ny
2385 56309590 : do ix=1,nx
2386 : rho(ix,iy,iz) = rho(ix,iy,iz) + weight_r * ur(1,ix,iy,iz)**2 &
2387 56298720 : & + weight_i * ur(2,ix,iy,iz)**2
2388 : end do
2389 : end do
2390 : end do
2391 :
2392 : else
2393 : ! It would be nice to use $OMP PARALLEL DO PRIVATE(izdat) REDUCTION(+:rho)
2394 : ! but it's risky as the private rho is allocated on the stack of the thread.
2395 : !$OMP PARALLEL PRIVATE(izdat)
2396 20 : do idat=1,ndat
2397 : !$OMP DO
2398 1620 : do iz=1,nz
2399 1600 : izdat = iz + (idat-1)*ldz
2400 161616 : do iy=1,ny
2401 16161600 : do ix=1,nx
2402 : rho(ix,iy,iz) = rho(ix,iy,iz) + weight_r * ur(1,ix,iy,izdat)**2 &
2403 16160000 : & + weight_i * ur(2,ix,iy,izdat)**2
2404 : end do
2405 : end do
2406 : end do
2407 : !$OMP END DO NOWAIT
2408 : end do
2409 : !$OMP END PARALLEL
2410 : end if
2411 :
2412 234 : end subroutine cg_addtorho
2413 : !!***
2414 :
2415 : !----------------------------------------------------------------------
2416 :
2417 : !!****f* m_cgtools/cg_vlocpsi
2418 : !! NAME
2419 : !! cg_vlocpsi
2420 : !!
2421 : !! FUNCTION
2422 : !! Apply the local part of the potentatil to the wavefunction in real space.
2423 : !!
2424 : !! INPUTS
2425 : !! nx,ny,nz=physical dimension of the FFT box.
2426 : !! ldx,ldy,ldz=leading dimensions of the arrays.
2427 : !! ndat=number of wavefunctions.
2428 : !! cplex= 1 if vloc is real, 2 for complex
2429 : !! vloc(cplex*ldx,ldy,ldz)=Local potential on the FFT box.
2430 : !!
2431 : !! SIDE EFFECTS
2432 : !! ur(2,ldx,ldy,ldz*ndat)=
2433 : !! Input = wavefunctions in real space.
2434 : !! Output= vloc |ur>
2435 : !!
2436 : !! SOURCE
2437 :
2438 0 : subroutine cg_vlocpsi(nx,ny,nz,ldx,ldy,ldz,ndat,cplex,vloc,ur)
2439 :
2440 : !Arguments ------------------------------------
2441 : !scalars
2442 : integer,intent(in) :: nx,ny,nz,ldx,ldy,ldz,ndat,cplex
2443 : !arrays
2444 : real(dp),intent(in) :: vloc(cplex*ldx,ldy,ldz)
2445 : real(dp),intent(inout) :: ur(2,ldx,ldy,ldz*ndat)
2446 :
2447 : !Local variables-------------------------------
2448 : !scalars
2449 : integer :: idat,ix,iy,iz,padat
2450 : real(dp) :: fim,fre
2451 : ! *************************************************************************
2452 :
2453 0 : if (cplex==1) then
2454 : !
2455 0 : if (ndat==1) then
2456 : !$OMP PARALLEL DO
2457 0 : do iz=1,nz
2458 0 : do iy=1,ny
2459 0 : do ix=1,nx
2460 0 : ur(1,ix,iy,iz) = vloc(ix,iy,iz) * ur(1,ix,iy,iz)
2461 0 : ur(2,ix,iy,iz) = vloc(ix,iy,iz) * ur(2,ix,iy,iz)
2462 : end do
2463 : end do
2464 : end do
2465 : !
2466 : else
2467 : !
2468 : !$OMP PARALLEL DO PRIVATE(padat)
2469 0 : do idat=1,ndat
2470 0 : padat = ldz*(idat-1)
2471 0 : do iz=1,nz
2472 0 : do iy=1,ny
2473 0 : do ix=1,nx
2474 0 : ur(1,ix,iy,iz+padat) = vloc(ix,iy,iz) * ur(1,ix,iy,iz+padat)
2475 0 : ur(2,ix,iy,iz+padat) = vloc(ix,iy,iz) * ur(2,ix,iy,iz+padat)
2476 : end do
2477 : end do
2478 : end do
2479 : end do
2480 : !
2481 : end if
2482 : !
2483 0 : else if (cplex==2)then
2484 : !
2485 0 : if (ndat==1) then
2486 : !$OMP PARALLEL DO PRIVATE(fre,fim)
2487 0 : do iz=1,nz
2488 0 : do iy=1,ny
2489 0 : do ix=1,nx
2490 0 : fre = ur(1,ix,iy,iz)
2491 0 : fim = ur(2,ix,iy,iz)
2492 0 : ur(1,ix,iy,iz) = vloc(2*ix-1,iy,iz)*fre - vloc(2*ix,iy,iz)*fim
2493 0 : ur(2,ix,iy,iz) = vloc(2*ix-1,iy,iz)*fim + vloc(2*ix,iy,iz)*fre
2494 : end do
2495 : end do
2496 : end do
2497 : else
2498 : !$OMP PARALLEL DO PRIVATE(padat,fre,fim)
2499 0 : do idat=1,ndat
2500 0 : padat = ldz*(idat-1)
2501 0 : do iz=1,nz
2502 0 : do iy=1,ny
2503 0 : do ix=1,nx
2504 0 : fre = ur(1,ix,iy,iz+padat)
2505 0 : fim = ur(2,ix,iy,iz+padat)
2506 0 : ur(1,ix,iy,iz+padat) = vloc(2*ix-1,iy,iz)*fre - vloc(2*ix,iy,iz)*fim
2507 0 : ur(2,ix,iy,iz+padat) = vloc(2*ix-1,iy,iz)*fim + vloc(2*ix,iy,iz)*fre
2508 : end do
2509 : end do
2510 : end do
2511 : end do
2512 : end if
2513 : !
2514 : else
2515 0 : ur = huge(one)
2516 : !ABI_BUG("Wrong cplex")
2517 : end if
2518 :
2519 0 : end subroutine cg_vlocpsi
2520 : !!***
2521 :
2522 : !----------------------------------------------------------------------
2523 :
2524 : !!****f* m_cgtools/cgnc_cholesky
2525 : !! NAME
2526 : !! cgnc_cholesky
2527 : !!
2528 : !! FUNCTION
2529 : !! Cholesky orthonormalization of the vectors stored in cg (version optimized for NC wavefunctions).
2530 : !!
2531 : !! INPUTS
2532 : !! npwsp=Size of each vector (usually npw*nspinor)
2533 : !! nband=Number of band in cg
2534 : !! istwfk=Storage mode for the wavefunctions. 1 for standard full mode
2535 : !! me_g0=1 if this node has G=0.
2536 : !! comm_pw=MPI communicator for the planewave group. Set to xmpi_comm_self for sequential mode.
2537 : !!
2538 : !! SIDE EFFECTS
2539 : !! cg(2*npwsp*nband)
2540 : !! input: Input set of vectors.
2541 : !! output: Orthonormalized set.
2542 : !!
2543 : !! OUTPUT
2544 : !! [umat]=Cholesky upper triangle matrix.
2545 : !!
2546 : !! SOURCE
2547 :
2548 620 : subroutine cgnc_cholesky(npwsp, nband, cg, istwfk, me_g0, comm_pw, use_gemm, umat)
2549 :
2550 : !Arguments ------------------------------------
2551 : !scalars
2552 : integer,intent(in) :: npwsp, nband, istwfk, comm_pw, me_g0
2553 : logical,optional,intent(in) :: use_gemm
2554 : !arrays
2555 : real(dp),intent(inout) :: cg(2*npwsp*nband)
2556 : real(dp),optional,allocatable,intent(out) :: umat(:,:,:)
2557 :
2558 : !Local variables ------------------------------
2559 : !scalars
2560 : integer :: ierr,b1,b2
2561 : #ifdef DEBUG_MODE
2562 : integer :: ptr
2563 : character(len=500) :: msg
2564 : #endif
2565 : !real(dp) :: max_absimag
2566 : logical :: my_usegemm
2567 : !arrays
2568 1240 : real(dp) :: rcg0(nband)
2569 620 : real(dp),allocatable :: r_ovlp(:,:), c_ovlp(:,:,:)
2570 : ! *************************************************************************
2571 :
2572 : #ifdef DEBUG_MODE
2573 : if (istwfk == 2 .and. me_g0 == 1) then
2574 : ierr = 0
2575 : do b1=1,nband
2576 : ptr = 2 + 2*(b1-1)*npwsp
2577 : if (abs(cg(ptr)) > zero) then
2578 : ierr = ierr + 1
2579 : write(msg,'(a,i0,es13.6)')" Input b1, Im u(g=0) should be zero ",b1,cg(ptr)
2580 : call wrtout(std_out, msg)
2581 : !cg(ptr) = zero
2582 : end if
2583 : end do
2584 : ABI_CHECK(ierr == 0, "Non zero imag part")
2585 : end if
2586 : #endif
2587 :
2588 : ! In matrix notation O = PSI^H PSI = U^H U where PSI is a (ng,nb) matrix with the input wavefunctions
2589 : ! The new orthogonalized states PHI is given by: PHI = PSI U^{-1}
2590 :
2591 620 : my_usegemm = .FALSE.; if (PRESENT(use_gemm)) my_usegemm = use_gemm
2592 :
2593 620 : if (istwfk /= 1) then
2594 : ! Version optimized for real wavefunctions.
2595 496 : ABI_MALLOC(r_ovlp, (nband, nband))
2596 :
2597 : !call cg_set_imag0_to_zero(istwfk, me_g0, npwsp, nband, cg, max_absimag)
2598 :
2599 : ! 1) Calculate O_ij = <phi_i|phi_j> (real symmetric matrix)
2600 124 : if (my_usegemm) then
2601 0 : call DGEMM("T", "N", nband, nband, 2*npwsp, one, cg, 2*npwsp, cg, 2*npwsp, zero, r_ovlp, nband)
2602 : else
2603 124 : call DSYRK("U", "T", nband, 2*npwsp, one, cg, 2*npwsp, zero, r_ovlp, nband)
2604 : end if
2605 :
2606 107356 : r_ovlp = two * r_ovlp
2607 124 : if (istwfk == 2 .and. me_g0 == 1) then
2608 : ! Extract the real part at G=0 and subtract its contribution to the overlap.
2609 31 : call dcopy(nband, cg, 2*npwsp, rcg0, 1)
2610 919 : do b2=1,nband
2611 14323 : do b1=1,b2
2612 14292 : r_ovlp(b1, b2) = r_ovlp(b1, b2) - rcg0(b1) * rcg0(b2)
2613 : end do
2614 : end do
2615 : end if
2616 :
2617 : ! Sum the overlap if PW are distributed.
2618 124 : if (comm_pw /= xmpi_comm_self) call xmpi_sum(r_ovlp, comm_pw, ierr)
2619 :
2620 : ! 2) Cholesky factorization: O = U^H U with U upper triangle matrix.
2621 124 : call DPOTRF('U', nband, r_ovlp, nband, ierr)
2622 124 : ABI_CHECK(ierr == 0, sjoin('DPOTRF returned info:', itoa(ierr)))
2623 :
2624 : ! 3) Solve X U = cg. On exit cg is orthonormalized.
2625 124 : call DTRSM('R', 'U', 'N', 'N', 2*npwsp, nband, one, r_ovlp, nband, cg, 2*npwsp)
2626 :
2627 124 : if (present(umat)) then
2628 372 : ABI_REMALLOC(umat, (1, nband, nband))
2629 107356 : umat(1,:,:) = r_ovlp
2630 : end if
2631 :
2632 124 : ABI_FREE(r_ovlp)
2633 :
2634 : else
2635 : ! Version for complex wavefunctions.
2636 1984 : ABI_MALLOC(c_ovlp, (2, nband, nband))
2637 :
2638 : ! 1) Calculate O_ij = <phi_i|phi_j> (complex Hermitean)
2639 496 : if (my_usegemm) then
2640 0 : call abi_zgemm_2r("C", "N", nband, nband, npwsp, cone, cg, npwsp, cg, npwsp, czero, c_ovlp, nband)
2641 : else
2642 496 : call ZHERK("U", "C", nband, npwsp, cone, cg, npwsp, czero, c_ovlp, nband)
2643 : end if
2644 :
2645 : ! Sum the overlap if PW are distributed.
2646 496 : if (comm_pw /= xmpi_comm_self) call xmpi_sum(c_ovlp, comm_pw, ierr)
2647 :
2648 : ! 2) Cholesky factorization: O = U^H U with U upper triangle matrix.
2649 496 : call ZPOTRF('U', nband, c_ovlp, nband, ierr)
2650 496 : ABI_CHECK(ierr == 0, sjoin('ZPOTRF returned info:', itoa(ierr)))
2651 :
2652 : ! 3) Solve X U = cg. On exit cg is orthonormalized.
2653 496 : call ZTRSM('R', 'U', 'N', 'N', npwsp, nband, cone, c_ovlp, nband, cg, npwsp)
2654 :
2655 496 : if (present(umat)) then
2656 1107 : ABI_REMALLOC(umat, (2, nband, nband))
2657 534762 : umat = c_ovlp
2658 : end if
2659 :
2660 496 : ABI_FREE(c_ovlp)
2661 : end if
2662 :
2663 : #ifdef DEBUG_MODE
2664 : if (istwfk == 2) then
2665 : ierr = 0
2666 : do b1=1,nband
2667 : ptr = 2 + 2*(b1-1)*npwsp
2668 : if (ABS(cg(ptr)) > zero) then
2669 : ierr = ierr + 1
2670 : write(msg,'(a,i0,es13.6)')" Output b1, Im u(g=0) should be zero ",b1,cg(ptr)
2671 : end if
2672 : end do
2673 : ABI_CHECK(ierr == 0, "Non zero imag part")
2674 : end if
2675 : #endif
2676 :
2677 620 : end subroutine cgnc_cholesky
2678 : !!***
2679 :
2680 : !----------------------------------------------------------------------
2681 :
2682 : !!****f* m_cgtools/cgpaw_cholesky
2683 : !! NAME
2684 : !! cgpaw_cholesky
2685 : !!
2686 : !! FUNCTION
2687 : !! Cholesky orthonormalization of the vectors stored in cg. (version for PAW wavefunctions).
2688 : !!
2689 : !! INPUTS
2690 : !! npwsp=Size of each vector (usually npw*nspinor)
2691 : !! nband=Number of band in cg and gsc
2692 : !! istwfk=Storage mode for the wavefunctions. 1 for standard full mode
2693 : !! me_g0=1 if this node has G=0.
2694 : !! comm_pw=MPI communicator for the planewave group. Set to xmpi_comm_self for sequential mode.
2695 : !!
2696 : !! SIDE EFFECTS
2697 : !! cg(2*npwsp*nband)
2698 : !! input: Input set of vectors |C>, S|C>
2699 : !! output: Orthonormalized set such as <C|S|C> = 1
2700 : !! gsc(2*npwsp*nband): destroyed in output.
2701 : !!
2702 : !! OUTPUT
2703 : !! [umat]=Cholesky upper triangle matrix.
2704 : !!
2705 : !! SOURCE
2706 :
2707 160 : subroutine cgpaw_cholesky(npwsp, nband, cg, gsc, istwfk, me_g0, comm_pw, umat)
2708 :
2709 : !Arguments ------------------------------------
2710 : !scalars
2711 : integer,intent(in) :: npwsp, nband, istwfk, me_g0, comm_pw
2712 : !arrays
2713 : real(dp),intent(inout) :: cg(2*npwsp*nband), gsc(2*npwsp*nband)
2714 : real(dp),optional,allocatable,intent(out) :: umat(:,:,:)
2715 :
2716 : !Local variables ------------------------------
2717 : !scalars
2718 : integer :: ierr, b1, b2
2719 : !real(dp) :: max_absimag
2720 : !character(len=500) :: msg
2721 : !arrays
2722 320 : real(dp) :: rcg0(nband), rg0sc(nband)
2723 160 : real(dp),allocatable :: r_ovlp(:,:), c_ovlp(:,:,:)
2724 : ! *************************************************************************
2725 :
2726 160 : if (istwfk /= 1) then
2727 : ! Version optimized for real wavefunctions.
2728 128 : ABI_MALLOC(r_ovlp, (nband, nband))
2729 :
2730 : !call cg_set_imag0_to_zero(istwfk, me_g0, npwsp, nband, cg, max_absimag)
2731 : !call cg_set_imag0_to_zero(istwfk, me_g0, npwsp, nband, gsc, max_absimag)
2732 :
2733 : #ifdef HAVE_LINALG_GEMMT
2734 : ! Use zgemmt extension BLAS3 provided by e.g. MKL
2735 10148 : r_ovlp = zero
2736 32 : call DGEMMT("U", "T", "N", nband, 2*npwsp, one, cg, 2*npwsp, gsc, 2*npwsp, zero, r_ovlp, nband)
2737 : #else
2738 : call DGEMM("T", "N", nband, nband, 2*npwsp, one, cg, 2*npwsp, gsc, 2*npwsp, zero, r_ovlp, nband)
2739 : #endif
2740 10148 : r_ovlp = two * r_ovlp
2741 :
2742 32 : if (istwfk == 2 .and. me_g0 == 1) then
2743 : ! Extract the real part at G=0 and subtract its contribution to the overlap.
2744 10 : call dcopy(nband, cg, 2*npwsp, rcg0, 1)
2745 10 : call dcopy(nband, gsc, 2*npwsp, rg0sc, 1)
2746 174 : do b2=1,nband
2747 1836 : do b1=1,b2
2748 1826 : r_ovlp(b1,b2) = r_ovlp(b1,b2) - rcg0(b1) * rg0sc(b2)
2749 : end do
2750 : end do
2751 : end if
2752 :
2753 : ! Sum the overlap if PW are distributed.
2754 32 : if (comm_pw /= xmpi_comm_self) call xmpi_sum(r_ovlp, comm_pw, ierr)
2755 :
2756 : ! 2) Cholesky factorization: O = U^H U with U upper triangle matrix.
2757 32 : call DPOTRF('U', nband, r_ovlp, nband, ierr)
2758 32 : ABI_CHECK(ierr == 0, sjoin('DPOTRF returned info:', itoa(ierr)))
2759 :
2760 : ! 3) Solve X U = cg.
2761 32 : call DTRSM('R', 'U', 'N', 'N', 2*npwsp, nband, one, r_ovlp, nband, cg, 2*npwsp)
2762 :
2763 : ! 4) Solve Y U = gsc. On exit <cg|gsc> = 1
2764 32 : call DTRSM('R', 'U', 'N', 'N', 2*npwsp, nband, one, r_ovlp, nband, gsc, 2*npwsp)
2765 :
2766 : !call cg_set_imag0_to_zero(istwfk, me_g0, npwsp, nband, cg, max_absimag)
2767 : !call cg_set_imag0_to_zero(istwfk, me_g0, npwsp, nband, gsc, max_absimag)
2768 :
2769 32 : if (present(umat)) then
2770 96 : ABI_REMALLOC(umat, (1, nband, nband))
2771 10148 : umat(1,:,:) = r_ovlp
2772 : end if
2773 :
2774 32 : ABI_FREE(r_ovlp)
2775 :
2776 : else
2777 : ! 1) Calculate O_ij = <phi_i|S|phi_j> (complex Hermitean)
2778 512 : ABI_MALLOC(c_ovlp, (2, nband, nband))
2779 :
2780 : #ifdef HAVE_LINALG_GEMMT
2781 63948 : c_ovlp = zero
2782 128 : call ZGEMMT("U", "C", "N", nband, npwsp, cone, cg, npwsp, gsc, npwsp, czero, c_ovlp, nband)
2783 : #else
2784 : call abi_zgemm_2r("C", "N", nband, nband, npwsp, cone, cg, npwsp, gsc, npwsp, czero, c_ovlp, nband)
2785 : #endif
2786 :
2787 : ! Sum the overlap if PW are distributed.
2788 128 : if (comm_pw /= xmpi_comm_self) call xmpi_sum(c_ovlp, comm_pw, ierr)
2789 : !
2790 : ! 2) Cholesky factorization: O = U^H U with U upper triangle matrix.
2791 128 : call ZPOTRF('U', nband, c_ovlp, nband, ierr)
2792 128 : ABI_CHECK(ierr == 0, sjoin('ZPOTRF returned info:', itoa(ierr)))
2793 :
2794 : ! 3) Solve X U = cg.
2795 128 : call ZTRSM('R', 'U', 'N', 'N', npwsp, nband, cone, c_ovlp, nband, cg, npwsp)
2796 :
2797 : ! 4) Solve Y U = gsc. On exit <cg|gsc> = 1
2798 128 : call ZTRSM('R', 'U', 'N', 'N', npwsp, nband, cone, c_ovlp, nband, gsc, npwsp)
2799 :
2800 128 : if (present(umat)) then
2801 384 : ABI_REMALLOC(umat, (2, nband, nband))
2802 64076 : umat = c_ovlp
2803 : end if
2804 :
2805 128 : ABI_FREE(c_ovlp)
2806 : end if
2807 :
2808 : !call cgpaw_normalize(npwsp, nband, cg, gsc, istwfk, me_g0, comm_pw)
2809 :
2810 160 : end subroutine cgpaw_cholesky
2811 : !!***
2812 :
2813 : !----------------------------------------------------------------------
2814 :
2815 : !!****f* m_cgtools/cgnc_normalize
2816 : !! NAME
2817 : !! cgnc_normalize
2818 : !!
2819 : !! FUNCTION
2820 : !!
2821 : !! INPUTS
2822 : !! npwsp=Size of each vector (usually npw*nspinor)
2823 : !! nband=Number of vectors in icg1
2824 : !!
2825 : !! SIDE EFFECTS
2826 : !!
2827 : !! SOURCE
2828 :
2829 1719 : subroutine cgnc_normalize(npwsp, nband, cg, istwfk, me_g0, comm_pw)
2830 :
2831 : !Arguments ------------------------------------
2832 : !scalars
2833 : integer,intent(in) :: npwsp,nband,istwfk,me_g0,comm_pw
2834 : !arrays
2835 : real(dp),intent(inout) :: cg(2*npwsp*nband)
2836 :
2837 : !Local variables ------------------------------
2838 : !scalars
2839 : integer :: ptr,ierr,band
2840 : !character(len=500) :: msg
2841 : !arrays
2842 3438 : real(dp) :: norm(nband),alpha(2)
2843 : ! *************************************************************************
2844 :
2845 : !$OMP PARALLEL DO PRIVATE(ptr) IF (nband > 1)
2846 31727 : do band=1,nband
2847 30008 : ptr = 1 + 2*npwsp*(band-1)
2848 30008 : norm(band) = cg_dznrm2(npwsp, cg(ptr))
2849 31727 : norm(band) = norm(band) ** 2
2850 : !norm(band) = cg_real_zdotc(npwsp, cg(ptr), cg(ptr))
2851 : end do
2852 :
2853 1719 : if (istwfk > 1) then
2854 10928 : norm = two * norm
2855 560 : if (istwfk == 2 .and. me_g0 == 1) then
2856 : !$OMP PARALLEL DO PRIVATE(ptr) IF (nband >1)
2857 2732 : do band=1,nband
2858 2592 : ptr = 1 + 2*npwsp*(band-1)
2859 2732 : norm(band) = norm(band) - cg(ptr)**2
2860 : end do
2861 : end if
2862 : end if
2863 :
2864 1719 : if (comm_pw /= xmpi_comm_self) call xmpi_sum(norm, comm_pw, ierr)
2865 :
2866 1719 : ierr = 0
2867 31727 : do band=1,nband
2868 31727 : if (norm(band) > zero) then
2869 30008 : norm(band) = SQRT(norm(band))
2870 : else
2871 0 : ierr = ierr + 1
2872 : end if
2873 : end do
2874 :
2875 1719 : if (ierr /= 0) then
2876 0 : ABI_ERROR(sjoin("Found ", itoa(ierr)," vectors with norm <= zero!"))
2877 : end if
2878 :
2879 : !$OMP PARALLEL DO PRIVATE(ptr,alpha) IF (nband > 1)
2880 31727 : do band=1,nband
2881 30008 : ptr = 1 + 2*npwsp*(band-1)
2882 90024 : alpha = [one / norm(band), zero]
2883 31727 : call cg_zscal(npwsp, alpha, cg(ptr))
2884 : end do
2885 :
2886 1719 : end subroutine cgnc_normalize
2887 : !!***
2888 :
2889 : !----------------------------------------------------------------------
2890 :
2891 : !!****f* m_cgtools/cgnc_gsortho
2892 : !! NAME
2893 : !! cgnc_gsortho
2894 : !!
2895 : !! FUNCTION
2896 : !!
2897 : !! INPUTS
2898 : !! npwsp=Size of each vector (usually npw*nspinor)
2899 : !! nband1=Number of vectors in icg1
2900 : !! nband1=Number of vectors in cg2
2901 : !! comm_pw=MPI communicator.
2902 : !!
2903 : !! SIDE EFFECTS
2904 : !! cg2(2*npwsp*nband2)
2905 : !! icg1(2*npwsp*nband1)
2906 : !! input: Input set of vectors.
2907 : !! output: Orthonormalized set.
2908 : !!
2909 : !! SOURCE
2910 :
2911 0 : subroutine cgnc_gsortho(npwsp, nband1, icg1, nband2, iocg2, istwfk, normalize, me_g0, comm_pw)
2912 :
2913 : !Arguments ------------------------------------
2914 : !scalars
2915 : integer,intent(in) :: npwsp,nband1,nband2,istwfk,me_g0
2916 : integer,optional,intent(in) :: comm_pw
2917 : logical,intent(in) :: normalize
2918 : !arrays
2919 : real(dp),intent(in) :: icg1(2*npwsp*nband1)
2920 : real(dp),intent(inout) :: iocg2(2*npwsp*nband2)
2921 :
2922 : !Local variables ------------------------------
2923 : !scalars
2924 : integer :: ierr,b1,b2
2925 : !arrays
2926 0 : real(dp) :: r_icg1(nband1),r_iocg2(nband2)
2927 : real(dp),allocatable :: proj(:,:,:)
2928 : ! *************************************************************************
2929 :
2930 0 : ABI_MALLOC(proj, (2, nband1, nband2))
2931 : !proj = zero
2932 :
2933 : ! 1) Calculate <cg1|cg2>
2934 0 : call cg_zgemm("C", "N", npwsp, nband1, nband2, icg1, iocg2, proj)
2935 :
2936 0 : if (istwfk>1) then
2937 : ! nspinor is always 1 in this case.
2938 : ! Account for the missing G and set the imaginary part to zero since wavefunctions are real.
2939 0 : proj(1,:,:) = two * proj(1,:,:)
2940 0 : proj(2,:,:) = zero
2941 : !
2942 0 : if (istwfk==2 .and. me_g0==1) then
2943 : ! Extract the real part at G=0 and subtract its contribution.
2944 0 : call dcopy(nband1,icg1, 2*npwsp,r_icg1, 1)
2945 0 : call dcopy(nband2,iocg2,2*npwsp,r_iocg2,1)
2946 0 : do b2=1,nband2
2947 0 : do b1=1,nband1
2948 0 : proj(1,b1,b2) = proj(1,b1,b2) - r_icg1(b1) * r_iocg2(b2)
2949 : end do
2950 : end do
2951 : end if
2952 : !
2953 : end if
2954 : !
2955 : ! This is for the MPI version
2956 0 : if (comm_pw /= xmpi_comm_self) call xmpi_sum(proj,comm_pw,ierr)
2957 :
2958 : ! 2) cg2 = cg2 - <cg1|cg2> cg1
2959 0 : call cg_zgemm("N","N",npwsp,nband1,nband2,icg1,proj,iocg2,alpha=-cg_cone,beta=cg_cone)
2960 :
2961 0 : ABI_FREE(proj)
2962 :
2963 : ! 3) Normalize iocg2 if required.
2964 0 : if (normalize) call cgnc_normalize(npwsp,nband2,iocg2,istwfk,me_g0,comm_pw)
2965 :
2966 0 : end subroutine cgnc_gsortho
2967 : !!***
2968 :
2969 : !----------------------------------------------------------------------
2970 :
2971 : !!****f* m_cgtools/cgnc_gramschmidt
2972 : !! NAME
2973 : !! cgnc_grortho
2974 : !!
2975 : !! FUNCTION
2976 : !! Gram-Schmidt orthonormalization of the vectors stored in cg
2977 : !!
2978 : !! INPUTS
2979 : !! npwsp=Size of each vector (usually npw*nspinor)
2980 : !! nband=Number of band in cg
2981 : !! istwfk=Storage mode for the wavefunctions. 1 for standard full mode
2982 : !! me_g0=1 if this node has G=0.
2983 : !! comm_pw=MPI communicator for the planewave group. Set to xmpi_comm_self for sequential mode.
2984 : !!
2985 : !! SIDE EFFECTS
2986 : !! cg(2*npwsp*nband)
2987 : !! input: Input set of vectors.
2988 : !! output: Orthonormalized set.
2989 : !!
2990 : !! SOURCE
2991 :
2992 0 : subroutine cgnc_gramschmidt(npwsp, nband, cg, istwfk, me_g0, comm_pw)
2993 :
2994 : !Arguments ------------------------------------
2995 : !scalars
2996 : integer,intent(in) :: npwsp, nband, istwfk, comm_pw, me_g0
2997 : !arrays
2998 : real(dp),intent(inout) :: cg(2*npwsp*nband)
2999 :
3000 : !Local variables ------------------------------
3001 : !scalars
3002 : integer :: b1,nb2,opt
3003 : logical :: normalize
3004 : ! *************************************************************************
3005 :
3006 : ! Normalize the first vector.
3007 0 : call cgnc_normalize(npwsp,1,cg(1),istwfk,me_g0,comm_pw)
3008 0 : if (nband == 1) RETURN
3009 :
3010 : ! Orthogonaluze b1 wrt to the bands in [1,b1-1].
3011 0 : normalize = .TRUE.
3012 0 : do b1=2,nband
3013 0 : opt = 1 + 2*npwsp*(b1-1)
3014 0 : nb2=b1-1
3015 0 : call cgnc_gsortho(npwsp,nb2,cg(1),1,cg(opt),istwfk,normalize,me_g0,comm_pw)
3016 : end do
3017 :
3018 : end subroutine cgnc_gramschmidt
3019 : !!***
3020 :
3021 : !----------------------------------------------------------------------
3022 :
3023 : !!****f* m_cgtools/cgpaw_normalize
3024 : !! NAME
3025 : !! cgpaw_normalize
3026 : !!
3027 : !! FUNCTION
3028 : !! Normalize a set of PAW pseudo wavefunctions.
3029 : !!
3030 : !! INPUTS
3031 : !! npwsp=Size of each vector (usually npw*nspinor)
3032 : !! nband=Number of band in cg and gsc
3033 : !! istwfk=Storage mode for the wavefunctions. 1 for standard full mode
3034 : !! me_g0=1 if this node has G=0.
3035 : !! comm_pw=MPI communicator for the planewave group. Set to xmpi_comm_self for sequential mode.
3036 : !!
3037 : !! SIDE EFFECTS
3038 : !! cg(2*npwsp*nband)
3039 : !! input: Input set of vectors |C>
3040 : !! output: Normalized set such as <C|S|C> = 1
3041 : !! gsc(2*npwsp*nband)
3042 : !! input: Input set of vectors S|C>
3043 : !! output: New S|C> compute with the new |C>
3044 : !!
3045 : !! SOURCE
3046 :
3047 991 : subroutine cgpaw_normalize(npwsp, nband, cg, gsc, istwfk, me_g0, comm_pw)
3048 :
3049 : !Arguments ------------------------------------
3050 : !scalars
3051 : integer,intent(in) :: npwsp, nband, istwfk, me_g0, comm_pw
3052 : !arrays
3053 : real(dp),intent(inout) :: cg(2*npwsp*nband), gsc(2*npwsp*nband)
3054 :
3055 : !Local variables ------------------------------
3056 : !scalars
3057 : integer :: ptr,ierr,band
3058 : character(len=500) :: msg
3059 : !arrays
3060 1982 : real(dp) :: norm(nband),alpha(2)
3061 : ! *************************************************************************
3062 :
3063 : !$OMP PARALLEL DO PRIVATE(ptr) IF (nband > 1)
3064 8631 : do band=1,nband
3065 7640 : ptr = 1 + 2*npwsp*(band-1)
3066 8631 : norm(band) = cg_real_zdotc(npwsp, gsc(ptr), cg(ptr))
3067 : end do
3068 :
3069 991 : if (istwfk>1) then
3070 2187 : norm = two * norm
3071 255 : if (istwfk==2 .and. me_g0==1) then
3072 : !$OMP PARALLEL DO PRIVATE(ptr) IF (nband > 1)
3073 711 : do band=1,nband
3074 628 : ptr = 1 + 2*npwsp*(band-1)
3075 711 : norm(band) = norm(band) - gsc(ptr) * cg(ptr)
3076 : end do
3077 : end if
3078 : end if
3079 :
3080 991 : if (comm_pw /= xmpi_comm_self) call xmpi_sum(norm, comm_pw, ierr)
3081 :
3082 991 : ierr = 0
3083 8631 : do band=1,nband
3084 8631 : if (norm(band) > zero) then
3085 7640 : norm(band) = SQRT(norm(band))
3086 : else
3087 0 : ierr = ierr + 1
3088 : end if
3089 : end do
3090 :
3091 991 : if (ierr/=0) then
3092 0 : write(msg,'(a,i0,a)')" Found ",ierr," vectors with norm <= zero!"
3093 0 : ABI_ERROR(msg)
3094 : end if
3095 :
3096 : ! Scale |C> and S|C>.
3097 : !$OMP PARALLEL DO PRIVATE(ptr,alpha) IF (nband > 1)
3098 8631 : do band=1,nband
3099 7640 : ptr = 1 + 2*npwsp*(band-1)
3100 22920 : alpha = [one / norm(band), zero]
3101 7640 : call cg_zscal(npwsp, alpha, cg(ptr))
3102 8631 : call cg_zscal(npwsp, alpha, gsc(ptr))
3103 : end do
3104 :
3105 991 : end subroutine cgpaw_normalize
3106 : !!***
3107 :
3108 : !----------------------------------------------------------------------
3109 :
3110 : !!****f* m_cgtools/cgpaw_gsortho
3111 : !! NAME
3112 : !! cgpaw_gsortho
3113 : !!
3114 : !! FUNCTION
3115 : !! This routine uses the Gram-Schmidt method to orthogonalize a set of PAW wavefunctions.
3116 : !! with respect to an input block of states.
3117 : !!
3118 : !! INPUTS
3119 : !! npwsp=Size of each vector (usually npw*nspinor)
3120 : !! nband1=Number of vectors in the input block icg1
3121 : !! icg1(2*npwsp*nband1)=Input block of vectors.
3122 : !! igsc1(2*npwsp*nband1)= S|C> for C in icg1.
3123 : !! nband2=Number of vectors to orthogonalize
3124 : !! normalize=True if output wavefunction must be normalized.
3125 : !! istwfk=Storage mode for the wavefunctions. 1 for standard full mode
3126 : !! me_g0=1 if this node has G=0.
3127 : !! comm_pw=MPI communicator for the planewave group. Set to xmpi_comm_self for sequential mode.
3128 : !!
3129 : !! SIDE EFFECTS
3130 : !! iocg2(2*npwsp*nband2), iogsc2(2*npwsp*nband1)
3131 : !! input: set of |C> and S|C> where |C> is the set of states to orthogonalize
3132 : !! output: Orthonormalized set.
3133 : !!
3134 : !! SOURCE
3135 :
3136 0 : subroutine cgpaw_gsortho(npwsp, nband1, icg1, igsc1, nband2, iocg2, iogsc2, istwfk, normalize, me_g0, comm_pw)
3137 :
3138 : !Arguments ------------------------------------
3139 : !scalars
3140 : integer,intent(in) :: npwsp, nband1, nband2, istwfk, me_g0
3141 : integer,optional,intent(in) :: comm_pw
3142 : logical,intent(in) :: normalize
3143 : !arrays
3144 : real(dp),intent(in) :: icg1(2*npwsp*nband1),igsc1(2*npwsp*nband1)
3145 : real(dp),intent(inout) :: iocg2(2*npwsp*nband2),iogsc2(2*npwsp*nband2)
3146 :
3147 : !Local variables ------------------------------
3148 : !scalars
3149 : integer :: ierr,b1,b2
3150 : !arrays
3151 0 : real(dp) :: r_icg1(nband1),r_iocg2(nband2)
3152 : real(dp),allocatable :: proj(:,:,:)
3153 : ! *************************************************************************
3154 :
3155 0 : ABI_MALLOC(proj,(2,nband1,nband2))
3156 :
3157 : ! 1) Calculate <cg1|cg2>
3158 0 : call cg_zgemm("C","N",npwsp,nband1,nband2,igsc1,iocg2,proj)
3159 :
3160 0 : if (istwfk>1) then
3161 : ! nspinor is always 1 in this case.
3162 : ! Account for the missing G and set the imaginary part to zero since wavefunctions are real.
3163 0 : proj(1,:,:) = two * proj(1,:,:)
3164 0 : proj(2,:,:) = zero
3165 : !
3166 0 : if (istwfk==2 .and. me_g0==1) then
3167 : ! Extract the real part at G=0 and subtract its contribution.
3168 0 : call dcopy(nband1,igsc1,2*npwsp,r_icg1, 1)
3169 0 : call dcopy(nband2,iocg2,2*npwsp,r_iocg2,1)
3170 0 : do b2=1,nband2
3171 0 : do b1=1,nband1
3172 0 : proj(1,b1,b2) = proj(1,b1,b2) - r_icg1(b1) * r_iocg2(b2)
3173 : end do
3174 : end do
3175 : end if
3176 :
3177 : end if
3178 :
3179 : ! This is for the MPI version
3180 0 : if (comm_pw /= xmpi_comm_self) call xmpi_sum(proj,comm_pw,ierr)
3181 :
3182 : ! 2)
3183 : ! cg2 = cg2 - <Scg1|cg2> cg1
3184 : ! S cg2 = S cg2 - <Scg1|cg2> S cg1
3185 0 : call cg_zgemm("N","N",npwsp,nband1,nband2,icg1,proj,iocg2,alpha=-cg_cone,beta=cg_cone)
3186 0 : call cg_zgemm("N","N",npwsp,nband1,nband2,igsc1,proj,iogsc2,alpha=-cg_cone,beta=cg_cone)
3187 :
3188 0 : ABI_FREE(proj)
3189 :
3190 : ! 3) Normalize iocg2 and iogsc2 if required.
3191 0 : if (normalize) call cgpaw_normalize(npwsp, nband2, iocg2, iogsc2, istwfk, me_g0, comm_pw)
3192 :
3193 0 : end subroutine cgpaw_gsortho
3194 : !!***
3195 :
3196 : !----------------------------------------------------------------------
3197 :
3198 : !!****f* m_cgtools/cgpaw_gramschmidt
3199 : !! NAME
3200 : !! cgpaw_gramschmidt
3201 : !!
3202 : !! FUNCTION
3203 : !! Gram-Schmidt orthonormalization of the vectors stored in cg
3204 : !!
3205 : !! INPUTS
3206 : !! npwsp=Size of each vector (usually npw*nspinor)
3207 : !! nband=Number of bands in cg
3208 : !! istwfk=Storage mode for the wavefunctions. 1 for standard full mode
3209 : !! me_g0=1 if this node has G=0.
3210 : !! comm_pw=MPI communicator for the planewave group. Set to xmpi_comm_self for sequential mode.
3211 : !!
3212 : !! SIDE EFFECTS
3213 : !! cg(2*npwsp*nband), gsc(2*npwsp*nband)
3214 : !! input: Input set of vectors.
3215 : !! output: Orthonormalized set.
3216 : !!
3217 : !! SOURCE
3218 :
3219 0 : subroutine cgpaw_gramschmidt(npwsp, nband, cg, gsc, istwfk, me_g0, comm_pw)
3220 :
3221 : !Arguments ------------------------------------
3222 : !scalars
3223 : integer,intent(in) :: npwsp,nband,istwfk,comm_pw,me_g0
3224 : !arrays
3225 : real(dp),intent(inout) :: cg(2*npwsp*nband),gsc(2*npwsp*nband)
3226 :
3227 : !Local variables ------------------------------
3228 : !scalars
3229 : integer :: b1,nb2,opt
3230 : logical :: normalize
3231 : ! *************************************************************************
3232 :
3233 : ! Normalize the first vector.
3234 0 : call cgpaw_normalize(npwsp,1,cg(1),gsc(1),istwfk,me_g0,comm_pw)
3235 0 : if (nband == 1) RETURN
3236 :
3237 : ! Orthogonalize b1 wrt to the bands in [1,b1-1].
3238 0 : normalize = .TRUE.
3239 0 : do b1=2,nband
3240 0 : opt = 1 + 2*npwsp*(b1-1)
3241 0 : nb2=b1-1
3242 0 : call cgpaw_gsortho(npwsp,nb2,cg(1),gsc(1),1,cg(opt),gsc(opt),istwfk,normalize,me_g0,comm_pw)
3243 : end do
3244 :
3245 : end subroutine cgpaw_gramschmidt
3246 : !!***
3247 :
3248 : !----------------------------------------------------------------------
3249 :
3250 : !!****f* m_cgtools/projbd
3251 : !!
3252 : !! NAME
3253 : !! projbd
3254 : !!
3255 : !! FUNCTION
3256 : !! Project out vector "direc" onto the bands contained in "cg".
3257 : !! if useoverlap==0
3258 : !! New direc=direc-$sum_{j/=i} { <cg_{j}|direc>.|cg_{j}> }$
3259 : !! if useoverlap==1 (use of overlap matrix S)
3260 : !! New direc=direc-$sum_{j/=i} { <cg_{j}|S|direc>.|cg_{j}> }$
3261 : !! (index i can be set to -1 to sum over all bands)
3262 : !!
3263 : !! INPUTS
3264 : !! cg(2,mcg)=wavefunction coefficients for ALL bands
3265 : !! iband0=which particular band we are interested in ("i" in the above formula)
3266 : !! Can be set to -1 to sum over all bands...
3267 : !! icg=shift to be given to the location of the data in cg
3268 : !! iscg=shift to be given to the location of the data in scg
3269 : !! istwf_k=option parameter that describes the storage of wfs
3270 : !! mcg=maximum size of second dimension of cg
3271 : !! mscg=maximum size of second dimension of scg
3272 : !! nband=number of bands
3273 : !! npw=number of planewaves
3274 : !! nspinor=number of spinorial components (on current proc)
3275 : !! scg(2,mscg*useoverlap)=<G|S|band> for ALL bands,
3276 : !! where S is an overlap matrix
3277 : !! scprod_io=0 if scprod array has to be computed; 1 if it is input (already in memory)
3278 : !! tim_projbd=timing code of the calling subroutine(can be set to 0 if not attributed)
3279 : !! useoverlap=describe the overlap of wavefunctions:
3280 : !! 0: no overlap (S=Identity_matrix)
3281 : !! 1: wavefunctions are overlapping
3282 : !! me_g0=1 if this processors treats G=0, 0 otherwise.
3283 : !! comm=MPI communicator (used if G vectors are distributed.
3284 : !!
3285 : !! SIDE EFFECTS
3286 : !! direc(2,npw)= input: vector to be orthogonalised with respect to cg (and S)
3287 : !! output: vector that has been orthogonalized wrt cg (and S)
3288 : !!
3289 : !! scprod(2,nband)=scalar_product
3290 : !! if useoverlap==0: scalar_product_i=$<cg_{j}|direc_{i}>$
3291 : !! if useoverlap==1: scalar_product_i=$<cg_{j}|S|direc_{i}>$
3292 : !! if scprod_io=0, scprod is output
3293 : !! if scprod_io=1, scprod is input
3294 : !!
3295 : !! NOTES
3296 : !! 1) MPIWF Might have to be recoded for efficient parallelism
3297 : !!
3298 : !! 2) The new version employs BLAS2 routine so that the OMP parallelism is delegated to BLAS library.
3299 : !! May use BLAS3 if multiple wavefunctions are optimized at the same time.
3300 : !!
3301 : !! 3) Note for PAW: ref.= PRB 73, 235101 (2006) [[cite:Audouze2006]], equations (71) and (72):
3302 : !! in normal use, projbd applies P_c projector
3303 : !! if cg and scg are inverted, projbd applies P_c+ projector
3304 : !!
3305 : !! 4) cg_zgemv wraps ZGEMM whose implementation is more efficient, especially in the threaded case.
3306 : !!
3307 : !! SOURCE
3308 :
3309 58071159 : subroutine projbd(cg,direc,iband0,icg,iscg,istwf_k,mcg,mscg,nband,&
3310 58071159 : npw,nspinor,scg,scprod,scprod_io,tim_projbd,useoverlap,me_g0,comm,gpu_option)
3311 :
3312 : !Arguments ------------------------------------
3313 : !scalars
3314 : integer,intent(in) :: iband0,icg,iscg,istwf_k,mcg,mscg,nband,npw,nspinor
3315 : integer,intent(in) :: scprod_io,tim_projbd,useoverlap,me_g0,comm
3316 : integer,optional,intent(in) :: gpu_option
3317 : !arrays
3318 : real(dp),intent(in) :: cg(2,mcg),scg(2,mscg*useoverlap)
3319 : real(dp),intent(inout) :: direc(2,npw*nspinor)
3320 : real(dp),intent(inout) :: scprod(2,nband)
3321 :
3322 : !Local variables-------------------------------
3323 : !scalars
3324 : integer :: nbandm,npw_sp,ierr, my_gpu_option
3325 : !arrays
3326 : real(dp) :: tsec(2),bkp_scprod(2),bkp_dirg0(2)
3327 : ! *************************************************************************
3328 :
3329 58071159 : call timab(210+tim_projbd,1,tsec)
3330 :
3331 58071159 : my_gpu_option = ABI_GPU_DISABLED; if (present(gpu_option)) my_gpu_option = gpu_option
3332 :
3333 58071159 : npw_sp=npw*nspinor
3334 :
3335 58071159 : nbandm=nband
3336 :
3337 58071159 : if (istwf_k==1) then
3338 :
3339 56820618 : if (scprod_io==0) then
3340 56505386 : if (useoverlap==1) then
3341 8866568 : call cg_zgemv("C",npw_sp,nbandm,scg(1,iscg+1),direc,scprod,gpu_option=my_gpu_option)
3342 : else
3343 47638818 : call cg_zgemv("C",npw_sp,nbandm,cg(1,icg+1), direc,scprod,gpu_option=my_gpu_option)
3344 : end if
3345 56505386 : call xmpi_sum(scprod,comm,ierr)
3346 : end if
3347 :
3348 56820618 : if (iband0>0.and.iband0<=nbandm) then
3349 : #ifdef HAVE_OPENMP_OFFLOAD
3350 : !$OMP TARGET MAP(to:bkp_scprod,scprod) IF(my_gpu_option==ABI_GPU_OPENMP)
3351 : #endif
3352 4926 : bkp_scprod(:) = scprod(:,iband0)
3353 4926 : scprod(:,iband0) = zero
3354 : #ifdef HAVE_OPENMP_OFFLOAD
3355 : !$OMP END TARGET
3356 : #endif
3357 : end if
3358 :
3359 56820618 : call cg_zgemv("N",npw_sp,nbandm,cg(1,icg+1),scprod,direc,alpha=-cg_cone,beta=cg_cone,gpu_option=my_gpu_option)
3360 :
3361 56820618 : if (iband0>0.and.iband0<=nbandm) then
3362 : ! Restore previous value as scprod is output.
3363 : #ifdef HAVE_OPENMP_OFFLOAD
3364 : !$OMP TARGET MAP(to:bkp_scprod,scprod) IF(my_gpu_option==ABI_GPU_OPENMP)
3365 : #endif
3366 4926 : scprod(:,iband0) = bkp_scprod(:)
3367 : #ifdef HAVE_OPENMP_OFFLOAD
3368 : !$OMP END TARGET
3369 : #endif
3370 : end if
3371 :
3372 1250541 : else if (istwf_k>=2) then
3373 1250541 : if(my_gpu_option/=ABI_GPU_DISABLED) ABI_BUG("Use case not handled with OpenMP GPU (use_gpu_cuda==2)")
3374 : !
3375 : ! u_{G0/2}(G) = u_{G0/2}(-G-G0)^*; k = G0/2
3376 : ! hence:
3377 : ! sum_G f*(G) g(G) = 2 REAL sum_G^{IZONE} w(G) f*(G)g(G)
3378 : ! where
3379 : ! w(G) = 1 except for k=0 and G=0 where w(G=0) = 1/2.
3380 : !
3381 1250541 : if (scprod_io==0) then
3382 :
3383 1250541 : if (useoverlap==1) then
3384 :
3385 272349 : if (istwf_k==2 .and. me_g0==1) then
3386 333504 : bkp_dirg0 = direc(:,1)
3387 111168 : direc(1,1) = half * direc(1,1)
3388 111168 : direc(2,1) = zero
3389 : end if
3390 :
3391 272349 : call cg_zgemv("C",npw_sp,nbandm,scg(1,iscg+1),direc,scprod,gpu_option=my_gpu_option)
3392 22617195 : scprod = two * scprod
3393 7720631 : scprod(2,:) = zero
3394 :
3395 605853 : if(istwf_k==2 .and. me_g0==1) direc(:,1) = bkp_dirg0
3396 :
3397 : else
3398 :
3399 978192 : if (istwf_k==2 .and. me_g0==1) then
3400 1494270 : bkp_dirg0 = direc(:,1)
3401 498090 : direc(1,1) = half * direc(1,1)
3402 498090 : direc(2,1) = zero
3403 : end if
3404 :
3405 978192 : call cg_zgemv("C",npw_sp,nbandm,cg(1,icg+1),direc,scprod,gpu_option=my_gpu_option)
3406 52301952 : scprod = two * scprod
3407 18086112 : scprod(2,:) = zero
3408 :
3409 2472462 : if (istwf_k==2 .and. me_g0==1) direc(:,1) = bkp_dirg0
3410 : end if ! useoverlap
3411 :
3412 1250541 : call xmpi_sum(scprod,comm,ierr)
3413 : end if
3414 :
3415 1250541 : if (iband0>0.and.iband0<=nbandm) then
3416 0 : bkp_scprod = scprod(:,iband0)
3417 0 : scprod(:,iband0) = zero
3418 : end if
3419 :
3420 1250541 : call cg_zgemv("N",npw_sp,nbandm,cg(1,icg+1),scprod,direc,alpha=-cg_cone,beta=cg_cone,gpu_option=my_gpu_option)
3421 :
3422 1250541 : if (iband0>0.and.iband0<=nbandm) scprod(:,iband0) = bkp_scprod ! Restore previous value as scprod is output.
3423 :
3424 : end if ! Test on istwf_k
3425 :
3426 58071159 : call timab(210+tim_projbd,2,tsec)
3427 :
3428 58071159 : end subroutine projbd
3429 : !!***
3430 :
3431 : !----------------------------------------------------------------------
3432 :
3433 : !!****f* m_cgtools/cg_envlop
3434 : !!
3435 : !! NAME
3436 : !! cg_envlop
3437 : !!
3438 : !! FUNCTION
3439 : !! Multiply random number values in cg by envelope function to lower initial kinetic energy.
3440 : !! Envelope $\left( 1-\left( G/G_{\max }\right) ^2\right) ^{power}$ for |G|<= Gmax.
3441 : !! Near G=0, little scaling, and goes to zero flatly near Gmax.
3442 : !!
3443 : !! INPUTS
3444 : !! cg(2,mcg)=initial random number wavefunctions
3445 : !! ecut=kinetic energy cutoff in Ha
3446 : !! gmet(3,3)=reciprocal space metric (bohr^-2)
3447 : !! icgmod=shift to be given to the location of data in cg
3448 : !! kg(3,npw)=reduced coordinates of G vectors in basis sphere
3449 : !! kpoint(3)=reduced coordinates of k point
3450 : !! mcg=maximum second dimension of cg (at least npw*nband*nspinor)
3451 : !! nband=number of bands being considered
3452 : !! npw=number of planewaves in basis sphere
3453 : !! nspinor=number of spinorial components of the wavefunctions
3454 : !!
3455 : !! OUTPUT
3456 : !! cg(2,mcg)=revised values (not orthonormalized)
3457 : !!
3458 : !! SOURCE
3459 :
3460 38538 : subroutine cg_envlop(cg, ecut, gmet, icgmod, kg, kpoint, mcg, nband, npw, nspinor)
3461 :
3462 : !Arguments ------------------------------------
3463 : !scalars
3464 : integer,intent(in) :: icgmod,mcg,nband,npw,nspinor
3465 : real(dp),intent(in) :: ecut
3466 : !arrays
3467 : integer,intent(in) :: kg(3,npw)
3468 : real(dp),intent(in) :: gmet(3,3),kpoint(3)
3469 : real(dp),intent(inout) :: cg(2,mcg)
3470 :
3471 : !Local variables-------------------------------
3472 : !scalars
3473 : integer,parameter :: re=1,im=2,power=12
3474 : integer :: i1,i2,i3,ig,igs,ispinor,nn,spad
3475 : real(dp) :: cutoff,gs,kpgsqc
3476 : !character(len=500) :: msg
3477 : !arrays
3478 38538 : real(dp),allocatable :: cut_pws(:)
3479 : ! *************************************************************************
3480 :
3481 : !$(k+G)^2$ cutoff from $(1/2)(2 Pi (k+G))^2 = ecut$
3482 38538 : kpgsqc=ecut/(2.0_dp*pi**2)
3483 38538 : cutoff = kpgsqc
3484 :
3485 115614 : ABI_MALLOC(cut_pws,(npw))
3486 :
3487 : !Run through G vectors in basis
3488 : !$OMP PARALLEL DO PRIVATE(gs,i1,i2,i3)
3489 8121709 : do ig=1,npw
3490 8083171 : i1=kg(1,ig) ; i2=kg(2,ig) ; i3=kg(3,ig)
3491 : !(k+G)^2 evaluated using metric and kpoint
3492 : gs = gmet(1,1)*(kpoint(1)+dble(i1))**2+&
3493 : & gmet(2,2)*(kpoint(2)+dble(i2))**2+&
3494 : & gmet(3,3)*(kpoint(3)+dble(i3))**2+&
3495 : & 2.0_dp*(gmet(2,1)*(kpoint(2)+dble(i2))*(kpoint(1)+dble(i1))+&
3496 : & gmet(3,2)*(kpoint(3)+dble(i3))*(kpoint(2)+dble(i2))+&
3497 8083171 : & gmet(1,3)*(kpoint(1)+dble(i1))*(kpoint(3)+dble(i3)))
3498 8121709 : if (gs>cutoff) then
3499 152828 : cut_pws(ig) = zero
3500 : else
3501 7930343 : cut_pws(ig) = (1.0_dp-(gs/cutoff))**power
3502 : end if
3503 : end do
3504 :
3505 : !Run through bands (real and imaginary components)
3506 : !$OMP PARALLEL DO PRIVATE(spad,igs)
3507 291454 : do nn=1,nband
3508 252916 : spad = (nn-1)*npw*nspinor+icgmod
3509 568930 : do ispinor=1,nspinor
3510 71952933 : do ig=1,npw
3511 71422541 : igs=ig+(ispinor-1)*npw
3512 71422541 : cg(1,igs+spad) = cg(1,igs+spad) * cut_pws(ig)
3513 71700017 : cg(2,igs+spad) = cg(2,igs+spad) * cut_pws(ig)
3514 : end do
3515 : end do
3516 : end do
3517 :
3518 38538 : ABI_FREE(cut_pws)
3519 :
3520 38538 : end subroutine cg_envlop
3521 : !!***
3522 :
3523 : !----------------------------------------------------------------------
3524 :
3525 : !!****f* m_cgtools/cg_normev
3526 : !! NAME
3527 : !! cg_normev
3528 : !!
3529 : !! FUNCTION
3530 : !! Normalize a set of nband eigenvectors of complex length npw
3531 : !! (real length 2*npw) and set phases to make cg(i,i) real and positive.
3532 : !! Near convergence, cg(i,j) approaches delta(i,j).
3533 : !!
3534 : !! INPUTS
3535 : !! cg(2*npw,nband)=unnormalized eigenvectors
3536 : !! npw=dimension of cg as shown
3537 : !! nband=number of eigenvectors and complex length thereof.
3538 : !!
3539 : !! OUTPUT
3540 : !! cg(2*npw,nband)=nband normalized eigenvectors
3541 : !!
3542 : !! SOURCE
3543 :
3544 445643 : subroutine cg_normev(cg, npw, nband)
3545 :
3546 : !Arguments ------------------------------------
3547 : !scalars
3548 : integer,intent(in) :: npw,nband
3549 : !arrays
3550 : real(dp),intent(inout) :: cg(2*npw,nband)
3551 :
3552 : !Local variables-------------------------------
3553 : !scalars
3554 : integer :: ii,jj
3555 : real(dp) :: den,evim,evre,phim,phre,xnorm
3556 : character(len=500) :: msg
3557 : ! *************************************************************************
3558 :
3559 : !Loop over vectors
3560 3634626 : do ii=1,nband
3561 : ! find norm
3562 3188983 : xnorm=0.0d0
3563 119926157 : do jj=1,2*npw
3564 119926157 : xnorm=xnorm+cg(jj,ii)**2
3565 : end do
3566 :
3567 3188983 : if((xnorm-one)**2>tol6)then
3568 0 : write(msg,'(6a,i6,a,es16.6,3a)' )ch10,&
3569 0 : 'normev: ',ch10,&
3570 0 : 'Starting xnorm should be close to one (tol is tol6).',ch10,&
3571 0 : 'However, for state number',ii,', xnorm=',xnorm,ch10,&
3572 0 : 'It might be that your LAPACK library has not been correctly installed.'
3573 0 : ABI_BUG(msg)
3574 : end if
3575 :
3576 3188983 : xnorm=1.0d0/sqrt(xnorm)
3577 : ! Set up phase
3578 3188983 : phre=cg(2*ii-1,ii)
3579 3188983 : phim=cg(2*ii,ii)
3580 3188983 : if (phim/=0.0d0) then
3581 2527414 : den=1.0d0/sqrt(phre**2+phim**2)
3582 2527414 : phre=phre*xnorm*den
3583 2527414 : phim=phim*xnorm*den
3584 : else
3585 : ! give xnorm the same sign as phre (negate if negative)
3586 661569 : phre=sign(xnorm,phre)
3587 661569 : phim=0.0d0
3588 : end if
3589 : ! normalize with phase change
3590 3634626 : do jj=1,2*npw,2
3591 58368587 : evre=cg(jj,ii)
3592 58368587 : evim=cg(jj+1,ii)
3593 58368587 : cg(jj,ii)=phre*evre+phim*evim
3594 58368587 : cg(jj+1,ii)=phre*evim-phim*evre
3595 : end do
3596 : end do
3597 :
3598 445643 : end subroutine cg_normev
3599 : !!***
3600 :
3601 : !----------------------------------------------------------------------
3602 :
3603 : !!****f* m_cgtools/cg_precon
3604 : !!
3605 : !! NAME
3606 : !! cg_precon
3607 : !!
3608 : !! FUNCTION
3609 : !! precondition <G|(H-e)|C>
3610 : !!
3611 : !! INPUTS
3612 : !! cg(2,npw)=<G|C>.
3613 : !! eval=current band eigenvalue = <C|H|C>.
3614 : !! istwf_k=option parameter that describes the storage of wfs
3615 : !! kinpw(npw)=(modified) kinetic energy for each plane wave (Hartree)
3616 : !! nspinor=number of spinorial components of the wavefunctions
3617 : !! vect(2,npw)=<G|H|C>.
3618 : !! npw=number of planewaves at this k point.
3619 : !! optekin= 1 if the kinetic energy used in preconditionning is modified
3620 : !! according to Kresse, Furthmuller, PRB 54, 11169 (1996) [[cite:Kresse1996]]
3621 : !! 0 otherwise
3622 : !! mg_g0=1 if the node treats G=0.
3623 : !! comm=MPI communicator
3624 : !!
3625 : !! OUTPUT
3626 : !! pcon(npw)=preconditioning matrix
3627 : !! vect(2,npw*nspinor)=<G|(H-eval)|C_{n,k}>*(polynomial ratio)
3628 : !!
3629 : !! SOURCE
3630 :
3631 43550422 : subroutine cg_precon(cg, eval, istwf_k, kinpw, npw, nspinor, me_g0, optekin, pcon, vect, comm)
3632 :
3633 : !Arguments ------------------------------------
3634 : !scalars
3635 : integer,intent(in) :: istwf_k,npw,nspinor,optekin,me_g0,comm
3636 : real(dp),intent(in) :: eval
3637 : !arrays
3638 : real(dp),intent(in) :: cg(2,npw*nspinor),kinpw(npw)
3639 : real(dp),intent(out) :: pcon(npw)
3640 : real(dp),intent(inout) :: vect(2,npw*nspinor)
3641 :
3642 : !Local variables-------------------------------
3643 : !scalars
3644 : integer :: ierr,ig,igs,ipw1,ispinor
3645 : real(dp) :: ek0,ek0_inv,fac,poly,xx
3646 : !character(len=500) :: msg
3647 : !arrays
3648 : real(dp) :: tsec(2)
3649 : ! *************************************************************************
3650 :
3651 : !Compute mean kinetic energy of band
3652 21775211 : if(istwf_k==1)then
3653 21195075 : ek0=zero
3654 43622381 : do ispinor=1,nspinor
3655 22427306 : igs=(ispinor-1)*npw
3656 6432103456 : do ig=1+igs,npw+igs
3657 6410908381 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
3658 6331263585 : ek0=ek0+kinpw(ig-igs)*(cg(1,ig)**2+cg(2,ig)**2)
3659 : end if
3660 : end do
3661 : end do
3662 :
3663 580136 : else if (istwf_k>=2)then
3664 580136 : if (istwf_k==2 .and. me_g0 == 1)then
3665 283976 : ek0=zero ; ipw1=2
3666 283976 : if(kinpw(1)<huge(zero)*1.d-11)ek0=0.5_dp*kinpw(1)*cg(1,1)**2
3667 : else
3668 296160 : ek0=zero ; ipw1=1
3669 : end if
3670 1160272 : do ispinor=1,nspinor
3671 580136 : igs=(ispinor-1)*npw
3672 360203415 : do ig=ipw1+igs,npw+igs
3673 359623279 : if(kinpw(ig)<huge(zero)*1.d-11)then
3674 351941633 : ek0=ek0+kinpw(ig)*(cg(1,ig)**2+cg(2,ig)**2)
3675 : end if
3676 : end do
3677 : end do
3678 580136 : ek0=2.0_dp*ek0
3679 : end if
3680 :
3681 21775211 : call timab(48,1,tsec)
3682 21775211 : call xmpi_sum(ek0,comm,ierr)
3683 21775211 : call timab(48,2,tsec)
3684 :
3685 21775211 : if(ek0<1.0d-10)then
3686 1 : ABI_WARNING('The mean kinetic energy of a wavefunction vanishes. It is reset to 0.1 Ha.')
3687 1 : ek0=0.1_dp
3688 : end if
3689 :
3690 21775211 : if (optekin==1) then
3691 1255439 : ek0_inv=2.0_dp/(3._dp*ek0)
3692 : else
3693 20519772 : ek0_inv=1.0_dp/ek0
3694 : end if
3695 :
3696 : !Carry out preconditioning
3697 44782653 : do ispinor=1,nspinor
3698 23007442 : igs=(ispinor-1)*npw
3699 : !$OMP PARALLEL DO PRIVATE(fac,ig,poly,xx) SHARED(cg,ek0_inv,eval,kinpw,igs,npw,vect,pcon)
3700 6792590847 : do ig=1+igs,npw+igs
3701 6770815636 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
3702 6683489194 : xx=kinpw(ig-igs)*ek0_inv
3703 : ! Teter polynomial ratio
3704 6683489194 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
3705 6683489194 : fac=poly/(poly+16._dp*xx**4)
3706 6683489194 : if (optekin==1) fac=two*fac
3707 6683489194 : pcon(ig-igs)=fac
3708 6683489194 : vect(1,ig)=( vect(1,ig)-eval*cg(1,ig) )*fac
3709 6683489194 : vect(2,ig)=( vect(2,ig)-eval*cg(2,ig) )*fac
3710 : else
3711 64319000 : pcon(ig-igs)=zero
3712 64319000 : vect(1,ig)=zero
3713 64319000 : vect(2,ig)=zero
3714 : end if
3715 : end do
3716 : end do
3717 :
3718 21775211 : end subroutine cg_precon
3719 : !!***
3720 :
3721 : !!****f* m_cgtools/cg_precon_block
3722 : !!
3723 : !! NAME
3724 : !! cg_precon_block
3725 : !!
3726 : !! FUNCTION
3727 : !! precondition $<G|(H-e_{n,k})|C_{n,k}>$ for a block of band (band-FFT parallelisation)
3728 : !! in the case of real WFs (istwfk/=1)
3729 : !!
3730 : !! INPUTS
3731 : !! blocksize= size of blocks of bands
3732 : !! cg(vectsize,blocksize)=<G|C_{n,k}> for a block of bands.
3733 : !! eval(blocksize,blocksize)=current block of bands eigenvalues=<C_{n,k}|H|C_{n,k}>.
3734 : !! ghc(vectsize,blocksize)=<G|H|C_{n,k}> for a block of bands.
3735 : !! iterationnumber=number of iterative minimizations in LOBPCG
3736 : !! kinpw(npw)=(modified) kinetic energy for each plane wave (Hartree)
3737 : !! nspinor=number of spinorial components of the wavefunctions (on current proc)
3738 : !! $vect(vectsize,blocksize)=<G|H|C_{n,k}> for a block of bands$.
3739 : !! npw=number of planewaves at this k point.
3740 : !! optekin= 1 if the kinetic energy used in preconditionning is modified
3741 : !! according to Kresse, Furthmuller, PRB 54, 11169 (1996) [[cite:Kresse1996]]
3742 : !! 0 otherwise
3743 : !! optpcon= 0 the TPA preconditionning matrix does not depend on band
3744 : !! 1 the TPA preconditionning matrix (not modified)
3745 : !! 2 the TPA preconditionning matrix is independent of iteration number
3746 : !! vectsize= size of vectors
3747 : !! mg_g0=1 if this node has Gamma, 0 otherwise.
3748 : !!
3749 : !! OUTPUT
3750 : !! vect(2,npw)=<g|(h-eval)|c_{n,k}>*(polynomial ratio)
3751 : !!
3752 : !! SIDE EFFECTS
3753 : !! pcon(npw,blocksize)=preconditionning matrix
3754 : !! input if optpcon=0,2 and iterationnumber/=1
3755 : !! output if optpcon=0,2 and iterationnumber==1
3756 : !!
3757 : !! SOURCE
3758 :
3759 2079 : subroutine cg_precon_block(cg,eval,blocksize,iterationnumber,kinpw,&
3760 2079 : & npw,nspinor,me_g0,optekin,optpcon,pcon,ghc,vect,vectsize,comm)
3761 :
3762 : !Arguments ------------------------------------
3763 : !scalars
3764 : integer,intent(in) :: blocksize,iterationnumber,npw,nspinor,optekin
3765 : integer,intent(in) :: optpcon,vectsize,me_g0,comm
3766 : !arrays
3767 : real(dp),intent(in) :: cg(vectsize,blocksize),eval(blocksize,blocksize)
3768 : real(dp),intent(in) :: ghc(vectsize,blocksize),kinpw(npw)
3769 : real(dp),intent(inout) :: pcon(npw,blocksize),vect(vectsize,blocksize)
3770 :
3771 : !Local variables-------------------------------
3772 : !scalars
3773 : integer :: iblocksize,ierr,ig,igs,ipw1,ispinor
3774 : real(dp) :: fac,poly,xx
3775 : character(len=500) :: msg
3776 : !arrays
3777 : real(dp) :: tsec(2)
3778 2079 : real(dp),allocatable :: ek0(:),ek0_inv(:)
3779 : ! *************************************************************************
3780 :
3781 2079 : call timab(536,1,tsec)
3782 :
3783 : !In this case, the Teter, Allan and Payne preconditioner is approximated:
3784 : !the factor xx=Ekin(G) and no more Ekin(G)/Ekin(iband)
3785 2079 : if (optpcon==0) then
3786 2588 : do ispinor=1,nspinor
3787 1294 : igs=(ispinor-1)*npw
3788 2588 : if (me_g0 == 1) then
3789 1034 : do ig=1+igs,1+igs !g=0
3790 1034 : if (iterationnumber==1) then
3791 66 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
3792 66 : xx=kinpw(ig-igs)
3793 : ! teter polynomial ratio
3794 66 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
3795 66 : fac=poly/(poly+16._dp*xx**4)
3796 66 : if (optekin==1) fac=two*fac
3797 66 : pcon(ig-igs,1)=fac
3798 594 : do iblocksize=1,blocksize
3799 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3800 594 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,1)
3801 : end do
3802 : else
3803 0 : pcon(ig-igs,1)=zero
3804 0 : vect(ig,:)=0.0_dp
3805 : end if
3806 : else
3807 4059 : do iblocksize=1,blocksize
3808 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3809 4059 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,1)
3810 : end do
3811 : end if
3812 : end do
3813 22464 : do ig=2+igs,npw+igs
3814 22464 : if (iterationnumber==1) then
3815 2805 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
3816 2805 : xx=kinpw(ig-igs)
3817 : ! teter polynomial ratio
3818 2805 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
3819 2805 : fac=poly/(poly+16._dp*xx**4)
3820 2805 : if (optekin==1) fac=two*fac
3821 2805 : pcon(ig-igs,1)=fac
3822 25245 : do iblocksize=1,blocksize
3823 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3824 22440 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,1)
3825 : vect(ig+npw-1,iblocksize)=(ghc(ig+npw-1,iblocksize)-&
3826 25245 : & eval(iblocksize,iblocksize)*cg(ig+npw-1,iblocksize))*pcon(ig-igs,1)
3827 : end do
3828 : else
3829 0 : pcon(ig-igs,1)=zero
3830 0 : vect(ig,:)=zero
3831 0 : vect(ig+npw-1,:)=zero
3832 : end if
3833 : else
3834 172278 : do iblocksize=1,blocksize
3835 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3836 153136 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,1)
3837 : vect(ig+npw-1,iblocksize)=(ghc(ig+npw-1,iblocksize)-&
3838 172278 : & eval(iblocksize,iblocksize)*cg(ig+npw-1,iblocksize))*pcon(ig-igs,1)
3839 : end do
3840 : end if
3841 : end do
3842 : else
3843 13986 : do ig=1+igs,npw+igs
3844 13986 : if (iterationnumber==1) then
3845 1683 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
3846 1683 : xx=kinpw(ig-igs)
3847 : ! teter polynomial ratio
3848 1683 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
3849 1683 : fac=poly/(poly+16._dp*xx**4)
3850 1683 : if (optekin==1) fac=two*fac
3851 1683 : pcon(ig-igs,1)=fac
3852 15147 : do iblocksize=1,blocksize
3853 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3854 13464 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,1)
3855 : vect(ig+npw,iblocksize)=(ghc(ig+npw,iblocksize)-&
3856 15147 : & eval(iblocksize,iblocksize)*cg(ig+npw,iblocksize))*pcon(ig-igs,1)
3857 : end do
3858 : else
3859 0 : pcon(ig-igs,:)=zero
3860 0 : vect(ig,:)=zero
3861 0 : vect(ig+npw,:)=zero
3862 : end if
3863 : else
3864 103734 : do iblocksize=1,blocksize
3865 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3866 92208 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,1)
3867 : vect(ig+npw,iblocksize)=(ghc(ig+npw,iblocksize)-&
3868 103734 : & eval(iblocksize,iblocksize)*cg(ig+npw,iblocksize))*pcon(ig-igs,1)
3869 : end do
3870 : end if
3871 : end do
3872 : end if
3873 : end do
3874 :
3875 785 : else if (optpcon>0) then
3876 : ! Compute mean kinetic energy of all bands
3877 2355 : ABI_MALLOC(ek0,(blocksize))
3878 1570 : ABI_MALLOC(ek0_inv,(blocksize))
3879 785 : if (iterationnumber==1.or.optpcon==1) then
3880 1570 : do iblocksize=1,blocksize
3881 1570 : if (me_g0 == 1)then
3882 785 : ek0(iblocksize)=0.0_dp ; ipw1=2
3883 785 : if(kinpw(1)<huge(zero)*1.d-11)ek0(iblocksize)=0.5_dp*kinpw(1)*cg(1,iblocksize)**2
3884 11775 : do ig=ipw1,npw
3885 11775 : if(kinpw(ig)<huge(zero)*1.d-11)then
3886 : ek0(iblocksize)=ek0(iblocksize)+&
3887 10990 : & kinpw(ig)*(cg(ig,iblocksize)**2+cg(ig+npw-1,iblocksize)**2)
3888 : end if
3889 : end do
3890 : else
3891 0 : ek0(iblocksize)=0.0_dp ; ipw1=1
3892 0 : do ig=ipw1,npw
3893 0 : if(kinpw(ig)<huge(zero)*1.d-11)then
3894 : ek0(iblocksize)=ek0(iblocksize)+&
3895 0 : & kinpw(ig)*(cg(ig,iblocksize)**2+cg(ig+npw,iblocksize)**2)
3896 : end if
3897 : end do
3898 : end if
3899 : end do
3900 :
3901 785 : call xmpi_sum(ek0,comm,ierr)
3902 :
3903 1570 : do iblocksize=1,blocksize
3904 1570 : if(ek0(iblocksize)<1.0d-10)then
3905 0 : write(msg, '(4a)' )ch10,&
3906 0 : 'cg_precon_block: the mean kinetic energy of a wavefunction vanishes.',ch10,&
3907 0 : 'it is reset to 0.1ha.'
3908 0 : ABI_WARNING(msg)
3909 0 : ek0(iblocksize)=0.1_dp
3910 : end if
3911 : end do
3912 785 : if (optekin==1) then
3913 0 : ek0_inv(:)=2.0_dp/(3._dp*ek0(:))
3914 : else
3915 1570 : ek0_inv(:)=1.0_dp/ek0(:)
3916 : end if
3917 : end if !iterationnumber==1.or.optpcon==1
3918 :
3919 : ! Carry out preconditioning
3920 1570 : do iblocksize=1,blocksize
3921 2355 : do ispinor=1,nspinor
3922 785 : igs=(ispinor-1)*npw
3923 1570 : if (me_g0 == 1) then
3924 1570 : do ig=1+igs,1+igs !g=0
3925 1570 : if (iterationnumber==1.or.optpcon==1) then
3926 785 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
3927 785 : xx=kinpw(ig-igs)*ek0_inv(iblocksize)
3928 : ! teter polynomial ratio
3929 785 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
3930 785 : fac=poly/(poly+16._dp*xx**4)
3931 785 : if (optekin==1) fac=two*fac
3932 785 : pcon(ig-igs,iblocksize)=fac
3933 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3934 785 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*fac
3935 : else
3936 0 : pcon(ig-igs,iblocksize)=zero
3937 0 : vect(ig,iblocksize)=0.0_dp
3938 : end if
3939 : else
3940 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3941 0 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,iblocksize)
3942 : end if
3943 : end do
3944 11775 : do ig=2+igs,npw+igs
3945 11775 : if (iterationnumber==1.or.optpcon==1) then
3946 10990 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
3947 10990 : xx=kinpw(ig-igs)*ek0_inv(iblocksize)
3948 : ! teter polynomial ratio
3949 10990 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
3950 10990 : fac=poly/(poly+16._dp*xx**4)
3951 10990 : if (optekin==1) fac=two*fac
3952 10990 : pcon(ig-igs,iblocksize)=fac
3953 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3954 10990 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*fac
3955 : vect(ig+npw-1,iblocksize)=(ghc(ig+npw-1,iblocksize)-&
3956 10990 : & eval(iblocksize,iblocksize)*cg(ig+npw-1,iblocksize))*fac
3957 : else
3958 0 : pcon(ig-igs,iblocksize)=zero
3959 0 : vect(ig,iblocksize)=zero
3960 0 : vect(ig+npw-1,iblocksize)=zero
3961 : end if
3962 : else
3963 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3964 0 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,iblocksize)
3965 : vect(ig+npw-1,iblocksize)=(ghc(ig+npw-1,iblocksize)-&
3966 0 : & eval(iblocksize,iblocksize)*cg(ig+npw-1,iblocksize))*pcon(ig-igs,iblocksize)
3967 : end if
3968 : end do
3969 : else
3970 0 : do ig=1+igs,npw+igs
3971 0 : if (iterationnumber==1.or.optpcon==1) then
3972 0 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
3973 0 : xx=kinpw(ig-igs)*ek0_inv(iblocksize)
3974 : ! teter polynomial ratio
3975 0 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
3976 0 : fac=poly/(poly+16._dp*xx**4)
3977 0 : if (optekin==1) fac=two*fac
3978 0 : pcon(ig-igs,iblocksize)=fac
3979 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3980 0 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*fac
3981 : vect(ig+npw,iblocksize)=(ghc(ig+npw,iblocksize)-&
3982 0 : & eval(iblocksize,iblocksize)*cg(ig+npw,iblocksize))*fac
3983 : else
3984 0 : pcon(ig-igs,iblocksize)=zero
3985 0 : vect(ig,iblocksize)=zero
3986 0 : vect(ig+npw,iblocksize)=zero
3987 : end if
3988 : else
3989 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
3990 0 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,iblocksize)
3991 : vect(ig+npw,iblocksize)=(ghc(ig+npw,iblocksize)-&
3992 0 : & eval(iblocksize,iblocksize)*cg(ig+npw,iblocksize))*pcon(ig-igs,iblocksize)
3993 : end if
3994 : end do
3995 : end if
3996 : end do
3997 : end do
3998 785 : ABI_FREE(ek0)
3999 785 : ABI_FREE(ek0_inv)
4000 : end if !optpcon
4001 :
4002 2079 : call timab(536,2,tsec)
4003 :
4004 2079 : end subroutine cg_precon_block
4005 : !!***
4006 :
4007 : !!****f* m_cgtools/cg_zprecon_block
4008 : !!
4009 : !! NAME
4010 : !! cg_zprecon_block
4011 : !!
4012 : !! FUNCTION
4013 : !! precondition $<G|(H-e_{n,k})|C_{n,k}>$ for a block of band (band-FFT parallelisation)
4014 : !!
4015 : !! INPUTS
4016 : !! blocksize= size of blocks of bands
4017 : !! $cg(vectsize,blocksize)=<G|C_{n,k}> for a block of bands$.
4018 : !! $eval(blocksize,blocksize)=current block of bands eigenvalues=<C_{n,k}|H|C_{n,k}>$.
4019 : !! $ghc(vectsize,blocksize)=<G|H|C_{n,k}> for a block of bands$.
4020 : !! iterationnumber=number of iterative minimizations in LOBPCG
4021 : !! kinpw(npw)=(modified) kinetic energy for each plane wave (Hartree)
4022 : !! nspinor=number of spinorial components of the wavefunctions (on current proc)
4023 : !! $vect(vectsize,blocksize)=<G|H|C_{n,k}> for a block of bands$.
4024 : !! npw=number of planewaves at this k point.
4025 : !! optekin= 1 if the kinetic energy used in preconditionning is modified
4026 : !! according to Kresse, Furthmuller, PRB 54, 11169 (1996) [[cite:Kresse1996]]
4027 : !! 0 otherwise
4028 : !! optpcon= 0 the TPA preconditionning matrix does not depend on band
4029 : !! 1 the TPA preconditionning matrix (not modified)
4030 : !! 2 the TPA preconditionning matrix is independent of iteration number
4031 : !! vectsize= size of vectors
4032 : !! comm=MPI communicator.
4033 : !!
4034 : !! OUTPUT
4035 : !! vect(2,npw)=<g|(h-eval)|c_{n,k}>*(polynomial ratio)
4036 : !!
4037 : !! SIDE EFFECTS
4038 : !! pcon(npw,blocksize)=preconditionning matrix
4039 : !! input if optpcon=0,2 and iterationnumber/=1
4040 : !! output if optpcon=0,2 and iterationnumber==1
4041 : !!
4042 : !! SOURCE
4043 :
4044 32472 : subroutine cg_zprecon_block(cg,eval,blocksize,iterationnumber,kinpw,&
4045 32472 : & npw,nspinor,optekin,optpcon,pcon,ghc,vect,vectsize,comm)
4046 :
4047 : !Arguments ------------------------------------
4048 : !scalars
4049 : integer,intent(in) :: blocksize,iterationnumber,npw,nspinor,optekin
4050 : integer,intent(in) :: optpcon,vectsize,comm
4051 : !arrays
4052 : real(dp),intent(in) :: kinpw(npw)
4053 : real(dp),intent(inout) :: pcon(npw,blocksize)
4054 : complex(dp),intent(in) :: cg(vectsize,blocksize),eval(blocksize,blocksize)
4055 : complex(dp),intent(in) :: ghc(vectsize,blocksize)
4056 : complex(dp),intent(inout) :: vect(vectsize,blocksize)
4057 :
4058 : !Local variables-------------------------------
4059 : !scalars
4060 : integer :: iblocksize,ierr,ig,igs,ispinor
4061 : real(dp) :: fac,poly,xx
4062 : !character(len=500) :: msg
4063 : !arrays
4064 : real(dp) :: tsec(2)
4065 32472 : real(dp),allocatable :: ek0(:),ek0_inv(:)
4066 : ! *************************************************************************
4067 :
4068 32472 : call timab(536,1,tsec)
4069 :
4070 : !In this case, the Teter, Allan and Payne preconditioner is approximated:
4071 : !the factor xx=Ekin(G) and no more Ekin(G)/Ekin(iband)
4072 32472 : if (optpcon==0) then
4073 36353 : do ispinor=1,nspinor
4074 20765 : igs=(ispinor-1)*npw
4075 1226695 : do ig=1+igs,npw+igs
4076 1211107 : if (iterationnumber==1) then
4077 152075 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
4078 152075 : xx=kinpw(ig-igs)
4079 : ! teter polynomial ratio
4080 152075 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
4081 152075 : fac=poly/(poly+16._dp*xx**4)
4082 152075 : if (optekin==1) fac=two*fac
4083 152075 : pcon(ig-igs,1)=fac
4084 1658899 : do iblocksize=1,blocksize
4085 1658899 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,1)
4086 : end do
4087 : else
4088 0 : pcon(ig-igs,1)=zero
4089 0 : vect(ig,:)=dcmplx(0.0_dp,0.0_dp)
4090 : end if
4091 : else
4092 11266179 : do iblocksize=1,blocksize
4093 11266179 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,1)
4094 : end do
4095 : end if
4096 : end do
4097 : end do
4098 :
4099 16884 : else if (optpcon>0) then
4100 : ! Compute mean kinetic energy of all bands
4101 50652 : ABI_MALLOC(ek0,(blocksize))
4102 33768 : ABI_MALLOC(ek0_inv,(blocksize))
4103 16884 : if (iterationnumber==1.or.optpcon==1) then
4104 50192 : do iblocksize=1,blocksize
4105 33308 : ek0(iblocksize)=0.0_dp
4106 83500 : do ispinor=1,nspinor
4107 33308 : igs=(ispinor-1)*npw
4108 7882840 : do ig=1+igs,npw+igs
4109 7849532 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
4110 : ek0(iblocksize)=ek0(iblocksize)+kinpw(ig-igs)*&
4111 7816224 : & (real(cg(ig,iblocksize))**2+aimag(cg(ig,iblocksize))**2)
4112 : end if
4113 : end do
4114 : end do
4115 : end do
4116 :
4117 16884 : call xmpi_sum(ek0,comm,ierr)
4118 :
4119 50192 : do iblocksize=1,blocksize
4120 50192 : if(ek0(iblocksize)<1.0d-10)then
4121 0 : ABI_WARNING('the mean kinetic energy of a wavefunction vanishes. it is reset to 0.1ha.')
4122 0 : ek0(iblocksize)=0.1_dp
4123 : end if
4124 : end do
4125 16884 : if (optekin==1) then
4126 0 : ek0_inv(:)=2.0_dp/(3._dp*ek0(:))
4127 : else
4128 50192 : ek0_inv(:)=1.0_dp/ek0(:)
4129 : end if
4130 : end if !iterationnumber==1.or.optpcon==1
4131 :
4132 : ! Carry out preconditioning
4133 50192 : do iblocksize=1,blocksize
4134 83500 : do ispinor=1,nspinor
4135 33308 : igs=(ispinor-1)*npw
4136 7882840 : do ig=1+igs,npw+igs
4137 7849532 : if (iterationnumber==1.or.optpcon==1) then
4138 7816224 : if(kinpw(ig-igs)<huge(zero)*1.d-11)then
4139 7816224 : xx=kinpw(ig-igs)*ek0_inv(iblocksize)
4140 : ! teter polynomial ratio
4141 7816224 : poly=27._dp+xx*(18._dp+xx*(12._dp+xx*8._dp))
4142 7816224 : fac=poly/(poly+16._dp*xx**4)
4143 7816224 : if (optekin==1) fac=two*fac
4144 7816224 : pcon(ig-igs,iblocksize)=fac
4145 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
4146 7816224 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,iblocksize)
4147 : else
4148 0 : pcon(ig-igs,iblocksize)=zero
4149 0 : vect(ig,iblocksize)=dcmplx(0.0_dp,0.0_dp)
4150 : end if
4151 : else
4152 : vect(ig,iblocksize)=(ghc(ig,iblocksize)-&
4153 0 : & eval(iblocksize,iblocksize)*cg(ig,iblocksize))*pcon(ig-igs,iblocksize)
4154 : end if
4155 : end do
4156 : end do
4157 : end do
4158 16884 : ABI_FREE(ek0)
4159 16884 : ABI_FREE(ek0_inv)
4160 : end if !optpcon
4161 :
4162 32472 : call timab(536,2,tsec)
4163 :
4164 32472 : end subroutine cg_zprecon_block
4165 : !!***
4166 :
4167 : !!****f* m_cgtools/fxphas_seq
4168 : !!
4169 : !! NAME
4170 : !! fxphas_seq
4171 : !!
4172 : !! FUNCTION
4173 : !! Fix phase of all bands. Keep normalization but maximize real part (minimize imag part).
4174 : !! Also fix the sign of real part by setting the first non-zero element to be positive.
4175 : !!
4176 : !! This version has been stripped of all the mpi_enreg junk by MJV
4177 : !! Use cgtk_fixphase if you need a routine that works with mpi_enreg and paral_kgb
4178 : !!
4179 : !! INPUTS
4180 : !! cg(2,mcg)= contains the wavefunction |c> coefficients.
4181 : !! gsc(2,mgsc)= if useoverlap==1, contains the S|c> coefficients,
4182 : !! where S is an overlap matrix.
4183 : !! icg=shift to be applied on the location of data in the array cg
4184 : !! igsc=shift to be applied on the location of data in the array gsc
4185 : !! istwfk=input option parameter that describes the storage of wfs
4186 : !! (set to 1 if usual complex vectors)
4187 : !! mcg=size of second dimension of cg
4188 : !! mgsc=size of second dimension of gsc
4189 : !! nband_k=number of bands
4190 : !! npw_k=number of planewaves
4191 : !! useoverlap=describe the overlap of wavefunctions:
4192 : !! 0: no overlap (S=Identity_matrix)
4193 : !! 1: PAW wavefunctions
4194 : !!
4195 : !! OUTPUT
4196 : !! cg(2,mcg)=same array with altered phase.
4197 : !! gsc(2,mgsc)= same array with altered phase.
4198 : !!
4199 : !! SOURCE
4200 :
4201 373055 : subroutine fxphas_seq(cg, gsc, icg, igsc, istwfk, mcg, mgsc, nband_k, npw_k, useoverlap)
4202 :
4203 : !Arguments ------------------------------------
4204 : !scalars
4205 : integer,intent(in) :: icg,igsc,istwfk,mcg,mgsc,nband_k,npw_k,useoverlap
4206 : !arrays
4207 : real(dp),intent(inout) :: cg(2,mcg),gsc(2,mgsc*useoverlap)
4208 :
4209 : !Local variables-------------------------------
4210 : !scalars
4211 : integer :: iband,ii,indx
4212 : real(dp) :: cim,cre,gscim,gscre,quotient,root1,root2,saa,sab,sbb,theta
4213 : real(dp) :: thppi,xx,yy
4214 : character(len=500) :: msg
4215 : !arrays
4216 373055 : real(dp),allocatable :: cimb(:),creb(:),saab(:),sabb(:),sbbb(:) !,sarr(:,:)
4217 : ! *************************************************************************
4218 :
4219 : !The general case, where a complex phase indeterminacy is present
4220 373055 : if(istwfk==1)then
4221 :
4222 1119165 : ABI_MALLOC(cimb,(nband_k))
4223 746110 : ABI_MALLOC(creb,(nband_k))
4224 746110 : ABI_MALLOC(saab,(nband_k))
4225 746110 : ABI_MALLOC(sabb,(nband_k))
4226 746110 : ABI_MALLOC(sbbb,(nband_k))
4227 5337587 : cimb(:)=zero ; creb(:)=zero
4228 :
4229 : ! Loop over bands
4230 : ! TODO: MG store saa arrays in sarr(3,nband_k) to reduce false sharing.
4231 2855321 : do iband=1,nband_k
4232 2482266 : indx=icg+(iband-1)*npw_k
4233 :
4234 : ! Compute several sums over Re, Im parts of c
4235 2482266 : saa=0.0_dp ; sbb=0.0_dp ; sab=0.0_dp
4236 26878422 : do ii=1+indx,npw_k+indx
4237 24396156 : saa=saa+cg(1,ii)*cg(1,ii)
4238 24396156 : sbb=sbb+cg(2,ii)*cg(2,ii)
4239 26878422 : sab=sab+cg(1,ii)*cg(2,ii)
4240 : end do
4241 2482266 : saab(iband)=saa
4242 2482266 : sbbb(iband)=sbb
4243 2855321 : sabb(iband)=sab
4244 : end do ! iband
4245 :
4246 :
4247 2855321 : do iband=1,nband_k
4248 :
4249 2482266 : indx=icg+(iband-1)*npw_k
4250 :
4251 2482266 : saa=saab(iband)
4252 2482266 : sbb=sbbb(iband)
4253 2482266 : sab=sabb(iband)
4254 :
4255 : ! Get phase angle theta
4256 2482266 : if (sbb+saa>tol8)then
4257 2482266 : if(abs(sbb-saa)>tol8*(sbb+saa) .or. 2*abs(sab)>tol8*(sbb+saa))then
4258 2481157 : if (abs(sbb-saa)>tol8*abs(sab)) then
4259 2480794 : quotient=sab/(sbb-saa)
4260 2480794 : theta=0.5_dp*atan(2.0_dp*quotient)
4261 : else
4262 : ! Taylor expansion of the atan in terms of inverse of its argument. Correct up to 1/x2, included.
4263 363 : theta=0.25_dp*(pi-(sbb-saa)/sab)
4264 : end if
4265 : ! Check roots to get theta for max Re part
4266 2481157 : root1=cos(theta)**2*saa+sin(theta)**2*sbb-2.0_dp*cos(theta)*sin(theta)*sab
4267 2481157 : thppi=theta+0.5_dp*pi
4268 2481157 : root2=cos(thppi)**2*saa+sin(thppi)**2*sbb-2.0_dp*cos(thppi)*sin(thppi)*sab
4269 2481157 : if (root2>root1) theta=thppi
4270 : else
4271 : ! The real part vector and the imaginary part vector are orthogonal, and of same norm. Strong indeterminacy.
4272 : ! Will determine the first non-zero coefficient, and fix its phase
4273 1746 : do ii=1+indx,npw_k+indx
4274 1746 : cre=cg(1,ii)
4275 1746 : cim=cg(2,ii)
4276 1746 : if(cre**2+cim**2>tol8**2*(saa+sbb))then
4277 1109 : if(cre**2>tol8**2**cim**2)then
4278 916 : theta=atan(cim/cre)
4279 : else
4280 : ! Taylor expansion of the atan in terms of inverse of its argument. Correct up to 1/x2, included.
4281 193 : theta=pi/2-cre/cim
4282 : end if
4283 : exit
4284 : end if
4285 : end do
4286 : end if
4287 : else
4288 : write(msg,'(a,i0,5a)')&
4289 0 : 'The eigenvector with band ',iband,' has zero norm.',ch10,&
4290 0 : 'This usually happens when the number of bands (nband) is comparable to the number of planewaves (mpw)',ch10,&
4291 0 : 'Action: Check the parameters of the calculation. If nband ~ mpw, then decrease nband or, alternatively, increase ecut'
4292 0 : ABI_ERROR(msg)
4293 : end if
4294 :
4295 2482266 : xx=cos(theta)
4296 2482266 : yy=sin(theta)
4297 :
4298 : ! Here, set the first non-zero element to be positive
4299 3112150 : do ii=1+indx,npw_k+indx
4300 3112150 : cre=cg(1,ii)
4301 3112150 : cim=cg(2,ii)
4302 3112150 : cre=xx*cre-yy*cim
4303 3112150 : if(abs(cre)>tol8)exit
4304 : end do
4305 2482266 : if(cre<zero)then
4306 1217696 : xx=-xx ; yy=-yy
4307 : end if
4308 :
4309 2482266 : creb(iband)=xx
4310 2855321 : cimb(iband)=yy
4311 :
4312 : end do
4313 :
4314 2855321 : do iband=1,nband_k
4315 :
4316 2482266 : indx=icg+(iband-1)*npw_k
4317 :
4318 2482266 : xx=creb(iband)
4319 2482266 : yy=cimb(iband)
4320 26878422 : do ii=1+indx,npw_k+indx
4321 24396156 : cre=cg(1,ii)
4322 24396156 : cim=cg(2,ii)
4323 24396156 : cg(1,ii)=xx*cre-yy*cim
4324 26878422 : cg(2,ii)=xx*cim+yy*cre
4325 : end do
4326 :
4327 : ! Alter phase of array S|cg>
4328 2855321 : if (useoverlap==1) then
4329 0 : indx=igsc+(iband-1)*npw_k
4330 0 : do ii=1+indx,npw_k+indx
4331 0 : gscre=gsc(1,ii)
4332 0 : gscim=gsc(2,ii)
4333 0 : gsc(1,ii)=xx*gscre-yy*gscim
4334 0 : gsc(2,ii)=xx*gscim+yy*gscre
4335 : end do
4336 : end if
4337 :
4338 : end do ! iband
4339 :
4340 373055 : ABI_FREE(cimb)
4341 373055 : ABI_FREE(creb)
4342 373055 : ABI_FREE(saab)
4343 373055 : ABI_FREE(sabb)
4344 373055 : ABI_FREE(sbbb)
4345 :
4346 : else ! if istwfk/=1
4347 : ! Storages that take into account the time-reversal symmetry: the freedom is only a sign freedom
4348 :
4349 0 : ABI_MALLOC(creb,(nband_k))
4350 0 : creb(:)=zero
4351 : ! Loop over bands
4352 0 : do iband=1,nband_k
4353 :
4354 0 : indx=icg+(iband-1)*npw_k
4355 :
4356 : ! Here, set the first non-zero real element to be positive
4357 0 : do ii=1+indx,npw_k+indx
4358 0 : cre=cg(1,ii)
4359 0 : if(abs(cre)>tol8)exit
4360 : end do
4361 0 : creb(iband)=cre
4362 :
4363 : end do ! iband
4364 :
4365 0 : do iband=1,nband_k
4366 :
4367 0 : cre=creb(iband)
4368 0 : if(cre<zero)then
4369 0 : indx=icg+(iband-1)*npw_k
4370 0 : do ii=1+indx,npw_k+indx
4371 0 : cg(1,ii)=-cg(1,ii)
4372 0 : cg(2,ii)=-cg(2,ii)
4373 : end do
4374 0 : if(useoverlap==1)then
4375 0 : indx=igsc+(iband-1)*npw_k
4376 0 : do ii=1+indx,npw_k+indx
4377 0 : gsc(1,ii)=-gsc(1,ii)
4378 0 : gsc(2,ii)=-gsc(2,ii)
4379 : end do
4380 : end if
4381 : end if
4382 :
4383 : end do ! iband
4384 :
4385 0 : ABI_FREE(creb)
4386 :
4387 : end if ! istwfk
4388 :
4389 373055 : end subroutine fxphas_seq
4390 : !!***
4391 :
4392 : !----------------------------------------------------------------------
4393 :
4394 : !!****f* m_cgtools/fxphas_and_cmp
4395 : !! NAME
4396 : !! fxphas_and_cmp
4397 : !!
4398 : !! FUNCTION
4399 : !! Fix phase and compare two set of wavefunctions
4400 : !!
4401 : !! OUTPUT
4402 : !!
4403 : !! SOURCE
4404 :
4405 0 : logical function fxphas_and_cmp(npw_k, nspinor, nband_k, istwfk, cg1, cg2, eig_k, msg, atol_rho, atol_dphi) result(ok)
4406 :
4407 : !Arguments ------------------------------------
4408 : integer,intent(in) :: npw_k, nspinor, nband_k, istwfk
4409 : real(dp),intent(inout) :: cg1(2, npw_k*nspinor, nband_k), cg2(2, npw_k*nspinor, nband_k)
4410 : real(dp),intent(in) :: eig_k(nband_k)
4411 : character(len=*),intent(out) :: msg
4412 : real(dp),optional,intent(in) :: atol_rho, atol_dphi
4413 :
4414 : !Local variables-------------------------------
4415 : integer, parameter :: useoverlap0 = 0, mgsc = 0
4416 : integer :: ipw, mcg, band, ipwsp, isp
4417 : real(dp) :: phi1, rho1, phi2, rho2, max_rho_adiff, atol_rho__, phi_diff_ref, max_dphi_adiff, atol_dphi__, gsc(0,0)
4418 : character(len=500) :: btype
4419 : ! ***********************************************************************
4420 :
4421 0 : atol_rho__ = tol6; if (present(atol_rho)) atol_rho__ = atol_rho
4422 0 : atol_dphi__ = tol3; if (present(atol_dphi)) atol_dphi__ = atol_dphi
4423 0 : max_rho_adiff = zero; max_dphi_adiff = zero; phi_diff_ref = huge(one)
4424 :
4425 0 : mcg = npw_k * nspinor * nband_k
4426 0 : call fxphas_seq(cg1, gsc, 1, 1, istwfk, mcg, mgsc, nband_k, npw_k * nspinor, useoverlap0)
4427 0 : call fxphas_seq(cg2, gsc, 1, 1, istwfk, mcg, mgsc, nband_k, npw_k * nspinor, useoverlap0)
4428 :
4429 0 : do band=1,nband_k
4430 0 : call band_type(band, btype)
4431 0 : if (btype == "degenerate") cycle
4432 : !write(234, *)"band: ", band, "istwfk: ", istwfk, trim(btype)
4433 : !write(235, *)"band: ", band, "istwfk:", istwfk, trim(btype)
4434 : !write(234, *)"cg1:"; write(235, *)"cg2:"
4435 : !write(234, *)"cg1 rho:"; write(235, *)"cg2 rho phi:"
4436 0 : do isp=1,nspinor
4437 0 : do ipw=1,npw_k
4438 0 : ipwsp = ipw + (isp - 1) * npw_k
4439 : !if (npw_k > 15 .and. ipw > 15 .and. ipw < npw_k - 15) cycle
4440 : !write(234, *)ipwsp, cg1(1, ipwsp, band); write(234, *)ipwsp, cg1(2, ipwsp, band)
4441 : !write(235, *)ipwsp, cg2(1, ipwsp, band); write(235, *)ipwsp, cg2(2, ipwsp, band)
4442 0 : call rhophi(cg1(:, ipwsp, band), phi1, rho1)
4443 0 : call rhophi(cg2(:, ipwsp, band), phi2, rho2)
4444 : !write(234, *)ipwsp, rho1!; write(234, *)ipwsp, phi1
4445 : !write(235, *)ipwsp, rho2!; write(235, *)ipwsp, phi2
4446 : end do
4447 : end do
4448 : end do
4449 :
4450 0 : do band=1,nband_k
4451 0 : do ipw=1,npw_k * nspinor
4452 0 : call rhophi(cg1(:, ipw, band), phi1, rho1)
4453 0 : call rhophi(cg2(:, ipw, band), phi2, rho2)
4454 0 : max_rho_adiff = max(max_rho_adiff, abs(rho1 - rho2))
4455 0 : if (rho1 > atol_rho__ ** 2) then
4456 : if (phi_diff_ref /= huge(one)) phi_diff_ref = phi1 - phi2
4457 0 : max_dphi_adiff = max(max_dphi_adiff, abs(phi_diff_ref - (phi1 - phi2)))
4458 : end if
4459 : end do
4460 : end do
4461 :
4462 0 : write(msg, "(2(a,es12.4))")"max_rho_adiff: ", max_rho_adiff, ", max_dphi_adiff: ", max_dphi_adiff
4463 0 : ok = (max_rho_adiff < atol_rho__ .and. max_dphi_adiff < atol_dphi__)
4464 :
4465 : contains
4466 0 : subroutine band_type(band, btype)
4467 : integer,intent(in) :: band
4468 : character(len=*),intent(out) :: btype
4469 : real(dp) :: e0
4470 :
4471 0 : e0 = eig_k(band)
4472 :
4473 0 : if (band == 1) then
4474 0 : btype = "last_state"
4475 0 : if (nband_k > 1) then
4476 0 : btype = "non-degenerate"
4477 0 : if (abs(e0 - eig_k(band + 1)) < tol6) btype = "degenerate"
4478 : end if
4479 :
4480 0 : else if (band == nband_k) then
4481 0 : btype = "last_state"
4482 0 : if (band - 1 > 0) then
4483 0 : if (abs(e0 - eig_k(band - 1)) < tol6) btype = "degenerate"
4484 : end if
4485 :
4486 : else
4487 0 : btype = "non-degenerate"
4488 0 : if (abs(e0 - eig_k(band - 1)) < tol6 .or. abs(e0 - eig_k(band + 1)) < tol6) btype = "degenerate"
4489 : end if
4490 :
4491 0 : end subroutine band_type
4492 :
4493 : end function fxphas_and_cmp
4494 : !!***
4495 :
4496 : !!****f* m_cgtools/overlap_g
4497 : !! NAME
4498 : !! overlap_g
4499 : !!
4500 : !! FUNCTION
4501 : !! Compute the scalar product between WF at two different k-points
4502 : !! < u_{n,k1} | u_{n,k2}>
4503 : !!
4504 : !! INPUTS
4505 : !! mpw = maximum dimensioned size of npw
4506 : !! npw_k1 = number of plane waves at k1
4507 : !! npw_k2 = number of plane waves at k2
4508 : !! nspinor = 1 for scalar, 2 for spinor wavefunctions
4509 : !! pwind_k = array required to compute the scalar product (see initberry.f)
4510 : !! vect1 = wavefunction at k1: | u_{n,k1} >
4511 : !! vect2 = wavefunction at k1: | u_{n,k2} >
4512 : !!
4513 : !! OUTPUT
4514 : !! doti = imaginary part of the scalarproduct
4515 : !! dotr = real part of the scalarproduct
4516 : !!
4517 : !! NOTES
4518 : !! In case a G-vector of the basis sphere of plane waves at k1
4519 : !! does not belong to the basis sphere of plane waves at k2,
4520 : !! pwind = 0. Therefore, the dimensions of vect1 &
4521 : !! vect2 are (1:2,0:mpw) and the element (1:2,0) MUST be set to zero.
4522 : !!
4523 : !! The current implementation if not compatible with TR-symmetry (i.e. istwfk/=1) !
4524 : !!
4525 : !! SOURCE
4526 :
4527 137044504 : subroutine overlap_g(doti,dotr,mpw,npw_k1,npw_k2,nspinor,pwind_k,vect1,vect2)
4528 :
4529 : !Arguments ------------------------------------
4530 : !scalars
4531 : integer,intent(in) :: mpw,npw_k1,npw_k2,nspinor
4532 : real(dp),intent(out) :: doti,dotr
4533 : !arrays
4534 : integer,intent(in) :: pwind_k(mpw)
4535 : real(dp),intent(in) :: vect1(1:2,0:mpw*nspinor),vect2(1:2,0:mpw*nspinor)
4536 :
4537 : !Local variables-------------------------------
4538 : !scalars
4539 : integer :: ipw,ispinor,jpw,spnshft1,spnshft2
4540 : ! *************************************************************************
4541 :
4542 : !Check if vect1(:,0) = 0 and vect2(:,0) = 0
4543 : if ((abs(vect1(1,0)) > tol12).or.(abs(vect1(2,0)) > tol12).or. &
4544 137044504 : & (abs(vect2(1,0)) > tol12).or.(abs(vect2(2,0)) > tol12)) then
4545 0 : ABI_BUG('vect1(:,0) and/or vect2(:,0) are not equal to zero')
4546 : end if
4547 :
4548 : !Compute the scalar product
4549 137044504 : dotr = zero; doti = zero
4550 276437008 : do ispinor = 1, nspinor
4551 139392504 : spnshft1 = (ispinor-1)*npw_k1
4552 139392504 : spnshft2 = (ispinor-1)*npw_k2
4553 : !$OMP PARALLEL DO PRIVATE(jpw) REDUCTION(+:doti,dotr)
4554 23151736580 : do ipw = 1, npw_k1
4555 22875299572 : jpw = pwind_k(ipw)
4556 22875299572 : dotr = dotr + vect1(1,spnshft1+ipw)*vect2(1,spnshft2+jpw) + vect1(2,spnshft1+ipw)*vect2(2,spnshft2+jpw)
4557 23014692076 : doti = doti + vect1(1,spnshft1+ipw)*vect2(2,spnshft2+jpw) - vect1(2,spnshft1+ipw)*vect2(1,spnshft2+jpw)
4558 : end do
4559 : end do
4560 :
4561 137044504 : end subroutine overlap_g
4562 : !!***
4563 :
4564 : !!****f* ABINIT/subdiago
4565 : !! NAME
4566 : !! subdiago
4567 : !!
4568 : !! FUNCTION
4569 : !! This routine diagonalizes the Hamiltonian in the trial subspace.
4570 : !!
4571 : !! INPUTS
4572 : !! icg=shift to be applied on the location of data in the array cg
4573 : !! igsc=shift to be applied on the location of data in the array gsc
4574 : !! istwf_k=input parameter that describes the storage of wfs
4575 : !! mcg=second dimension of the cg array
4576 : !! mgsc=second dimension of the gsc array
4577 : !! nband_k=number of bands at this k point for that spin polarization
4578 : !! npw_k=number of plane waves at this k point
4579 : !! my_nspinor=number of spinorial components of the wavefunctions (on current proc)
4580 : !! use_subovl=1 if the overlap matrix is not identity in WFs subspace
4581 : !! usepaw= 0 for non paw calculation; =1 for paw calculation
4582 : !! me_g0=1 if this processor has G=0, 0 otherwise.
4583 : !!
4584 : !! OUTPUT
4585 : !! eig_k(nband_k)=array for holding eigenvalues (hartree)
4586 : !! evec(2*nband_k,nband_k)=array for holding eigenvectors
4587 : !!
4588 : !! SIDE EFFECTS
4589 : !! subham(nband_k*(nband_k+1))=Hamiltonian expressed in the WFs subspace. Hermitianized in output.
4590 : !! subovl(nband_k*(nband_k+1)*use_subovl)=overlap matrix expressed in the WFs subspace. Hermitianized in output.
4591 : !! cg(2,mcg)=wavefunctions
4592 : !! gsc(2,mgsc)=<g|S|c> matrix elements (S=overlap)
4593 : !!
4594 : !! SOURCE
4595 :
4596 445643 : subroutine subdiago(cg, eig_k, evec, gsc, icg, igsc, istwf_k, mcg, mgsc, nband_k, npw_k, my_nspinor, paral_kgb, &
4597 445643 : subham, subovl, use_subovl, usepaw, me_g0)
4598 :
4599 : !Arguments ------------------------------------
4600 : integer,intent(in) :: icg,igsc,istwf_k,mcg,mgsc,nband_k,npw_k,me_g0
4601 : integer,intent(in) :: my_nspinor,paral_kgb,use_subovl,usepaw
4602 : real(dp),intent(inout) :: subham(nband_k*(nband_k+1)),subovl(nband_k*(nband_k+1)*use_subovl)
4603 : real(dp),intent(out) :: eig_k(nband_k),evec(2*nband_k,nband_k)
4604 : real(dp),intent(inout) :: cg(2,mcg),gsc(2,mgsc)
4605 :
4606 : !Local variables-------------------------------
4607 : integer :: iband,ii,ierr,rvectsize,vectsize,use_slk
4608 : !real(dp) :: cpu, wall, gflops
4609 : character(len=500) :: msg
4610 : ! real(dp) :: tsec(2)
4611 445643 : real(dp),allocatable :: evec_re(:,:),subovl_re(:),subham_tmp(:), work(:,:)
4612 445643 : real(dp),allocatable :: blockvectora(:,:),blockvectorb(:,:),blockvectorc(:,:)
4613 :
4614 : ! *********************************************************************
4615 :
4616 445643 : if (paral_kgb<0) then
4617 0 : ABI_BUG('paral_kgb should be positive ')
4618 : end if
4619 :
4620 : ! 1 if Scalapack version is used.
4621 : ! MG TODO: This should not be bound to paral_kgb
4622 445643 : use_slk = paral_kgb
4623 :
4624 445643 : rvectsize=npw_k*my_nspinor
4625 445643 : vectsize=2*rvectsize;if (me_g0==1) vectsize=vectsize-1
4626 : !call cwtime(cpu, wall, gflops, "start")
4627 :
4628 : !Impose Hermiticity on diagonal elements of subham (and subovl, if needed)
4629 : ! MG FIXME: In these two calls we are aliasing the args
4630 445643 : call hermit(subham, subham, ierr, nband_k)
4631 445643 : if (use_subovl==1) call hermit(subovl, subovl, ierr, nband_k)
4632 : !call cwtime_report(" hermit", cpu, wall, gflops)
4633 :
4634 : ! Diagonalize the Hamitonian matrix
4635 445643 : if (istwf_k==2) then
4636 2230598 : ABI_CALLOC(evec_re, (nband_k,nband_k))
4637 50355 : ABI_MALLOC(subham_tmp, (nband_k*(nband_k+1)/2))
4638 1115299 : subham_tmp=subham(1:nband_k*(nband_k+1):2)
4639 16785 : if (use_subovl==1) then
4640 0 : ABI_MALLOC(subovl_re, (nband_k*(nband_k+1)/2))
4641 0 : subovl_re=subovl(1:nband_k*(nband_k+1):2)
4642 : ! TODO: Not sure this one has been fully tested
4643 0 : call abi_xhpgv(1,'V','U',nband_k,subham_tmp,subovl_re,eig_k,evec_re,nband_k,istwf_k=istwf_k,use_slk=use_slk)
4644 0 : ABI_FREE(subovl_re)
4645 : else
4646 16785 : call abi_xhpev('V','U',nband_k,subham_tmp,eig_k,evec_re,nband_k,istwf_k=istwf_k,use_slk=use_slk)
4647 : end if
4648 6392466 : evec(:,:)=zero; evec(1:2*nband_k:2,:) = evec_re
4649 16785 : ABI_FREE(evec_re)
4650 16785 : ABI_FREE(subham_tmp)
4651 : else
4652 428858 : if (use_subovl==1) then
4653 0 : call abi_xhpgv(1,'V','U',nband_k,subham,subovl,eig_k,evec,nband_k,istwf_k=istwf_k,use_slk=use_slk)
4654 : else
4655 428858 : call abi_xhpev('V','U',nband_k,subham,eig_k,evec,nband_k,istwf_k=istwf_k,use_slk=use_slk)
4656 : end if
4657 : end if
4658 : !call cwtime_report(" hdiago", cpu, wall, gflops)
4659 :
4660 : ! Normalize each eigenvector and set phase:
4661 : ! this is because of the simultaneous diagonalisation of this
4662 : ! matrix by different processors, allowing to get different unitary transforms, thus breaking the
4663 : ! coherency of parts of cg stored on different processors).
4664 : !
4665 : ! The problem with minus/plus signs might be present also if .not. use_subovl
4666 : !
4667 : !if(use_subovl == 0) then
4668 445643 : call cg_normev(evec, nband_k, nband_k)
4669 : !end if
4670 :
4671 445643 : if(istwf_k==2)then
4672 131478 : do iband=1,nband_k
4673 2180243 : do ii=1,nband_k
4674 2163458 : if(abs(evec(2*ii,iband))>1.0d-10)then
4675 0 : write(msg,'(3a,2i0,2es16.6,a,a)')ch10,&
4676 0 : ' For istwf_k=2, observed the following element of evec:',ch10,&
4677 0 : iband,ii,evec(2*ii-1,iband),evec(2*ii,iband),ch10,' with a non-negligible imaginary part.'
4678 0 : ABI_BUG(msg)
4679 : end if
4680 : end do
4681 : end do
4682 : end if
4683 : !call cwtime_report(" normev", cpu, wall, gflops)
4684 :
4685 : !=====================================================
4686 : ! Carry out rotation of bands C(G,n) according to evecs
4687 : ! ZGEMM if istwfk==1, DGEMM if istwfk==2
4688 : !=====================================================
4689 891286 : if (istwf_k==2) then
4690 :
4691 67140 : ABI_MALLOC_OR_DIE(blockvectora, (vectsize, nband_k), ierr)
4692 67140 : ABI_MALLOC_OR_DIE(blockvectorb, (nband_k, nband_k), ierr)
4693 50355 : ABI_MALLOC_OR_DIE(blockvectorc, (vectsize, nband_k), ierr)
4694 :
4695 131478 : do iband=1,nband_k
4696 114693 : if (me_g0 == 1) then
4697 111733 : call abi_xcopy(1,cg(1,cgindex_subd(iband)),1,blockvectora(1,iband),1)
4698 111733 : call abi_xcopy(rvectsize-1,cg(1,cgindex_subd(iband)+1),2,blockvectora(2,iband),1)
4699 111733 : call abi_xcopy(rvectsize-1,cg(2,cgindex_subd(iband)+1),2,blockvectora(rvectsize+1,iband),1)
4700 : else
4701 2960 : call abi_xcopy(rvectsize,cg(1,cgindex_subd(iband)),2,blockvectora(1,iband),1)
4702 2960 : call abi_xcopy(rvectsize,cg(2,cgindex_subd(iband)),2,blockvectora(rvectsize+1,iband),1)
4703 : end if
4704 131478 : call abi_xcopy(nband_k,evec(2*iband-1,1),2*nband_k,blockvectorb(iband,1),nband_k)
4705 : end do
4706 :
4707 : !MG TODO: This one is a DGEMM.
4708 : call abi_xgemm('N','N',vectsize,nband_k,nband_k,&
4709 16785 : cone,blockvectora,vectsize,blockvectorb,nband_k,czero,blockvectorc,vectsize)
4710 :
4711 131478 : do iband=1,nband_k
4712 131478 : if (me_g0 == 1) then
4713 111733 : call abi_xcopy(1,blockvectorc(1,iband),1,cg(1,cgindex_subd(iband)),1)
4714 111733 : call abi_xcopy(rvectsize-1,blockvectorc(2,iband),1,cg(1,cgindex_subd(iband)+1),2)
4715 111733 : call abi_xcopy(rvectsize-1,blockvectorc(rvectsize+1,iband),1,cg(2,cgindex_subd(iband)+1),2)
4716 : else
4717 2960 : call abi_xcopy(rvectsize,blockvectorc(1,iband),1,cg(1,cgindex_subd(iband)),2)
4718 2960 : call abi_xcopy(rvectsize,blockvectorc(rvectsize+1,iband),1,cg(2,cgindex_subd(iband)),2)
4719 : end if
4720 : end do
4721 :
4722 16785 : if (usepaw==1) then
4723 : ! If paw, must also rotate S.C(G,n):
4724 :
4725 35013 : do iband=1,nband_k
4726 31287 : if (me_g0 == 1) then
4727 30799 : call abi_xcopy(1,gsc(1,gscindex_subd(iband)),1,blockvectora(1,iband),1)
4728 30799 : call abi_xcopy(rvectsize-1,gsc(1,gscindex_subd(iband)+1),2,blockvectora(2,iband),1)
4729 30799 : call abi_xcopy(rvectsize-1,gsc(2,gscindex_subd(iband)+1),2,blockvectora(rvectsize+1,iband),1)
4730 : else
4731 488 : call abi_xcopy(rvectsize ,gsc(1,gscindex_subd(iband)),2,blockvectora(1,iband),1)
4732 488 : call abi_xcopy(rvectsize ,gsc(2,gscindex_subd(iband)),2,blockvectora(rvectsize+1,iband),1)
4733 : end if
4734 35013 : call abi_xcopy(nband_k,evec(2*iband-1,1),2*nband_k,blockvectorb(iband,1),nband_k)
4735 : end do
4736 :
4737 : call abi_xgemm('N','N',vectsize,nband_k,nband_k,&
4738 3726 : cone,blockvectora,vectsize,blockvectorb,nband_k,czero,blockvectorc,vectsize)
4739 :
4740 35013 : do iband=1,nband_k
4741 35013 : if (me_g0 == 1) then
4742 30799 : call abi_xcopy(1,blockvectorc(1,iband),1,gsc(1,gscindex_subd(iband)),1)
4743 30799 : call abi_xcopy(rvectsize-1,blockvectorc(2,iband),1,gsc(1,gscindex_subd(iband)+1),2)
4744 30799 : call abi_xcopy(rvectsize-1,blockvectorc(rvectsize+1,iband),1,gsc(2,gscindex_subd(iband)+1),2)
4745 : else
4746 488 : call abi_xcopy(rvectsize,blockvectorc(1,iband),1,gsc(1,gscindex_subd(iband)),2)
4747 488 : call abi_xcopy(rvectsize,blockvectorc(rvectsize+1,iband),1,gsc(2,gscindex_subd(iband)),2)
4748 : end if
4749 : end do
4750 :
4751 : end if
4752 :
4753 16785 : ABI_FREE(blockvectora)
4754 16785 : ABI_FREE(blockvectorb)
4755 16785 : ABI_FREE(blockvectorc)
4756 :
4757 : else
4758 : ! istwf_k /= 2
4759 1286574 : ABI_MALLOC_OR_DIE(work, (2,npw_k*my_nspinor*nband_k), ierr)
4760 :
4761 : ! MG: Do not remove this initialization.
4762 : ! telast_06 stops in fxphase on inca_debug and little_buda (very very strange, due to atlas?)
4763 : !work=zero
4764 :
4765 : call abi_xgemm('N','N',npw_k*my_nspinor,nband_k,nband_k,cone, &
4766 : cg(:,icg+1:npw_k*my_nspinor*nband_k+icg),npw_k*my_nspinor, &
4767 428858 : evec,nband_k,czero,work,npw_k*my_nspinor,x_cplx=2)
4768 :
4769 428858 : call abi_xcopy(npw_k*my_nspinor*nband_k,work(1,1),1,cg(1,1+icg),1,x_cplx=2)
4770 :
4771 428858 : if (usepaw==1) then
4772 : ! If paw, must also rotate S.C(G,n):
4773 : call abi_xgemm('N','N',npw_k*my_nspinor,nband_k,nband_k,cone, &
4774 : gsc(:,1+igsc:npw_k*my_nspinor*nband_k+igsc),npw_k*my_nspinor, &
4775 95575 : evec,nband_k,czero,work,npw_k*my_nspinor,x_cplx=2)
4776 95575 : call abi_xcopy(npw_k*my_nspinor*nband_k, work(1,1),1,gsc(1,1+igsc),1,x_cplx=2)
4777 : end if
4778 :
4779 428858 : ABI_FREE(work)
4780 : end if
4781 : !call cwtime_report(" rotation", cpu, wall, gflops)
4782 :
4783 : contains
4784 :
4785 682238 : function cgindex_subd(iband)
4786 : integer :: iband,cgindex_subd
4787 682238 : cgindex_subd=npw_k*my_nspinor*(iband-1)+icg+1
4788 682238 : end function cgindex_subd
4789 :
4790 186746 : function gscindex_subd(iband)
4791 : integer :: iband,gscindex_subd
4792 186746 : gscindex_subd=npw_k*my_nspinor*(iband-1)+igsc+1
4793 186746 : end function gscindex_subd
4794 :
4795 : end subroutine subdiago
4796 : !!***
4797 :
4798 : !!****f* ABINIT/subdiago_low_memory
4799 : !! NAME
4800 : !! subdiago_low_memory
4801 : !!
4802 : !! FUNCTION
4803 : !! This routine diagonalizes the Hamiltonian in the eigenfunction subspace
4804 : !! Separate the computation in blocks of plane waves to save memory
4805 : !!
4806 : !! INPUTS
4807 : !! icg=shift to be applied on the location of data in the array cg
4808 : !! istwf_k=input parameter that describes the storage of wfs
4809 : !! mcg=second dimension of the cg array
4810 : !! nband_k=number of bands at this k point for that spin polarization
4811 : !! npw_k=number of plane waves at this k point
4812 : !! nspinor=number of spinorial components of the wavefunctions (on current proc)
4813 : !! subham(nband_k*(nband_k+1))=Hamiltonian expressed in the WFs subspace
4814 : !!
4815 : !! OUTPUT
4816 : !! eig_k(nband_k)=array for holding eigenvalues (hartree)
4817 : !! evec(2*nband_k,nband_k)=array for holding eigenvectors
4818 : !!
4819 : !! SIDE EFFECTS
4820 : !! cg(2,mcg)=wavefunctions
4821 : !!
4822 : !! SOURCE
4823 :
4824 0 : subroutine subdiago_low_memory(cg,eig_k,evec,icg,istwf_k,&
4825 : & mcg,nband_k,npw_k,nspinor,paral_kgb,&
4826 0 : & subham)
4827 :
4828 : !Arguments ------------------------------------
4829 : integer,intent(in) :: icg,istwf_k,mcg,nband_k,npw_k
4830 : integer,intent(in) :: nspinor,paral_kgb
4831 : real(dp),intent(inout) :: subham(nband_k*(nband_k+1))
4832 : real(dp),intent(out) :: eig_k(nband_k),evec(2*nband_k,nband_k)
4833 : real(dp),intent(inout),target :: cg(2,mcg)
4834 :
4835 : !Local variables-------------------------------
4836 : integer :: ig,igfirst,block_size,iblock,nblock,block_size_tmp,wfsize
4837 : integer :: iband,ii,ierr,vectsize,use_slk
4838 : character(len=500) :: message
4839 : ! real(dp) :: tsec(2)
4840 0 : real(dp),allocatable :: evec_tmp(:,:),subham_tmp(:), work(:,:)
4841 0 : real(dp),allocatable :: blockvectora(:,:),blockvectorb(:,:),blockvectorc(:,:)
4842 0 : real(dp), contiguous, pointer :: cg_block(:,:)
4843 : ! *********************************************************************
4844 :
4845 0 : if (paral_kgb<0) then
4846 0 : ABI_BUG('paral_kgb should be positive ')
4847 : end if
4848 :
4849 : ! 1 if Scalapack version is used.
4850 0 : use_slk = paral_kgb
4851 :
4852 : !Impose Hermiticity on diagonal elements of subham (and subovl, if needed)
4853 : ! MG FIXME: In these two calls we are aliasing the args
4854 0 : call hermit(subham,subham,ierr,nband_k)
4855 :
4856 : !Diagonalize the Hamitonian matrix
4857 0 : if(istwf_k==2) then
4858 0 : ABI_MALLOC(evec_tmp,(nband_k,nband_k))
4859 0 : ABI_MALLOC(subham_tmp,(nband_k*(nband_k+1)/2))
4860 0 : subham_tmp=subham(1:nband_k*(nband_k+1):2)
4861 0 : evec_tmp=zero
4862 0 : call abi_xhpev('V','U',nband_k,subham_tmp,eig_k,evec_tmp,nband_k,istwf_k=istwf_k,use_slk=use_slk)
4863 0 : evec(:,:)=zero;evec(1:2*nband_k:2,:) =evec_tmp
4864 0 : ABI_FREE(evec_tmp)
4865 0 : ABI_FREE(subham_tmp)
4866 : else
4867 0 : call abi_xhpev('V','U',nband_k,subham,eig_k,evec,nband_k,istwf_k=istwf_k,use_slk=use_slk)
4868 : end if
4869 :
4870 : !Normalize each eigenvector and set phase:
4871 : !The problem with minus/plus signs might be present also if .not. use_subovl
4872 : !if(use_subovl == 0) then
4873 0 : call cg_normev(evec,nband_k,nband_k)
4874 : !end if
4875 :
4876 0 : if(istwf_k==2)then
4877 0 : do iband=1,nband_k
4878 0 : do ii=1,nband_k
4879 0 : if(abs(evec(2*ii,iband))>1.0d-10)then
4880 0 : write(message,'(3a,2i0,2es16.6,a,a)')ch10,&
4881 0 : & ' subdiago: For istwf_k=2, observed the following element of evec :',ch10,&
4882 0 : & iband,ii,evec(2*ii-1,iband),evec(2*ii,iband),ch10,' with a non-negligible imaginary part.'
4883 0 : ABI_BUG(message)
4884 : end if
4885 : end do
4886 : end do
4887 : end if
4888 :
4889 : !=====================================================
4890 : !Carry out rotation of bands C(G,n) according to evecs
4891 : ! ZGEMM if istwfk==1, DGEMM if istwfk==2
4892 : !=====================================================
4893 0 : wfsize=npw_k*nspinor
4894 :
4895 0 : block_size=100
4896 :
4897 0 : if (wfsize<block_size) block_size=wfsize
4898 :
4899 0 : nblock=wfsize/block_size
4900 0 : if (mod(wfsize,block_size)/=0) nblock=nblock+1
4901 :
4902 0 : if (istwf_k>1) then ! evec is real
4903 :
4904 0 : vectsize=2*block_size
4905 :
4906 0 : ABI_MALLOC_OR_DIE(blockvectora,(vectsize,nband_k), ierr)
4907 0 : ABI_MALLOC_OR_DIE(blockvectorb,(nband_k,nband_k), ierr)
4908 0 : ABI_MALLOC_OR_DIE(blockvectorc,(vectsize,nband_k), ierr)
4909 :
4910 0 : do iband=1,nband_k
4911 0 : call abi_xcopy(nband_k,evec(2*iband-1,1),2*nband_k,blockvectorb(iband,1),nband_k)
4912 : end do
4913 :
4914 0 : do iblock=1,nblock
4915 :
4916 0 : igfirst=(iblock-1)*block_size
4917 0 : block_size_tmp=block_size
4918 0 : if (igfirst+block_size>wfsize) then
4919 0 : block_size_tmp=wfsize-igfirst
4920 : end if
4921 :
4922 0 : do iband=1,nband_k
4923 0 : call abi_xcopy(block_size_tmp,cg(1,1+cgindex_subd(iblock,iband)),2,blockvectora(1,iband),1)
4924 0 : call abi_xcopy(block_size_tmp,cg(2,1+cgindex_subd(iblock,iband)),2,blockvectora(block_size+1,iband),1)
4925 0 : if (block_size_tmp<block_size) then
4926 0 : blockvectora(block_size_tmp+1:block_size,iband) = zero
4927 0 : blockvectora(block_size+block_size_tmp+1:2*block_size,iband) = zero
4928 : end if
4929 : end do
4930 :
4931 : call abi_xgemm('N','N',vectsize,nband_k,nband_k,&
4932 0 : & cone,blockvectora,vectsize,blockvectorb,nband_k,czero,blockvectorc,vectsize)
4933 :
4934 0 : do iband=1,nband_k
4935 0 : call abi_xcopy(block_size_tmp,blockvectorc(1,iband),1,cg(1,1+cgindex_subd(iblock,iband)),2)
4936 0 : call abi_xcopy(block_size_tmp,blockvectorc(block_size+1,iband),1,cg(2,1+cgindex_subd(iblock,iband)),2)
4937 : end do
4938 :
4939 : end do
4940 :
4941 0 : ABI_FREE(blockvectora)
4942 0 : ABI_FREE(blockvectorb)
4943 0 : ABI_FREE(blockvectorc)
4944 :
4945 : else ! evec is complex
4946 :
4947 0 : ABI_MALLOC_OR_DIE(work,(2,block_size*nband_k), ierr)
4948 0 : if (nblock==1) then
4949 0 : cg_block => cg(:,icg+1:icg+nband_k*wfsize)
4950 : else
4951 0 : ABI_MALLOC_OR_DIE(cg_block,(2,block_size*nband_k), ierr)
4952 : end if
4953 :
4954 0 : do iblock=1,nblock
4955 0 : igfirst=(iblock-1)*block_size
4956 0 : block_size_tmp=block_size
4957 0 : if (igfirst+block_size>wfsize) then
4958 0 : block_size_tmp=wfsize-igfirst
4959 : end if
4960 0 : if (nblock/=1) then
4961 0 : do iband=1,nband_k
4962 0 : do ig=1,block_size_tmp
4963 0 : cg_block(:,ig+(iband-1)*block_size) = cg(:,ig+cgindex_subd(iblock,iband))
4964 : end do
4965 0 : if (block_size_tmp<block_size) then
4966 0 : do ig=block_size_tmp+1,block_size
4967 0 : cg_block(:,ig+(iband-1)*block_size) = zero
4968 : end do
4969 : end if
4970 : end do
4971 : end if
4972 : call abi_xgemm('N','N',block_size,nband_k,nband_k,cone,cg_block,block_size,evec,nband_k,czero,work,&
4973 0 : & block_size,x_cplx=2)
4974 0 : do iband=1,nband_k
4975 0 : do ig=1,block_size_tmp
4976 0 : cg(:,ig+cgindex_subd(iblock,iband)) = work(:,ig+(iband-1)*block_size)
4977 : end do
4978 : end do
4979 : end do
4980 :
4981 0 : ABI_FREE(work)
4982 0 : if (nblock/=1) then
4983 0 : ABI_FREE(cg_block)
4984 : end if
4985 :
4986 : end if
4987 :
4988 : contains
4989 :
4990 0 : function cgindex_subd(iblock,iband)
4991 :
4992 : integer :: iband,iblock,cgindex_subd
4993 0 : cgindex_subd=(iblock-1)*block_size+(iband-1)*wfsize+icg
4994 : end function cgindex_subd
4995 :
4996 : end subroutine subdiago_low_memory
4997 : !!***
4998 :
4999 : !!****f* m_cgtools/pw_orthon
5000 : !! NAME
5001 : !! pw_orthon
5002 : !!
5003 : !! FUNCTION
5004 : !! Normalize nvec complex vectors each of length nelem and then orthogonalize by modified Gram-Schmidt.
5005 : !! Two orthogonality conditions are available:
5006 : !!
5007 : !! 1) Simple orthogonality: ${<Vec_{i}|Vec_{j}>=Delta_ij}$
5008 : !! 2) Orthogonality with overlap S: ${<Vec_{i}|S|Vec_{j}>=Delta_ij}$
5009 : !!
5010 : !! INPUTS
5011 : !! icg=shift to be given to the location of the data in cg(=vecnm)
5012 : !! igsc=shift to be given to the location of the data in gsc(=ovl_vecnm)
5013 : !! istwf_k=option parameter that describes the storage of wfs
5014 : !! mcg=maximum size of second dimension of cg(=vecnm)
5015 : !! mgsc=maximum size of second dimension of gsc(=ovl_vecnm)
5016 : !! nelem=number of complex elements in each vector
5017 : !! nvec=number of vectors to be orthonormalized
5018 : !! ortalgo= option for the choice of the algorithm
5019 : !! -1: no orthogonalization (direct return)
5020 : !! 0 or 2: old algorithm (use of buffers)
5021 : !! 1: new algorithm (use of blas)
5022 : !! 3: new new algorithm (use of lapack without copy)
5023 : !! useoverlap=select the orthogonality condition
5024 : !! 0: no overlap between vectors
5025 : !! 1: vectors are overlapping
5026 : !! me_g0=1 if this processor has G=0, 0 otherwise
5027 : !! comm=MPI communicator
5028 : !!
5029 : !! SIDE EFFECTS
5030 : !! vecnm= input: vectors to be orthonormalized; array of nvec column
5031 : !! vectors,each of length nelem,shifted by icg
5032 : !! This array is complex or else real(dp) of twice length
5033 : !! output: orthonormalized set of vectors
5034 : !! if (useoverlap==1) only:
5035 : !! ovl_vecnm= input: product of overlap and input vectors:
5036 : !! S|vecnm>,where S is the overlap operator
5037 : !! output: updated S|vecnm> according to vecnm
5038 : !!
5039 : !! NOTES
5040 : !! Note that each vector has an arbitrary phase which is not fixed in this routine.
5041 : !!
5042 : !! WARNING: not yet suited for nspinor=2 with istwfk/=1
5043 : !!
5044 : !! SOURCE
5045 :
5046 493069 : subroutine pw_orthon(icg, igsc, istwf_k, mcg, mgsc, nelem, nvec, ortalgo, ovl_vecnm, useoverlap, vecnm, me_g0, comm)
5047 :
5048 : !Arguments ------------------------------------
5049 : !scalars
5050 : integer,intent(in) :: icg,igsc,istwf_k,mcg,mgsc,nelem,nvec,ortalgo,useoverlap,me_g0,comm
5051 : !arrays
5052 : real(dp),intent(inout) :: ovl_vecnm(2,mgsc*useoverlap),vecnm(2,mcg)
5053 :
5054 : !Local variables-------------------------------
5055 : !scalars
5056 : integer :: ierr,ii,ii0,ii1,ii2,ivec,ivec2
5057 : integer :: rvectsiz,vectsize,cg_idx,gsc_idx
5058 : real(dp) :: doti,dotr,sum,xnorm
5059 : !real(dp) :: cpu, wall, gflops
5060 : #ifdef DEBUG_MODE
5061 : character(len=500) :: msg
5062 : #endif
5063 : !arrays
5064 0 : integer :: cgindex(nvec), gscindex(nvec)
5065 : real(dp) :: buffer2(2),tsec(2)
5066 493069 : real(dp),allocatable :: rblockvectorbx(:,:),rblockvectorx(:,:),rgramxbx(:,:)
5067 493069 : complex(dp),allocatable :: cblockvectorbx(:,:),cblockvectorx(:,:), cgramxbx(:,:)
5068 : ! *************************************************************************
5069 :
5070 : #ifdef DEBUG_MODE
5071 : !Make sure imaginary part at G=0 vanishes
5072 : if (istwf_k == 2 .and. me_g0 == 1) then
5073 : do ivec=1,nvec
5074 : if(abs(vecnm(2,1+nelem*(ivec-1)+icg))>zero)then
5075 : ! if(abs(vecnm(2,1+nelem*(ivec-1)+icg))>tol16)then
5076 : write(msg,'(2a,3i0,2es16.6,a,a)')&
5077 : ' For istwf_k = 2, observed the following element of vecnm :',ch10,&
5078 : nelem,ivec,icg,vecnm(1:2,1+nelem*(ivec-1)+icg), ch10,' with a non-negligible imaginary part.'
5079 : ABI_BUG(msg)
5080 : end if
5081 : end do
5082 : end if
5083 : #endif
5084 :
5085 : ! Nothing to do if ortalgo=-1
5086 493069 : if(ortalgo==-1) return
5087 :
5088 : !call wrtout(std_out, sjoin(" Begin wavefunction orthogonalization with ortalgo:", itoa(ortalgo)))
5089 : !call cwtime(cpu, wall, gflops, "start")
5090 :
5091 3966649 : do ivec=1,nvec
5092 3473580 : cgindex(ivec)=nelem*(ivec-1)+icg+1
5093 3966649 : gscindex(ivec)=nelem*(ivec-1)+igsc+1
5094 : end do
5095 :
5096 : if (ortalgo==3) then
5097 : ! =========================
5098 : ! First (new new) algorithm
5099 : ! =========================
5100 : ! NEW VERSION: avoid copies, use ZHERK for NC
5101 127 : cg_idx = cgindex(1)
5102 127 : if (useoverlap == 1) then
5103 0 : gsc_idx = gscindex(1)
5104 0 : call cgpaw_cholesky(nelem, nvec, vecnm(1,cg_idx), ovl_vecnm(1,gsc_idx), istwf_k, me_g0, comm)
5105 : else
5106 127 : call cgnc_cholesky(nelem, nvec, vecnm(1,cg_idx), istwf_k, me_g0, comm, use_gemm=.FALSE.)
5107 : end if
5108 :
5109 : else if (ortalgo==1) then
5110 : ! =======================
5111 : ! Second (new) algorithm
5112 : ! =======================
5113 : ! This first algorithm seems to be more efficient especially in the parallel band-FFT mode.
5114 :
5115 32 : if(istwf_k==1) then
5116 32 : vectsize=nelem
5117 128 : ABI_MALLOC(cgramxbx,(nvec,nvec))
5118 128 : ABI_MALLOC(cblockvectorx,(vectsize,nvec))
5119 96 : ABI_MALLOC(cblockvectorbx,(vectsize,nvec))
5120 32 : call abi_xcopy(nvec*vectsize,vecnm(:,cgindex(1):cgindex(nvec)-1),1,cblockvectorx,1,x_cplx=2)
5121 32 : if (useoverlap == 1) then
5122 32 : call abi_xcopy(nvec*vectsize,ovl_vecnm(:,gscindex(1):gscindex(nvec)-1),1,cblockvectorbx,1,x_cplx=2)
5123 : else
5124 0 : call abi_xcopy(nvec*vectsize,vecnm(:,cgindex(1):cgindex(nvec)-1),1,cblockvectorbx,1,x_cplx=2)
5125 : end if
5126 32 : call abi_xorthonormalize(cblockvectorx,cblockvectorbx,nvec,comm,cgramxbx,vectsize)
5127 32 : call abi_xcopy(nvec*vectsize,cblockvectorx,1,vecnm(:,cgindex(1):cgindex(nvec)-1),1,x_cplx=2)
5128 32 : if (useoverlap == 1) then
5129 32 : call abi_xtrsm('r','u','n','n',vectsize,nvec,cone,cgramxbx,nvec,cblockvectorbx,vectsize)
5130 32 : call abi_xcopy(nvec*vectsize,cblockvectorbx,1,ovl_vecnm(:,gscindex(1):gscindex(nvec)-1),1,x_cplx=2)
5131 : end if
5132 32 : ABI_FREE(cgramxbx)
5133 32 : ABI_FREE(cblockvectorx)
5134 32 : ABI_FREE(cblockvectorbx)
5135 :
5136 0 : else if (istwf_k==2) then
5137 : ! Pack real and imaginary part of the wavefunctions.
5138 0 : rvectsiz=nelem
5139 0 : vectsize=2*nelem; if(me_g0==1) vectsize=vectsize-1
5140 0 : ABI_MALLOC(rgramxbx,(nvec,nvec))
5141 0 : ABI_MALLOC(rblockvectorx,(vectsize,nvec))
5142 0 : ABI_MALLOC(rblockvectorbx,(vectsize,nvec))
5143 0 : do ivec=1,nvec
5144 0 : if (me_g0 == 1) then
5145 0 : call abi_xcopy(1,vecnm(1,cgindex(ivec)),1,rblockvectorx (1,ivec),1)
5146 0 : call abi_xcopy(rvectsiz-1,vecnm(1,cgindex(ivec)+1),2,rblockvectorx(2,ivec),1)
5147 0 : call abi_xcopy(rvectsiz-1,vecnm(2,cgindex(ivec)+1),2,rblockvectorx(rvectsiz+1,ivec),1)
5148 0 : if (useoverlap == 1) then
5149 0 : call abi_xcopy(1,ovl_vecnm(1,gscindex(ivec)),1,rblockvectorbx(1,ivec),1)
5150 0 : call abi_xcopy(rvectsiz-1,ovl_vecnm(1,gscindex(ivec)+1),2,rblockvectorbx(2,ivec),1)
5151 0 : call abi_xcopy(rvectsiz-1,ovl_vecnm(2,gscindex(ivec)+1),2,rblockvectorbx(rvectsiz+1,ivec),1)
5152 : else
5153 0 : call abi_xcopy(1,vecnm(1,cgindex(ivec)),1,rblockvectorbx(1,ivec),1)
5154 0 : call abi_xcopy(rvectsiz-1,vecnm(1,cgindex(ivec)+1),2,rblockvectorbx(2,ivec),1)
5155 0 : call abi_xcopy(rvectsiz-1,vecnm(2,cgindex(ivec)+1),2,rblockvectorbx(rvectsiz+1,ivec),1)
5156 : end if
5157 0 : rblockvectorx (2:vectsize,ivec)=rblockvectorx (2:vectsize,ivec)*sqrt2
5158 0 : rblockvectorbx(2:vectsize,ivec)=rblockvectorbx(2:vectsize,ivec)*sqrt2
5159 : else
5160 0 : call abi_xcopy(rvectsiz,vecnm(1,cgindex(ivec)),2,rblockvectorx(1,ivec),1)
5161 0 : call abi_xcopy(rvectsiz,vecnm(2,cgindex(ivec)),2,rblockvectorx(rvectsiz+1,ivec),1)
5162 0 : if (useoverlap == 1) then
5163 0 : call abi_xcopy(rvectsiz,ovl_vecnm(1,gscindex(ivec)),2,rblockvectorbx(1,ivec),1)
5164 0 : call abi_xcopy(rvectsiz,ovl_vecnm(2,gscindex(ivec)),2,rblockvectorbx(rvectsiz+1,ivec),1)
5165 : else
5166 0 : call abi_xcopy(rvectsiz,vecnm(1,cgindex(ivec)),2,rblockvectorbx(1,ivec),1)
5167 0 : call abi_xcopy(rvectsiz,vecnm(2,cgindex(ivec)),2,rblockvectorbx(rvectsiz+1,ivec),1)
5168 : end if
5169 0 : rblockvectorx (1:vectsize,ivec)=rblockvectorx (1:vectsize,ivec)*sqrt2
5170 0 : rblockvectorbx(1:vectsize,ivec)=rblockvectorbx(1:vectsize,ivec)*sqrt2
5171 : end if
5172 : end do
5173 :
5174 0 : call ortho_reim(rblockvectorx,rblockvectorbx,nvec,comm,rgramxbx,vectsize)
5175 :
5176 0 : do ivec=1,nvec
5177 : ! Unpack results
5178 0 : if (me_g0 == 1) then
5179 0 : call abi_xcopy(1,rblockvectorx(1,ivec),1,vecnm(1,cgindex(ivec)),1)
5180 0 : vecnm(2,cgindex(ivec))=zero
5181 0 : rblockvectorx(2:vectsize,ivec)=rblockvectorx(2:vectsize,ivec)/sqrt2
5182 0 : call abi_xcopy(rvectsiz-1,rblockvectorx(2,ivec),1,vecnm(1,cgindex(ivec)+1),2)
5183 0 : call abi_xcopy(rvectsiz-1,rblockvectorx(rvectsiz+1,ivec),1,vecnm(2,cgindex(ivec)+1),2)
5184 : else
5185 0 : rblockvectorx(1:vectsize,ivec)=rblockvectorx(1:vectsize,ivec)/sqrt2
5186 0 : call abi_xcopy(rvectsiz,rblockvectorx(1,ivec),1,vecnm(1,cgindex(ivec)),2)
5187 0 : call abi_xcopy(rvectsiz,rblockvectorx(rvectsiz+1,ivec),1,vecnm(2,cgindex(ivec)),2)
5188 : end if
5189 :
5190 0 : if(useoverlap == 1) then
5191 0 : call abi_xtrsm('r','u','n','n',vectsize,nvec,one,rgramxbx,nvec,rblockvectorbx,vectsize)
5192 0 : if (me_g0 == 1) then
5193 0 : call abi_xcopy(1,rblockvectorbx(1,ivec),1,ovl_vecnm(1,gscindex(ivec)),1)
5194 0 : ovl_vecnm(2,gscindex(ivec))=zero
5195 0 : rblockvectorbx(2:vectsize,ivec)=rblockvectorbx(2:vectsize,ivec)/sqrt2
5196 0 : call abi_xcopy(rvectsiz-1,rblockvectorbx(2,ivec),1,ovl_vecnm(1,gscindex(ivec)+1),2)
5197 0 : call abi_xcopy(rvectsiz-1,rblockvectorbx(rvectsiz+1,ivec),1,ovl_vecnm(2,gscindex(ivec)+1),2)
5198 : else
5199 0 : rblockvectorbx(1:vectsize,ivec)=rblockvectorbx(1:vectsize,ivec)/sqrt2
5200 0 : call abi_xcopy(rvectsiz,rblockvectorbx(1,ivec),1,ovl_vecnm(1,gscindex(ivec)),2)
5201 0 : call abi_xcopy(rvectsiz,rblockvectorbx(rvectsiz+1,ivec),1,ovl_vecnm(2,gscindex(ivec)),2)
5202 : end if
5203 : end if
5204 : end do
5205 0 : ABI_FREE(rgramxbx)
5206 0 : ABI_FREE(rblockvectorx)
5207 0 : ABI_FREE(rblockvectorbx)
5208 : end if
5209 :
5210 : else if (ortalgo==4) then
5211 : ! else if (ANY(ortalgo==(/0,2/))) then
5212 :
5213 0 : cg_idx = cgindex(1)
5214 0 : if (useoverlap==0) then
5215 0 : call cgnc_gramschmidt(nelem,nvec,vecnm(1,cg_idx),istwf_k,me_g0,comm)
5216 : else
5217 0 : gsc_idx = gscindex(1)
5218 0 : call cgpaw_gramschmidt(nelem,nvec,vecnm(1,cg_idx),ovl_vecnm(1,gsc_idx),istwf_k,me_g0,comm)
5219 : end if
5220 :
5221 : else if (ANY(ortalgo==(/0,2/))) then
5222 : ! =======================
5223 : ! Third (old) algorithm
5224 : ! =======================
5225 : ! TODO: This algo should be removed. Ref files should be updated though.
5226 :
5227 3957804 : do ivec=1,nvec
5228 : ! Normalize each vecnm(n,m) in turn:
5229 :
5230 3464894 : if (useoverlap==1) then ! Using overlap S...
5231 1243486 : if(istwf_k/=2)then
5232 1213123 : sum=zero;ii0=1
5233 : else
5234 30363 : if (me_g0 ==1) then
5235 30363 : sum=half*ovl_vecnm(1,1+nelem*(ivec-1)+igsc)*vecnm(1,1+nelem*(ivec-1)+icg)
5236 30363 : ii0=2
5237 : else
5238 0 : sum=zero;ii0=1
5239 : end if
5240 : end if
5241 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:sum) SHARED(icg,ivec,nelem,vecnm)
5242 427485747 : do ii=ii0+nelem*(ivec-1),nelem*ivec
5243 427485747 : sum=sum+vecnm(1,ii+icg)*ovl_vecnm(1,ii+igsc)+vecnm(2,ii+icg)*ovl_vecnm(2,ii+igsc)
5244 : end do
5245 :
5246 : else ! Without overlap...
5247 2221408 : if(istwf_k/=2)then
5248 2132603 : sum=zero;ii0=1
5249 : else
5250 88805 : if (me_g0 ==1) then
5251 88805 : sum=half*vecnm(1,1+nelem*(ivec-1)+icg)**2
5252 88805 : ii0=2
5253 : else
5254 0 : sum=zero;ii0=1
5255 : end if
5256 : end if
5257 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:sum) SHARED(icg,ivec,nelem,vecnm)
5258 727403488 : do ii=ii0+nelem*(ivec-1)+icg,nelem*ivec+icg
5259 727403488 : sum=sum+vecnm(1,ii)**2+vecnm(2,ii)**2
5260 : end do
5261 : end if
5262 :
5263 3464894 : call timab(48,1,tsec)
5264 3464894 : call xmpi_sum(sum,comm,ierr)
5265 3464894 : call timab(48,2,tsec)
5266 :
5267 3464894 : if(istwf_k>=2)sum=two*sum
5268 3464894 : xnorm = sqrt(abs(sum)) ; sum=1.0_dp/xnorm
5269 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(icg,ivec,nelem,sum,vecnm)
5270 1155008403 : do ii=1+nelem*(ivec-1)+icg,nelem*ivec+icg
5271 1151543509 : vecnm(1,ii)=vecnm(1,ii)*sum
5272 1155008403 : vecnm(2,ii)=vecnm(2,ii)*sum
5273 : end do
5274 3464894 : if (useoverlap==1) then
5275 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(icg,ivec,nelem,sum,ovl_vecnm)
5276 427516110 : do ii=1+nelem*(ivec-1)+igsc,nelem*ivec+igsc
5277 426272624 : ovl_vecnm(1,ii)=ovl_vecnm(1,ii)*sum
5278 427516110 : ovl_vecnm(2,ii)=ovl_vecnm(2,ii)*sum
5279 : end do
5280 : end if
5281 :
5282 : ! Remove projection in all higher states.
5283 7422698 : if (ivec<nvec) then
5284 :
5285 2971984 : if(istwf_k==1)then
5286 : ! Cannot use time-reversal symmetry
5287 :
5288 2744937 : if (useoverlap==1) then ! Using overlap.
5289 11636647 : do ivec2=ivec+1,nvec
5290 : ! First compute scalar product
5291 10560222 : dotr=zero ; doti=zero
5292 10560222 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+igsc
5293 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:doti,dotr) SHARED(ii1,ii2,nelem,vecnm)
5294 3641452686 : do ii=1,nelem
5295 3630892464 : dotr=dotr+vecnm(1,ii1+ii)*ovl_vecnm(1,ii2+ii)+vecnm(2,ii1+ii)*ovl_vecnm(2,ii2+ii)
5296 3641452686 : doti=doti+vecnm(1,ii1+ii)*ovl_vecnm(2,ii2+ii)-vecnm(2,ii1+ii)*ovl_vecnm(1,ii2+ii)
5297 : end do
5298 :
5299 10560222 : call timab(48,1,tsec)
5300 10560222 : buffer2(1)=doti;buffer2(2)=dotr
5301 10560222 : call xmpi_sum(buffer2,comm,ierr)
5302 10560222 : call timab(48,2,tsec)
5303 10560222 : doti=buffer2(1)
5304 10560222 : dotr=buffer2(2)
5305 :
5306 : ! Then subtract the appropriate amount of the lower state
5307 10560222 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+icg
5308 : #ifdef FC_INTEL
5309 : ! DIR$ ivdep
5310 : #endif
5311 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(doti,dotr,ii1,ii2,nelem,vecnm)
5312 3641452686 : do ii=1,nelem
5313 3630892464 : vecnm(1,ii2+ii)=vecnm(1,ii2+ii)-dotr*vecnm(1,ii1+ii)+doti*vecnm(2,ii1+ii)
5314 3641452686 : vecnm(2,ii2+ii)=vecnm(2,ii2+ii)-doti*vecnm(1,ii1+ii)-dotr*vecnm(2,ii1+ii)
5315 : end do
5316 :
5317 10560222 : ii1=nelem*(ivec-1)+igsc;ii2=nelem*(ivec2-1)+igsc
5318 3642529111 : do ii=1,nelem
5319 : ovl_vecnm(1,ii2+ii)=ovl_vecnm(1,ii2+ii)&
5320 : & -dotr*ovl_vecnm(1,ii1+ii)&
5321 3630892464 : & +doti*ovl_vecnm(2,ii1+ii)
5322 : ovl_vecnm(2,ii2+ii)=ovl_vecnm(2,ii2+ii)&
5323 : -doti*ovl_vecnm(1,ii1+ii)&
5324 3641452686 : & -dotr*ovl_vecnm(2,ii1+ii)
5325 : end do
5326 : end do
5327 : else
5328 : ! ----- No overlap -----
5329 17431701 : do ivec2=ivec+1,nvec
5330 : ! First compute scalar product
5331 15763189 : dotr=zero ; doti=zero
5332 15763189 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+icg
5333 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:doti,dotr) SHARED(ii1,ii2,nelem,vecnm)
5334 6368777193 : do ii=1,nelem
5335 : dotr=dotr+vecnm(1,ii1+ii)*vecnm(1,ii2+ii)+&
5336 6353014004 : & vecnm(2,ii1+ii)*vecnm(2,ii2+ii)
5337 : doti=doti+vecnm(1,ii1+ii)*vecnm(2,ii2+ii)-&
5338 6368777193 : & vecnm(2,ii1+ii)*vecnm(1,ii2+ii)
5339 : end do
5340 : ! Init mpi_comm
5341 15763189 : buffer2(1)=doti
5342 15763189 : buffer2(2)=dotr
5343 15763189 : call timab(48,1,tsec)
5344 15763189 : call xmpi_sum(buffer2,comm,ierr)
5345 : ! call xmpi_sum(doti,spaceComm,ierr)
5346 : ! call xmpi_sum(dotr,spaceComm,ierr)
5347 15763189 : call timab(48,2,tsec)
5348 15763189 : doti=buffer2(1)
5349 15763189 : dotr=buffer2(2)
5350 :
5351 : ! Then subtract the appropriate amount of the lower state
5352 : #ifdef FC_INTEL
5353 : ! DIR$ ivdep
5354 : #endif
5355 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(doti,dotr,ii1,ii2,nelem,vecnm)
5356 6370445705 : do ii=1,nelem
5357 : vecnm(1,ii2+ii)=vecnm(1,ii2+ii)-dotr*vecnm(1,ii1+ii)+&
5358 6353014004 : & doti*vecnm(2,ii1+ii)
5359 : vecnm(2,ii2+ii)=vecnm(2,ii2+ii)-doti*vecnm(1,ii1+ii)-&
5360 6368777193 : & dotr*vecnm(2,ii1+ii)
5361 : end do
5362 : end do
5363 :
5364 : end if ! Test on useoverlap
5365 :
5366 227047 : else if(istwf_k==2)then
5367 : ! At gamma point use of time-reversal symmetry saves cpu time.
5368 :
5369 101215 : if (useoverlap==1) then
5370 : ! ----- Using overlap -----
5371 349663 : do ivec2=ivec+1,nvec
5372 : ! First compute scalar product
5373 322921 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+igsc
5374 322921 : if (me_g0 ==1) then
5375 322921 : dotr=half*vecnm(1,ii1+1)*ovl_vecnm(1,ii2+1)
5376 : ! Avoid double counting G=0 contribution
5377 : ! Imaginary part of vecnm at G=0 should be zero,so only take real part
5378 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotr) SHARED(ii1,ii2,nelem,vecnm)
5379 334515967 : do ii=2,nelem
5380 : dotr=dotr+vecnm(1,ii1+ii)*ovl_vecnm(1,ii2+ii)+&
5381 334515967 : & vecnm(2,ii1+ii)*ovl_vecnm(2,ii2+ii)
5382 : end do
5383 : else
5384 0 : dotr=0._dp
5385 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotr) SHARED(ii1,ii2,nelem,vecnm)
5386 0 : do ii=1,nelem
5387 : dotr=dotr+vecnm(1,ii1+ii)*ovl_vecnm(1,ii2+ii)+&
5388 0 : & vecnm(2,ii1+ii)*ovl_vecnm(2,ii2+ii)
5389 : end do
5390 : end if
5391 :
5392 322921 : dotr=two*dotr
5393 :
5394 322921 : call timab(48,1,tsec)
5395 322921 : call xmpi_sum(dotr,comm,ierr)
5396 322921 : call timab(48,2,tsec)
5397 :
5398 : ! Then subtract the appropriate amount of the lower state
5399 322921 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+icg
5400 : #ifdef FC_INTEL
5401 : ! DIR$ ivdep
5402 : #endif
5403 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(dotr,ii1,ii2,nelem,vecnm)
5404 334838888 : do ii=1,nelem
5405 334515967 : vecnm(1,ii2+ii)=vecnm(1,ii2+ii)-dotr*vecnm(1,ii1+ii)
5406 334838888 : vecnm(2,ii2+ii)=vecnm(2,ii2+ii)-dotr*vecnm(2,ii1+ii)
5407 : end do
5408 322921 : ii1=nelem*(ivec-1)+igsc;ii2=nelem*(ivec2-1)+igsc
5409 335188551 : do ii=1,nelem
5410 334515967 : ovl_vecnm(1,ii2+ii)=ovl_vecnm(1,ii2+ii)-dotr*ovl_vecnm(1,ii1+ii)
5411 334838888 : ovl_vecnm(2,ii2+ii)=ovl_vecnm(2,ii2+ii)-dotr*ovl_vecnm(2,ii1+ii)
5412 : end do
5413 : end do
5414 : else
5415 : ! ----- No overlap -----
5416 771810 : do ivec2=ivec+1,nvec
5417 : ! First compute scalar product
5418 697337 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+icg
5419 697337 : if (me_g0 ==1) then
5420 : ! Avoid double counting G=0 contribution
5421 : ! Imaginary part of vecnm at G=0 should be zero,so only take real part
5422 697337 : dotr=half*vecnm(1,ii1+1)*vecnm(1,ii2+1)
5423 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotr) SHARED(ii1,ii2,nelem,vecnm)
5424 436551603 : do ii=2,nelem
5425 436551603 : dotr=dotr+vecnm(1,ii1+ii)*vecnm(1,ii2+ii)+vecnm(2,ii1+ii)*vecnm(2,ii2+ii)
5426 : end do
5427 : else
5428 0 : dotr=0._dp
5429 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotr) SHARED(ii1,ii2,nelem,vecnm)
5430 0 : do ii=1,nelem
5431 0 : dotr=dotr+vecnm(1,ii1+ii)*vecnm(1,ii2+ii)+vecnm(2,ii1+ii)*vecnm(2,ii2+ii)
5432 : end do
5433 : end if
5434 697337 : dotr=two*dotr
5435 :
5436 697337 : call timab(48,1,tsec)
5437 697337 : call xmpi_sum(dotr,comm,ierr)
5438 697337 : call timab(48,2,tsec)
5439 :
5440 : ! Then subtract the appropriate amount of the lower state
5441 : #ifdef FC_INTEL
5442 : ! DIR$ ivdep
5443 : #endif
5444 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(dotr,ii1,ii2,nelem,vecnm)
5445 437323413 : do ii=1,nelem
5446 436551603 : vecnm(1,ii2+ii)=vecnm(1,ii2+ii)-dotr*vecnm(1,ii1+ii)
5447 437248940 : vecnm(2,ii2+ii)=vecnm(2,ii2+ii)-dotr*vecnm(2,ii1+ii)
5448 : end do
5449 : end do
5450 : end if ! Test on useoverlap
5451 :
5452 : else
5453 : ! At other special points,use of time-reversal symmetry saves cpu time.
5454 :
5455 125832 : if (useoverlap==1) then
5456 : ! ----- Using overlap -----
5457 690726 : do ivec2=ivec+1,nvec
5458 : ! First compute scalar product
5459 648020 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+igsc
5460 : ! Avoid double counting G=0 contribution
5461 : ! Imaginary part of vecnm at G=0 should be zero,so only take real part
5462 648020 : dotr=zero
5463 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotr) SHARED(ii1,ii2,nelem,vecnm)
5464 598498339 : do ii=1,nelem
5465 598498339 : dotr=dotr+vecnm(1,ii1+ii)*ovl_vecnm(1,ii2+ii)+vecnm(2,ii1+ii)*ovl_vecnm(2,ii2+ii)
5466 : end do
5467 648020 : dotr=two*dotr
5468 :
5469 648020 : call timab(48,1,tsec)
5470 648020 : call xmpi_sum(dotr,comm,ierr)
5471 648020 : call timab(48,2,tsec)
5472 :
5473 : ! Then subtract the appropriate amount of the lower state
5474 648020 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+icg
5475 : #ifdef FC_INTEL
5476 : ! DIR$ ivdep
5477 : #endif
5478 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(dotr,ii1,ii2,nelem,vecnm)
5479 598498339 : do ii=1,nelem
5480 597850319 : vecnm(1,ii2+ii)=vecnm(1,ii2+ii)-dotr*vecnm(1,ii1+ii)
5481 598498339 : vecnm(2,ii2+ii)=vecnm(2,ii2+ii)-dotr*vecnm(2,ii1+ii)
5482 : end do
5483 648020 : ii1=nelem*(ivec-1)+igsc;ii2=nelem*(ivec2-1)+igsc
5484 599189065 : do ii=1,nelem
5485 597850319 : ovl_vecnm(1,ii2+ii)=ovl_vecnm(1,ii2+ii)-dotr*ovl_vecnm(1,ii1+ii)
5486 598498339 : ovl_vecnm(2,ii2+ii)=ovl_vecnm(2,ii2+ii)-dotr*ovl_vecnm(2,ii1+ii)
5487 : end do
5488 : end do
5489 : else
5490 : ! ----- No overlap -----
5491 1178817 : do ivec2=ivec+1,nvec
5492 : ! First compute scalar product
5493 1095691 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+icg
5494 : ! Avoid double counting G=0 contribution
5495 : ! Imaginary part of vecnm at G=0 should be zero,so only take real part
5496 1095691 : dotr=zero
5497 : !$OMP PARALLEL DO PRIVATE(ii) REDUCTION(+:dotr) SHARED(ii1,ii2,nelem,vecnm)
5498 574788833 : do ii=1,nelem
5499 574788833 : dotr=dotr+vecnm(1,ii1+ii)*vecnm(1,ii2+ii)+vecnm(2,ii1+ii)*vecnm(2,ii2+ii)
5500 : end do
5501 1095691 : dotr=two*dotr
5502 :
5503 1095691 : call timab(48,1,tsec)
5504 1095691 : call xmpi_sum(dotr,comm,ierr)
5505 1095691 : call timab(48,2,tsec)
5506 :
5507 : ! Then subtract the appropriate amount of the lower state
5508 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(dotr,ii1,ii2,nelem,vecnm)
5509 574871959 : do ii=1,nelem
5510 573693142 : vecnm(1,ii2+ii)=vecnm(1,ii2+ii)-dotr*vecnm(1,ii1+ii)
5511 574788833 : vecnm(2,ii2+ii)=vecnm(2,ii2+ii)-dotr*vecnm(2,ii1+ii)
5512 : end do
5513 : end do
5514 : end if
5515 :
5516 : end if ! End use of time-reversal symmetry
5517 : end if ! Test on "ivec"
5518 : end do ! end loop over vectors (or bands) with index ivec :
5519 :
5520 : else
5521 0 : ABI_ERROR(sjoin("Wrong value for ortalgo:", itoa(ortalgo)))
5522 : end if
5523 :
5524 : !call cwtime_report(sjoin(" pw_orthon with ortalgo: ", itoa(ortalgo)), cpu, wall, gflops)
5525 :
5526 493069 : end subroutine pw_orthon
5527 : !!***
5528 :
5529 : !!****f* m_cgtools/pw_orthon_paw
5530 : !! NAME
5531 : !! pw_orthon_paw
5532 : !!
5533 : !! FUNCTION
5534 : !! Normalize nvec complex vectors each of length nelem and then orthogonalize by modified Gram-Schmidt.
5535 : !! The overlap matrix <c_m|S|c_n> (S can be identity) has to be provided as input, and is overwritten.
5536 : !!
5537 : !! INPUTS
5538 : !! icg=shift to be given to the location of the data in cg(=vecnm)
5539 : !! mcg=maximum size of second dimension of cg(=vecnm)
5540 : !! nelem=number of complex elements in each vector
5541 : !! nspinor=number of spinorial components of the wavefunctions (on current proc)
5542 : !! nvec=number of vectors to be orthonormalized
5543 : !! ortalgo= option for the choice of the algorithm
5544 : !! -1: no orthogonalization (direct return)
5545 : !! 0: do orthogonalization
5546 : !! comm=MPI communicator
5547 : !!
5548 : !! SIDE EFFECTS
5549 : !! cprj(optional)=<p_i|c_n> coefficients, updated to keep them consistent with the WF at output
5550 : !! ovl_mat=overlap matrix <c_m|S|c_n> for m<=n
5551 : !! vecnm= input: vectors to be orthonormalized; array of nvec column
5552 : !! vectors,each of length nelem,shifted by icg
5553 : !! This array is complex or else real(dp) of twice length
5554 : !! output: orthonormalized set of vectors
5555 : !!
5556 : !! NOTES
5557 : !! Note that each vector has an arbitrary phase which is not fixed in this routine.
5558 : !!
5559 : !! SOURCE
5560 :
5561 0 : subroutine pw_orthon_cprj(icg,mcg,nelem,nspinor,nvec,ortalgo,ovl_mat,vecnm,cprj)
5562 :
5563 : !Arguments ------------------------------------
5564 : !scalars
5565 : integer,intent(in) :: icg,mcg,nelem,nspinor,nvec,ortalgo
5566 : !arrays
5567 : real(dp),intent(inout) :: ovl_mat(nvec*(nvec+1)),vecnm(2,mcg)
5568 : type(pawcprj_type),intent(inout),optional,target :: cprj(:,:)
5569 :
5570 : !Local variables-------------------------------
5571 : !scalars
5572 : logical :: do_cprj
5573 : integer :: ii,ii1,ii2,ivec,ivec2,ivec3,iv1l,iv2l,iv3l,iv1r,iv2r,iv3r,ncprj
5574 : real(dp) :: doti,dotr,summ,xnorm
5575 : !arrays
5576 0 : real(dp) :: ovl_row_tmp(2*nvec),ovl_col_tmp(2*nvec)
5577 : real(dp) :: re,im
5578 : ! *************************************************************************
5579 :
5580 : !Nothing to do if ortalgo=-1
5581 0 : if(ortalgo==-1) return
5582 :
5583 0 : do_cprj=.false.
5584 0 : if (present(cprj)) then
5585 0 : do_cprj=.true.
5586 0 : ncprj = size(cprj,2)
5587 0 : if (ncprj/=nspinor*nvec) then
5588 0 : ABI_ERROR('bad size for cprj')
5589 : end if
5590 : end if
5591 :
5592 : ! The overlap matrix is : ovl(i,j) = <psi_i|S|psi_j> = (<psi_j|S|psi_i>)^*
5593 : ! The row index stands for the "left" band index
5594 : ! The column index stands for the "right" band index
5595 : ! Only the upper triangular part of the (complex) overlap matrix is stored, so only elements with i<=j.
5596 : ! They are stored in the following order: ovl(1,1),ovl(1,2),ovl(2,2),ovl(1,3),ovl(2,3),...
5597 : ! so:
5598 : ! -- shift for the ith row : 2.(i.(i-1)/2) = i.(i-1)
5599 : ! -- shift for the ith column : 2.(i-1)+1 = 2.i-1
5600 : ! => index of real part of elem in the jth column and ith row (=ovl(i,j)) : 2.i-1+j.(j-1) (for i<=j)
5601 : ! => index of imaginary part = index of real part + 1
5602 : ! After orthogonalizing the first n vectors, we have:
5603 : ! for i<=n, i<=j : ovl(i,j) = delta_ij
5604 :
5605 0 : do ivec=1,nvec
5606 :
5607 : ! First we normalize the current vector
5608 0 : iv1r = ivec*(ivec-1) ! ith row
5609 0 : iv1l = 2*ivec-1 ! ith column
5610 : ! ovl(i1,i1) = <psi_i1|S|psi_i1>
5611 0 : summ = ovl_mat(iv1r+iv1l)
5612 0 : xnorm = sqrt(abs(summ)) ; summ=1.0_dp/xnorm
5613 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(icg,ivec,nelem,summ,vecnm)
5614 0 : do ii=1+nelem*(ivec-1)+icg,nelem*ivec+icg
5615 0 : vecnm(1,ii)=vecnm(1,ii)*summ
5616 0 : vecnm(2,ii)=vecnm(2,ii)*summ
5617 : end do
5618 : ! Apply the normalization to cprj coeffs
5619 0 : if (do_cprj) call pawcprj_axpby(zero,summ,cprj(:,nspinor*(ivec-1)+1:nspinor*ivec),cprj(:,nspinor*(ivec-1)+1:nspinor*ivec))
5620 :
5621 : ! As the norm of |psi_i1> changed, we update the overlap matrix accordingly.
5622 : ! From previous iterations, we already have:
5623 : ! ovl(i2,i1) = <psi_i2|S|psi_i1> = 0 for i2<i1
5624 : ! so we need to change only:
5625 : ! ovl(i1,i2) = <psi_i1|S|psi_i2> for i1<=i2
5626 0 : do ivec2=ivec,nvec
5627 0 : iv2r=ivec2*(ivec2-1)
5628 0 : if (ivec<ivec2) then
5629 0 : ovl_mat(iv2r+iv1l ) = ovl_mat(iv2r+iv1l )*summ
5630 0 : ovl_mat(iv2r+iv1l+1) = ovl_mat(iv2r+iv1l+1)*summ
5631 0 : else if (ivec==ivec2) then
5632 0 : ovl_mat(iv2r+iv1l ) = ovl_mat(iv2r+iv1l )*summ*summ
5633 0 : ovl_mat(iv2r+iv1l+1) = ovl_mat(iv2r+iv1l+1)*summ*summ
5634 0 : re = ovl_mat(iv2r+iv1l )
5635 0 : im = ovl_mat(iv2r+iv1l+1)
5636 0 : if (abs(re-1)>tol10.or.abs(im)>tol10) then
5637 0 : write(std_out,'(a,es21.10e3)') '(pw_ortho) ovl (re)',re
5638 0 : write(std_out,'(a,es21.10e3)') '(pw_ortho) ovl (im)',im
5639 0 : ABI_WARNING('In pw_orthon_cprj: the result should be equal to one!')
5640 : end if
5641 : end if
5642 : end do
5643 :
5644 : ! Remove projection in all higher states.
5645 0 : if (ivec<nvec) then
5646 :
5647 0 : do ivec2=ivec+1,nvec
5648 :
5649 0 : iv2r = ivec2*(ivec2-1)
5650 0 : iv2l = 2*ivec2-1
5651 : ! (dotr,doti) = <psi_i1|S|psi_i2>
5652 0 : dotr = ovl_mat(iv2r+iv1l )
5653 0 : doti = ovl_mat(iv2r+iv1l+1)
5654 :
5655 : ! Then subtract the appropriate amount of the lower state
5656 0 : ii1=nelem*(ivec-1)+icg;ii2=nelem*(ivec2-1)+icg
5657 : ! |psi'_i2> = |psi_i2> - <psi_i1|S|psi_i2> |psi_i1>
5658 : !$OMP PARALLEL DO PRIVATE(ii) SHARED(doti,dotr,ii1,ii2,nelem,vecnm)
5659 0 : do ii=1,nelem
5660 0 : vecnm(1,ii2+ii)=vecnm(1,ii2+ii)-dotr*vecnm(1,ii1+ii)+doti*vecnm(2,ii1+ii)
5661 0 : vecnm(2,ii2+ii)=vecnm(2,ii2+ii)-doti*vecnm(1,ii1+ii)-dotr*vecnm(2,ii1+ii)
5662 : end do
5663 0 : if (do_cprj) call pawcprj_zaxpby((/-dotr,-doti/),(/one,zero/),cprj(:,nspinor*(ivec-1)+1:nspinor*ivec),&
5664 0 : cprj(:,nspinor*(ivec2-1)+1:nspinor*ivec2))
5665 : ! As |psi_i2> changed, we update the overlap matrix accordingly.
5666 : ! We have: <psi'_i3|S|psi'_i2> = <psi'_i3|S|psi_i2> - <psi_i1|S|psi_i2> <psi'_i3|S|psi_i1>
5667 : ! Remember that i2>i1.
5668 : ! For i3<=i2, we compute the new column i2.
5669 : ! For i3<i1:
5670 : ! (1) <psi'_i3|S|psi'_i2> = <psi_i3|S|psi_i2> - <psi_i1|S|psi_i2> <psi_i3|S|psi_i1>
5671 : ! = <psi_i3|S|psi_i2>
5672 : ! as for i3<i1 we have <psi_i3|S|psi_i1> = 0
5673 : ! For i1<=i3<i2:
5674 : ! (2) <psi'_i3|S|psi'_i2> = <psi_i3|S|psi_i2> - <psi_i1|S|psi_i2> <psi_i3|S|psi_i1>
5675 : ! = <psi_i3|S|psi_i2> - <psi_i1|S|psi_i2> (<psi_i1|S|psi_i3>)^*
5676 : ! For i3=i2:
5677 : ! (3) <psi'_i3|S|psi'_i2> = <psi'_i2|S|psi_i2> - <psi_i1|S|psi_i2> <psi'_i2|S|psi_i1>
5678 : ! = <psi_i2|S|psi_i2> - <psi_i1|S|psi_i2> <psi_i2|S|psi_i1>
5679 : ! - <psi_i1|S|psi_i2> <psi_i2|S|psi_i1> + <psi_i1|S|psi_i2> <psi_1|S|psi_1> <psi_i2|S|psi_i1>
5680 : ! = <psi_i2|S|psi_i2> - <psi_i1|S|psi_i2> <psi_i2|S|psi_i1>
5681 : ! = <psi_i2|S|psi_i2> - <psi_i1|S|psi_i2> (<psi_i1|S|psi_i2>)^*
5682 : ! so the case i3=i2 (3) is equivalent to the case i1<=i3<i2 (2) with i3=i2.
5683 : ! Here we compute (2) and (3) in a temporary array:
5684 0 : do ivec3=ivec,ivec2
5685 0 : iv3r=ivec3*(ivec3-1)
5686 0 : iv3l=2*ivec3-1
5687 0 : ovl_col_tmp(iv3l ) = ovl_mat(iv2r+iv3l ) - dotr*ovl_mat(iv3r+iv1l) - doti*ovl_mat(iv3r+iv1l+1)
5688 0 : ovl_col_tmp(iv3l+1) = ovl_mat(iv2r+iv3l+1) - doti*ovl_mat(iv3r+iv1l) + dotr*ovl_mat(iv3r+iv1l+1)
5689 : end do
5690 : ! For i2<i3, we compute the new row i2.
5691 : ! (4) <psi'_i2|S|psi_i3> = <psi_i2|S|psi_i3> - <psi_i2|S|psi_i1> <psi_i1|S|psi_i3>
5692 : ! = <psi_i2|S|psi_i3> - (<psi_i1|S|psi_i2>)^* <psi_i1|S|psi_i3>
5693 : ! Here we compute (4) in a temporary array:
5694 0 : do ivec3=ivec2+1,nvec
5695 0 : iv3r=ivec3*(ivec3-1)
5696 0 : iv3l=2*ivec3-1
5697 0 : ovl_row_tmp(iv3l ) = ovl_mat(iv3r+iv2l ) - dotr*ovl_mat(iv3r+iv1l) - doti*ovl_mat(iv3r+iv1l+1)
5698 0 : ovl_row_tmp(iv3l+1) = ovl_mat(iv3r+iv2l+1) + doti*ovl_mat(iv3r+iv1l) - dotr*ovl_mat(iv3r+iv1l+1)
5699 : end do
5700 : ! We update the column i2 (starting from ivec and not 1, thanks to (1))
5701 0 : do ivec3=ivec,ivec2
5702 0 : iv3l=2*ivec3-1
5703 0 : ovl_mat(iv2r+iv3l ) = ovl_col_tmp(iv3l )
5704 0 : ovl_mat(iv2r+iv3l+1) = ovl_col_tmp(iv3l+1)
5705 : end do
5706 : ! We update the row i2
5707 0 : do ivec3=ivec2+1,nvec
5708 0 : iv3r=ivec3*(ivec3-1)
5709 0 : iv3l=2*ivec3-1
5710 0 : ovl_mat(iv3r+iv2l ) = ovl_row_tmp(iv3l )
5711 0 : ovl_mat(iv3r+iv2l+1) = ovl_row_tmp(iv3l+1)
5712 : end do
5713 : end do
5714 :
5715 : end if ! Test on "ivec"
5716 :
5717 : !end loop over vectors (or bands) with index ivec :
5718 : end do
5719 :
5720 : end subroutine pw_orthon_cprj
5721 : !!***
5722 :
5723 : !!****f* m_cgtools/cg_hprotate_and_get_diag
5724 : !! NAME
5725 : !! cg_hprotate_and_get_diag
5726 : !!
5727 : !! FUNCTION
5728 : !! Compute the diagonal elements of E^H VNLX E
5729 : !! where VNLX is an Hermitean matrixin packed form and E is the matrix with eigenvectors as column vectors.
5730 : !! Mainly used to rotate the matrix elements of an operator after the subspace diagonalization.
5731 : !!
5732 : !! INPUTS
5733 : !!
5734 : !! OUTPUT
5735 : !!
5736 : !! SOURCE
5737 :
5738 223339 : subroutine cg_hprotate_and_get_diag(nband_k, subvnlx, evec, enlx_k)
5739 :
5740 : !Arguments ------------------------------------
5741 : !scalars
5742 : integer,intent(in) :: nband_k
5743 : !arrays
5744 : real(dp),intent(in) :: subvnlx(nband_k*(nband_k+1))
5745 : real(dp),intent(in) :: evec(2*nband_k,nband_k)
5746 : real(dp), intent(out) :: enlx_k(nband_k)
5747 :
5748 : !Local variables ------------------------------
5749 : !scalars
5750 : integer :: ii,jj,pidx,iband
5751 223339 : real(dp),allocatable :: mat1(:,:,:),matvnl(:,:,:)
5752 : ! *************************************************************************
5753 :
5754 893356 : ABI_MALLOC(matvnl,(2,nband_k,nband_k))
5755 670017 : ABI_MALLOC(mat1,(2,nband_k,nband_k))
5756 :
5757 : ! Construct upper triangle of matvnl from subvnlx using full storage mode.
5758 1335682 : pidx=0
5759 1335682 : do jj=1,nband_k
5760 9825017 : do ii=1,jj
5761 8489335 : pidx=pidx+1
5762 8489335 : matvnl(1,ii,jj)=subvnlx(2*pidx-1)
5763 9601678 : matvnl(2,ii,jj)=subvnlx(2*pidx )
5764 : end do
5765 : end do
5766 :
5767 223339 : call zhemm('L','U',nband_k,nband_k,cone,matvnl,nband_k,evec,nband_k,czero,mat1,nband_k)
5768 :
5769 : !$OMP PARALLEL DO
5770 1335682 : do iband=1,nband_k
5771 1335682 : enlx_k(iband) = cg_real_zdotc(nband_k,evec(:,iband),mat1(:,:,iband))
5772 : end do
5773 :
5774 223339 : ABI_FREE(matvnl)
5775 223339 : ABI_FREE(mat1)
5776 :
5777 223339 : end subroutine cg_hprotate_and_get_diag
5778 : !!***
5779 :
5780 : !!****f* m_cgtools/cg_hrotate_and_get_diag
5781 : !! NAME
5782 : !! cg_hrotate_and_get_diag
5783 : !!
5784 : !! FUNCTION
5785 : !! Compute the diagonal elements of E^H VNLX E
5786 : !! where VNLX is an Hermitean matrix.
5787 : !! Mainly used to rotate the matrix elements of an operator after the subspace diagonalization.
5788 : !!
5789 : !! INPUTS
5790 : !!
5791 : !! OUTPUT
5792 : !!
5793 : !! SOURCE
5794 :
5795 612 : subroutine cg_hrotate_and_get_diag(istwf_k, nband_k, totvnlx, evec, enlx_k)
5796 :
5797 : !Arguments ------------------------------------
5798 : !scalars
5799 : integer,intent(in) :: istwf_k, nband_k
5800 : !arrays
5801 : real(dp),intent(in) :: totvnlx(2*nband_k,nband_k)
5802 : real(dp),intent(in) :: evec(2*nband_k,nband_k)
5803 : real(dp),intent(out) :: enlx_k(nband_k)
5804 :
5805 : !Local variables ------------------------------
5806 : !scalars
5807 : real(dp),external :: ddot
5808 : integer :: jj,iband
5809 612 : real(dp),allocatable :: mat_loc(:,:),mat1(:,:,:),matvnl(:,:,:), evec_loc(:,:)
5810 : ! *************************************************************************
5811 :
5812 2448 : ABI_MALLOC(matvnl, (2,nband_k, nband_k))
5813 1836 : ABI_MALLOC(mat1, (2, nband_k, nband_k))
5814 118540 : mat1=zero
5815 :
5816 5404 : enlx_k(1:nband_k)=zero
5817 :
5818 612 : if (istwf_k==1) then
5819 536 : call zhemm('l','l',nband_k,nband_k,cone,totvnlx,nband_k,evec,nband_k,czero,mat1,nband_k)
5820 4732 : do iband=1,nband_k
5821 4732 : enlx_k(iband)= cg_real_zdotc(nband_k,evec(:,iband),mat1(:,:,iband))
5822 : end do
5823 :
5824 76 : else if (istwf_k==2) then
5825 304 : ABI_MALLOC(evec_loc,(nband_k,nband_k))
5826 228 : ABI_MALLOC(mat_loc,(nband_k,nband_k))
5827 672 : do iband=1,nband_k
5828 5368 : do jj=1,nband_k
5829 5292 : evec_loc(iband,jj)=evec(2*iband-1,jj)
5830 : end do
5831 : end do
5832 76 : call dsymm('l','l',nband_k,nband_k,one,totvnlx,nband_k,evec_loc,nband_k,zero,mat_loc,nband_k)
5833 672 : do iband=1,nband_k
5834 672 : enlx_k(iband)=ddot(nband_k,evec_loc(:,iband),1,mat_loc(:,iband),1)
5835 : end do
5836 76 : ABI_FREE(evec_loc)
5837 76 : ABI_FREE(mat_loc)
5838 : end if
5839 :
5840 612 : ABI_FREE(matvnl)
5841 612 : ABI_FREE(mat1)
5842 :
5843 612 : end subroutine cg_hrotate_and_get_diag
5844 : !!***
5845 :
5846 : !!****f* m_cgtools/cg_get_eigens
5847 : !! NAME
5848 : !! cg_get_eigens
5849 : !!
5850 : !! FUNCTION
5851 : !! Helper functions to compute <i|H|i> / <i|S|i> for ndat states.
5852 : !! Assume normalized input wavefunctions.
5853 : !!
5854 : !! INPUTS
5855 : !!
5856 : !! OUTPUT
5857 : !!
5858 : !! SOURCE
5859 :
5860 2758 : subroutine cg_get_eigens(usepaw, istwf_k, npwsp, ndat, cg, ghc, gsc, eig, me_g0, comm)
5861 :
5862 : integer,intent(in) :: usepaw, istwf_k, npwsp, ndat, me_g0, comm
5863 : real(dp),intent(in) :: ghc(2*npwsp, ndat), cg(2*npwsp, ndat), gsc(2*npwsp, ndat*usepaw)
5864 : real(dp),intent(out) :: eig(ndat)
5865 :
5866 : !Local variables-------------------------------
5867 : integer,parameter :: option1 = 1
5868 : integer :: idat, ierr
5869 5516 : real(dp) :: doti, dots_r(ndat)
5870 : ! *************************************************************************
5871 :
5872 : ! <psi|H|psi> / <psi|S|psi>
5873 : !$OMP PARALLEL DO IF (ndat > 1)
5874 40790 : do idat=1,ndat
5875 38032 : call dotprod_g(eig(idat), doti, istwf_k, npwsp, option1, ghc(:,idat), cg(:,idat), me_g0, xmpi_comm_self)
5876 40790 : if (usepaw == 1) then
5877 7640 : call dotprod_g(dots_r(idat), doti, istwf_k, npwsp, option1, gsc(:,idat), cg(:,idat), me_g0, xmpi_comm_self)
5878 : end if
5879 : end do
5880 :
5881 2758 : if (xmpi_comm_size(comm) > 1) then
5882 1548 : call xmpi_sum(eig, comm, ierr)
5883 1548 : if (usepaw == 1) call xmpi_sum(dots_r, comm, ierr)
5884 : end if
5885 :
5886 11389 : if (usepaw == 1) eig(:) = eig(:) / dots_r(:)
5887 :
5888 2758 : end subroutine cg_get_eigens
5889 : !!***
5890 :
5891 : !!****f* m_cgtools/cg_get_residvecs
5892 : !! NAME
5893 : !! cg_get_residvecs
5894 : !!
5895 : !! FUNCTION
5896 : !! Compute residual vectors (H - eS) |psi> for ndat states.
5897 : !!
5898 : !! INPUTS
5899 : !!
5900 : !! OUTPUT
5901 : !!
5902 : !! SOURCE
5903 :
5904 4496 : subroutine cg_get_residvecs(usepaw, npwsp, ndat, eig, cg, ghc, gsc, residvecs)
5905 :
5906 : integer,intent(in) :: usepaw, npwsp, ndat
5907 : real(dp),intent(in) :: eig(ndat)
5908 : real(dp),intent(in) :: ghc(2*npwsp, ndat), cg(2*npwsp, ndat), gsc(2*npwsp, ndat*usepaw)
5909 : real(dp),intent(out) :: residvecs(2*npwsp, ndat)
5910 :
5911 : !Local variables-------------------------------
5912 : integer :: idat
5913 : ! *************************************************************************
5914 :
5915 4496 : if (usepaw == 1) then
5916 : ! (H - e) |psi>
5917 : !$OMP PARALLEL DO IF (ndat > 1)
5918 13047 : do idat=1,ndat
5919 7426151 : residvecs(:,idat) = ghc(:,idat) - eig(idat) * gsc(:,idat)
5920 : end do
5921 : else
5922 : ! (H - eS) |psi>
5923 : !$OMP PARALLEL DO IF (ndat > 1)
5924 54073 : do idat=1,ndat
5925 126221017 : residvecs(:,idat) = ghc(:,idat) - eig(idat) * cg(:,idat)
5926 : end do
5927 : end if
5928 :
5929 4496 : end subroutine cg_get_residvecs
5930 : !!***
5931 :
5932 : !!****f* m_cgtools/cg_norm2g
5933 : !! NAME
5934 : !! cg_norm2g
5935 : !!
5936 : !! FUNCTION
5937 : !! Compute <psi|psi> for ndat states distributed inside communicator comm.
5938 : !!
5939 : !! INPUTS
5940 : !!
5941 : !! OUTPUT
5942 : !!
5943 : !! SOURCE
5944 :
5945 4496 : subroutine cg_norm2g(istwf_k, npwsp, ndat, cg, norms, me_g0, comm)
5946 :
5947 : integer,intent(in) :: istwf_k, npwsp, ndat, me_g0, comm
5948 : real(dp),intent(in) :: cg(2*npwsp, ndat)
5949 : real(dp),intent(out) :: norms(ndat)
5950 :
5951 : !Local variables-------------------------------
5952 : integer :: idat, ierr
5953 : ! *************************************************************************
5954 :
5955 : !$OMP PARALLEL DO IF (ndat > 1)
5956 67120 : do idat=1,ndat
5957 67120 : call sqnorm_g(norms(idat), istwf_k, npwsp, cg(:,idat), me_g0, xmpi_comm_self)
5958 : end do
5959 4496 : if (xmpi_comm_size(comm) > 1) call xmpi_sum(norms, comm, ierr)
5960 :
5961 4496 : end subroutine cg_norm2g
5962 : !!***
5963 :
5964 : !!****f* m_cgtools/cg_zdotg_zip
5965 : !! NAME
5966 : !! cg_zdotg_zip
5967 : !!
5968 : !! FUNCTION
5969 : !! Compute <cg1|cg2> for ndat states
5970 : !!
5971 : !! INPUTS
5972 : !!
5973 : !! OUTPUT
5974 : !!
5975 : !! SOURCE
5976 :
5977 2575 : subroutine cg_zdotg_zip(istwf_k, npwsp, ndat, option, cg1, cg2, dots, me_g0, comm)
5978 :
5979 : integer,intent(in) :: istwf_k, npwsp, ndat, option, me_g0, comm
5980 : real(dp),intent(in) :: cg1(2*npwsp,ndat), cg2(2*npwsp,ndat)
5981 : real(dp),intent(out) :: dots(2,ndat)
5982 :
5983 : !Local variables-------------------------------
5984 : integer :: idat, ierr
5985 5150 : real(dp) :: dotr, doti, re_dots(ndat)
5986 : ! *************************************************************************
5987 :
5988 : !$OMP PARALLEL DO IF (ndat > 1) PRIVATE(dotr, doti)
5989 51143 : do idat=1,ndat
5990 48568 : call dotprod_g(dotr, doti, istwf_k, npwsp, option, cg1(:,idat), cg2(:,idat), me_g0, xmpi_comm_self)
5991 51143 : if (istwf_k == 2) then
5992 14096 : re_dots(idat) = dotr
5993 : else
5994 103416 : dots(:, idat) = [dotr, doti]
5995 : end if
5996 : end do
5997 :
5998 2575 : if (xmpi_comm_size(comm) > 1) then
5999 1660 : if (istwf_k == 2) then
6000 476 : call xmpi_sum(re_dots, comm, ierr)
6001 : else
6002 1184 : call xmpi_sum(dots, comm, ierr)
6003 : end if
6004 : end if
6005 :
6006 2575 : if (istwf_k == 2) then
6007 14648 : do idat=1,ndat
6008 14096 : dots(1,idat) = re_dots(idat)
6009 14648 : dots(2,idat) = zero
6010 : end do
6011 : end if
6012 :
6013 2575 : end subroutine cg_zdotg_zip
6014 : !!***
6015 :
6016 : !!****f* m_cgtools/cg_precon_many
6017 : !! NAME
6018 : !! cg_precon_many
6019 : !!
6020 : !! FUNCTION
6021 : !!
6022 : !! INPUTS
6023 : !!
6024 : !! OUTPUT
6025 : !!
6026 : !! SOURCE
6027 :
6028 2454 : subroutine cg_precon_many(istwf_k, npw, nspinor, ndat, cg, optekin, kinpw, vect, me_g0, comm)
6029 :
6030 : integer,intent(in) :: istwf_k, npw, nspinor, optekin, ndat, me_g0, comm
6031 : real(dp),intent(in) :: cg(2*npw*nspinor,ndat), kinpw(npw)
6032 : real(dp),intent(inout) :: vect(2*npw*nspinor,ndat)
6033 :
6034 : !Local variables-------------------------------
6035 : integer :: idat
6036 2454 : real(dp),allocatable :: pcon(:)
6037 : ! *************************************************************************
6038 :
6039 : ! TODO: Optimized version for MPI with ndat > 1
6040 7362 : ABI_MALLOC(pcon, (npw))
6041 :
6042 : !$OMP PARALLEL DO IF (ndat > 1)
6043 38150 : do idat=1,ndat
6044 38150 : call cg_precon(cg(:,idat), zero, istwf_k, kinpw, npw, nspinor, me_g0, optekin, pcon, vect(:,idat), comm)
6045 : end do
6046 2454 : ABI_FREE(pcon)
6047 :
6048 : !call cg_kinene(istwf_k, npw, nspinor, ndat, cg, me_g0, comm)
6049 : !call cg_zprecon_block(cg,eval,blocksize,iterationnumber,kinpw, npw,nspinor,optekin,optpcon,pcon,ghc,vect,vectsize,comm)
6050 :
6051 2454 : end subroutine cg_precon_many
6052 : !!***
6053 :
6054 : !----------------------------------------------------------------------
6055 :
6056 : !!****f* m_cgtools/cg_zaxpy_many_areal
6057 : !! NAME
6058 : !! cg_zaxpy_many_areal
6059 : !!
6060 : !! FUNCTION
6061 : !! Computes y = alpha*x + y
6062 : !!
6063 : !! INPUTS
6064 : !! n = Specifies the number of elements in vectors x and y.
6065 : !! ndat
6066 : !! alpha(ndat) = Specifies the scalar alpha.
6067 : !! x = Array
6068 : !!
6069 : !! SIDE EFFECTS
6070 : !! y = Array. In output, y contains the updated vector.
6071 : !!
6072 : !! SOURCE
6073 :
6074 1561 : subroutine cg_zaxpy_many_areal(npwsp, ndat, alphas, x, y)
6075 :
6076 : !Arguments ------------------------------------
6077 : !scalars
6078 : integer,intent(in) :: npwsp, ndat
6079 : real(dp),intent(in) :: alphas(ndat)
6080 : !arrays
6081 : real(dp),intent(in) :: x(2*npwsp, ndat)
6082 : real(dp),intent(inout) :: y(2*npwsp, ndat)
6083 :
6084 : !Local variables-------------------------------
6085 : integer :: idat
6086 : ! *************************************************************************
6087 :
6088 : !$OMP PARALLEL DO IF (ndat > 1)
6089 24769 : do idat=1,ndat
6090 24769 : call daxpy(2*npwsp, alphas(idat), x(1,idat), 1, y(1,idat), 1)
6091 : end do
6092 :
6093 1561 : end subroutine cg_zaxpy_many_areal
6094 : !!***
6095 :
6096 : !----------------------------------------------------------------------
6097 :
6098 : !!****f* m_cgtools/cg_set_imag0_to_zero
6099 : !! NAME
6100 : !! cg_set_imag0_to_zero
6101 : !!
6102 : !! FUNCTION
6103 : !! Set the imaginary part at G=0 to zero if istwfk == 2 and this proc has the gamma point
6104 : !!
6105 : !! INPUTS
6106 : !! npwsp=Size of each vector (usually npw*nspinor)
6107 : !! istwfk=Storage mode for the wavefunctions. 1 for standard full mode
6108 : !! me_g0=1 if this node has G=0.
6109 : !!
6110 : !! SIDE EFFECTS
6111 : !! cg(2*npwsp*nband)
6112 : !! input: Input set of vectors.
6113 : !! output: Orthonormalized set.
6114 : !!
6115 : !! SOURCE
6116 :
6117 0 : pure subroutine cg_set_imag0_to_zero(istwfk, me_g0, npwsp, nband, cg, max_absimag)
6118 :
6119 : !Arguments ------------------------------------
6120 : !scalars
6121 : integer,intent(in) :: istwfk, me_g0, npwsp, nband
6122 : !arrays
6123 : real(dp),intent(inout) :: cg(2,npwsp*nband)
6124 : real(dp),intent(out) :: max_absimag
6125 :
6126 : !Local variables ------------------------------
6127 : integer :: ib, ii
6128 : ! *************************************************************************
6129 :
6130 0 : max_absimag = zero
6131 0 : if (istwfk == 2 .and. me_g0 == 1) then
6132 0 : do ib=1,nband
6133 0 : ii = 1 + (ib - 1) * npwsp
6134 0 : max_absimag = max(max_absimag, abs(cg(2, ii)))
6135 0 : cg(2, ii) = zero
6136 : end do
6137 : end if
6138 :
6139 0 : end subroutine cg_set_imag0_to_zero
6140 : !!***
6141 :
6142 : !----------------------------------------------------------------------
6143 :
6144 : !!****f* m_cgtools/cg_randomize
6145 : !! NAME
6146 : !! cg_randomize
6147 : !!
6148 : !! FUNCTION
6149 : !! Initialize block of wavefunctions with random numbers. See wfconv
6150 : !!
6151 : !! INPUTS
6152 : !!
6153 : !! SOURCE
6154 :
6155 44 : subroutine cg_randomize(istwf_k, npw_k, nspinor, nband_k, me_g0, cg_k)
6156 :
6157 : !Arguments ------------------------------------
6158 : !scalars
6159 : integer,intent(in) :: istwf_k, npw_k, nspinor, nband_k, me_g0
6160 : !arrays
6161 : real(dp),intent(inout) :: cg_k(2,npw_k*nspinor,nband_k)
6162 :
6163 : !Local variables ------------------------------
6164 : integer :: ipw, ispinor, index
6165 : integer, parameter :: int64 = selected_int_kind(18)
6166 : integer(KIND=int64) :: seed
6167 : integer :: fold1,fold2,foldim,foldre,iband
6168 : ! *************************************************************************
6169 :
6170 836 : do iband=1,nband_k
6171 : index = 0
6172 1628 : do ispinor=1,nspinor
6173 1017378 : do ipw=1,npw_k
6174 1015794 : index=index+1
6175 1015794 : seed=(iband-1)*npw_k*nspinor + (ispinor-1)*npw_k + ipw
6176 :
6177 : ! For portability, use only integer numbers
6178 : ! The series of couples (fold1,fold2) is periodic with a period of
6179 : ! 3x5x7x11x13x17x19x23x29x31, that is, larger than 2**32, the largest integer*4
6180 : ! fold1 is between 0 and 34, fold2 is between 0 and 114. As sums of five
6181 : ! uniform random variables, their distribution is close to a gaussian
6182 1015794 : fold1=modulo(seed,3)+modulo(seed,5)+modulo(seed,7)+modulo(seed,11)+modulo(seed,13)
6183 1015794 : fold2=modulo(seed,17)+modulo(seed,19)+modulo(seed,23)+modulo(seed,29)+modulo(seed,31)
6184 :
6185 : ! The gaussian distributions are folded, in order to be back to a uniform distribution
6186 : ! foldre is between 0 and 20, foldim is between 0 and 18
6187 1015794 : foldre=mod(fold1+fold2,21)
6188 1015794 : foldim=mod(3*fold1+2*fold2,19)
6189 :
6190 1015794 : cg_k(1,index,iband) = dble(foldre)
6191 1015794 : cg_k(2,index,iband) = dble(foldim)
6192 :
6193 : ! XG030513: Time-reversal symmetry for k=gamma imposes zero imaginary part at G=0
6194 : ! XG: I do not know what happens for spin-orbit here.
6195 1016586 : if (istwf_k == 2 .and. me_g0 == 1) cg_k(2,1,iband)=zero
6196 : end do ! ipw
6197 : end do ! ispinor
6198 : end do ! iband
6199 :
6200 44 : end subroutine cg_randomize
6201 : !!***
6202 :
6203 : !----------------------------------------------------------------------
6204 :
6205 : !!****f* m_cgtools/cg_copy_spin
6206 : !! NAME
6207 : !! cg_copy_spin
6208 : !!
6209 : !! FUNCTION
6210 : !!
6211 : !! INPUTS
6212 : !!
6213 : !! SOURCE
6214 :
6215 281148 : subroutine cg_copy_spin(spin, npw_k, nspinor, ndat, in_cg, out_cg)
6216 :
6217 : !Arguments ------------------------------------
6218 : !scalars
6219 : integer,intent(in) :: spin, npw_k, nspinor, ndat
6220 : !arrays
6221 : real(dp),intent(inout) :: in_cg(2,npw_k,nspinor,ndat)
6222 : real(dp),intent(out) :: out_cg(2,npw_k,ndat)
6223 :
6224 : !Local variables ------------------------------
6225 : integer :: idat
6226 : ! *************************************************************************
6227 :
6228 : !$OMP PARALLEL DO IF (ndat > 1)
6229 562296 : do idat=1,ndat
6230 192742308 : out_cg(:,:,idat) = in_cg(:,:,spin,idat)
6231 : end do
6232 :
6233 281148 : end subroutine cg_copy_spin
6234 : !!***
6235 :
6236 : !----------------------------------------------------------------------
6237 :
6238 : !!****f* m_cgtools/cg_put_spin
6239 : !! NAME
6240 : !! cg_put_spin
6241 : !!
6242 : !! FUNCTION
6243 : !!
6244 : !! INPUTS
6245 : !!
6246 : !! SOURCE
6247 :
6248 278238 : subroutine cg_put_spin(spin, npw_k, nspinor, ndat, in_cg, out_cg)
6249 :
6250 : !Arguments ------------------------------------
6251 : !scalars
6252 : integer,intent(in) :: spin, npw_k, nspinor, ndat
6253 : !arrays
6254 : real(dp),intent(inout) :: in_cg(2,npw_k,ndat)
6255 : real(dp),intent(out) :: out_cg(2,npw_k,nspinor,ndat)
6256 :
6257 : !Local variables ------------------------------
6258 : integer :: idat
6259 : ! *************************************************************************
6260 :
6261 : !$OMP PARALLEL DO IF (ndat > 1)
6262 556476 : do idat=1,ndat
6263 190909440 : out_cg(:,:,spin, idat) = in_cg(:,:,idat)
6264 : end do
6265 :
6266 278238 : end subroutine cg_put_spin
6267 : !!***
6268 :
6269 : !----------------------------------------------------------------------
6270 :
6271 : !!****f* m_cgtools/cg_p_psi
6272 : !! NAME
6273 : !! cg_g_psi
6274 : !!
6275 : !! FUNCTION
6276 : !! Compute <g|-i\Nabla |psi_nk>.
6277 : !!
6278 : !! INPUTS
6279 : !!
6280 : !! SOURCE
6281 :
6282 0 : subroutine cg_p_psi(npw_k, nspinor, ndat, kk, kg_k, cg_k, p_cg_k)
6283 :
6284 : !Arguments ------------------------------------
6285 : !scalars
6286 : integer,intent(in) :: npw_k, nspinor, ndat
6287 : !arrays
6288 : real(dp),intent(in) :: kk(3)
6289 : integer,intent(in) :: kg_k(3,npw_k)
6290 : real(dp),intent(in) :: cg_k(2,npw_k*nspinor,ndat)
6291 : real(dp),intent(out) :: p_cg_k(2,npw_k*nspinor,ndat,3)
6292 :
6293 : !Local variables ------------------------------
6294 : integer :: idir, ig, ispinor, idat, spad, ipwsp
6295 : ! *************************************************************************
6296 :
6297 : !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(spad, ipwsp)
6298 0 : do idir=1,3
6299 0 : do idat=1,ndat
6300 0 : do ispinor=1,nspinor
6301 0 : spad = (ispinor - 1) * npw_k
6302 0 : do ig=1,npw_k
6303 0 : ipwsp = ig + spad
6304 0 : p_cg_k(:, ipwsp, idat, idir) = cg_k(:, ipwsp, idat) * (kg_k(idir, ig) + kk(idir))
6305 : end do ! ig
6306 : end do ! ispinor
6307 : end do ! idir
6308 : end do ! idat
6309 :
6310 0 : end subroutine cg_p_psi
6311 : !!**
6312 :
6313 : end module m_cgtools
6314 : !!***
|