PROGRESS  master
prg_pulaymixer_mod.F90
Go to the documentation of this file.
1 
6 
7  use bml
10 
11  implicit none
12 
13  private
14 
15  integer, parameter :: dp = kind(1.0d0)
16 
17  type, public :: mx_type
18 
20  character(20) :: mixertype
21 
23  integer :: verbose
24 
26  integer :: mpulay
27 
29  real(dp) :: mixcoeff
30 
32  logical :: mixeron
33 
34  end type mx_type
35 
37 
38 contains
39 
42  subroutine prg_parse_mixer(input,filename)
43  implicit none
44  type(mx_type), intent(inout) :: input
45  integer, parameter :: nkey_char = 1, nkey_int = 2, nkey_re = 1, nkey_log = 1
46  character(len=*) :: filename
47 
48  !Library of keywords with the respective defaults.
49  character(len=50), parameter :: keyvector_char(nkey_char) = [character(len=100) :: &
50  'MixerType=']
51  character(len=100) :: valvector_char(nkey_char) = [character(len=100) :: &
52  'Linear']
53 
54  character(len=50), parameter :: keyvector_int(nkey_int) = [character(len=50) :: &
55  'Verbose=','MPulay=']
56  integer :: valvector_int(nkey_int) = (/ &
57  0,5/)
58 
59  character(len=50), parameter :: keyvector_re(nkey_re) = [character(len=50) :: &
60  'MixCoeff=']
61  real(dp) :: valvector_re(nkey_re) = (/&
62  0.25 /)
63 
64  character(len=50), parameter :: keyvector_log(nkey_log) = [character(len=100) :: &
65  'MixerON=']
66  logical :: valvector_log(nkey_log) = (/&
67  .true./)
68 
69  !Start and stop characters
70  character(len=50), parameter :: startstop(2) = [character(len=50) :: &
71  'MIXER{', '}']
72 
73  call prg_parsing_kernel(keyvector_char,valvector_char&
74  ,keyvector_int,valvector_int,keyvector_re,valvector_re,&
75  keyvector_log,valvector_log,trim(filename),startstop)
76 
77  !Characters
78  input%mixertype = valvector_char(1)
79 
80  !Integers
81  input%verbose = valvector_int(1)
82  input%mpulay = valvector_int(2)
83 
84  !Logicals
85  input%mixeron = valvector_log(1)
86 
87  !Reals
88  input%mixcoeff = valvector_re(1)
89 
90  end subroutine prg_parse_mixer
91 
92 
103  subroutine prg_qmixer(charges,oldcharges,dqin,dqout,scferror,piter,pulaycoef,mpulay,verbose)
104 
105  implicit none
106  integer :: i,j,info,s,k,n
107  real(dp) :: alpha,coeff
108  real(dp), intent(in) :: pulaycoef
109  real(dp), intent(inout) :: scferror
110  real(dp) :: error, errop
111  integer :: piter
112  real(dp) :: dt, atenuacion
113  integer :: nint, na, nb
114  integer, intent(in) :: mpulay,verbose
115  real(dp), allocatable :: d(:),dl(:),dnewin(:)
116  real(dp), allocatable :: dnewout(:)
117  real(dp), intent(inout) :: charges(:)
118  real(dp), allocatable, intent(inout) :: oldcharges(:)
119  real(dp), allocatable, intent(inout) :: dqin(:,:),dqout(:,:)
120  real(dp), allocatable :: coef(:,:),b(:),ipiv(:)
121 
122  if(verbose > 0)write(*,*)"Performing Pulay mixing scheme ..."
123  n=size(charges)
124 
125  alpha = pulaycoef !the coefficient for mixing
126 
127  if(allocated(oldcharges).eqv..false.)then
128  allocate(oldcharges(n),dqin(n,mpulay),dqout(n,mpulay))
129  endif
130 
131  if(allocated(dqin).eqv..false.)then
132  allocate(dqin(n,mpulay),dqout(n,mpulay))
133  endif
134 
135  s=min(piter-1,mpulay) !mpulay is the iteration number
136 
137  if(piter.eq.1) then
138  charges=(1.0_dp-alpha)*oldcharges + alpha*charges
139  scferror = prg_norm2(charges(:)-oldcharges(:))
140  if(verbose.ge.1)then
141  write(*,*)"SCF error =", scferror
142  endif
143  oldcharges=charges
144  else
145 
146  allocate(d(n),dnewin(n),dnewout(n))
147 
148  d=charges
149 
150  allocate(coef(s+1,s+1)) !Allocating the coeffs matrix
151  allocate(b(s+1))
152  allocate(ipiv(s+1))
153 
154  if(piter.le.mpulay+1)then !If piter=6 => mpulay=5
155  dqin(:,piter-1)=oldcharges(:)
156  dqout(:,piter-1)=d(:)
157  endif
158 
159  if(piter.gt.mpulay+1)then
160 
161  do j=1,s-1
162  dqin(:,j)=dqin(:,j+1)
163  dqout(:,j)=dqout(:,j+1)
164  enddo
165 
166  dqin(:,s)=oldcharges(:)
167  dqout(:,s)=d(:)
168 
169  endif
170 
171  coef=0.0_dp
172 
173  do i=1,s+1
174  coef(s+1,i)=-1.0d0
175  coef(i,s+1)=-1.0d0
176  b(i)=0
177  enddo
178  b(s+1)=-1.0d0
179  coef(s+1,s+1)=0.0_dp
180 
181  do i=1,s
182  do j=1,s
183  do k=1,n
184  coef(i,j)=coef(i,j)+(dqout(k,i)-dqin(k,i))*(dqout(k,j)-dqin(k,j))
185  enddo
186  enddo
187  enddo
188 
189  if(verbose.ge.1)then
190  write(*,*)"coefs"
191  do i=1,s+1
192  write(*,'(10f12.5)')(coef(i,j),j=1,s+1)
193  enddo
194  write(*,*)"dqin"
195  write(*,'(10f12.5)')(dqin(n,j),j=1,s)
196  endif
197 
198  call dgesv(s+1,1,coef,s+1,ipiv,b,s+1,info)
199 
200  if(info.ne.0)then
201  write(*,*)'WARNING: Singular matrix in pulay. Doing linear mixing'
202  stop
203  charges=(1.0_dp-alpha)*oldcharges + alpha*charges
204  scferror = prg_norm2(charges(:)-oldcharges(:))
205  oldcharges = charges
206  piter = 1
207  else
208 
209  dnewin=0.0_dp
210  dnewout=0.0_dp
211 
212  if(verbose.ge.1)then
213  write(*,*)"eigen coefs"
214  write(*,'(6f10.5)')(b(j),j=1,s)
215  endif
216 
217  do j=1,s
218  dnewin(:)=dnewin(:)+b(j)*dqin(:,j)
219  dnewout(:)= dnewout(:)+b(j)*dqout(:,j)
220  enddo
221 
222  d=(1.0_dp-alpha)*dnewin + alpha*dnewout
223 
224  scferror = prg_norm2(charges(:)-oldcharges(:))
225 
226  if(verbose.ge.1)then
227  write(*,*)"SCF error =", scferror
228  endif
229 
230  charges=d
231 
232  oldcharges=d
233  endif
234 
235  endif
236 
237  end subroutine prg_qmixer
238 
245  subroutine prg_linearmixer(charges,oldcharges,scferror,linmixcoef,verbose)
246  implicit none
247  real(dp), intent(in) :: linmixcoef
248  real(dp), intent(inout) :: scferror
249  integer, intent(in) :: verbose
250  real(dp), allocatable, intent(inout) :: charges(:),oldcharges(:)
251 
252  scferror = prg_norm2(charges(:)-oldcharges(:))
253 
254  if(verbose.ge.1)then
255  write(*,*)"SCF error =", scferror
256  endif
257 
258  charges = (1.0_dp - linmixcoef)*oldcharges + linmixcoef*charges
259  oldcharges = charges
260 
261  end subroutine prg_linearmixer
262 
263 end module prg_pulaymixer_mod
Extra routines.
integer, parameter dp
real(dp) function, public prg_norm2(a)
Gets the norm2 of a vector.
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...
Pulay mixer mode.
subroutine, public prg_parse_mixer(input, filename)
The parser for the mixer routines.
subroutine, public prg_qmixer(charges, oldcharges, dqin, dqout, scferror, piter, pulaycoef, mpulay, verbose)
Mixing the charges to acelerate scf convergence.
subroutine, public prg_linearmixer(charges, oldcharges, scferror, linmixcoef, verbose)
Routine to perform linear mixing.