TABLE OF CONTENTS
ABINIT/scfcge [ Functions ]
NAME
scfcge
FUNCTION
Compute the next vtrial of the SCF cycle. Uses a conjugate gradient minimization of the total energy Can move only the trial potential (if moved_atm_inside==0), or move the trial atomic positions as well (if moved_atm_inside==1).
COPYRIGHT
Copyright (C) 1998-2018 ABINIT group (XG) This file is distributed under the terms of the GNU General Public License, see ~abinit/COPYING or http://www.gnu.org/copyleft/gpl.txt . For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
INPUTS
cplex= if 1, real space functions on FFT grid are REAL, if 2, COMPLEX dtn_pc(3,natom)=preconditioned change of atomic position, in reduced coordinates. Will be quickly transferred to f_atm(:,:,i_vrespc(1)) etotal=the actual total energy initialized= if 0, the initialization of the gstate run is not yet finished iscf =5 => SCF cycle, CG based on estimation of energy gradient =6 => SCF cycle, CG based on true minimization of the energy isecur=level of security of the computation istep= number of the step in the SCF cycle moved_atm_inside: if==1, the atoms are allowed to move. mpicomm=the mpi communicator used for the summation mpi_summarize=set it to .true. if parallelisation is done over FFT natom=number of atoms nfft=(effective) number of FFT grid points (for this processor) nfftot=total number of FFT grid points nspden=number of spin-density components n_fftgr=third dimension of the array f_fftgr n_index=dimension for indices of potential/density (see i_vresid, ivrespc, i_rhor...) opt_denpot= 0 vtrial (and also f_fftgr) really contains the trial potential 1 vtrial (and also f_fftgr) actually contains the trial density response= if 0, GS calculation, if 1, RF calculation, intrinsically harmonic ! rhor(cplex*nfft,nspden)=actual density ucvol=unit cell volume in bohr**3
OUTPUT
dbl_nnsclo=1 if nnsclo has to be doubled to secure the convergence.
SIDE EFFECTS
Input/Output: vtrial(cplex*nfft,nspden)= at input, it is the trial potential that gave the input residual of the potential and Hellman-Feynman forces at output, it is the new trial potential . xred(3,natom)=(needed if moved_atm_inside==1) reduced dimensionless atomic coordinates at input, those that generated the input residual of the potential and Hellman-Feynman forces, at output, these are the new ones. f_fftgr(cplex*nfft,nspden,n_fftgr)=different functions defined on the fft grid : The input vtrial is transferred, at output, in f_fftgr(:,:,1). The input f_fftgr(:,:,i_vresid(1)) contains the last residual. the value of i_vresid(1) is transferred to i_vresid(2) at output. The input f_fftgr(:,:,i_vresid(2)) contains the old residual. the value of i_vresid(2) is transferred to i_vresid(3) at output. The input f_fftgr(:,:,i_vresid(3)) contains the previous last residual. For the preconditioned potential residual, the same logic as for the the potential residual is used, with i_vrespc replacing i_vresid. The input rhor is transferred, at output, in f_fft(:,:,i_rhor(2)). The old density is input in f_fft(:,:,i_rhor(2)), and the value of i_rhor(2) is transferred to i_rhor(3) before the end of the routine. The input/output search vector is stored in f_fftgr(:,:,6) f_atm(3,natom,n_fftgr)=different functions defined for each atom : The input xred is transferred, at output, in f_atm(:,:,1). The input f_atm(:,:,i_vresid(1)) contains minus the HF forces. the value of i_vresid(1) is transferred to i_vresid(2) at output. The input f_atm(:,:,i_vresid(2)) contains minus the old HF forces. the value of i_vresid(2) is transferred to i_vresid(3) at output. The input f_atm(:,:,i_vresid(3)) contains minus the previous old HF forces. For the preconditioned change of atomic positions, the same logic as for the the potential residual is used, with i_vrespc replacing i_vresid. The input/output search vector is stored in f_atm(:,:,6) i_rhor(2:3)=index of the density (past and previous past) in the array f_fftgr i_vresid(3)=index of the residual potentials (present, past and previous past) in the array f_fftgr; also similar index for minus Hellman-Feynman forces in the array f_atm . i_vrespc(3)=index of the preconditioned residual potentials (present, past and previous past) in the array f_fftgr ; also similar index for the preconditioned change of atomic position (dtn_pc).
TODO
This routine is much too difficult to read ! Should be rewritten ... Maybe make separate subroutines for line search and CG step ?!
PARENTS
m_ab7_mixing
CHILDREN
aprxdr,findminscf,sqnormm_v,wrtout
SOURCE
101 #if defined HAVE_CONFIG_H 102 #include "config.h" 103 #endif 104 105 #include "abi_common.h" 106 107 108 subroutine scfcge(cplex,dbl_nnsclo,dtn_pc,etotal,f_atm,& 109 & f_fftgr,initialized,iscf,isecur,istep,& 110 & i_rhor,i_vresid,i_vrespc,moved_atm_inside,mpicomm,mpi_summarize,& 111 & natom,nfft,nfftot,nspden,n_fftgr,n_index,opt_denpot,response,rhor,ucvol,vtrial,xred,errid,errmess) 112 113 use defs_basis 114 use m_profiling_abi 115 use m_errors 116 117 !This section has been created automatically by the script Abilint (TD). 118 !Do not modify the following lines by hand. 119 #undef ABI_FUNC 120 #define ABI_FUNC 'scfcge' 121 use interfaces_14_hidewrite 122 use interfaces_56_mixing, except_this_one => scfcge 123 !End of the abilint section 124 125 implicit none 126 127 !Arguments ------------------------------------ 128 !scalars 129 integer,intent(in) :: cplex,initialized,iscf,isecur,istep,moved_atm_inside,mpicomm 130 integer,intent(in) :: n_fftgr,n_index,natom,nfft,nfftot,nspden,opt_denpot,response 131 integer,intent(out) :: dbl_nnsclo, errid 132 character(len = 500), intent(out) :: errmess 133 logical, intent(in) :: mpi_summarize 134 real(dp),intent(in) :: etotal,ucvol 135 !arrays 136 integer,intent(inout) :: i_rhor(n_index),i_vresid(n_index),i_vrespc(n_index) 137 real(dp),intent(in) :: dtn_pc(3,natom),rhor(cplex*nfft,nspden) 138 real(dp),intent(inout) :: f_atm(3,natom,n_fftgr) 139 real(dp),intent(inout) :: f_fftgr(cplex*nfft,nspden,n_fftgr) 140 real(dp),intent(inout) :: vtrial(cplex*nfft,nspden),xred(3,natom) 141 142 !Local variables------------------------------- 143 !mlinmin gives the maximum number of steps in the line minimization 144 ! after which the algorithm is restarted (with a decrease of the 145 ! adaptative trial step length). This number should not be large, 146 ! since if the potential landscape is harmonic, the number of 147 ! search steps should be small. If it is large, we are not in the 148 ! harmonic region, and the CG algorithm will not be really useful, 149 ! so one can just restart the algorithm ... 150 !scalars 151 integer,parameter :: mlinmin=5 152 integer,save :: end_linmin,iline_cge,ilinear,ilinmin,isecur_eff,nlinear 153 integer,save :: number_of_restart,status 154 integer :: choice,iatom,idir,ifft,iline_cge_input,ilinmin_input,isp 155 integer :: testcg,tmp,errid_ 156 real(dp),save :: d2edv2_old2,d_lambda_old2,dedv_old2,etotal_old 157 real(dp),save :: etotal_previous,lambda_adapt,lambda_new,lambda_old,resid_old 158 real(dp) :: d2e11,d2e12,d2e22,d2edv2_new,d2edv2_old 159 real(dp) :: d2edv2_predict,d_lambda,de1,de2,dedv_mix 160 real(dp) :: dedv_new,dedv_old,dedv_predict,determ,etotal_input 161 real(dp) :: etotal_predict,gamma,lambda_input,lambda_predict2 162 real(dp) :: lambda_predict=1.0_dp,ratio,reduction 163 real(dp) :: resid_input,temp 164 character(len=500) :: message 165 !arrays 166 real(dp) :: resid_new(1) 167 real(dp), allocatable :: tmp_fft1(:,:) 168 169 ! ************************************************************************* 170 171 errid = AB7_NO_ERROR 172 dbl_nnsclo = 0 173 174 !reduction gives the level of reduction of the error in 175 !the line minimization to be reached for the minimization to be 176 !considered successfull 177 reduction=0.1_dp 178 179 !nlinear increases with the number of times the 2D minimization succeded 180 !to reach the true minimum directly. It is a measure of the 181 !degree of parabolicity of the problem, and is used to 182 !skip some steps by performing extrapolation. 183 if(istep==1)then 184 185 ! Skipping some steps is sometimes unsecure, so it is possible 186 ! to make nlinear start at a negative value - if isecur is positive 187 isecur_eff=isecur 188 nlinear=min(-isecur_eff,0) 189 ilinear=0 190 191 ! Response function calculation are intrinsically harmonic, so one 192 ! can shift isecur (by -2), and start with a positive nlinear 193 if(response==1)then 194 isecur_eff=isecur-2 195 nlinear=-isecur_eff 196 ilinear=nlinear 197 end if 198 199 iline_cge=0 200 ilinmin=0 201 end if 202 203 !Compute actual residual resid_new (residual of f_fftgr(:,:,i_vrespc(1)) 204 call sqnormm_v(cplex,i_vrespc(1),mpicomm,mpi_summarize,1,nfft,resid_new,n_fftgr,nspden,opt_denpot,f_fftgr) 205 206 !Save input residual and ilinmin for final printing 207 resid_input=resid_new(1) 208 etotal_input=etotal 209 ilinmin_input=ilinmin 210 iline_cge_input=iline_cge 211 !Transfer dtn_pc in f_atm 212 if(moved_atm_inside==1)then 213 f_atm(:,:,i_vrespc(1))=dtn_pc(:,:) 214 end if 215 216 !======================================================================= 217 !Now the routine is decomposed in three mutually exclusive parts : 218 !if(istep==1)then initialize the algorithm 219 !else if(ilinmin>0)then perform the line minimisation 220 !else if(ilinmin==0)then determine the new search direction (CG step) 221 !======================================================================= 222 223 224 !-------------------------------------- 225 !Here initialize the algorithm 226 if(istep==1)then 227 228 ! At the beginning of each gstate run, lambda_adapt is forced to have the 229 ! same value, that is 1.0_dp. In the other cases when istep=1 (at different 230 ! broyden steps, for example), the previously obtained 231 ! adaptive value is kept. 232 if(initialized==0)lambda_adapt=1.0_dp 233 lambda_old=0.0_dp 234 lambda_input=0.0_dp 235 number_of_restart=0 236 lambda_new=lambda_adapt 237 238 f_fftgr(:,:,1)=vtrial(:,:) 239 f_fftgr(:,:,i_rhor(2))=rhor(:,:) 240 241 ! This copy must be written in F77, because of stack problems on the DECs 242 do isp=1,nspden 243 do ifft=1,cplex*nfft 244 f_fftgr(ifft,isp,6)=f_fftgr(ifft,isp,i_vrespc(1)) 245 end do 246 end do 247 vtrial(:,:)=f_fftgr(:,:,1)+(lambda_new-lambda_old)*f_fftgr(:,:,6) 248 if(moved_atm_inside==1)then 249 f_atm(:,:,1)=xred(:,:) 250 f_atm(:,:,i_rhor(2))=xred(:,:) 251 ! There shouldn t be problems with the stack size for this small array. 252 f_atm(:,:,6)=f_atm(:,:,i_vrespc(1)) 253 xred(:,:)=f_atm(:,:,1)+(lambda_new-lambda_old)*f_atm(:,:,6) 254 end if 255 tmp=i_vrespc(2) ; i_vrespc(2)=i_vrespc(1) ; i_vrespc(1)=tmp 256 tmp=i_vresid(2) ; i_vresid(2)=i_vresid(1) ; i_vresid(1)=tmp 257 ilinmin=1 258 resid_old=resid_new(1) 259 etotal_old=etotal 260 261 status=0 262 263 ! -------------------------------------- 264 265 ! Here performs the line minimisation 266 else if(ilinmin>0)then 267 268 lambda_input=lambda_new 269 270 ! The choice with the Brent algorithm has been abandoned in version 1.6.m 271 272 ! Compute the approximate energy derivatives dedv_new and dedv_old, 273 ! from vresid and vresid_old 274 choice=2 275 call aprxdr(cplex,choice,dedv_mix,dedv_new,dedv_old,& 276 & f_atm,f_fftgr,i_rhor(2),i_vresid,moved_atm_inside,mpicomm,mpi_summarize,& 277 & natom,nfft,nfftot,nspden,n_fftgr,rhor,ucvol,xred) 278 d_lambda=lambda_new-lambda_old 279 dedv_old=dedv_old/d_lambda 280 dedv_new=dedv_new/d_lambda 281 282 ! DEBUG 283 ! write(std_out,'(a,4es12.4,i3)' )' scfcge:lold,lnew,dold,dnew,status', & 284 ! & lambda_old,lambda_new,dedv_old,dedv_new,status 285 ! ENDDEBUG 286 287 if(status==0 .or. status==3)then 288 ! 289 ! Then, compute a predicted point along the line 290 ! The value of choice determines the minimization algorithm 291 ! choice=1 uses the two values of the derivative of the energy 292 ! choice=2 uses the two values of the energy, and and estimate of the 293 ! second derivative at the mid-point. 294 295 choice=1 296 if(iscf==6)choice=2 297 call findminscf(choice,dedv_new,dedv_old,dedv_predict,& 298 & d2edv2_new,d2edv2_old,d2edv2_predict,& 299 & etotal,etotal_old,etotal_predict,& 300 & lambda_new,lambda_old,lambda_predict,errid_,message) 301 if (errid_ /= AB7_NO_ERROR) then 302 call wrtout(std_out,message,'COLL') 303 end if 304 305 ! Suppress the next line for debugging (there is another such line) 306 status=0 307 308 ! DEBUG 309 ! Keep this debugging feature : it gives access to the investigation of lines 310 ! in a different approach 311 ! if(response==1 .and. istep>8)then 312 ! lambda_predict=1.2d-2 313 ! if(istep>=15)lambda_predict=lambda_predict-0.002 314 ! if(istep>=14)stop 315 ! status=3 316 ! end if 317 ! ENDDEBUG 318 319 else 320 if(status/=-1)then 321 status=-1 322 lambda_predict=-2.5_dp 323 else 324 lambda_predict=lambda_predict+0.1_dp 325 end if 326 end if 327 328 ! If the predicted point is very close to the most recent 329 ! computed point, while this is the first trial on this line, 330 ! then we are in the linear regime : 331 ! nlinear is increased by one unit. For the time being, do this even when 332 ! moved_atm_inside==1 (the code still works when it is done, but it 333 ! seems to be a bit unstable). The maximal value of nlinear is 1, except 334 ! when isecur_eff is a negative number, less than -1. 335 if( abs(lambda_predict-lambda_new)/& 336 & (abs(lambda_predict)+abs(lambda_new)) < 0.01 .and. ilinmin==1 ) then 337 ! if(moved_atm_inside==0 .and. nlinear<max(1,-isecur_eff) )nlinear=nlinear+1 338 if(nlinear<max(1,-isecur_eff))nlinear=nlinear+1 339 ilinear=nlinear 340 end if 341 342 ! If the predicted point is close to the most recent computed point, 343 ! or the previous one, set on the flag of end of line minization 344 end_linmin=0 345 if(abs(lambda_new-lambda_predict)*2.0_dp& 346 & /(abs(lambda_predict)+abs(lambda_new)) <reduction) end_linmin=1 347 if(abs(lambda_old-lambda_predict)*2.0_dp& 348 & /(abs(lambda_predict)+abs(lambda_new)) <reduction) end_linmin=1 349 350 if(status/=0)end_linmin=0 351 352 ! Save the closest old lambda, if needed, 353 ! also examine the reduction of the interval, and eventual stop 354 ! the present line minimisation, because of convergence (end_linmin=1) 355 ! Also treat the case in which the predicted value of lambda is negative, 356 ! or definitely too small in which case the algorithm has to be restarted 357 ! (not a very good solution, though ...) 358 ! Finally also treat the case where insufficiently converged 359 ! density at lambda=0.0_dp happens, which screws up the line minimisation. 360 361 ! Here restart the algorithm with the best vtrial. 362 ! Also make reduction in lambda_adapt 363 ! DEBUG 364 ! write(std_out,*)' scfcge : status=',status 365 ! ENDDEBUG 366 if( end_linmin==0 .and. status==0 .and. & 367 & ( (lambda_predict<0.005_dp*lambda_adapt .and. iscf==5) .or. & 368 & (abs(lambda_predict)<0.005_dp*lambda_adapt .and. iscf==6).or. & 369 & ilinmin==mlinmin ) )then 370 if(number_of_restart>12)then 371 errid = AB7_ERROR_MIXING_CONVERGENCE 372 write(errmess,'(a,a,i0,a,a,a,a,a)')& 373 & 'Potential-based CG line minimization not',' converged after ',number_of_restart,' restarts. ',ch10,& 374 & 'Action : read the eventual warnings about lack of convergence.',ch10,& 375 & 'Some might be relevant. Otherwise, raise nband. Returning' 376 MSG_WARNING(errmess) 377 return 378 end if 379 ! Make reduction in lambda_adapt (kind of steepest descent...) 380 write(message,'(a,a,a)')& 381 & 'Potential-based CG line minimization has trouble to converge.',ch10,& 382 & 'The algorithm is restarted with more secure parameters.' 383 MSG_WARNING(message) 384 number_of_restart=number_of_restart+1 385 ! At the second restart, double the number of non-self consistent loops. 386 if(number_of_restart>=2)dbl_nnsclo=1 387 lambda_adapt=lambda_adapt*0.7_dp 388 lambda_new=lambda_adapt 389 ! If the last energy is better than the old one, transfer the data. 390 ! Otherwise, no transfer must occur (very simple to code...) 391 if(etotal<etotal_old .or. abs(lambda_old)<1.0d-8)then 392 f_fftgr(:,:,1)=vtrial(:,:) 393 f_fftgr(:,:,i_rhor(2))=rhor(:,:) 394 do isp=1,nspden 395 do ifft=1,cplex*nfft 396 f_fftgr(ifft,isp,6)=f_fftgr(ifft,isp,i_vrespc(1)) 397 end do 398 end do 399 if(moved_atm_inside==1)then 400 f_atm(:,:,1)=xred(:,:) 401 f_atm(:,:,i_rhor(2))=xred(:,:) 402 f_atm(:,:,6)=f_atm(:,:,i_vrespc(1)) 403 end if 404 tmp=i_vrespc(2) ; i_vrespc(2)=i_vrespc(1) ; i_vrespc(1)=tmp 405 tmp=i_vresid(2) ; i_vresid(2)=i_vresid(1) ; i_vresid(1)=tmp 406 resid_old=resid_new(1) 407 etotal_old=etotal 408 end if 409 lambda_old=0.0_dp 410 ilinmin=1 411 ! Putting the flag to -1 avoids the usual actions taken with end_linmin=1 412 end_linmin=-1 413 ! Also put ilinear and nlinear to 0 414 ilinear=0 415 nlinear=0 416 417 ! Here lambda_new is the closest to lambda_predict, 418 ! or lambda_old is still 0.0_dp, while the energy shows that the minimum 419 ! is away from 0.0_dp (insufficiently converged density at lambda=0.0_dp). 420 else if( abs(lambda_new-lambda_predict)<abs(lambda_old-lambda_predict) & 421 & .or. & 422 & ( abs(lambda_old)<1.0d-6 .and. & 423 & ilinmin>1 .and. & 424 & etotal>etotal_previous ) & 425 & )then 426 f_fftgr(:,:,1)=vtrial(:,:) 427 tmp=i_rhor(3) ; i_rhor(3)=i_rhor(2) ; i_rhor(2)=tmp 428 f_fftgr(:,:,i_rhor(2))=rhor(:,:) 429 tmp=i_vrespc(3) ; i_vrespc(3)=i_vrespc(2) 430 i_vrespc(2)=i_vrespc(1); i_vrespc(1)=tmp; 431 tmp=i_vresid(3); i_vresid(3)=i_vresid(2) 432 i_vresid(2)=i_vresid(1) ; i_vresid(1)=tmp 433 if(moved_atm_inside==1)then 434 f_atm(:,:,1)=xred(:,:) 435 f_atm(:,:,i_rhor(2))=xred(:,:) 436 end if 437 d_lambda_old2=lambda_old-lambda_new 438 lambda_old=lambda_new 439 etotal_old=etotal 440 resid_old=resid_new(1) 441 d2edv2_old2=d2edv2_new 442 dedv_old=dedv_new 443 dedv_old2=dedv_new 444 ! if(abs(lambda_new-lambda_predict)*2.0_dp& 445 ! & /abs(lambda_new+lambda_predict) <reduction) end_linmin=1 446 447 ! Here lambda_old is the closest to lambda_predict (except for avoiding 448 ! lambda_old==0.0_dp) 449 else 450 tmp=i_vresid(3) ; i_vresid(3)=i_vresid(1) ; i_vresid(1)=tmp 451 f_fftgr(:,:,i_rhor(3))=rhor(:,:) 452 if(moved_atm_inside==1) f_atm(:,:,i_rhor(3))=xred(:,:) 453 tmp=i_vrespc(3) ; i_vrespc(3)=i_vrespc(1) ; i_vrespc(1)=tmp 454 d_lambda_old2=lambda_new-lambda_old 455 etotal_previous=etotal 456 d2edv2_old2=d2edv2_old 457 dedv_old2=dedv_old 458 ! if(abs(lambda_old-lambda_predict)*2.0_dp& 459 ! & /abs(lambda_old+lambda_predict) <reduction) end_linmin=1 460 end if 461 462 ! If the interval has not yet been sufficiently reduced, 463 ! continue the search 464 if(end_linmin==0)then 465 lambda_new=lambda_predict 466 467 ! DEBUG 468 ! write(std_out,'(a,2es16.6)' )& 469 ! & ' scfcge : continue search, lambda_old,lambda_new=',lambda_old,lambda_new 470 ! write(std_out,'(a,2es16.6)' )& 471 ! & ' scfcge : f_fftgr(3:4,1,1)=',f_fftgr(3:4,1,1) 472 ! write(std_out,'(a,2es16.6)' )& 473 ! & ' scfcge : f_fftgr(3:4,1,6)=',f_fftgr(3:4,1,6) 474 ! ENDDEBUG 475 476 vtrial(:,:)=f_fftgr(:,:,1)+(lambda_new-lambda_old)*f_fftgr(:,:,6) 477 if(moved_atm_inside==1)then 478 xred(:,:)=f_atm(:,:,1)+(lambda_new-lambda_old)*f_atm(:,:,6) 479 end if 480 481 ilinmin=ilinmin+1 482 ! 483 ! Here generates a starting point for next line search 484 else 485 iline_cge=iline_cge+1 486 if(end_linmin==1)ilinmin=0 487 lambda_old=0.0_dp 488 489 ! In order to generate the new step, take into account previous 490 ! optimal lambdas (including those of previous ion moves), 491 ! and the selected new one, if it is positive. 492 ! However, wait iline_cge>1 to select new ones. 493 ! lambda_adapt has been initialized at 1.0_dp 494 if(iline_cge>1 .and. lambda_new>0.0_dp )then 495 ! Actually compute a geometric mean 496 lambda_adapt= ( lambda_adapt**(dble(iline_cge-1)) * abs(lambda_new)) & 497 & **(1.0_dp/dble(iline_cge)) 498 ! In order to recover the previous algorithm, it is enough 499 ! to decomment the next line 500 ! lambda_adapt=1.0_dp 501 end if 502 lambda_new=lambda_adapt 503 504 vtrial(:,:)=f_fftgr(:,:,1)+lambda_new*f_fftgr(:,:,i_vrespc(2)) 505 if(moved_atm_inside==1)then 506 xred(:,:)=f_atm(:,:,1)+lambda_new*f_atm(:,:,i_vrespc(2)) 507 end if 508 509 ! End choice between continue line minim and determine new direction 510 end if 511 512 ! 513 ! ------------------------------- 514 515 ! Here perform the CG step 516 517 else if(ilinmin==0)then 518 519 ! Compute the approximate energy derivatives dedv_mix,dedv_new,dedv_old 520 choice=3 521 call aprxdr(cplex,choice,dedv_mix,dedv_new,dedv_old,& 522 & f_atm,f_fftgr,i_rhor(2),i_vresid,moved_atm_inside,mpicomm,mpi_summarize,& 523 & natom,nfft,nfftot,nspden,n_fftgr,rhor,ucvol,xred) 524 525 dedv_mix=dedv_mix/lambda_new 526 dedv_new=dedv_new/lambda_new 527 dedv_old=dedv_old/lambda_new 528 529 ! DEBUG 530 ! write(message, '(a,3es12.4)' )' scfcge: lambda_adapt',& 531 ! & lambda_adapt 532 ! call wrtout(std_out,message,'COLL') 533 534 ! write(message, '(a,3es12.4)' )' scfcge: dedv_old,dedv_new,dedv_mix',& 535 ! & dedv_old,dedv_new,dedv_mix 536 ! call wrtout(std_out,message,'COLL') 537 ! ENDDEBUG 538 539 ! Then, compute a predicted point, either along the line, 540 ! or in a 2D plane 541 testcg=1 542 if(testcg==0)then 543 ! This part corresponds to steepest descent, 544 ! in which the line minimisation can be done 545 ! using different algorithms, varying with the value of choice 546 choice=1 547 if(iscf==6)choice=2 548 call findminscf(choice,dedv_new,dedv_old,dedv_predict,& 549 & d2edv2_new,d2edv2_old,d2edv2_predict,& 550 & etotal,etotal_old,etotal_predict,& 551 & lambda_new,lambda_old,lambda_predict,errid_,message) 552 if (errid_ /= AB7_NO_ERROR) then 553 call wrtout(std_out,message,'COLL') 554 end if 555 lambda_predict2=0.0_dp 556 ! Suppress the next line for debugging (there is another such line) 557 status=0 558 else 559 ! This part corresponds to conjugate gradient 560 ! A 2D minimisation is performed 561 ! oldest direction is labelled 2 562 ! newest direction is labelled 1 563 de1=dedv_old ; de2=dedv_old2 564 d2e11=(dedv_new-dedv_old)/lambda_new 565 d2e22=d2edv2_old2 566 d2e12=(dedv_mix-dedv_old)/d_lambda_old2 567 ! The system to be solved is 568 ! 0 = de1 + lambda1 d2e11 + lambda2 d2d12 569 ! 0 = de2 + lambda1 d2e12 + lambda2 d2d22 570 determ=d2e11*d2e22-d2e12*d2e12 571 lambda_predict=-(de1*d2e22-de2*d2e12)/determ 572 lambda_predict2=(de1*d2e12-de2*d2e11)/determ 573 d2edv2_new=d2e11 ; d2edv2_old=d2e11 574 end if 575 576 ! DEBUG 577 ! write(message, '(a,5es11.3)' )' scfcge: de1,de2,d2e11,d2e22,d2e12',& 578 ! & de1,de2,d2e11,d2e22,d2e12 579 ! call wrtout(std_out,message,'COLL') 580 ! write(std_out,'(a,2es12.4)' )' scfcge: la_predict,la_predict2',& 581 ! & lambda_predict,lambda_predict2 582 ! ----- 583 ! write(std_out,*)'residues ', 584 ! !$ de1+lambda_predict*d2e11+lambda_predict2*d2e12, 585 ! !$ de2+lambda_predict*d2e12+lambda_predict2*d2e22 586 ! if(.true.)stop 587 ! ENDDEBUG 588 ! 589 590 ! Determine the region of the 2D search space 591 ! in which the predicted point is located, 592 ! or use linear indicator to decide interpolation 593 ! and advance to next 2D search. 594 end_linmin=0 595 write(message, '(a,2i3)' )' nlinear, ilinear',nlinear,ilinear 596 call wrtout(std_out,message,'COLL') 597 if(lambda_predict<0.0_dp)then 598 ! Something is going wrong. Just take a reasonable step 599 ! along the steepest descent direction (Region III). 600 ! Actually, Region I and region III are treated in the same way later. 601 ! In effect, this corresponds to restart the algorithm 602 end_linmin=3 603 ! Also put ilinear and nlinear to 0 604 ilinear=0 605 nlinear=0 606 ! Decrease the adaptive step to predict next direction 607 lambda_adapt=lambda_adapt*0.7_dp 608 else if(ilinear>=1) then 609 ! Region IV : will do an interpolation 610 end_linmin=4 611 ilinear=ilinear-1 612 else if(abs(lambda_predict2)>reduction .or.& 613 & lambda_predict<0.5_dp .or.& 614 & lambda_predict>2.5_dp .or.& 615 & lambda_predict-abs(lambda_predict2)/reduction <0.0_dp ) then 616 ! Region II : lambda_predict is not too good, and not too bad. 617 end_linmin=2 618 else if (abs(1.0_dp-lambda_predict)<reduction)then 619 ! Region I, the out-of-line point is OK. 620 end_linmin=1 621 else 622 ! If everything fails, then region II. 623 end_linmin=2 624 end if 625 626 ! DEBUG 627 ! write(message, '(a,2es12.4,i2)' )& 628 ! & ' scfcge : la_predict, la_predict2, region',& 629 ! & lambda_predict,lambda_predict2,end_linmin 630 ! call wrtout(std_out,message,'COLL') 631 ! ENDDEBUG 632 633 ! Treat region I, in the same way as region III 634 if(end_linmin==1 .or. end_linmin==3)then 635 636 ! In region I, the line search is 637 ! along vtrial-vtrial_old. 638 ! The closest point is the new point 639 ! thus to be transfered in the "old" locations 640 641 do isp=1,nspden 642 do ifft=1,cplex*nfft 643 f_fftgr(ifft,isp,6)=(vtrial(ifft,isp)-f_fftgr(ifft,isp,1))/lambda_new 644 end do 645 end do 646 f_fftgr(:,:,1)=vtrial(:,:) 647 f_fftgr(:,:,i_rhor(2))=rhor(:,:) 648 if(moved_atm_inside==1)then 649 f_atm(:,:,6)=(xred(:,:)-f_atm(:,:,1))/lambda_new 650 f_atm(:,:,1)=xred(:,:) 651 f_atm(:,:,i_rhor(2))=xred(:,:) 652 end if 653 tmp=i_vrespc(2) ; i_vrespc(2)=i_vrespc(1) ; i_vrespc(1)=tmp 654 tmp=i_vresid(3) ; i_vresid(3)=i_vresid(2) 655 i_vresid(2)=i_vresid(1) ; i_vresid(1)=tmp 656 d_lambda_old2=-lambda_new 657 lambda_old=lambda_new 658 etotal_old=etotal 659 resid_old=resid_new(1) 660 d2edv2_old=d2edv2_new 661 dedv_old=dedv_new 662 663 ! Region I or III : one is close of the 2D minimum, 664 ! or lambda_predict was negative (indicate a problem of convergence) 665 ! Compute next trial potential along the 666 ! PC residual and not along this search direction. 667 ilinmin=0 668 ! Question : isn t it here that one should prevent region I to called 669 ! itself more than 1 time ??? 670 ! Here the small difference between region I and region III 671 if(end_linmin==3)ilinmin=1 672 lambda_old=0.0_dp 673 lambda_new=lambda_adapt 674 675 vtrial(:,:)=f_fftgr(:,:,1)+lambda_new*f_fftgr(:,:,i_vrespc(2)) 676 if(moved_atm_inside==1)then 677 xred(:,:)=f_atm(:,:,1)+lambda_new*f_atm(:,:,i_vrespc(2)) 678 end if 679 ! The new vtrial has been generated 680 681 else 682 683 ! Here region II or IV 684 ilinmin=1 685 if (lambda_predict==0._dp) then 686 gamma=zero 687 else 688 gamma=lambda_predict2/lambda_predict 689 end if 690 ! Compute new search direction and trial potential 691 write(message,*)' compute new search direction ' 692 call wrtout(std_out,message,'COLL') 693 do isp=1,nspden 694 do ifft=1,cplex*nfft 695 f_fftgr(ifft,isp,6)=(vtrial(ifft,isp)-f_fftgr(ifft,isp,1))/lambda_new+ & 696 & gamma*f_fftgr(ifft,isp,6) 697 end do 698 end do 699 vtrial(:,:)=f_fftgr(:,:,1)+ lambda_predict*f_fftgr(:,:,6) 700 if(moved_atm_inside==1)then 701 f_atm(:,:,6)=(xred(:,:)-f_atm(:,:,1))/lambda_new+ gamma*f_atm(:,:,6) 702 xred(:,:)=f_atm(:,:,1)+ lambda_predict*f_atm(:,:,6) 703 end if 704 705 ! If end_linmin==2, then this vtrial is the good one 706 707 if(end_linmin==2)then 708 709 lambda_old=0.0_dp 710 lambda_new=lambda_predict 711 712 else if(end_linmin==4)then 713 714 ! predict the result of the computation at the trial potential 715 ! defined in the end_linmin==2 case 716 gamma=lambda_predict2/d_lambda_old2 717 ratio=lambda_predict/lambda_new 718 719 ! Take care of vtrial 720 f_fftgr(:,:,1)=vtrial(:,:) 721 722 ABI_ALLOCATE(tmp_fft1,(cplex*nfft,nspden)) 723 ! Take care of vresid 724 tmp_fft1(:,:)=f_fftgr(:,:,i_vresid(2)) 725 f_fftgr(:,:,i_vresid(2))=tmp_fft1(:,:)& 726 & +ratio*(f_fftgr(:,:,i_vresid(1))-tmp_fft1(:,:))& 727 & +gamma*(f_fftgr(:,:,i_vresid(3))-tmp_fft1(:,:)) 728 f_fftgr(:,:,i_vresid(3))=tmp_fft1(:,:) 729 730 ! Take care of rhor 731 tmp_fft1(:,:)=f_fftgr(:,:,i_rhor(2)) 732 f_fftgr(:,:,i_rhor(2))=tmp_fft1(:,:)& 733 & +ratio*(rhor(:,:)-tmp_fft1(:,:))& 734 & +gamma*(f_fftgr(:,:,i_rhor(3))-tmp_fft1(:,:)) 735 f_fftgr(:,:,i_rhor(3))=tmp_fft1(:,:) 736 737 ! Take care of vrespc 738 tmp_fft1(:,:)=f_fftgr(:,:,i_vrespc(2)) 739 f_fftgr(:,:,i_vrespc(2))=tmp_fft1(:,:)& 740 & +ratio*(f_fftgr(:,:,i_vrespc(1))-tmp_fft1(:,:))& 741 & +gamma*(f_fftgr(:,:,i_vrespc(3))-tmp_fft1(:,:)) 742 f_fftgr(:,:,i_vrespc(3))=tmp_fft1(:,:) 743 ABI_DEALLOCATE(tmp_fft1) 744 745 if(moved_atm_inside==1)then 746 do idir=1,3 747 do iatom=1,natom 748 749 ! Take care of xred 750 f_atm(idir,iatom,1)=xred(idir,iatom) 751 752 ! Take care of -HF forces 753 temp=f_atm(idir,iatom,i_vresid(2)) 754 f_atm(idir,iatom,i_vresid(2))=f_atm(idir,iatom,i_vresid(2))& 755 & +ratio*(f_atm(idir,iatom,i_vresid(1))-f_atm(idir,iatom,i_vresid(2)))& 756 & +gamma*(f_atm(idir,iatom,i_vresid(3))-f_atm(idir,iatom,i_vresid(2))) 757 f_atm(idir,iatom,i_vresid(3))=temp 758 759 ! Take care of old xreds 760 temp=f_atm(idir,iatom,i_rhor(2)) 761 f_atm(idir,iatom,i_rhor(2))=f_atm(idir,iatom,i_rhor(2))& 762 & +ratio*( xred(idir,iatom) -f_atm(idir,iatom,i_rhor(2)))& 763 & +gamma*(f_atm(idir,iatom,i_rhor(3))-f_atm(idir,iatom,i_rhor(2))) 764 f_atm(idir,iatom,i_rhor(3))=temp 765 766 ! Take care of preconditioned changes of atomic positions 767 temp=f_atm(idir,iatom,i_vrespc(2)) 768 f_atm(idir,iatom,i_vrespc(2))=f_atm(idir,iatom,i_vrespc(2))& 769 & +ratio*(f_atm(idir,iatom,i_vrespc(1))-f_atm(idir,iatom,i_vrespc(2)))& 770 & +gamma*(f_atm(idir,iatom,i_vrespc(3))-f_atm(idir,iatom,i_vrespc(2))) 771 f_atm(idir,iatom,i_vrespc(3))=temp 772 773 end do 774 end do 775 end if 776 777 ! Since we are at the 2D minimum, the derivative is supposed 778 ! to vanish. Note that dedv_old should not change, by contrast. 779 dedv_old2=0.0_dp 780 d_lambda_old2=-lambda_predict 781 d2edv2_old2=-dedv_old/lambda_predict 782 lambda_old=lambda_predict 783 ilinmin=0 784 785 ! So, jump to the next line 786 iline_cge=iline_cge+1 787 write(message,*)' energy CG update : after 2D interpolation,' 788 call wrtout(std_out,message,'COLL') 789 write(message,*)' computation in the next plane ' 790 call wrtout(std_out,message,'COLL') 791 write(message,*) 792 call wrtout(std_out,message,'COLL') 793 lambda_old=0.0_dp 794 lambda_new=lambda_adapt 795 796 vtrial(:,:)=f_fftgr(:,:,1)+lambda_new*f_fftgr(:,:,i_vrespc(2)) 797 if(moved_atm_inside==1)then 798 xred(:,:)=f_atm(:,:,1)+lambda_new*f_atm(:,:,i_vrespc(2)) 799 end if 800 801 ! The new trial potential is now generated 802 803 ! End the specific treatment of region IV 804 end if 805 ! 806 ! End the choice between treatment of region I, II, or IV 807 end if 808 809 ! End of choice between initialisation or more developed parts of the CG algorithm 810 else 811 errid = AB7_ERROR_MIXING_ARG 812 errmess = 'scfcge : BUG You should not be here ! ' 813 return 814 end if 815 816 !-------------------------------------- 817 818 !Write information : it will be easy to read by typing grep scfcge logfile 819 820 if(istep==1)then 821 write(message,'(a,a,a)') ' scfcge:',ch10,' scfcge:istep-iline_cge-ilinmin lambda etot resid ' 822 call wrtout(std_out,message,'COLL') 823 end if 824 825 if(ilinmin_input/=0 .or. istep==1)then 826 ! Usual line minimisation step 827 828 if(iline_cge_input<10)then 829 write(message, '(a,i4,a,i1,a,i1,es13.4,es20.12,es12.4)' )& 830 & ' scfcge: actual ',istep,'-',iline_cge_input,'-',ilinmin_input,lambda_input,etotal_input,resid_input 831 else 832 write(message, '(a,i3,a,i2,a,i1,es13.4,es20.12,es12.4)' )& 833 & ' scfcge: actual ',istep,'-',iline_cge_input,'-',ilinmin_input,lambda_input,etotal_input,resid_input 834 end if 835 call wrtout(std_out,message,'COLL') 836 837 if( (end_linmin==1.or.end_linmin==-1) .and. istep/=1 )then 838 839 if(end_linmin==1)then 840 write(message, '(a,es13.4,a,i2,a,a)' )& 841 & ' scfcge: predict ',lambda_predict,& 842 & ' suff. close => next line, ilinear=',ilinear,ch10,& 843 & ' scfcge:' 844 else if(end_linmin==-1)then 845 write(message, '(a,es13.4,a,a,a)' )& 846 & ' scfcge: predict ',lambda_predict,& 847 & ' restart the algorithm ',ch10,& 848 & ' scfcge:' 849 end if 850 call wrtout(std_out,message,'COLL') 851 852 if(iline_cge_input<9)then 853 write(message, '(a,i4,a,i1,a,i1,es13.4,es20.12,es12.4)' ) & 854 & ' scfcge: start ',istep,'-',iline_cge,'-',0,0.0,etotal_old,resid_old 855 else 856 write(message, '(a,i3,a,i2,a,i1,es13.4,es20.12,es12.4)' ) & 857 & ' scfcge: start ',istep,'-',iline_cge,'-',0,0.0,etotal_old,resid_old 858 end if 859 call wrtout(std_out,message,'COLL') 860 861 else if(istep/=1) then 862 write(message, '(a,es13.4,a)' )& 863 & ' scfcge: predict ',lambda_predict,& 864 & ' not close enough => continue minim.' 865 call wrtout(std_out,message,'COLL') 866 end if 867 868 else 869 ! CG prediction 870 if(iline_cge_input<10)then 871 write(message, '(a,i4,a,i1,a,es11.4,es20.12,es12.4,a,i1)' )& 872 & ' scfcge: actual ',istep,'-',iline_cge_input,'-off',& 873 & lambda_adapt,etotal_input,resid_input,', end=',end_linmin 874 else 875 write(message, '(a,i3,a,i2,a,es11.4,es20.12,es12.4,a,i1)' )& 876 & ' scfcge: actual ',istep,'-',iline_cge_input,'-off',& 877 & lambda_adapt,etotal_input,resid_input,', end=',end_linmin 878 end if 879 call wrtout(std_out,message,'COLL') 880 881 if(end_linmin==4)then 882 write(message, '(a)' ) ' scfcge:' 883 call wrtout(std_out,message,'COLL') 884 end if 885 886 end if 887 888 end subroutine scfcge