PROGRESS  master
prg_chebyshev_mod.F90
Go to the documentation of this file.
1 
11 
12  use bml
16  use prg_extras_mod
18 
19  implicit none
20 
21  private
22 
23  integer, parameter :: dp = kind(1.0d0)
24  real(dp), parameter :: pi = 3.14159265358979323846264338327950_dp
25 
28  type, public :: chebdata_type
29  character(100) :: flavor
30  character(100) :: bml_type, jobname
31  integer :: mdim, ncoeffs, ndim, verbose
32  integer :: npts
33  real(dp) :: atr, bndfil, ef, estep
34  real(dp) :: fermitol, kbt, threshold
35  logical :: getef, jon, trkfunc
36  end type chebdata_type
37 
39  public :: prg_parse_cheb
40 
41 contains
42 
53  subroutine prg_parse_cheb(chebdata,filename)
54 
55  implicit none
56  type(chebdata_type), intent(inout) :: chebdata
57  integer, parameter :: nkey_char = 3, nkey_int = 5, nkey_re = 7, nkey_log = 3
58  character(len=*) :: filename
59 
60  !Library of keywords with the respective defaults.
61  character(len=50), parameter :: keyvector_char(nkey_char) = [character(len=50) :: &
62  'JobName=', 'BMLType=', 'Flavor=' ]
63  character(len=100) :: valvector_char(nkey_char) = [character(len=100) :: &
64  'MyJob' , 'Dense' , 'Alg1' ]
65 
66  character(len=50), parameter :: keyvector_int(nkey_int) = [character(len=50) :: &
67  'MDim=', 'NDim=', 'NCoeffs=','Verbose=','NPoints=']
68  integer :: valvector_int(nkey_int) = (/ &
69  -1 , 0 , 50 , 0, 500 /)
70 
71  character(len=50), parameter :: keyvector_re(nkey_re) = [character(len=50) :: &
72  'NumThresh=','FermiTol=','BndFil=','EStep=',"ATr=","Kbt=","Ef=" ]
73  real(dp) :: valvector_re(nkey_re) = (/&
74  0.0 , 0.00000001 ,0.0, 0.01, 0.0, 0.0, 0.0 /)
75 
76  character(len=50), parameter :: keyvector_log(nkey_log) = [character(len=50) :: &
77  'GetEf=', 'Jackson=','TRKFunction=']
78  logical :: valvector_log(nkey_log) = (/&
79  .false., .false., .false./)
80 
81  !Start and stop characters
82  character(len=50), parameter :: startstop(2) = [character(len=50) :: &
83  'CHEB{', '}']
84 
85  call prg_parsing_kernel(keyvector_char,valvector_char&
86  ,keyvector_int,valvector_int,keyvector_re,valvector_re,&
87  keyvector_log,valvector_log,trim(filename),startstop)
88 
89  !Characters
90  chebdata%JobName = valvector_char(1)
91 
92  if(valvector_char(2) == "Dense")then
93  chebdata%bml_type = bml_matrix_dense
94  elseif(valvector_char(2) == "Ellpack")then
95  chebdata%bml_type = bml_matrix_ellpack
96  endif
97  chebdata%flavor = valvector_char(3)
98 
99  !Reals
100  chebdata%threshold = valvector_re(1)
101  chebdata%fermitol = valvector_re(2)
102  chebdata%bndfil = valvector_re(3)
103  chebdata%estep = valvector_re(4)
104  chebdata%atr = valvector_re(5)
105  chebdata%kbt = valvector_re(6)
106  chebdata%ef = valvector_re(7)
107 
108  !Logicals
109  chebdata%getef = valvector_log(1)
110  chebdata%jon = valvector_log(2)
111  chebdata%trkfunc = valvector_log(3)
112 
113  !Integers
114  chebdata%mdim = valvector_int(1)
115  chebdata%ndim = valvector_int(2)
116  chebdata%ncoeffs = valvector_int(3)
117  chebdata%verbose = valvector_int(4)
118  chebdata%npts = valvector_int(5)
119 
120  end subroutine prg_parse_cheb
121 
141  subroutine prg_build_density_cheb(ham_bml, rho_bml, athr, threshold, ncoeffs, &
142  kbt, ef, bndfil, jon, verbose)
143  character(20) :: bml_type
144  integer :: npts, enpts, i, io
145  integer :: norb, mdim
146  integer, intent(in) :: ncoeffs, verbose
147  real(dp) :: alpha, de, maxder, mls_i
148  real(dp) :: mycoeff, occ, scaledef, scaledkbt
149  real(dp) :: threshold1
150  real(dp), allocatable :: coeffs(:), coeffs1(:), domain(:), domain0(:)
151  real(dp), allocatable :: domain2(:), gbnd(:), tn(:), tnm1(:)
152  real(dp), allocatable :: tnp1(:), tnp1_dense(:,:), tracest(:)
153  real(dp), intent(in) :: athr, bndfil, kbt, threshold
154  real(dp), intent(in) :: ef
155  type(bml_matrix_t) :: aux_bml, tn_bml, tnm1_bml, tnp1_bml
156  type(bml_matrix_t) :: x_bml
157  type(bml_matrix_t), intent(in) :: ham_bml
158  type(bml_matrix_t), intent(inout) :: rho_bml
159  logical, intent(in) :: jon
160 
161  if(verbose >= 1)write(*,*)"Building rho via Chebyshev expansion of the Fermi function ..."
162 
163  norb = bml_get_n(ham_bml) !Get the number of orbitals from H
164  bml_type = bml_get_type(ham_bml) !Get the bml type
165 
166  if(verbose >= 1)mls_i = mls()
167  call bml_copy_new(ham_bml,x_bml)
168  call bml_gershgorin(x_bml, gbnd)
169  call prg_normalize_cheb(x_bml,ef,gbnd(1),gbnd(2),alpha,scaledef)
170  if(verbose >= 1)write(*,*)"Time for gershgorin and normalize",mls()-mls_i
171  de = 0.01_dp !This energy step can be set smaller if needed
172  enpts = floor((gbnd(2)-gbnd(1))/de)
173 
174  ! Defining a function with "Real domain" to keep track of the expansion
175  allocate(domain0(enpts))
176  allocate(domain(enpts))
177  allocate(domain2(enpts))
178 
179  ! Chebyshev polynomial for recursion applied to the tracking function
180  allocate(tnp1(enpts))
181  allocate(tnm1(enpts))
182  allocate(tn(enpts))
183  allocate(tnp1_dense(norb,norb))
184 
185  ! Chebyshev coefficients for the expansion
186  allocate(coeffs(ncoeffs))
187  allocate(coeffs1(ncoeffs))
188  allocate(tracest(ncoeffs))
189  tracest = 0.0_dp
190 
191  ! First computation of the Chebyshev coefficients (Non-Ef)
192  if(verbose >= 1)mls_i = mls()
193  call prg_get_chebcoeffs(npts,kbt,ef,ncoeffs,coeffs,gbnd(1),gbnd(2))
194  if(verbose >= 1)write(*,*)"Time for prg_get_chebcoeffs",mls()-mls_i
195 
196  ! Prepare bml matrices for recursion.
197  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,norb,tnp1_bml)
198  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,norb,tn_bml)
199  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,norb,tnm1_bml)
200  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,norb,aux_bml)
201 
202  ! Set the domain for the tracking function
203  if(verbose >= 1)mls_i = mls()
204  do i=1,enpts
205  domain0(i) = gbnd(1) + i*de
206  domain0(i) = 2.0_dp*(domain0(i) - gbnd(1))/(gbnd(2)-gbnd(1)) - 1.0_dp
207  tnp1(i) = 0.0_dp
208  tnm1(i) = 1.0_dp
209  tn(i) = domain0(i)
210  domain(i) = 0.0_dp
211  enddo
212  if(verbose >= 1)write(*,*)"Time for setting the tracking function",mls()-mls_i
213 
214  !First step of recursion ...
215  if(verbose >= 1)mls_i = mls()
216  mycoeff = jackson(ncoeffs,1,jon)*coeffs(1) !Application of the Jackson kernel
217  call bml_add_identity(tnm1_bml, 1.0_dp, threshold) !T0
218  call bml_scale(mycoeff,tnm1_bml,aux_bml) !Rho(0) = coeffs(1)*T0
219  !Second step of recursion ...
220  call bml_copy(x_bml,tn_bml) !T1
221  call bml_add_deprecated(1.0_dp,aux_bml,mycoeff,tn_bml,threshold) !Rho(1) = Rho(0) + coeffs(2)*T(1)
222 
223  tracest(1) = bml_trace(tnm1_bml)
224  domain = 0.0_dp + mycoeff*tnm1
225  mycoeff = jackson(ncoeffs,2,jon)*coeffs(2)
226  tracest(2) = bml_trace(tn_bml)
227  domain = domain + mycoeff*tn
228 
229  !Third to n-1 step of recursion ...
230  if(verbose >= 1) write(*,*)"Chebyshev recursion ..."
231  do i=2,ncoeffs-1
232 
233  mycoeff = coeffs(i+1)*jackson(ncoeffs,i+1,jon)
234 
235  call bml_copy(tnm1_bml,tnp1_bml)
236  tnp1 = tnm1
237 
238  threshold1 = threshold*(athr*real(i-1) + (1.0_dp-athr))
239 
240  call bml_multiply(x_bml,tn_bml,tnp1_bml,2.0_dp,-1.0_dp,threshold1) !T(n+1) = 2xT(n) - T(n-1)
241  tracest(i+1) = bml_trace(tnp1_bml)
242 
243  if(verbose >= 3)then
244  write(*,*)"Time for mult",mls()-mls_i
245  write(*,*)"Coeff",abs(mycoeff)
246  write(*,*)"Bandwidth of Tn, Threshold",bml_get_bandwidth(tnp1_bml),threshold1
247  write(*,*)"Sparsity of Tn",bml_get_sparsity(tnp1_bml,threshold)
248  endif
249 
250  tnp1 = 2.0_dp*domain0*tn - tnp1
251 
252  call bml_add_deprecated(1.0_dp,aux_bml,mycoeff,tnp1_bml,threshold) !Rho(n+1) = Rho(n) + b(n+1)*T(n+1)
253  domain = domain + mycoeff*tnp1
254 
255  call bml_copy(tn_bml,tnm1_bml)
256  call bml_copy(tnp1_bml,tn_bml)
257  tnm1 = tn
258  tn = tnp1
259 
260  enddo
261  if(verbose >= 1)write(*,*)"Time for recursion",mls()-mls_i
262 
263  if(verbose >= 2) then
264  call prg_open_file(io,"fermi_approx.out")
265  write(io,*)"# Energy, FApprox, Fermi"
266  do i=1,enpts
267  write(io,*)gbnd(1) + i*de,domain(i),fermi(gbnd(1) + i*de, ef, kbt)
268  enddo
269  endif
270 
271  if(verbose >= 2) then
272  maxder = absmaxderivative(domain,de)
273  write(*,*)"TargetKbt =",scaledkbt
274  write(*,*)"AbsMaxDerivative =",maxder
275  write(*,*)"kbT = 1/(4*AbsMaxDerivative) =",1.0_dp/(4.0_dp*maxder)
276  endif
277 
278  call bml_copy(aux_bml,rho_bml)
279  call bml_scale(2.0d0, rho_bml)
280 
281  if(verbose >= 1)write(*,*)"TotalOccupation =", bml_trace(rho_bml)
282 
283  end subroutine prg_build_density_cheb
284 
307  subroutine prg_build_density_cheb_fermi(ham_bml, rho_bml, athr, threshold, ncoeffs, &
308  kbt, ef, bndfil, getef, fermitol, jon, npts, trkfunc, verbose)
309 
310  character(20) :: bml_type
311  integer :: npts, enpts, i, io
312  integer :: norb, mdim
313  integer, intent(in) :: ncoeffs, verbose
314  real(dp) :: alpha, de, maxder, mls_i, mls_r
315  real(dp) :: mycoeff, occ, scaledef
316  real(dp) :: threshold1, fermitol
317  real(dp), allocatable :: coeffs(:), coeffs1(:), domain(:), domain0(:)
318  real(dp), allocatable :: domain2(:), gbnd(:), tn(:), tnm1(:)
319  real(dp), allocatable :: tnp1(:), tnp1_dense(:,:), tracest(:)
320  real(dp), intent(in) :: athr, bndfil, kbt, threshold
321  real(dp), intent(out) :: ef
322  type(bml_matrix_t) :: aux_bml, tn_bml, tnm1_bml, tnp1_bml
323  type(bml_matrix_t) :: x_bml
324  type(bml_matrix_t), intent(in) :: ham_bml
325  type(bml_matrix_t), intent(inout) :: rho_bml
326  logical, intent(in) :: getef, jon, trkfunc
327 
328  if(verbose >= 1)write(*,*)"Building rho via Chebyshev expansion of the Fermi function ..."
329  ef = 0.0_dp
330  write(*,*)"ef",ef
331  norb = bml_get_n(ham_bml) !Get the number of orbitals from H
332  mdim = bml_get_m(ham_bml)
333  bml_type = bml_get_type(ham_bml) !Get the bml type
334  mdim = bml_get_m(ham_bml)
335  if(verbose >= 1)mls_i = mls()
336  call bml_copy_new(ham_bml,x_bml)
337  allocate(gbnd(2))
338  call bml_gershgorin(x_bml, gbnd)
339  if(verbose >= 1)write(*,*)"Estimation for emin, emax", gbnd(1), gbnd(2)
340  call prg_normalize_cheb(x_bml,ef,gbnd(1),gbnd(2),alpha,scaledef)
341  if(verbose >= 1)write(*,*)"Time for gershgorin and normalize",mls()-mls_i
342 
343  if(trkfunc)then
344  de = 0.001_dp !This energy step can be set smaller if needed
345  enpts = floor((gbnd(2)-gbnd(1))/de)
346 
347  ! Defining a function with "Real domain" to keep track of the expansion
348  allocate(domain0(enpts))
349  allocate(domain(enpts))
350  allocate(domain2(enpts))
351 
352  ! Chebyshev polynomial for recursion applied to the tracking function
353  allocate(tnp1(enpts))
354  allocate(tnm1(enpts))
355  allocate(tn(enpts))
356  allocate(tnp1_dense(norb,norb))
357  endif
358 
359  ! Chebyshev coefficients for the expansion
360  allocate(coeffs(ncoeffs))
361  allocate(coeffs1(ncoeffs))
362  allocate(tracest(ncoeffs))
363  tracest = 0.0_dp
364 
365  ! First computation of the Chebyshev coefficients (Non-Ef)
366  if(verbose >= 1)mls_i = mls()
367  call prg_get_chebcoeffs(npts,kbt,ef,ncoeffs,coeffs,gbnd(1),gbnd(2))
368  if(verbose >= 1)write(*,*)"Time for prg_get_chebcoeffs",mls()-mls_i
369 
370  ! Prepare bml matrices for recursion.
371  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,mdim,tnp1_bml)
372  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,mdim,tn_bml)
373  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,mdim,tnm1_bml)
374  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,mdim,aux_bml)
375 
376  ! Set the domain for the tracking function
377  if(trkfunc)then
378  mls_i = mls()
379  do i=1,enpts
380  domain0(i) = gbnd(1) + i*de
381  domain0(i) = 2.0_dp*(domain0(i) - gbnd(1))/(gbnd(2)-gbnd(1)) - 1.0_dp
382  tnp1(i) = 0.0_dp
383  tnm1(i) = 1.0_dp
384  tn(i) = domain0(i)
385  domain(i) = 0.0_dp
386  enddo
387  write(*,*)"Time for setting the tracking function",mls()-mls_i
388  endif
389 
390  if(getef)then
391  if(verbose >= 1)write(*,*)"Computing Ef ..."
392  !Compute Ts to get the traces
393  if(verbose >= 1)mls_i = mls()
394  call bml_add_identity(tnm1_bml, 1.0_dp, threshold) !T0
395  tracest(1) = norb
396  call bml_copy(x_bml,tn_bml) !T1
397  tracest(2) = bml_trace(tn_bml)
398  do i=2,ncoeffs-1
399  call bml_copy(tnm1_bml,tnp1_bml)
400  threshold1 = threshold*(athr*real(i-1) + (1.0_dp-athr))
401  call bml_multiply(x_bml,tn_bml,tnp1_bml,2.0_dp,-1.0_dp,threshold1) !T(n+1) = 2xT(n) - T(n-1)
402  tracest(i+1) = bml_trace(tnp1_bml)
403  call bml_copy(tn_bml,tnm1_bml)
404  call bml_copy(tnp1_bml,tn_bml)
405  enddo
406  if(verbose >= 1)write(*,*)"Time for computing traces",mls()-mls_i
407 
408  ! Clear bml matrices
409  call bml_deallocate(tnp1_bml)
410  call bml_deallocate(tn_bml)
411  call bml_deallocate(tnm1_bml)
412  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,mdim,tnp1_bml)
413  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,mdim,tn_bml)
414  call bml_zero_matrix(bml_type,bml_element_real,dp,norb,mdim,tnm1_bml)
415 
416  mls_i = mls()
417  call prg_get_chebcoeffs_fermi_nt(npts,kbt,ef,tracest,ncoeffs,coeffs,gbnd(1),&
418  gbnd(2),bndfil,norb,fermitol,jon,verbose)
419  if(verbose >= 1)write(*,*)"Time for prg_get_chebcoeffs_fermi_nt",mls()-mls_i
420  if(verbose >= 1)write(*,*)"Converged Ef",ef
421  call prg_get_chebcoeffs(npts,kbt,ef,ncoeffs,coeffs,gbnd(1),gbnd(2))
422  endif
423 
424  !First step of recursion ...
425  if(verbose >= 1)mls_r = mls()
426  mycoeff = jackson(ncoeffs,1,jon)*coeffs(1) !Application of the Jackson kernel
427  call bml_add_identity(tnm1_bml, 1.0_dp, threshold) !T0
428  call bml_scale(mycoeff,tnm1_bml,aux_bml) !Rho(0) = coeffs(1)*T0
429  if(trkfunc)then
430  tracest(1) = bml_trace(tnm1_bml)
431  domain = 0.0_dp + mycoeff*tnm1
432  endif
433 
434  !Second step of recursion ...
435  mycoeff = jackson(ncoeffs,2,jon)*coeffs(2)
436  call bml_copy(x_bml,tn_bml) !T1
437  call bml_add_deprecated(1.0_dp,aux_bml,mycoeff,tn_bml,threshold) !Rho(1) = Rho(0) + coeffs(2)*T(1)
438  if(trkfunc)then
439  tracest(2) = bml_trace(tn_bml)
440  domain = domain + mycoeff*tn
441  endif
442 
443  !Third to n-1 step of recursion ...
444  if(verbose >= 1) write(*,*)"Chebyshev recursion ..."
445  do i=2,ncoeffs-1
446 
447  mycoeff = coeffs(i+1)*jackson(ncoeffs,i+1,jon)
448 
449  call bml_copy(tnm1_bml,tnp1_bml)
450  if(trkfunc)tnp1 = tnm1
451 
452  if(verbose >= 4)mls_i = mls()
453  threshold1 = threshold*(athr*real(i-1) + (1.0_dp-athr))
454 
455  call bml_multiply(x_bml,tn_bml,tnp1_bml,2.0_dp,-1.0_dp,threshold1) !T(n+1) = 2xT(n) - T(n-1)
456  tracest(i+1) = bml_trace(tnp1_bml)
457 
458  if(verbose >= 4)then
459  write(*,*)"Time for mult",mls()-mls_i
460  write(*,*)"Coeff",i,abs(mycoeff)
461  write(*,*)"Bandwidth of Tn, Threshold",bml_get_bandwidth(tnp1_bml),threshold1
462  write(*,*)"Sparsity of Tn",bml_get_sparsity(tnp1_bml,threshold)
463  endif
464 
465  if(trkfunc)tnp1 = 2.0_dp*domain0*tn - tnp1
466 
467  call bml_add_deprecated(1.0_dp,aux_bml,mycoeff,tnp1_bml,threshold) !Rho(n+1) = Rho(n) + b(n+1)*T(n+1)
468  if(trkfunc)domain = domain + mycoeff*tnp1
469 
470  call bml_copy(tn_bml,tnm1_bml)
471  call bml_copy(tnp1_bml,tn_bml)
472  if(trkfunc)then
473  tnm1 = tn
474  tn = tnp1
475  endif
476 
477  if(verbose >= 4)then
478  occ = 2.0_dp*bml_trace(aux_bml)
479  if(verbose >= 1) write(*,*)"Step, Occupation",i,occ
480  write(*,*)"Time for", i,"recursion",mls()-mls_i
481  endif
482  enddo
483  if(verbose >= 1)write(*,*)"Time for recursion",mls()-mls_r
484 
485  if(trkfunc) then
486  call prg_open_file(io,"fermi_approx.out")
487  write(io,*)"# Energy, FApprox, Fermi"
488  do i=1,enpts
489  write(io,*)gbnd(1) + i*de,domain(i),fermi(gbnd(1) + i*de, ef, kbt)
490  enddo
491  close(io)
492  endif
493 
494  if(verbose >= 2) then
495  maxder = absmaxderivative(domain,de)
496  write(*,*)"TargetKbt =",kbt
497  write(*,*)"AbsMaxDerivative =",maxder
498  write(*,*)"Actual Kbt = 1/(4*AbsMaxDerivative) =",1.0_dp/(4.0_dp*maxder)
499  endif
500 
501  call bml_copy(aux_bml,rho_bml)
502  call bml_scale(2.0d0, rho_bml)
503 
504  if(verbose >= 1)write(*,*)"TotalOccupation =", bml_trace(rho_bml)
505 
506  if(trkfunc)then
507  deallocate(domain0)
508  deallocate(domain)
509  deallocate(domain2)
510  deallocate(tnp1)
511  deallocate(tnm1)
512  deallocate(tn)
513  deallocate(tnp1_dense)
514  endif
515 
516  deallocate(coeffs)
517  deallocate(coeffs1)
518  deallocate(tracest)
519  call bml_deallocate(tnp1_bml)
520  call bml_deallocate(tn_bml)
521  call bml_deallocate(tnm1_bml)
522  call bml_deallocate(aux_bml)
523  call bml_deallocate(x_bml)
524 
525  end subroutine prg_build_density_cheb_fermi
526 
531  real(dp) function jackson(ncoeffs,i,jon)
532 
533  integer, intent(in) :: ncoeffs,i
534  logical, intent(in) :: jon
535 
536  if(jon)then
537  if(i == 1)then
538  jackson = 1.0_dp
539  endif
540 
541  if(i == 2)then
542  jackson = real(ncoeffs)*cos(pi/(real(ncoeffs+1))) &
543  + sin(pi/(real(ncoeffs+1)))*1.0_dp/tan(pi/(real(ncoeffs+1)))
544  jackson = jackson/real(ncoeffs+1)
545  endif
546 
547  if(i > 2)then
548  jackson = real(ncoeffs - i + 1)*cos(pi*i/(real(ncoeffs+1))) &
549  + sin(pi*i/(real(ncoeffs+1)))*1.0_dp/tan(pi/(real(ncoeffs+1)))
550  jackson = jackson/real(ncoeffs + 1)
551  endif
552  else
553  jackson = 1.0_dp
554  endif
555 
556  end function jackson
557 
567  subroutine prg_get_chebcoeffs(npts,kbt,ef,ncoeffs,coeffs,emin,emax)
568 
569  integer :: i,j
570  integer, intent(in) :: ncoeffs, npts
571  real(dp) :: Int, Kr, Kr0, x
572  real(dp) :: xj
573  real(dp), intent(in) :: ef, emax, emin, kbt
574  real(dp), intent(inout) :: coeffs(:)
575 
576  !Get coefficient of nth cheb expansion.
577  kr = 0.5_dp*real(npts+1.0d0)
578  kr0 = real(npts+1.0d0)
579 
580  coeffs = 0.0d0
581 
582  !$omp parallel do default(none) private(i) &
583  !$omp private(j,x,xj,Int) &
584  !$omp shared(emin,emax,npts,ef,kbt,Kr,Kr0,coeffs,ncoeffs)
585  do i = 0,ncoeffs-1
586 
587  int = 0.0d0
588  do j=0,npts
589  xj = cos((j+0.5_dp)*pi/(npts + 1))
590  x = (emax-emin)*(xj + 1.0d0)/2.0d0 + emin
591  int = int + tr(i,xj)*fermi(x,ef,kbt)
592  enddo
593 
594  if(i == 0) then
595  coeffs(i+1) = int/kr0
596  else
597  coeffs(i+1) = int/kr
598  endif
599 
600  enddo
601  ! $omp end parallel do
602 
603  end subroutine prg_get_chebcoeffs
604 
618  subroutine prg_get_chebcoeffs_fermi_bs(npts,kbt,ef,tracesT,ncoeffs,coeffs,emin,&
619  emax,bndfil,norb,tol,jon,verbose)
620 
621  integer :: i, m
622  integer, intent(in) :: ncoeffs, norb, verbose, npts
623  real(dp) :: f1, f2, nel
624  real(dp) :: prod, step
625  real(dp), intent(in) :: bndfil, emax, emin, kbt
626  real(dp), intent(in) :: tol, tracesT(:)
627  real(dp), intent(inout) :: coeffs(:), ef
628  logical, intent(in) :: jon
629 
630  nel = bndfil*2.0_dp*real(norb,dp)
631  ef=emin
632  step=abs(emax-emin)
633  f1=0.0_dp
634  f2=0.0_dp
635  prod=0.0_dp
636 
637  if(verbose >= 1)write(*,*)"In prg_get_chebcoeffs_fermi ..."
638 
639  !Sum of the occupations
640  do i=1,ncoeffs
641  f1 = f1 + 2.0_dp*jackson(ncoeffs,i,jon)*coeffs(i)*tracest(i)
642  enddo
643  f1=f1-nel
644 
645  do m=1,1000001
646 
647  if(m.gt.1000000)then
648  stop "Bisection method in prg_get_chebcoeffs_fermi is not converging ..."
649  endif
650 
651  if(verbose >= 2)write(*,*)"ef,f(ef)",ef,f1
652  if(abs(f1).lt.tol)then !tolerance control
653  return
654  endif
655 
656  ef = ef + step
657 
658  f2=0.0_dp
659  call prg_get_chebcoeffs(npts,kbt,ef,ncoeffs,coeffs,emin,emax)
660  !New sum of the occupations
661  do i=1,ncoeffs
662  f2 = f2 + 2.0_dp*jackson(ncoeffs,i,jon)*coeffs(i)*tracest(i)
663  enddo
664  f2=f2-nel
665 
666  !Product to see the change in sign.
667  prod = f2*f1
668 
669  if(prod.lt.0)then
670  ef=ef-step
671  step=step/2.0_dp !If the root is inside we shorten the step.
672  else
673  f1=f2 !If not, Ef moves forward.
674  endif
675 
676  enddo
677 
678  end subroutine prg_get_chebcoeffs_fermi_bs
679 
695  subroutine prg_get_chebcoeffs_fermi_nt(npts,kbt,ef,tracesT,ncoeffs,coeffs,emin,emax &
696  ,bndfil,norb,tol,jon,verbose)
697 
698  integer :: i, m
699  integer, intent(in) :: ncoeffs, norb, verbose, npts
700  real(dp) :: ef0, f1, f2, nel
701  real(dp) :: step
702  real(dp), intent(in) :: bndfil, emax, emin, kbt
703  real(dp), intent(in) :: tol, tracesT(:)
704  real(dp), intent(inout) :: coeffs(:), ef
705  logical, intent(in) :: jon
706 
707  nel = bndfil*2.0_dp*real(norb,dp)
708  ef0 = ef
709  f1 = 0.0_dp
710  f2 = 0.0_dp
711  step = 0.1_dp
712 
713  if(verbose >= 1) write(*,*)"In prg_get_chebcoeffs_fermi_nt ..."
714 
715  !Sum of the occupations
716  !$omp parallel do default(none) private(i) &
717  !$omp shared(jon,coeffs,ncoeffs,tracesT) &
718  !$omp reduction(+:f1)
719  do i=1,ncoeffs
720  f1 = f1 + 2.0_dp*jackson(ncoeffs,i,jon)*coeffs(i)*tracest(i)
721  enddo
722  !$omp end parallel do
723 
724  f1=f1-nel
725  ef = ef0 + step
726  call prg_get_chebcoeffs(npts,kbt,ef,ncoeffs,coeffs,emin,emax)
727  f2 = 0.0_dp
728 
729  !$omp parallel do default(none) private(i) &
730  !$omp shared(jon,coeffs,ncoeffs,tracesT) &
731  !$omp reduction(+:f2)
732  do i=1,ncoeffs
733  f2 = f2 + 2.0_dp*jackson(ncoeffs,i,jon)*coeffs(i)*tracest(i)
734  enddo
735  !$omp end parallel do
736 
737  f2=f2-nel
738  ef0 = ef
739  ef = -f2*step/(f2-f1) + ef0
740  f1 = f2
741  step = ef - ef0
742 
743  do m = 1,1000001
744  if(m.gt.1000000)then
745  stop "Newton method in prg_get_chebcoeffs_fermi_nt is not converging ..."
746  endif
747  !New sum of the occupations
748  f2 = 0.0_dp
749  call prg_get_chebcoeffs(npts,kbt,ef,ncoeffs,coeffs,emin,emax)
750 
751  !$omp parallel do default(none) private(i) &
752  !$omp shared(jon,coeffs,ncoeffs,tracesT) &
753  !$omp reduction(+:f2)
754  do i=1,ncoeffs
755  f2 = f2 + 2.0_dp*jackson(ncoeffs,i,jon)*coeffs(i)*tracest(i)
756  enddo
757  !$omp end parallel do
758 
759  f2=f2-nel
760  if(verbose >= 2) write(*,*)"ef,f(ef)",ef,f2
761  ef0 = ef
762  ef = -f2*step/(f2-f1) + ef0
763  f1 = f2
764  step = ef - ef0
765  if(abs(f1).lt.tol)then !tolerance control
766  return
767  endif
768  enddo
769 
770  end subroutine prg_get_chebcoeffs_fermi_nt
771 
776  real(dp) function tr(r,x)
777 
778  real(dp), intent(in) :: x
779  integer, intent(in) :: r
780 
781  tr = cos(r*acos(x))
782 
783  end function tr
784 
789  real(dp) function fermi(e,ef,kbt)
790 
791  real(dp), intent(in) :: e, ef, kbt
792 
793  fermi = 1.0_dp/(1.0_dp+exp((e-ef)/(kbt)))
794 
795  end function fermi
796 
801  real(dp) function absmaxderivative(func,de)
802 
803  real(dp), intent(in) :: func(:), de
804  integer :: j
805 
806  absmaxderivative = -10000.0d0
807 
808  do j=1,size(func, dim=1)-1
809  if(abs(func(j+1) - func(j))/de > absmaxderivative) &
810  absmaxderivative = abs(func(j+1) - func(j))/de
811  enddo
812 
813  end function absmaxderivative
814 
815 
816 end module prg_chebyshev_mod
Module to obtain the density matrix by applying a Chebyshev polynomial expansion.
subroutine prg_get_chebcoeffs_fermi_nt(npts, kbt, ef, tracesT, ncoeffs, coeffs, emin, emax, bndfil, norb, tol, jon, verbose)
Gets the coefficients of the Chebyshev expansion with Ef computation.
integer, parameter dp
real(dp) function jackson(ncoeffs, i, jon)
Evaluates the Jackson Kernel Coefficients.
subroutine, public prg_build_density_cheb_fermi(ham_bml, rho_bml, athr, threshold, ncoeffs, kbt, ef, bndfil, getef, fermitol, jon, npts, trkfunc, verbose)
Builds the density matrix from for a Fermi function approximated with a Chebyshev polynomial expansi...
real(dp) function absmaxderivative(func, de)
Gets the absolute maximum of the derivative of a function.
subroutine, public prg_build_density_cheb(ham_bml, rho_bml, athr, threshold, ncoeffs, kbt, ef, bndfil, jon, verbose)
Builds the density matrix from for a Fermi function approximated with a Chebyshev polynomial expansi...
subroutine prg_get_chebcoeffs_fermi_bs(npts, kbt, ef, tracesT, ncoeffs, coeffs, emin, emax, bndfil, norb, tol, jon, verbose)
Gets the coefficients of the Chebyshev expansion with Ef computation.
real(dp), parameter pi
subroutine, public prg_parse_cheb(chebdata, filename)
Chebyshev parser. This module is used to parse all the input variables for the cheb electronic struct...
real(dp) function tr(r, x)
Chebyshev polynomial obtained by recursion.
subroutine prg_get_chebcoeffs(npts, kbt, ef, ncoeffs, coeffs, emin, emax)
Gets the coefficients of the Chebyshev expansion.
real(dp) function fermi(e, ef, kbt)
Gives the Fermi distribution value for energy e.
Module to obtain the density matrix by diagonalizing an orthogonalized Hamiltonian.
Extra routines.
real(dp) function, public mls()
To get the actual time in milliseconds.
Some general parsing functions.
subroutine, public prg_parsing_kernel(keyvector_char, valvector_char, keyvector_int, valvector_int, keyvector_re, valvector_re, keyvector_log, valvector_log, filename, startstop)
The general parsing function. It is used to vectorize a set of "keywords" "value" pairs as included i...
The prg_normalize module.
subroutine, public prg_normalize_cheb(h_bml, mu, emin, emax, alpha, scaledmu)
Normalize a Hamiltonian matrix prior to running the Chebyshev algorithm.
Module to handle input output files for the PROGRESS lib.
subroutine, public prg_open_file(io, name)
Opens a file to write.