pwdft  0.1
PW-DFT code for education
scf.F90
Go to the documentation of this file.
1 !
2 ! Copyright (c) 2018 Mitsuaki Kawamura
3 !
4 ! Permission is hereby granted, free of charge, to any person obtaining a
5 ! copy of this software and associated documentation files (the
6 ! "Software"), to deal in the Software without restriction, including
7 ! without limitation the rights to use, copy, modify, merge, publish,
8 ! distribute, sublicense, and/or sell copies of the Software, and to
9 ! permit persons to whom the Software is furnished to do so, subject to
10 ! the following conditions:
11 !
12 ! The above copyright notice and this permission notice shall be included
13 ! in all copies or substantial portions of the Software.
14 !
15 ! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 ! OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ! MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ! IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ! TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ! SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 !
23 module scf
24  !
25  implicit none
26  !
27  integer,save :: &
28  & electron_maxstep !< Max number of iteration
29  real(8),save :: &
30  & mixing_beta, & !< Mixing for SCF
31  & conv_thr !< Convergence threshold [Htr]
32  !
33 contains
34  !
35  subroutine scf_loop()
36  !
37  use gvec, only : g_rh
38  use rho_v, only : vks
39  use constant, only : htr2ev
40  !
41  integer :: istep, jstep
42  logical :: linit
43  real(8) :: alpha, res, &
44  & Fvec0(g_rh%nr), dVks(g_rh%nr), Fvec(g_rh%nr), dFvec(g_rh%nr), &
45  & jacob1(g_rh%nr,2:electron_maxstep), jacob2(g_rh%nr,2:electron_maxstep)
46  !
47  linit = .true.
48  !
49  do istep = 1, electron_maxstep
50  !
51  write(*,*) " Iteration ", istep
52  !
53  call kohn_sham_eq(linit, fvec)
54  linit = .false.
55  res = sqrt(dot_product(fvec(1:g_rh%nr), fvec(1:g_rh%nr))) / dble(g_rh%nr)
56  write(*,*) " delta Vks [eV] : ", res * htr2ev
57  if(res < conv_thr) exit
58  !
59  if(istep > 1) then
60  !
61  ! Update Jacobian with dFvec
62  !
63  dfvec(1:g_rh%nr) = fvec(1:g_rh%nr) - fvec0(1:g_rh%nr)
64  !
65  jacob1(1:g_rh%nr,istep) = mixing_beta * dfvec(1:g_rh%nr) + dvks(1:g_rh%nr)
66  do jstep = 2, istep - 1
67  alpha = dot_product(jacob2(1:g_rh%nr,jstep), dfvec(1:g_rh%nr))
68  jacob1(1:g_rh%nr,istep) = jacob1(1:g_rh%nr,istep) - jacob1(1:g_rh%nr,jstep) * alpha
69  end do
70  !
71  alpha = dot_product(dfvec(1:g_rh%nr), dfvec(1:g_rh%nr))
72  jacob2(1:g_rh%nr,istep) = dfvec(1:g_rh%nr) / alpha
73  !
74  end if
75  !
76  ! Compute dVks with new Jacobian & Fvec
77  !
78  dvks(1:g_rh%nr) = mixing_beta * fvec(1:g_rh%nr)
79  do jstep = 2, istep
80  alpha = dot_product(jacob2(1:g_rh%nr,jstep), fvec(1:g_rh%nr))
81  dvks(1:g_rh%nr) = dvks(1:g_rh%nr) - jacob1(1:g_rh%nr,jstep) * alpha
82  end do
83  fvec0(1:g_rh%nr) = fvec(1:g_rh%nr)
84  !
85  vks(1:g_rh%nr) = vks(1:g_rh%nr) + dvks(1:g_rh%nr)
86  !
87  end do ! istep
88  !
89  if(istep >= electron_maxstep) then
90  write(*,'(/,7x,"Not converged ! res = ",e12.5,/)') res
91  else
92  write(*,'(/,7x,"Converged ! iter = ",i0,/)') istep
93  end if
94  !
95  end subroutine scf_loop
96  !
97  !
98  !
99  subroutine kohn_sham_eq(linit,Fvec)
100  !
101  use gvec, only : g_wf, g_rh
102  use kohn_sham, only : nbnd, eval, evec, calculation
103  use k_point, only : kvec, nk, ksum_rho
104  use rho_v, only : vks, vps, hartree_pot, xc_pot
105  use diag_direct, only : direct
106  use lobpcg, only : lobpcg_main
107  !
108  logical,intent(in) :: linit
109  real(8),intent(out) :: Fvec(g_rh%nr)
110  !
111  integer :: ik, istep, avestep
112  !
113  if(calculation == "direct") then
114  do ik = 1, nk
115  call direct(g_wf%npw,kvec(1:3,ik),evec(1:g_wf%npw,1:nbnd,ik),eval(1:nbnd,ik))
116  end do
117  else
118  avestep = 0
119  if(linit) call initialize_wf(evec(1:g_wf%npw,1:nbnd,1))
120  do ik = 1, nk
121  call lobpcg_main(g_wf%npw, kvec(1:3,ik),&
122  & evec(1:g_wf%npw,1:nbnd,ik),eval(1:nbnd,ik), istep)
123  avestep = avestep + istep
124  if(linit .and. ik /= nk) evec(1:g_wf%npw,1:nbnd,ik+1) &
125  & = evec(1:g_wf%npw,1:nbnd,ik)
126  end do
127  write(*,*) " Average LOBPCG steps : ", avestep / nk
128  end if
129  !
130  if(calculation == "scf") then
131  !
132  call ksum_rho()
133  !
134  fvec(1:g_rh%nr) = vps(1:g_rh%nr)
135  call hartree_pot(fvec)
136  call xc_pot(fvec)
137  !
138  fvec(1:g_rh%nr) = fvec(1:g_rh%nr) - vks(1:g_rh%nr)
139  !
140  else
141  fvec(1:g_rh%nr) = 0.0d0
142  end if
143  !
144  end subroutine kohn_sham_eq
148  subroutine initialize_wf(psi)
149  !
150  use kohn_sham, only : nbnd
151  use gvec, only : g_wf
152  !
153  complex(8),intent(out) :: psi(g_wf%npw,nbnd)
154  !
155  integer :: ibnd, nseed
156  integer :: seed(256)
157  real(8) :: rpsi(g_wf%npw,nbnd), ipsi(g_wf%npw,nbnd), norm
158  !
159  call random_seed(size=nseed)
160  seed(1:nseed)=2
161  call random_seed(put=seed)
162  call random_number(rpsi)
163  call random_number(ipsi)
164  !
165  psi(1:g_wf%npw,1:nbnd) = cmplx(rpsi(1:g_wf%npw,1:nbnd), &
166  & ipsi(1:g_wf%npw,1:nbnd), 8)
167  !
168  do ibnd = 1, nbnd
169  norm = sqrt(dble(dot_product(psi(1:g_wf%npw,ibnd), psi(1:g_wf%npw,ibnd))))
170  psi(1:g_wf%npw,ibnd) = psi(1:g_wf%npw,ibnd) / norm
171  end do
172  !
173  end subroutine initialize_wf
174  !
175 end module scf
diag_direct
Definition: diag_direct.F90:23
constant
Definition: constant.F90:23
kohn_sham::calculation
character(256), save calculation
Calculation mode.
Definition: kohn_sham.F90:27
scf::scf_loop
subroutine scf_loop()
Definition: scf.F90:36
gvec::g_wf
type(fft), save g_wf
Definition: gvec.F90:38
rho_v::xc_pot
subroutine xc_pot(Vloc)
Add XC potential (LDA)
Definition: rho_v.F90:175
rho_v
Definition: rho_v.F90:23
kohn_sham::evec
complex(8), dimension(:,:,:), allocatable, save evec
(g_wfnpw,nbnd,nk) Kohn-Sham eigenvector (orbital)
Definition: kohn_sham.F90:35
rho_v::vps
real(8), dimension(:), allocatable vps
(g_rhnr) Pseudopotential [Htr]
Definition: rho_v.F90:27
k_point
Definition: k_point.F90:23
k_point::ksum_rho
subroutine ksum_rho()
Definition: k_point.F90:35
lobpcg
Definition: lobpcg.F90:23
gvec
Definition: gvec.F90:23
scf::mixing_beta
real(8), save mixing_beta
Mixing for SCF.
Definition: scf.F90:29
kohn_sham::nbnd
integer, save nbnd
Number of bands.
Definition: kohn_sham.F90:29
k_point::nk
integer, save nk
Definition: k_point.F90:27
scf::initialize_wf
subroutine initialize_wf(psi)
Initialize wave function with random number.
Definition: scf.F90:149
kohn_sham::eval
real(8), dimension(:,:), allocatable, save eval
(nbnd,nk) Kohn-Sham eigenvalue (energy)
Definition: kohn_sham.F90:33
rho_v::vks
real(8), dimension(:), allocatable vks
(g_rhnr) Kohn-Sham potential [Htr]
Definition: rho_v.F90:27
gvec::g_rh
type(fft), save g_rh
Definition: gvec.F90:37
scf
Definition: scf.F90:23
scf::electron_maxstep
integer, save electron_maxstep
Max number of iteration.
Definition: scf.F90:27
constant::htr2ev
real(8), parameter htr2ev
Definition: constant.F90:27
rho_v::hartree_pot
subroutine hartree_pot(Vloc)
Add Hartree potential.
Definition: rho_v.F90:143
scf::conv_thr
real(8), save conv_thr
Convergence threshold [Htr].
Definition: scf.F90:29
lobpcg::lobpcg_main
subroutine lobpcg_main(npw, kvec, evec, eval, istep)
Definition: lobpcg.F90:75
k_point::kvec
real(8), dimension(:,:), allocatable, save kvec
Definition: k_point.F90:30
scf::kohn_sham_eq
subroutine kohn_sham_eq(linit, Fvec)
Definition: scf.F90:100
kohn_sham
Definition: kohn_sham.F90:23
diag_direct::direct
subroutine direct(npw, kvec, evec, eval)
Definition: diag_direct.F90:30