6 USE v3_utilities,
ONLY:
assert
8 USE stel_constants,
ONLY: zero, one
9 USE descriptor_mod,
ONLY: siesta_comm, iam, nprocs
13 USE nscalingtools,
ONLY: parfunctisl, mpi_err, startglobrow, &
25 USE hessian,
ONLY: levmarq_param, dmin=>mindiag, apply_precond, &
34 INTEGER :: j, iter, istat
35 REAL(dp),
PARAMETER :: levscan(1) = (/16._dp/)
37 REAL(dp) :: wmhd, fmhd, skston, skstoff, eps, lm0, fsq_min, &
38 xmax_lin, mupars, scale_fac
39 REAL(dp),
ALLOCATABLE :: xc1(:), xcmin(:), brhs(:)
59 ALLOCATE (brhs(
neqs), stat=istat)
60 CALL assert(istat.eq.0,
'ALLOCATION ERROR IN GMRES_FUN')
72 gmres_funct_island_time=gmres_funct_island_time+(skstoff-skston)
78 ALLOCATE(xc1(
neqs), xcmin(
neqs), stat=istat)
79 CALL assert(istat.eq.0,
'Allocation error in GMRES')
95 lfast:
IF (.NOT.l_diagonal_only .AND.
lcolscale)
THEN
97 IF (iam.EQ.0 .AND.
lverbose) print 925, dmin
98 925
FORMAT(
' DMIN: ',1pe12.3,/,1x,
'FAST CONVERGENCE SUMMARY',
99 /,
' -------------',/,1x,
'ITER',7x,
'FSQ_NL',
100 10x,
'||X||',9x,
'MAX|X|')
101 CALL assert(all(
xc.EQ.zero),
' XC != 0')
106 eps = abs(levmarq_param)*dmin
108 CALL apply_precond(
xc)
113 IF (eps .EQ. zero)
GOTO 927
115 CALL apply_precond(
gc)
129 sqrt(sum(
xc*
xc)), maxval(abs(
xc))
130 IF (fsq_min.LE.
ftol .OR. bterm .OR. eps.EQ.zero)
EXIT
139 lgmres:
IF (fsq_min.GT.
ftol .AND. fsq_min.GT.fmhd/10)
THEN
147 CALL gmres_wrap (
xc, brhs)
148 CALL second0(skstoff)
149 gmres_wrap_time=gmres_wrap_time+(skstoff-skston)
151 IF (
fsq_total1.LT.fsq_min .OR. all(xcmin.EQ.zero))
THEN
154 IF (lm0 .GT. zero) scale_fac = levmarq_param/lm0
161 IF (fsq_min.GE.0.95_dp*fmhd .AND. iter.LT.
SIZE(levscan))
THEN
163 levmarq_param = lm0*levscan(iter)
165 IF (levmarq_param .GE. levmarq_param0) levmarq_param = levmarq_param0
166 IF (iam.EQ.0 .AND.
lverbose) print 930,
' Refactoring Hessian: LM = '
167 CALL refactorhessian(levmarq_param)
173 912
FORMAT(i5,3(3x,1pe12.3))
174 930
FORMAT (/,a,1pe12.3)
183 xmax_lin = maxval(abs(xcmin))
186 WRITE (
unit_out, 1020)
' ||X||-GMRES = ', sqrt(sum(xcmin*xcmin)
' MAX(|X|) = '
188 1020
FORMAT(2(a,1p,e11.3))
194 IF (fsq_min .GT.
ftol)
THEN
202 CALL linesearch(xcmin, fsq_min)
218 CALL second0(skstoff)
219 gmres_funct_island_time=gmres_funct_island_time+(skstoff-skston)
224 DEALLOCATE (xcmin, brhs)
226 END SUBROUTINE gmres_fun
228 SUBROUTINE init_gmres0 (icntl, cntl, etak, m, n)
229 INTEGER,
INTENT(OUT) :: icntl(9), m, n
230 REAL(dp),
INTENT(OUT) :: cntl(5)
231 REAL(dp),
INTENT(IN) :: etak
232 REAL(dp) :: skston, skstoff
233 INTEGER,
PARAMETER :: noPrec=0, leftprec=1, rightprec=2, dbleprec
236 CALL init_dgmres(icntl ,cntl)
237 CALL second0(skstoff)
238 gmres_init_dgmres_time=gmres_init_dgmres_time+(skstoff-skston)
251 IF (
nprecon .gt. 1) icntl(3) = 20
277 END SUBROUTINE init_gmres0
279 SUBROUTINE gmres_wrap (x0, b)
281 USE nscalingtools,
ONLY: pargmres, rcounts, disp
282 USE hessian,
ONLY: apply_precond
283 USE gmres_lib,
ONLY:
gmres_info, gmres_par, gmres_ser
287 REAL(dp),
INTENT(IN) :: b(:)
288 REAL(dp),
INTENT(INOUT) :: x0(:)
301 CALL init_gmres0(gi%icntl, gi%cntl, etak, gi%m, n)
312 gi%iam=iam; gi%nprocs=nprocs; gi%ngmres_type=
ngmres_type
313 IF (parsolver .AND. pargmres)
THEN
314 gi%endglobrow=endglobrow; gi%startglobrow=startglobrow
315 gi%mblk_size=
mblk_size; gi%rcounts=>rcounts; gi%disp=>disp
317 gi%my_comm = siesta_comm
318 gi%my_comm_world = siesta_comm
320 CALL gmres_par (n, gi, matvec_par, apply_precond, getnlforce,
323 CALL gmres_ser (n, gi, matvec, apply_precond, getnlforce,
328 CALL assert(all(
xc.EQ.x0),
'XC != X0 IN GMRES_WRAP')
330 END SUBROUTINE gmres_wrap
332 SUBROUTINE matvec_par (ploc, Ap, nloc)
339 INTEGER,
INTENT(IN) :: nloc
340 REAL(dp),
INTENT(IN),
DIMENSION(nloc) :: ploc
341 REAL(dp),
INTENT(OUT),
DIMENSION(nloc) :: Ap
343 LOGICAL,
PARAMETER :: LPARMATVEC=.false.
344 INTEGER :: myrowstart, myrowend, istat
345 REAL(dp),
ALLOCATABLE :: p(:)
346 REAL(dp) :: delta, skston, skstoff
357 istat = (endglobrow-startglobrow+1)*
mblk_size
358 CALL assert(istat.EQ.nloc,
'nloc wrong in matvec_par')
361 myrowend=myrowstart+nloc-1
365 CALL assert(istat.eq.0,
'Allocation error in matvec_par')
368 p(myrowstart:myrowend) = ploc
371 CALL second0(skstoff)
372 gmres_wrap_allgather_time=gmres_wrap_allgather_time+(skstoff-skston
377 .OR. mupar.NE.zero)
THEN
378 delta = sqrt(epsilon(delta))*eps_factor
383 ap =
gc(myrowstart:myrowend)/delta
386 CALL parmatvec(p,ap,nloc)
391 WHERE (abs(ap) .LT. 1.e-10_dp) ap = 0
393 CALL second0(skstoff)
395 paryax_time=paryax_time+(skstoff-skston)
397 END SUBROUTINE matvec_par
399 SUBROUTINE matvec (p, Ap, ndim)
408 INTEGER,
INTENT(IN) :: ndim
409 REAL(dp),
INTENT(IN) :: p(ndim)
410 REAL(dp),
INTENT(OUT) :: Ap(ndim)
414 REAL(dp),
PARAMETER :: zero=0
419 delta = sqrt(epsilon(delta))*eps_factor
427 CALL assert(
SIZE(
gc).EQ.
SIZE(ap),
'gc and Ap wrong sizes')
440 WHERE (abs(ap) .LT. 1.e-10_dp) ap = 0
442 END SUBROUTINE matvec
445 SUBROUTINE get_etak(fk, fkm, ftol, etak)
449 REAL(dp),
INTENT(in) :: fk, fkm, ftol
450 REAL(dp),
INTENT(inout) :: etak
454 REAL(dp),
PARAMETER :: gamma1=0.9_dp, alpha=1.5_dp, eta0 = 1.e-02_dp
461 etak = gamma1*(fk/fkm)**alpha
464 etak = min(eta0, max(etak, gamma1*etakm**alpha))
467 etak = min(eta0, max(etak, gamma1*ftol/fk))
469 END SUBROUTINE get_etak
472 SUBROUTINE getnlforce(xcstate, fsq_nl, bnorm)
479 REAL(dp),
INTENT(IN) :: xcstate(neqs), bnorm
480 REAL(dp),
INTENT(OUT) :: fsq_nl
484 INTEGER :: nloc, myrowstart, myrowend
485 LOGICAL :: l_linloc, l_Apploc, l_getloc
493 nloc=(endglobrow-startglobrow+1)*
mblk_size
495 myrowend=myrowstart+nloc-1
499 xc(myrowstart:myrowend) = bnorm*xcstate(myrowstart:myrowend)
516 END SUBROUTINE getnlforce
522 INTEGER :: ndim, nlen, nlim, ierr, info(4), j
523 INTEGER :: revcom, colx, colb
524 REAL(dp),
DIMENSION(:,:),
ALLOCATABLE :: vecs
525 REAL(dp) :: tol = 1.e-4_dp, gnorm
532 CALL assert(j.eq.0,
'Allocation error in qmr_fun')
553 vecs(:ndim,2) = -
gc(:ndim)/gnorm
554 vecs(:ndim,3) =
gc(:ndim)/gnorm
560 10
CALL dutfx (ndim,nlen,nlim,vecs,tol,info)
564 IF (revcom .eq. 1)
THEN
565 CALL matvec (vecs(1,colx), vecs(1,colb), ndim)
569 xc(1:ndim) =
xc0(1:ndim) + gnorm*vecs(:,1)
580 DEALLOCATE (
xc0,
gc0, vecs)
582 END SUBROUTINE qmr_fun