Skip to content

Commit 418ee60

Browse files
authored
Merge pull request #68 from lanl/fermirec
Changed the type to match the input matrix when calling diagonalization.
2 parents 095c2d1 + 49810df commit 418ee60

File tree

2 files changed

+149
-1
lines changed

2 files changed

+149
-1
lines changed

src/prg_sp2_fermi_mod.F90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ function sp2_entropy_ts(D0_bml, GG, ee) result(TS)
363363
allocate(hh(N))
364364

365365
! Diagonalize D0
366-
call bml_zero_matrix(bml_matrix_dense, bml_element_real, &
366+
call bml_zero_matrix(bml_type, bml_element_real, &
367367
dp, N, N, aux_bml)
368368

369369
call bml_diagonalize(D0_bml, hh, aux_bml)

src/prg_sp2_fermirec_mod.F90

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
!> The SP2 Recursive Fermi O(N) module.
2+
!! \ingroup PROGRESS
3+
!
4+
! This subroutine implements Niklasson's SP2 recursive fermi dirac exact
5+
! density matrix purification algorithm.
6+
!
7+
8+
module prg_sp2_fermirec_mod
9+
10+
use bml
11+
use prg_normalize_mod
12+
use prg_timer_mod
13+
use prg_parallel_mod
14+
15+
implicit none
16+
17+
private !Everything is private by default
18+
19+
integer, parameter :: dp = kind(1.0d0)
20+
21+
public :: prg_sp2_fermirec
22+
23+
contains
24+
25+
!> Recursive SP2 Fermi.
26+
!! \param h_bml Input Hamiltonian matrix.
27+
!! \param xio_bml Input ? matrix.
28+
!! \param nsteps Number of sp2 iterations.
29+
!! \param nocc Number of occupied states.
30+
!! \param threshold Threshold for multiplication.
31+
!! \param occErrLimit Occupation error limit.
32+
!! \param traceLimit Trace limit.
33+
!! \param x_bml Output initial matrix.
34+
!! \param mu Shifted chemical potential
35+
!! \param beta Output inverse temperature.
36+
subroutine prg_sp2_fermirec(h_bml, xio_bml, nsteps, nocc, threshold, occErrLimit, &
37+
x_bml, mu, beta)
38+
39+
implicit none
40+
41+
type(bml_matrix_t), intent(in) :: h_bml
42+
type(bml_matrix_t), intent(inout) :: x_bml
43+
integer, intent(in) :: nsteps
44+
real(dp), intent(in) :: nocc, threshold
45+
real(dp), intent(in) :: occErrLimit
46+
real(dp), intent(inout) :: mu, beta
47+
48+
type(bml_matrix_t) :: x1_bml, x2_bml, i_bml, xi_bml
49+
type(bml_matrix_t) :: y_bml
50+
real(dp) :: trdPdmu, trP0, occErr
51+
real(dp) :: cnst, ofactor
52+
real(dp), allocatable :: trace(:)
53+
character(20) :: bml_type
54+
integer :: N, M, i, cnt, NrSchultz
55+
logical :: firstTime
56+
57+
bml_type = bml_get_type(h_bml)
58+
N = bml_get_N(h_bml)
59+
M = bml_get_M(h_bml)
60+
61+
allocate(trace(2))
62+
63+
call bml_identity_matrix(bml_type, bml_element_real, dp, N, M, i_bml)
64+
call bml_zero_matrix(bml_type, bml_element_real, dp, N, M, x1_bml)
65+
call bml_zero_matrix(bml_type, bml_element_real, dp, N, M, x2_bml)
66+
call bml_zero_matrix(bml_type, bml_element_real, dp, N, M, xi_bml)
67+
call bml_zero_matrix(bml_type, bml_element_real, dp, N, M, y_bml)
68+
69+
occErr = 1.0_dp
70+
cnt = 0
71+
firstTime = .true.
72+
73+
do while (occErr .gt. occErrLimit)
74+
75+
!Calculate beta before entering this subroutine
76+
!beta = 1.0_dp/(kB*T) ! Temp in K
77+
78+
! Is this a normalization?
79+
! yes, make as separate routine in normalize_mod
80+
! P0 = 0.5*II - cnst*(H0-mu0*II)
81+
cnst = beta/(2**(2+nsteps))
82+
call bml_copy(h_bml, x_bml)
83+
call bml_add_deprecated(1.0_dp, x_bml, -mu, i_bml, threshold)
84+
call bml_add_deprecated(-cnst, x_bml, 0.5_dp, i_bml, threshold)
85+
call bml_copy(xio_bml, xi_bml) !XI = XIO
86+
87+
do i = 1, nsteps
88+
call bml_multiply_x2(x_bml, x2_bml, threshold, trace)
89+
! Y = 2*(P02-P0) + II
90+
call bml_copy(x2_bml, y_bml)
91+
call bml_add_deprecated(1.0_dp, y_bml, -1.0_dp, x_bml, threshold)
92+
call bml_add_deprecated(2.0_dp, y_bml, 1.0_dp, i_bml, threshold)
93+
94+
if (firstTime .eqv. .true.) then
95+
call bml_inverse(y_bml, xi_bml)
96+
else
97+
NrSchulz = 4
98+
do i = 1, NrSchulz
99+
call bml_copy(xi_bml, xtmp_bml)
100+
call bml_multiply(xtmp_bml, y_bml, x_bml, &
101+
-1.0_dp, 0.0_dp)
102+
call bml_multiply(x_bml, xtmp_bml, xi_bml, &
103+
1.0_dp, 2.0_dp)
104+
enddo
105+
endif
106+
firsttime = .false.
107+
108+
109+
if (j == 1) then
110+
call bml_copy(xi_bml, xio_bml)
111+
endif
112+
113+
call bml_multiply(xi_bml, x2_bml, x_bml, 1.0_dp, 0.0_dp, threshold)
114+
enddo
115+
116+
! Need to write sumDiagonal routine?
117+
trdPdmu = bml_sumDiagonal(x_bml)
118+
trP0 = trdPdmu
119+
! Need to write sumX2 routine?
120+
trdPdmu = trdPdmu - bml_sumX2(x_bml) ! sum x(i,j)**2
121+
122+
trdPdmu = beta * trdPdmu
123+
mu = mu + (nocc - trP0)/trdPdmu
124+
occErr = abs(trP0 - nocc)
125+
cnt = cnt + 1
126+
if (cnt .ge. MaxIt) then
127+
occErr = 0.0_dp
128+
endif
129+
enddo
130+
131+
! Adjust occupation
132+
call bml_copy(i_bml, x1_bml)
133+
call bml_add_deprecated(1.0_dp, x1_bml, -1.0_dp, x_bml, threshold)
134+
call bml_multiply(x_bml, x1_bml, xi_bml, 1.0_dp, 0.0_dp, threshold)
135+
ofactor = ((nocc - trP0)/trdPmu) * beta
136+
call bml_add_deprecated(1.0_dp, x_bml, ofactor, xi_bml, threshold)
137+
138+
deallocate(trace)
139+
140+
call bml_deallocate(xi_bml)
141+
call bml_deallocate(i_bml)
142+
call bml_deallocate(x1_bml)
143+
call bml_deallocate(x2_bml)
144+
call bml_deallocate(y_bml)
145+
146+
end subroutine prg_sp2_fermirec
147+
148+
end module prg_sp2_fermirec_mod

0 commit comments

Comments
 (0)