Line data Source code
1 : !!****f* ABINIT/m_chebfi2_cprj
2 : !! NAME
3 : !! m_chebfi2_cprj
4 : !!
5 : !! FUNCTION
6 : !! This module contains the types and routines used to apply the
7 : !! Chebyshev filtering method (2021 implementation using xG abstraction layer)
8 : !! It mainly defines a 'chebfi' datatypes and associated methods.
9 : !!
10 : !! COPYRIGHT
11 : !! Copyright (C) 2023-2026 ABINIT group (LB)
12 : !! This file is distributed under the terms of the
13 : !! gnu general public license, see ~abinit/COPYING
14 : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : !! for the initials of contributors, see ~abinit/doc/developers/contributors.txt .
16 : !!
17 : !! SOURCE
18 :
19 : #if defined HAVE_CONFIG_H
20 : #include "config.h"
21 : #endif
22 :
23 : #include "abi_common.h"
24 :
25 : module m_chebfi2_cprj
26 :
27 : use defs_basis
28 : use defs_abitypes
29 : use m_abicore
30 : use m_errors
31 : use m_time, only : timab
32 :
33 : use m_cgtools
34 : use m_xg
35 : use m_xgTransposer
36 : use m_xg_ortho_RR
37 : use m_xg_nonlop
38 :
39 : use m_xmpi
40 : use m_xomp
41 : #ifdef HAVE_OPENMP
42 : use omp_lib
43 : #endif
44 :
45 : implicit none
46 :
47 : private
48 :
49 : !Several (private) parameters
50 : !-------------------------------------------------
51 :
52 : integer, parameter :: tim_init = 2061
53 : integer, parameter :: tim_free = 2062
54 : integer, parameter :: tim_cprj = 2063
55 : integer, parameter :: tim_invovl = 2065
56 : integer, parameter :: tim_residu = 2066
57 : integer, parameter :: tim_RR = 2067
58 : integer, parameter :: tim_transpose = 2068
59 : integer, parameter :: tim_RR_q = 2069
60 : integer, parameter :: tim_postinvovl = 2070
61 : integer, parameter :: tim_swap = 2071
62 : integer, parameter :: tim_amp_f = 2072
63 : integer, parameter :: tim_oracle = 2073
64 : integer, parameter :: tim_barrier = 2074
65 : integer, parameter :: tim_copy = 2075
66 : integer, parameter :: tim_ax_k = 2076
67 : integer, parameter :: tim_ax_v = 2077
68 : integer, parameter :: tim_ax_nl = 2078
69 : integer, parameter :: tim_enl = 2079
70 :
71 : !Public 'chebfi' datatype
72 : !-------------------------------------------------
73 :
74 : type, public :: chebfi_t
75 : integer :: space
76 : integer :: space_cprj
77 : integer :: spacedim ! Space dimension for one vector
78 : integer :: cprjdim ! cprj dimension
79 : integer :: total_spacedim ! Maybe not needed
80 : integer :: neigenpairs ! Number of eigen values/vectors we want
81 : integer :: ndeg_filter ! Degree of the polynomial filter
82 : integer :: nbdbuf ! Number of bands in the buffer
83 : integer :: spacecom ! Communicator for MPI
84 : integer :: oracle ! Option to compute ndeg_filter from residuals
85 : real(dp) :: tolerance ! Tolerance on the residu to stop the minimization
86 : real(dp) :: ecut ! Ecut for Chebfi oracle
87 : real(dp) :: oracle_factor ! factor used to decrease residuals
88 : real(dp) :: oracle_min_occ ! threshold on occupancies used for nbdbuf=-101
89 :
90 : integer :: bandpp
91 :
92 : logical :: paw
93 : integer :: eigenProblem !1 (A*x = (lambda)*B*x), 2 (A*B*x = (lambda)*x), 3 (B*A*x = (lambda)*x)
94 : integer :: me_g0
95 : integer :: me_g0_fft
96 :
97 : type(xg_nonlop_t) :: xg_nonlop
98 :
99 : !ARRAYS
100 : type(xgBlock_t) :: X
101 :
102 : type(xg_t) :: X_NP
103 : type(xgBlock_t) :: X_next
104 : type(xgBlock_t) :: X_prev
105 :
106 : type(xg_t) :: AX
107 : type(xgBlock_t) :: cprjX
108 : type(xg_t) :: cprj_work
109 : type(xg_t) :: cprj_work2
110 : type(xg_t) :: proj_work
111 :
112 : type(xgBlock_t) :: xXColsRows
113 : type(xgBlock_t) :: xAXColsRows
114 :
115 : type(xgTransposer_t) :: xgTransposerX
116 : type(xgTransposer_t) :: xgTransposerAX
117 :
118 : type(xgBlock_t) :: eigenvalues
119 :
120 : !SWAP POINTERS
121 : type(xgBlock_t) :: X_swap
122 : type(xgBlock_t) :: AX_swap
123 :
124 : end type chebfi_t
125 :
126 : !Public methods associated to 'chebfi' datatype
127 : !-------------------------------------------------
128 : public :: chebfi_init
129 : public :: chebfi_free
130 : public :: chebfi_memInfo
131 : public :: chebfi_run_cprj
132 :
133 : CONTAINS !========================================================================================
134 : !!***
135 :
136 : !!****f* m_chebfi2_cprj/chebfi_init
137 : !! NAME
138 : !! chebfi_init
139 : !!
140 : !! FUNCTION
141 : !! Initialize a 'chebfi' datastructure.
142 : !!
143 : !! INPUTS
144 : !! bandpp= number of 'bands' handled by a processor
145 : !! eigenProblem= type of eigenpb: 1 (A*x = (lambda)*B*x), 2 (A*B*x = (lambda)*x), 3 (B*A*x = (lambda)*x)
146 : !! me_g0= 1 if this processors treats G=0, 0 otherwise
147 : !! neigenpairs= number of requested eigenvectors/eigenvalues
148 : !! ndeg_filter= polynomial degree of the Chebyshev filter (.i.e. number of H applications)
149 : !! space= defines in which space we are (columns, rows, etc.)
150 : !! spacecom= MPI communicator
151 : !! spacedim= space dimension for one vector
152 : !! paw= flag. TRUE if current calculation ses the PAW approach
153 : !! ecut= plane-wave cut-off energy
154 : !! tolerance= tolerance criterion on the residu to stop the minimization
155 : !!
156 : !! OUTPUT
157 : !!
158 : !! SIDE EFFECTS
159 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
160 : !!
161 : !! SOURCE
162 :
163 15368 : subroutine chebfi_init(chebfi,neigenpairs,spacedim,cprjdim,tolerance,ecut,bandpp, &
164 : ndeg_filter,nbdbuf,space,space_cprj,eigenProblem,spacecom,me_g0,paw,&
165 : oracle,oracle_factor,oracle_min_occ,xg_nonlop,me_g0_fft)
166 :
167 : !Arguments ------------------------------------
168 : integer , intent(in ) :: bandpp
169 : integer , intent(in ) :: eigenProblem
170 : integer , intent(in ) :: me_g0
171 : integer , intent(in ) :: me_g0_fft
172 : integer , intent(in ) :: neigenpairs
173 : integer , intent(in ) :: ndeg_filter
174 : integer , intent(in ) :: nbdbuf
175 : integer , intent(in ) :: space
176 : integer , intent(in ) :: space_cprj
177 : integer , intent(in ) :: spacecom
178 : integer , intent(in ) :: spacedim
179 : integer , intent(in ) :: cprjdim
180 : integer , intent(in ) :: oracle
181 : logical , intent(in ) :: paw
182 : real(dp) , intent(in ) :: ecut
183 : real(dp) , intent(in ) :: tolerance
184 : real(dp) , intent(in ) :: oracle_factor
185 : real(dp) , intent(in ) :: oracle_min_occ
186 : type(xg_nonlop_t), intent(in ) :: xg_nonlop
187 : type(chebfi_t) , intent(inout) :: chebfi
188 :
189 : !Local variables-------------------------------
190 : real(dp) :: tsec(2)
191 :
192 : ! *********************************************************************
193 :
194 15368 : call timab(tim_init,1,tsec)
195 :
196 15368 : chebfi%space = space
197 15368 : chebfi%space_cprj = space_cprj
198 15368 : chebfi%neigenpairs = neigenpairs
199 15368 : chebfi%spacedim = spacedim
200 15368 : chebfi%cprjdim = cprjdim
201 15368 : if (tolerance > 0.0) then
202 2312 : chebfi%tolerance = tolerance
203 : else
204 13056 : chebfi%tolerance = 1.0e-20
205 : end if
206 15368 : chebfi%ecut = ecut
207 15368 : chebfi%bandpp = bandpp
208 15368 : chebfi%ndeg_filter = ndeg_filter
209 15368 : chebfi%nbdbuf = nbdbuf
210 15368 : chebfi%spacecom = spacecom
211 15368 : chebfi%eigenProblem = eigenProblem
212 15368 : chebfi%me_g0 = me_g0
213 15368 : chebfi%me_g0_fft = me_g0_fft
214 15368 : chebfi%paw = paw
215 15368 : chebfi%xg_nonlop = xg_nonlop
216 15368 : chebfi%oracle = oracle
217 15368 : chebfi%oracle_factor = oracle_factor
218 15368 : chebfi%oracle_min_occ = oracle_min_occ
219 :
220 15368 : call chebfi_allocateAll(chebfi)
221 :
222 15368 : call timab(tim_init,2,tsec)
223 :
224 15368 : end subroutine chebfi_init
225 : !!***
226 :
227 : !----------------------------------------------------------------------
228 :
229 : !!****f* m_chebfi2_cprj/chebfi_allocateAll
230 : !! NAME
231 : !! chebfi_allocateAll
232 : !!
233 : !! FUNCTION
234 : !! Allocate all memory spaces in a 'chebfi' datastructure.
235 : !!
236 : !! INPUTS
237 : !!
238 : !! OUTPUT
239 : !!
240 : !! SIDE EFFECTS
241 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
242 : !!
243 : !! SOURCE
244 :
245 30736 : subroutine chebfi_allocateAll(chebfi)
246 :
247 : ! Arguments ------------------------------------
248 : type(chebfi_t) , intent(inout) :: chebfi
249 :
250 : ! Local variables-------------------------------
251 : ! scalars
252 : integer :: neigenpairs
253 : integer :: space,space_cprj
254 : integer :: spacedim
255 : integer :: total_spacedim, ierr
256 : integer :: nspinor
257 :
258 : ! *********************************************************************
259 :
260 15368 : space = chebfi%space
261 15368 : space_cprj = chebfi%space_cprj
262 15368 : spacedim = chebfi%spacedim
263 15368 : neigenpairs = chebfi%neigenpairs
264 15368 : nspinor = chebfi%xg_nonlop%nspinor
265 :
266 15368 : call chebfi_free(chebfi)
267 :
268 15368 : total_spacedim = spacedim
269 15368 : call xmpi_sum(total_spacedim,chebfi%spacecom,ierr)
270 15368 : chebfi%total_spacedim = total_spacedim
271 15368 : call xg_init(chebfi%X_NP,space,total_spacedim,2*chebfi%bandpp,xmpi_comm_self,me_g0=chebfi%me_g0_fft) !transposed arrays
272 15368 : call xg_setBlock(chebfi%X_NP,chebfi%X_next,total_spacedim,chebfi%bandpp)
273 15368 : call xg_setBlock(chebfi%X_NP,chebfi%X_prev,total_spacedim,chebfi%bandpp,fcol=chebfi%bandpp+1)
274 :
275 15368 : call xg_init(chebfi%AX,space,spacedim,neigenpairs,chebfi%spacecom,me_g0=chebfi%me_g0)
276 15368 : call xg_init(chebfi%cprj_work ,space_cprj,chebfi%cprjdim,chebfi%bandpp*nspinor,chebfi%spacecom)
277 15368 : call xg_init(chebfi%cprj_work2,space_cprj,chebfi%cprjdim,chebfi%bandpp*nspinor,chebfi%spacecom)
278 :
279 15368 : call xg_init(chebfi%proj_work,space,chebfi%xg_nonlop%max_npw_k,chebfi%xg_nonlop%cprjdim,chebfi%spacecom,me_g0=chebfi%me_g0)
280 :
281 15368 : end subroutine chebfi_allocateAll
282 : !!***
283 :
284 : !----------------------------------------------------------------------
285 :
286 : !!****f* m_chebfi2_cprj/chebfi_free
287 : !! NAME
288 : !! chebfi_free
289 : !!
290 : !! FUNCTION
291 : !! Destroy a 'chebfi' datastructure.
292 : !!
293 : !! INPUTS
294 : !!
295 : !! OUTPUT
296 : !! arraymem(2)= memory information
297 : !!
298 : !! SIDE EFFECTS
299 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
300 : !!
301 : !! SOURCE
302 :
303 30736 : subroutine chebfi_free(chebfi)
304 :
305 : !Arguments ------------------------------------
306 : type(chebfi_t) , intent(inout) :: chebfi
307 :
308 : ! *********************************************************************
309 :
310 30736 : call xg_free(chebfi%X_NP)
311 :
312 30736 : call xg_free(chebfi%AX)
313 30736 : call xg_free(chebfi%cprj_work)
314 30736 : call xg_free(chebfi%cprj_work2)
315 30736 : call xg_free(chebfi%proj_work)
316 :
317 30736 : end subroutine chebfi_free
318 : !!***
319 :
320 : !----------------------------------------------------------------------
321 :
322 : !!****f* m_chebfi2_cprj/chebfi_memInfo
323 : !! NAME
324 : !! chebfi_memInfo
325 : !!
326 : !! FUNCTION
327 : !! Provides memory information about a 'chebfi' datastructure.
328 : !!
329 : !! INPUTS
330 : !! bandpp= number of 'bands' handled by a processor
331 : !! neigenpairs= number of requested eigenvectors/eigenvalues
332 : !! paral_kgb= flag controlling (k,g,bands) parallelization
333 : !! space= defines in which space we are (columns, rows, etc.)
334 : !! spacedim= dimension of MPI communicator
335 : !! total_spacedim= size of global KGB communicator (typically 'banspinorfft' comm.)
336 : !!
337 : !! OUTPUT
338 : !! arraymem(2)= memory information
339 : !!
340 : !! SIDE EFFECTS
341 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
342 : !!
343 : !! SOURCE
344 :
345 0 : function chebfi_memInfo(neigenpairs,spacedim,space,total_spacedim,bandpp) result(arraymem)
346 :
347 : !Arguments ------------------------------------
348 : integer, intent(in ) :: bandpp
349 : integer, intent(in ) :: neigenpairs
350 : integer, intent(in ) :: space
351 : integer, intent(in ) :: spacedim
352 : integer, intent(in ) :: total_spacedim
353 :
354 : !Local variables-------------------------------
355 : !scalars
356 : real(dp) :: memX
357 : real(dp) :: memX_next
358 : real(dp) :: memX_prev
359 : real(dp) :: memAX
360 : real(dp) :: memBX
361 : !Transposer variables
362 : real(dp) :: memX_CR
363 : real(dp) :: memAX_CR
364 : real(dp) :: memBX_CR
365 : !chebfi_rayleighRitz function variables
366 : real(dp) :: memA_und_X
367 : real(dp) :: memB_und_X
368 : real(dp) :: memEigenvalues
369 : real(dp) :: cplx
370 : !arrays
371 : real(dp) :: arraymem(2)
372 :
373 : ! *********************************************************************
374 0 : cplx = 1
375 0 : if ( space == SPACE_C ) cplx = 2 !for now only complex
376 :
377 : !Permanent in chebfi
378 0 : memX = cplx * kind(1.d0) * spacedim * neigenpairs
379 :
380 : ! if (paral_kgb == 0) then
381 : ! memX_next = cplx * kind(1.d0) * spacedim * neigenpairs
382 : ! memX_prev = cplx * kind(1.d0) * spacedim * neigenpairs
383 : ! else
384 0 : memX_next = cplx * kind(1.d0) * total_spacedim * bandpp
385 0 : memX_prev = cplx * kind(1.d0) * total_spacedim * bandpp
386 : ! end if
387 :
388 0 : memAX = cplx * kind(1.d0) * spacedim * neigenpairs
389 0 : memBX = cplx * kind(1.d0) * spacedim * neigenpairs
390 :
391 : !Transposer colrow array
392 : ! if (paral_kgb == 1) then
393 0 : memX_CR = cplx * kind(1.d0) * total_spacedim * bandpp
394 0 : memAX_CR = cplx * kind(1.d0) * total_spacedim * bandpp
395 0 : memBX_CR = cplx * kind(1.d0) * total_spacedim * bandpp
396 : ! else
397 : ! memX_CR = 0
398 : ! memAX_CR = 0
399 : ! memBX_CR = 0
400 : ! end if
401 :
402 : !chebfi_rayleighRitz function variables
403 0 : memA_und_X = cplx * kind(1.d0) * neigenpairs * neigenpairs
404 0 : memB_und_X = cplx * kind(1.d0) * neigenpairs * neigenpairs
405 0 : memEigenvalues = kind(1.d0) * neigenpairs
406 :
407 : arraymem(1) = memX + memX_next + memX_prev + &
408 0 : memAX + memBX + memX_CR + memAX_CR + memBX_CR
409 0 : arraymem(2) = memA_und_X + memB_und_X + memEigenvalues
410 :
411 0 : end function chebfi_memInfo
412 : !!***
413 :
414 : !----------------------------------------------------------------------
415 :
416 : !!****f* m_chebfi2_cprj/chebfi_run
417 : !! NAME
418 : !! chebfi_run
419 : !!
420 : !! FUNCTION
421 : !! Apply the Chebyshev Filtering algorithm on a set of vectors.
422 : !!
423 : !! INPUTS
424 : !! mpi_enreg = information about MPI parallelization
425 : !! getAX_BX= pointer to the function giving A|X> and B|X>
426 : !! A is typically the Hamiltonian H, and B the overlap operator S
427 : !! getBm1X= pointer to the function giving B^-1|X>
428 : !! B is typically the overlap operator S
429 : !!
430 : !! OUTPUT
431 : !!
432 : !! SIDE EFFECTS
433 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
434 : !! eigen= Full eigenvalues (initial values on entry)
435 : !! residu= residuals, i.e. norm of (A-lambdaB)|X>
436 : !! X0= Full set of vectors (initial values on entry)
437 : !!
438 : !! SOURCE
439 :
440 15368 : subroutine chebfi_run_cprj(chebfi,X0,cprjX0,getAX,kin,eigen,occ,residu,enl,nspinor)
441 :
442 : !Arguments ------------------------------------
443 : type(chebfi_t) , intent(inout) :: chebfi
444 : integer, intent(in) :: nspinor
445 : type(xgBlock_t), intent(inout) :: X0
446 : type(xgBlock_t), intent(inout) :: cprjX0
447 : type(xgBlock_t), intent(inout) :: eigen
448 : type(xgBlock_t), intent(in) :: occ
449 : type(xgBlock_t), intent(inout) :: residu
450 : type(xgBlock_t), intent(inout) :: enl
451 : type(xgBlock_t), intent(in ) :: kin
452 : interface
453 : subroutine getAX(X,AX)
454 : use m_xg, only : xgBlock_t
455 : type(xgBlock_t), intent(inout) :: X
456 : type(xgBlock_t), intent(inout) :: AX
457 : end subroutine getAX
458 : end interface
459 :
460 : !Local variables-------------------------------
461 : !scalars
462 : integer :: spacedim
463 : integer :: space_res
464 : integer :: neigenpairs
465 : integer :: ndeg_filter,ndeg_filter_max
466 : integer :: ideg, ierr
467 : real(dp) :: tolerance
468 : real(dp) :: maxeig, maxeig_global
469 : real(dp) :: mineig, mineig_global
470 : real(dp) :: lambda_minus
471 : real(dp) :: lambda_plus
472 : real(dp) :: one_over_r
473 : real(dp) :: two_over_r
474 : real(dp) :: center
475 : real(dp) :: radius
476 : type(xg_t) :: DivResults
477 : !arrays
478 : real(dp) :: tsec(2)
479 : !Pointers similar to old Chebfi
480 15368 : integer,allocatable :: ndeg_filter_bands(:) !Oracle variable
481 15368 : type(xg_nonlop_t) :: xg_nonlop
482 :
483 : ! *********************************************************************
484 :
485 15368 : spacedim = chebfi%spacedim
486 15368 : neigenpairs = chebfi%neigenpairs
487 15368 : ndeg_filter = chebfi%ndeg_filter
488 15368 : xg_nonlop = chebfi%xg_nonlop
489 15368 : chebfi%eigenvalues = eigen
490 :
491 46104 : ABI_MALLOC(ndeg_filter_bands,(chebfi%bandpp))
492 15368 : if (chebfi%space==SPACE_C) then
493 9112 : space_res = SPACE_C
494 6256 : else if (chebfi%space==SPACE_CR) then
495 6256 : space_res = SPACE_R
496 : else
497 0 : ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
498 : end if
499 15368 : call xg_init(DivResults, space_res, chebfi%bandpp, 1)
500 :
501 15368 : tolerance = chebfi%tolerance
502 15368 : lambda_plus = chebfi%ecut
503 15368 : chebfi%X = X0
504 15368 : chebfi%cprjX = cprjX0
505 :
506 : ! Transpose
507 15368 : call timab(tim_transpose,1,tsec)
508 : call xgTransposer_constructor(chebfi%xgTransposerX,chebfi%X,chebfi%xXColsRows,nspinor,&
509 15368 : STATE_LINALG,TRANS_ALL2ALL,xmpi_comm_self,chebfi%spacecom,0,0,chebfi%me_g0_fft)
510 :
511 15368 : call xgTransposer_copyConstructor(chebfi%xgTransposerAX,chebfi%xgTransposerX,chebfi%AX%self,chebfi%xAXColsRows,STATE_LINALG)
512 :
513 15368 : call xgTransposer_transpose(chebfi%xgTransposerX,STATE_COLSROWS)
514 15368 : chebfi%xgTransposerAX%state = STATE_COLSROWS
515 15368 : call timab(tim_transpose,2,tsec)
516 :
517 15368 : call timab(tim_cprj,1,tsec)
518 15368 : call xg_nonlop_getcprj(xg_nonlop,chebfi%xXColsRows,chebfi%cprjX,chebfi%proj_work%self)
519 15368 : call timab(tim_cprj,2,tsec)
520 15368 : call timab(tim_AX_v,1,tsec)
521 15368 : call getAX(chebfi%xXColsRows,chebfi%xAXColsRows)
522 15368 : call timab(tim_AX_v,2,tsec)
523 15368 : call timab(tim_AX_k,1,tsec)
524 15368 : call xgBlock_add_diag(chebfi%xXColsRows,kin,nspinor,chebfi%xAXColsRows)
525 15368 : call timab(tim_AX_k,2,tsec)
526 15368 : call timab(tim_AX_nl,1,tsec)
527 15368 : call xg_nonlop_getHX(xg_nonlop,chebfi%xAXcolsRows,chebfi%cprjX,chebfi%cprj_work%self,chebfi%proj_work%self)
528 15368 : call timab(tim_AX_nl,2,tsec)
529 :
530 15368 : call timab(tim_barrier,1,tsec)
531 15368 : call xmpi_barrier(chebfi%spacecom)
532 15368 : call timab(tim_barrier,2,tsec)
533 :
534 : !********************* Compute Rayleigh quotients for every band, and set lambda equal to the largest one *****
535 15368 : call timab(tim_RR_q, 1, tsec)
536 15368 : call chebfi_rayleighRitzQuotients(chebfi, maxeig, mineig, DivResults%self)
537 :
538 15368 : call xmpi_max(maxeig,maxeig_global,chebfi%spacecom,ierr)
539 15368 : call xmpi_min(mineig,mineig_global,chebfi%spacecom,ierr)
540 15368 : call timab(tim_RR_q, 2, tsec)
541 :
542 15368 : lambda_minus = maxeig_global
543 :
544 15368 : call timab(tim_oracle,1,tsec)
545 :
546 : ! ndeg_filter_max limits the reduction of the residual of the smallest eigenvalue (i.e. the most amplified one by the filter) by a factor 1e8.
547 : ! Also, the maximal value of ndeg_filter_max is 40.
548 15368 : ndeg_filter_max = cheb_oracle1(mineig_global, lambda_minus, lambda_plus, 1D-16, 40)
549 15368 : ndeg_filter = MIN(ndeg_filter_max,chebfi%ndeg_filter)
550 15368 : if (chebfi%oracle>0) then
551 2312 : call chebfi_set_ndeg_from_residu(chebfi,lambda_minus,lambda_plus,occ,DivResults%self,ndeg_filter_max,ndeg_filter)
552 : end if
553 96712 : ndeg_filter_bands(:) = ndeg_filter
554 :
555 15368 : call timab(tim_oracle,2,tsec)
556 :
557 15368 : center = (lambda_plus + lambda_minus)*0.5
558 15368 : radius = (lambda_plus - lambda_minus)*0.5
559 :
560 15368 : one_over_r = 1/radius
561 15368 : two_over_r = 2/radius
562 :
563 129554 : do ideg = 0, ndeg_filter - 1
564 :
565 114186 : call timab(tim_cprj,1,tsec)
566 114186 : call xg_nonlop_getcprj(xg_nonlop,chebfi%xAXcolsrows,chebfi%cprjX,chebfi%proj_work%self)
567 114186 : call timab(tim_cprj,2,tsec)
568 114186 : call chebfi_computeNextOrderChebfiPolynom(chebfi, ideg, center, one_over_r, two_over_r)
569 :
570 114186 : call timab(tim_swap,1,tsec)
571 114186 : call chebfi_swapInnerBuffers(chebfi, chebfi%total_spacedim, chebfi%bandpp)
572 114186 : call timab(tim_swap,2,tsec)
573 :
574 : !A * Psi
575 114186 : call timab(tim_AX_v,1,tsec)
576 114186 : call getAX(chebfi%xXColsRows,chebfi%xAXColsRows)
577 114186 : call timab(tim_AX_v,2,tsec)
578 114186 : call timab(tim_AX_k,1,tsec)
579 114186 : call xgBlock_add_diag(chebfi%xXColsRows,kin,nspinor,chebfi%xAXColsRows)
580 114186 : call timab(tim_AX_k,2,tsec)
581 114186 : call timab(tim_cprj,1,tsec)
582 114186 : call xg_nonlop_getcprj(xg_nonlop,chebfi%xXColsRows,chebfi%cprjX,chebfi%proj_work%self)
583 114186 : call timab(tim_cprj,2,tsec)
584 114186 : call timab(tim_AX_nl,1,tsec)
585 114186 : call xg_nonlop_getHX(xg_nonlop,chebfi%xAXcolsRows,chebfi%cprjX,chebfi%cprj_work%self,chebfi%proj_work%self)
586 129554 : call timab(tim_AX_nl,2,tsec)
587 :
588 : end do
589 :
590 15368 : call timab(tim_barrier,1,tsec)
591 15368 : call xmpi_barrier(chebfi%spacecom)
592 15368 : call timab(tim_barrier,2,tsec)
593 :
594 15368 : call timab(tim_amp_f,1,tsec)
595 15368 : call chebfi_ampfactor(chebfi, DivResults%self, lambda_minus, lambda_plus, ndeg_filter_bands)
596 : ! this results in higher condition number so avoid
597 : !call chebfi_ampfactorMax(chebfi, DivResults%self, lambda_minus, lambda_plus, ndeg_filter_bands)
598 15368 : call timab(tim_amp_f,2,tsec)
599 :
600 15368 : call xg_free(DivResults)
601 15368 : ABI_FREE(ndeg_filter_bands)
602 :
603 15368 : call timab(tim_transpose,1,tsec)
604 15368 : call xmpi_barrier(chebfi%spacecom)
605 :
606 15368 : call xgTransposer_transpose(chebfi%xgTransposerX,STATE_LINALG)
607 15368 : call xgTransposer_transpose(chebfi%xgTransposerAX,STATE_LINALG)
608 :
609 15368 : if (xmpi_comm_size(chebfi%spacecom) == 1) then !only one MPI proc reset buffers to right addresses (because of X-Xcolwise swaps)
610 4216 : call xgBlock_setBlock(chebfi%xXColsRows , chebfi%X , spacedim, neigenpairs)
611 4216 : call xgBlock_setBlock(chebfi%xAXColsRows, chebfi%AX%self, spacedim, neigenpairs)
612 : end if
613 15368 : call timab(tim_transpose,2,tsec)
614 :
615 15368 : call timab(tim_cprj,1,tsec)
616 15368 : call xg_nonlop_getcprj(xg_nonlop,chebfi%X,chebfi%cprjX,chebfi%cprj_work%self)
617 15368 : call timab(tim_cprj,2,tsec)
618 : call xg_RayleighRitz_cprj(chebfi%xg_nonlop,chebfi%X,chebfi%cprjX,chebfi%AX%self,chebfi%eigenvalues,ierr,0,&
619 15368 : tim_RR,ABI_GPU_DISABLED,solve_ax_bx=.true.)
620 :
621 15368 : if (chebfi%paw) then
622 12920 : call timab(tim_AX_nl,1,tsec)
623 : call xg_nonlop_getHmeSX(xg_nonlop,chebfi%X,chebfi%cprjX,chebfi%AX%self,chebfi%eigenvalues,chebfi%cprj_work%self,&
624 12920 : & chebfi%cprj_work2%self,no_H=.True.)
625 12920 : call timab(tim_AX_nl,2,tsec)
626 : end if
627 :
628 15368 : call timab(tim_residu, 1, tsec)
629 :
630 15368 : if (.not.chebfi%paw) then
631 2448 : call xgBlock_yxmax(chebfi%AX%self,chebfi%eigenvalues,chebfi%X)
632 : end if
633 :
634 15368 : call xgBlock_colwiseNorm2(chebfi%AX%self, residu)
635 15368 : call timab(tim_residu, 2, tsec)
636 :
637 15368 : call timab(tim_copy, 1, tsec)
638 15368 : call xgBlock_copy(chebfi%X,X0)
639 15368 : call timab(tim_copy, 2, tsec)
640 :
641 15368 : call xgTransposer_free(chebfi%xgTransposerX)
642 15368 : call xgTransposer_free(chebfi%xgTransposerAX)
643 :
644 15368 : if (.not.chebfi%paw) then
645 2448 : call timab(tim_enl,1,tsec)
646 2448 : call xg_nonlop_colwiseXHX(chebfi%xg_nonlop,chebfi%cprjX,chebfi%cprj_work%self,enl)
647 2448 : call timab(tim_enl,2,tsec)
648 : end if
649 :
650 46104 : end subroutine chebfi_run_cprj
651 : !!***
652 :
653 : !----------------------------------------------------------------------
654 :
655 : !!****f* m_chebfi2_cprj/chebfi_rayleighRitzQuotients
656 : !! NAME
657 : !! chebfi_rayleighRitzQuotients
658 : !!
659 : !! FUNCTION
660 : !! Compute the Rayleigh-Ritz quotients.
661 : !!
662 : !! INPUTS
663 : !!
664 : !! OUTPUT
665 : !!
666 : !! SIDE EFFECTS
667 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
668 : !! maxeig= highest eigenvalue
669 : !! mineig= lowest eigenvalue
670 : !! DivResults= Rayleigh-Ritz quotients
671 : !!
672 : !! SOURCE
673 :
674 15368 : subroutine chebfi_rayleighRitzQuotients(chebfi,maxeig,mineig,DivResults)
675 :
676 : !Arguments ------------------------------------
677 : real(dp), intent(inout) :: maxeig
678 : real(dp), intent(inout) :: mineig
679 : type(chebfi_t), intent(inout) :: chebfi
680 : type(xgBlock_t), intent(inout) :: DivResults
681 :
682 : !Local variables-------------------------------
683 : !scalars
684 : type(xg_t)::Results1
685 : type(xg_t)::Results2
686 : type(xg_t)::Results_work
687 : !arrays
688 : integer :: maxeig_pos(2)
689 : integer :: mineig_pos(2)
690 : integer :: space_res
691 :
692 : ! *********************************************************************
693 :
694 15368 : if (space(chebfi%xXcolsRows)==SPACE_C) then
695 9112 : space_res = SPACE_C
696 6256 : else if (space(chebfi%xXcolsRows)==SPACE_CR) then
697 6256 : space_res = SPACE_R
698 : else
699 0 : ABI_ERROR('space(X) should be SPACE_C or SPACE_CR')
700 : end if
701 15368 : call xg_init(Results1, space_res, chebfi%bandpp, 1)
702 15368 : call xg_init(Results2, space_res, chebfi%bandpp, 1)
703 :
704 15368 : call xgBlock_colwiseDotProduct(chebfi%xXColsRows,chebfi%xAXColsRows,Results1%self,comm_loc=xmpi_comm_null)
705 :
706 15368 : call xgBlock_colwiseDotProduct(chebfi%xXColsRows,chebfi%xXColsRows,Results2%self,comm_loc=xmpi_comm_null)
707 15368 : if (chebfi%xg_nonlop%paw) then
708 12920 : call xg_init(Results_work, space_res, chebfi%bandpp, 1)
709 12920 : call xg_nonlop_colwiseXAX(chebfi%xg_nonlop,chebfi%xg_nonlop%Sij%self,chebfi%cprjX,chebfi%cprj_work%self,Results_work%self)
710 12920 : call xgBlock_add(Results2%self,Results_work%self)
711 12920 : call xg_free(Results_work)
712 : end if
713 :
714 15368 : call xgBlock_colwiseDivision(Results1%self, Results2%self, DivResults, maxeig, maxeig_pos, mineig, mineig_pos)
715 :
716 15368 : call xg_free(Results1)
717 15368 : call xg_free(Results2)
718 :
719 15368 : end subroutine chebfi_rayleighRitzQuotients
720 : !!***
721 :
722 : !----------------------------------------------------------------------
723 :
724 : !!****f* m_chebfi2_cprj/chebfi_computeNextOrderChebfiPolynom
725 : !! NAME
726 : !! chebfi_computeNextOrderChebfiPolynom
727 : !!
728 : !! FUNCTION
729 : !! From P_n(B-^1.A)|X> (where P_n is the Chebyshev polynom of order n),
730 : !! computes P_n+1(B-^1.A)|X>
731 : !!
732 : !! INPUTS
733 : !! ideg=current degree of polynom
734 : !! center=filter center
735 : !! one_over_r,two_over_r=1/R, 2/R, R being the radius of the filter
736 : !! getBm1X= pointer to the function giving B^-1|X>
737 : !! B is typically the overlap operator S
738 : !!
739 : !! OUTPUT
740 : !!
741 : !! SIDE EFFECTS
742 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
743 : !!
744 : !! SOURCE
745 :
746 114186 : subroutine chebfi_computeNextOrderChebfiPolynom(chebfi,ideg,center,one_over_r,two_over_r)
747 :
748 : !Arguments ------------------------------------
749 : real(dp) , intent(in) :: center
750 : integer , intent(in) :: ideg
751 : real(dp) , intent(in) :: one_over_r
752 : real(dp) , intent(in) :: two_over_r
753 : type(chebfi_t) , intent(inout) :: chebfi
754 :
755 : !Local variables-------------------------------
756 : real(dp) :: tsec(2)
757 :
758 : ! *********************************************************************
759 :
760 114186 : call timab(tim_copy, 1, tsec)
761 114186 : call xgBlock_copy(chebfi%xAXColsRows,chebfi%X_next)
762 114186 : call timab(tim_copy, 2, tsec)
763 :
764 114186 : if (chebfi%paw) then
765 94950 : call timab(tim_invovl, 1, tsec)
766 : call xg_nonlop_getSm1X(chebfi%xg_nonlop,chebfi%X_next,chebfi%cprjX,&
767 94950 : & chebfi%cprj_work%self,chebfi%cprj_work2%self,chebfi%proj_work%self)
768 94950 : call timab(tim_invovl, 2, tsec)
769 : else
770 19236 : call timab(tim_copy, 1, tsec)
771 19236 : call xgBlock_copy(chebfi%xAXColsRows,chebfi%X_next)
772 19236 : call timab(tim_copy, 2, tsec)
773 : end if
774 :
775 114186 : call timab(tim_postinvovl, 1, tsec)
776 114186 : call xgBlock_scale(chebfi%xXColsRows, center, 1) !scale by center
777 :
778 : !(B-1 * A * Psi^i-1 - c * Psi^i-1)
779 114186 : call xgBlock_saxpy(chebfi%X_next, dble(-1.0), chebfi%xXColsRows)
780 :
781 : !Psi^i-1 = 1/c * Psi^i-1
782 114186 : call xgBlock_scale(chebfi%xXColsRows, 1/center, 1) !counter scale by 1/center
783 :
784 114186 : if (ideg == 0) then
785 14984 : call xgBlock_scale(chebfi%X_next, one_over_r, 1)
786 : else
787 99202 : call xgBlock_scale(chebfi%X_next, two_over_r, 1)
788 :
789 99202 : call xgBlock_saxpy(chebfi%X_next, dble(-1.0), chebfi%X_prev)
790 : end if
791 :
792 114186 : call timab(tim_postinvovl, 2, tsec)
793 :
794 114186 : end subroutine chebfi_computeNextOrderChebfiPolynom
795 : !!***
796 :
797 : !----------------------------------------------------------------------
798 :
799 : !!****f* m_chebfi2_cprj/chebfi_swapInnerBuffers
800 : !! NAME
801 : !! chebfi_swapInnerBuffers
802 : !!
803 : !! FUNCTION
804 : !! Swap buffers inside a 'chebfi' datastructure.
805 : !!
806 : !! INPUTS
807 : !! neigenpairs= number of requested eigenvectors/eigenvalues
808 : !! spacedim= space dimension for one vector
809 : !!
810 : !! OUTPUT
811 : !!
812 : !! SIDE EFFECTS
813 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
814 : !!
815 : !! SOURCE
816 :
817 114186 : subroutine chebfi_swapInnerBuffers(chebfi,spacedim,neigenpairs)
818 :
819 : ! Arguments ------------------------------------
820 : integer , intent(in ) :: spacedim
821 : integer , intent(in ) :: neigenpairs
822 : type(chebfi_t) , intent(inout) :: chebfi
823 :
824 : ! *********************************************************************
825 :
826 114186 : call xgBlock_setBlock(chebfi%X_prev, chebfi%X_swap, spacedim, neigenpairs) !X_swap = X_prev
827 114186 : call xgBlock_setBlock(chebfi%xXColsRows, chebfi%X_prev, spacedim, neigenpairs) !X_prev = xXColsRows
828 114186 : call xgBlock_setBlock(chebfi%X_next, chebfi%xXColsRows, spacedim, neigenpairs) !xXColsRows = X_next
829 114186 : call xgBlock_setBlock(chebfi%X_swap, chebfi%X_next, spacedim, neigenpairs) !X_next = X_swap
830 :
831 114186 : end subroutine chebfi_swapInnerBuffers
832 : !!***
833 :
834 : !----------------------------------------------------------------------
835 :
836 : !!****f* m_chebfi2_cprj/chebfi_ampfactor
837 : !! NAME
838 : !! chebfi_ampfactor
839 : !!
840 : !! FUNCTION
841 : !! Compute amplification factor
842 : !!
843 : !! INPUTS
844 : !! eig (:,:)= eigenvalues
845 : !! lambda_minus,lambda_plus=
846 : !! ndeg_filter_bands(:)= degree of Chebyshev polynomial filter for each band
847 : !!
848 : !! OUTPUT
849 : !!
850 : !! SIDE EFFECTS
851 : !! residu<type(xgBlock_t)>= vector of residuals
852 : !! chebfi <type(chebfi_t)>=all data used to apply Chebyshev Filtering algorithm
853 : !!
854 : !! SOURCE
855 :
856 15368 : subroutine chebfi_ampfactor(chebfi,DivResults,lambda_minus,lambda_plus,ndeg_filter_bands)
857 :
858 : ! Arguments ------------------------------------
859 : integer, intent(in ) :: ndeg_filter_bands(:)
860 : type(xgBlock_t), intent(in ) :: DivResults
861 : real(dp), intent(in ) :: lambda_minus
862 : real(dp), intent(in ) :: lambda_plus
863 : type(chebfi_t), intent(inout) :: chebfi
864 :
865 : ! Local variables-------------------------------
866 : ! scalars
867 : integer :: iband
868 : real(dp) :: ampfactor
869 : real(dp) :: eig_per_band
870 : type(xgBlock_t) :: X_part
871 : type(xgBlock_t) :: AX_part
872 15368 : real(dp),pointer :: eig(:,:)
873 :
874 : ! *********************************************************************
875 :
876 15368 : call xgBlock_reverseMap(DivResults,eig,rows=1,cols=chebfi%bandpp)
877 :
878 96712 : do iband = 1, chebfi%bandpp
879 :
880 81344 : eig_per_band = eig(1,iband)
881 :
882 : !cheb_poly1(x, n, a, b)
883 81344 : ampfactor = cheb_poly1(eig_per_band, ndeg_filter_bands(iband), lambda_minus, lambda_plus)
884 :
885 81344 : if(abs(ampfactor) < 1e-3) ampfactor = 1e-3 !just in case, avoid amplifying too much
886 :
887 81344 : call xgBlock_setBlock(chebfi%xXColsRows, X_part, chebfi%total_spacedim, 1, fcol=iband)
888 81344 : call xgBlock_setBlock(chebfi%xAXColsRows, AX_part, chebfi%total_spacedim, 1, fcol=iband)
889 :
890 81344 : call xgBlock_scale(X_part, 1/ampfactor, 1)
891 96712 : call xgBlock_scale(AX_part, 1/ampfactor, 1)
892 :
893 : end do
894 :
895 15368 : end subroutine chebfi_ampfactor
896 : !!***
897 :
898 : subroutine chebfi_ampfactorMax(chebfi,DivResults,lambda_minus,lambda_plus,ndeg_filter_bands)
899 :
900 : ! Arguments ------------------------------------
901 : integer, intent(in ) :: ndeg_filter_bands(:)
902 : type(xgBlock_t), intent(in ) :: DivResults
903 : real(dp), intent(in ) :: lambda_minus
904 : real(dp), intent(in ) :: lambda_plus
905 : type(chebfi_t), intent(inout) :: chebfi
906 :
907 : ! Local variables-------------------------------
908 : ! scalars
909 : integer :: iband
910 : real(dp) :: ampfactor
911 : !type(xgBlock_t) :: X_part
912 : !type(xgBlock_t) :: AX_part
913 : real(dp),pointer :: eig(:,:)
914 :
915 : ! *********************************************************************
916 :
917 : call xgBlock_reverseMap(DivResults,eig,rows=1,cols=cols(DivResults))
918 :
919 : !cheb_poly1(x, n, a, b)
920 : ampfactor = maxval( (/ (cheb_poly1(eig(1,iband), ndeg_filter_bands(iband), lambda_minus, lambda_plus),&
921 : iband=1,cols(DivResults)) /) )
922 :
923 : call xgBlock_scale(chebfi%xXColsRows, 1/ampfactor, 1)
924 : call xgBlock_scale(chebfi%xAXColsRows, 1/ampfactor, 1)
925 :
926 : end subroutine chebfi_ampfactorMax
927 : !!***
928 :
929 : !----------------------------------------------------------------------
930 :
931 : !!****f* m_chebfi2_cprj/chebfi_oracle1
932 : !! NAME
933 : !! chebfi_oracle1
934 : !!
935 : !! FUNCTION
936 : !! Compute order of Chebyshev polynom necessary to converge to a given tol
937 : !!
938 : !! INPUTS
939 : !! xx= input variable
940 : !! aa= left bound of the interval
941 : !! bb= right bound of the interval
942 : !! tol= needed precision
943 : !! nmax= max number of iterations
944 : !!
945 : !! OUTPUT
946 : !!
947 : !! SIDE EFFECTS
948 : !!
949 : !! SOURCE
950 :
951 22620 : function cheb_oracle1(xx,aa,bb,tol,nmax) result(nn)
952 :
953 : ! Arguments ------------------------------------
954 : integer :: nn
955 : integer, intent(in) :: nmax
956 : real(dp), intent(in) :: xx,aa,bb
957 : real(dp), intent(in) :: tol
958 :
959 : ! Local variables-------------------------------
960 : integer :: ii
961 : real(dp) :: yy,yim1,xred,temp
962 :
963 : ! *************************************************************************
964 :
965 22620 : xred = (xx-(aa+bb)/2)/(bb-aa)*2
966 22620 : yy = xred
967 22620 : yim1 = 1 !ONE
968 :
969 22620 : nn = nmax
970 22620 : if(1/(yy**2) < tol) then
971 : nn = 1
972 : else
973 422342 : do ii=2, nmax-1
974 421826 : temp = yy
975 421826 : yy = 2*xred*yy - yim1
976 421826 : yim1 = temp
977 422342 : if(1/(yy**2) < tol) then
978 : nn = ii
979 : exit
980 : end if
981 : end do
982 : end if
983 :
984 22620 : end function cheb_oracle1
985 : !!***
986 :
987 : !----------------------------------------------------------------------
988 :
989 : !!****f* m_chebfi2_cprj/chebfi_poly1
990 : !! NAME
991 : !! chebfi_poly1
992 : !!
993 : !! FUNCTION
994 : !! Compute Chebyshev polynomial???
995 : !!
996 : !! INPUTS
997 : !! xx= input variable
998 : !! aa= left bound of the interval
999 : !! bb= right bound of the interval
1000 : !! nn=
1001 : !!
1002 : !! OUTPUT
1003 : !!
1004 : !! SIDE EFFECTS
1005 : !!
1006 : !! SOURCE
1007 :
1008 81344 : function cheb_poly1(xx,nn,aa,bb) result(yy)
1009 :
1010 : ! Arguments ------------------------------------
1011 : integer, intent(in) :: nn
1012 : real(dp), intent(in) :: xx, aa, bb
1013 : real(dp) :: yy
1014 :
1015 : ! Local variables-------------------------------
1016 : integer :: ii
1017 : real(dp) :: xred,yim1,temp
1018 :
1019 : ! *************************************************************************
1020 :
1021 81344 : xred = (xx-(aa+bb)/2)/(bb-aa)*2
1022 81344 : yy = xred
1023 81344 : yim1 = 1
1024 611328 : do ii= 2, nn
1025 529984 : temp = yy
1026 529984 : yy = 2*xred*yy - yim1
1027 611328 : yim1 = temp
1028 : end do
1029 :
1030 81344 : end function cheb_poly1
1031 : !!***
1032 :
1033 : !!****f* m_chebfi2_cprj/chebfi_set_ndeg_from_residu
1034 : !! NAME
1035 : !! chebfi_set_ndeg_from_residu
1036 : !!
1037 : !! FUNCTION
1038 : !! Compute ndeg_filter using the oracle and residuals.
1039 : !!
1040 : !! INPUTS
1041 : !!
1042 : !! OUTPUT
1043 : !!
1044 : !! SIDE EFFECTS
1045 : !!
1046 : !! SOURCE
1047 :
1048 2312 : subroutine chebfi_set_ndeg_from_residu(chebfi,lambda_minus,lambda_plus,occ,DivResults,ndeg_filter_max,ndeg_filter)
1049 :
1050 : integer,intent(in) :: ndeg_filter_max
1051 : integer,intent(out) :: ndeg_filter
1052 : type(chebfi_t), intent(inout) :: chebfi
1053 : type(xgBlock_t), intent(in) :: occ
1054 : type(xgBlock_t), intent(in) :: DivResults
1055 : real(dp), intent(in) :: lambda_minus, lambda_plus
1056 :
1057 : logical :: test1,test2,test3
1058 : integer :: iband_tot,iband
1059 : integer :: bandpp,ierr,ndeg_filter_tolwfr,ndeg_filter_decrease,nbdbuf,ndeg_filter_all,shift
1060 2312 : integer,allocatable :: ndeg_filter_bands(:)
1061 : type(xgBlock_t) :: occBlock,occ_reshaped
1062 : type(xg_t) :: residu
1063 2312 : real(dp),pointer :: residu_(:,:),occ_(:,:)
1064 : real(dp) :: eig_iband,res_iband,occ_iband
1065 2312 : real(dp),pointer :: eig(:,:)
1066 :
1067 2312 : bandpp = chebfi%bandpp
1068 :
1069 : !Compute residu here for oracle, use X_next as a work space
1070 : ! X_next = S|Psi>
1071 2312 : call xgBlock_copy(chebfi%xXColsRows,chebfi%X_next)
1072 2312 : if (chebfi%paw) then
1073 2312 : call xg_nonlop_getSX(chebfi%xg_nonlop,chebfi%X_next,chebfi%cprjX,chebfi%cprj_work%self,chebfi%proj_work%self)
1074 : end if
1075 : ! X_next = - eig * S|Psi>
1076 2312 : call xgBlock_ymax(chebfi%X_next,DivResults,0,1)
1077 : ! X_next = H|Psi> - eig * S|Psi>
1078 2312 : call xgBlock_add(chebfi%X_next,chebfi%xAXColsRows)
1079 : ! resid = |X_next|^2
1080 2312 : call xg_init(residu,SPACE_R,bandpp,1)
1081 2312 : call xgBlock_colwiseNorm2(chebfi%X_next, residu%self,comm_loc=xmpi_comm_null)
1082 :
1083 2312 : occ_reshaped = occ
1084 2312 : shift=xmpi_comm_rank(chebfi%spacecom)*bandpp
1085 2312 : call xgBlock_reshape(occ_reshaped,1,chebfi%neigenpairs)
1086 2312 : call xgBlock_setBlock(occ_reshaped,occBlock,1,bandpp,fcol=1+shift)
1087 2312 : call xgBlock_reshape(occBlock,bandpp,1)
1088 2312 : if (chebfi%nbdbuf==-101) then
1089 952 : call xgBlock_apply_diag(residu%self,occBlock,1)
1090 : end if
1091 :
1092 6936 : ABI_MALLOC(ndeg_filter_bands,(bandpp))
1093 :
1094 : ! DivResults could be complex (with null imaginary part), so bandpp has to be in cols, not rows
1095 2312 : call xgBlock_reverseMap(DivResults,eig,rows=1,cols=bandpp)
1096 2312 : call xgBlock_reverseMap(residu%self,residu_,rows=1,cols=bandpp)
1097 2312 : call xgBlock_reverseMap(occBlock,occ_,rows=1,cols=bandpp)
1098 :
1099 2312 : if (chebfi%nbdbuf>0) then
1100 : nbdbuf = chebfi%nbdbuf
1101 952 : else if (chebfi%nbdbuf==-101) then
1102 952 : nbdbuf = 0
1103 : end if
1104 :
1105 12104 : do iband=1, bandpp
1106 9792 : eig_iband = eig(1,iband)
1107 9792 : res_iband = residu_(1,iband)
1108 9792 : occ_iband = occ_(1,iband)
1109 9792 : iband_tot = iband + shift
1110 9792 : test1 = res_iband<chebfi%tolerance ! band already converged
1111 9792 : test2 = iband_tot>chebfi%neigenpairs-nbdbuf ! band in the buffer
1112 9792 : test3 = chebfi%nbdbuf==-101.and.occ_iband<chebfi%oracle_min_occ ! occupancy is too low
1113 12104 : if (test1.or.test2.or.test3) then
1114 5750 : ndeg_filter_bands(iband) = 0
1115 : else
1116 : !ndeg_filter necessary to converge to tolerance
1117 4042 : ndeg_filter_tolwfr = cheb_oracle1(eig_iband, lambda_minus, lambda_plus, chebfi%tolerance / res_iband, 1000)
1118 4042 : if (chebfi%oracle==1) then
1119 832 : ndeg_filter_bands(iband) = MIN(ndeg_filter_max, ndeg_filter_tolwfr, chebfi%ndeg_filter)
1120 3210 : else if (chebfi%oracle==2) then
1121 : !ndeg_filter necessary to decrease residual by a constant factor
1122 3210 : ndeg_filter_decrease = cheb_oracle1(eig_iband, lambda_minus, lambda_plus, chebfi%oracle_factor, 15)
1123 3210 : ndeg_filter_bands(iband) = MIN(ndeg_filter_max, ndeg_filter_tolwfr, ndeg_filter_decrease)
1124 : else
1125 0 : ABI_ERROR('Wrong value for chebfi%oracle')
1126 : end if
1127 : end if
1128 : end do
1129 12104 : ndeg_filter = MAXVAL(ndeg_filter_bands)
1130 2312 : call xmpi_max(ndeg_filter,ndeg_filter_all,chebfi%spacecom,ierr)
1131 2312 : ndeg_filter=ndeg_filter_all
1132 :
1133 2312 : call xg_free(residu)
1134 2312 : ABI_FREE(ndeg_filter_bands)
1135 :
1136 4624 : end subroutine chebfi_set_ndeg_from_residu
1137 : !!***
1138 :
1139 : !!****f* m_chebfi2/jackson_lowpass_coeffs
1140 : !! NAME
1141 : !! jackson_lowpass_coeffs
1142 : !!
1143 : !! FUNCTION
1144 : !! Compute Jackson-damped Chebyshev coefficients for a lowpass step
1145 : !! on interval [lambda_min, lambda_max], degree M
1146 :
1147 : subroutine jackson_lowpass_coeffs(M, c)
1148 : implicit none
1149 : integer, intent(in) :: M
1150 : real(dp), intent(out) :: c(1:M+1)
1151 : integer :: k
1152 : real(dp) :: theta, g
1153 :
1154 : ! Chebyshev coefficients for step at left end (-1 in scaled coords)
1155 : theta = acos(-1.0d0) ! step at left edge
1156 : c(1) = theta / Pi ! k = 0
1157 :
1158 : do k = 1, M
1159 : c(k+1) = -2.0d0 / Pi * sin(k*theta) / k
1160 : end do
1161 :
1162 : ! Apply Jackson damping
1163 : do k = 0, M
1164 : g = ((M-k+1)*cos(Pi*k/(M+1)) + sin(Pi*k/(M+1))/tan(Pi/(M+1)))/(M+1)
1165 : c(k+1) = c(k+1) * g
1166 : end do
1167 :
1168 : end subroutine jackson_lowpass_coeffs
1169 : !!***
1170 :
1171 0 : end module m_chebfi2_cprj
1172 : !!***
|