V3FIT
gmres_mod.f
1  MODULE gmres_mod
2  USE vmec_main, ONLY: dp, rprec, neqs, ns, nthreed,
3  1 one, fsqr, fsqz, fsql
4  USE parallel_include_module
5  USE parallel_vmec_module, ONLY: copylastntype, saxpbylastntype,
6  1 saxpbylastns, saxpby1lastns,
7  2 getderivlastns, saxlastntype
8  USE precon2d, ONLY: ictrl_prec2d
9  IMPLICIT NONE
10  INTEGER :: nfcn = 0, lqmrstep = 0
11  INTEGER :: ier_flag_res
12  LOGICAL :: lqmr, lfirst
13  LOGICAL, PARAMETER :: lscreen0 = .false.
14 
15 !
16 ! nfcn : number of calls to function (funct3d)
17 ! lqmr : logical, used by external programs to control calling these routines
18 !
19  CONTAINS
20 
21  SUBROUTINE matvec_par (ploc, Ap, nloc)
22  USE blocktridiagonalsolver, ONLY: parmatvec
23  USE stel_kinds
24  USE xstuff, ONLY: pxc, px0=>pxsave, pgc0=>pxcdot, pgc
25 C-----------------------------------------------
26 C D u m m y A r g u m e n t s
27 C-----------------------------------------------
28  INTEGER, INTENT(IN) :: nloc
29  REAL(dp), INTENT(IN) ::
30  & ploc(ntmaxblocksize,tlglob:trglob)
31  REAL(dp), INTENT(OUT) ::
32  & Ap(ntmaxblocksize,tlglob:trglob)
33 C-----------------------------------------------
34 C L o c a l V a r i a b l e s
35 C-----------------------------------------------
36  INTEGER :: mblk_size, istat
37  REAL(dp) :: delta, lmax, gmax, pmax, apmax
38 C-----------------------------------------------
39  mblk_size = neqs/ns
40 !
41 ! Computes linearized matrix product A*p = [F(x0+delta*p) - F(x0)]/delta, about point x0
42 ! Must scale p so delta*max|p| ~ sqrt(epsilon) to get accurate numerical derivative
43 ! Because the block preconditioner is applied in funct3d, the net result
44 ! should be Ap ~ -p.
45 
46  delta = sqrt(epsilon(delta))
47 
48  lactive0: IF (lactive) THEN
49  IF (nloc .NE. (trglob - tlglob + 1)*mblk_size) THEN
50  stop 'nloc wrong in matvec_par'
51  END IF
52  lmax = sum(ploc*ploc)
53  CALL mpi_allreduce(lmax, pmax, 1, mpi_real8, mpi_sum, ns_comm,
54  & mpi_err)
55  pmax = sqrt(pmax)
56  delta = delta/max(delta, pmax)
57 
58  CALL saxpbylastns(delta, ploc, one, px0, pxc)
59 
60  CALL last_ntype_par
61  CALL padsides(pxc)
62  END IF lactive0
63 
64  CALL funct3d_par(lscreen0, ier_flag_res)
65 
66  IF (lactive) THEN
67  CALL last_ns_par
68  CALL getderivlastns(pgc, pgc0, delta, ap)
69  ENDIF
70 
71  IF (ier_flag_res.NE.0 .AND. rank.EQ.0) THEN
72  print *,'IN MATVEC_PAR, IER_FLAG = ', ier_flag_res
73  END IF
74 
75  90 CONTINUE
76  nfcn = nfcn + 1
77 
78  END SUBROUTINE matvec_par
79 
80  SUBROUTINE getnlforce_par(xcstate, fsq_nl, bnorm)
81  USE xstuff, ONLY: pxc, pgc, x0=>pxsave
82 !-----------------------------------------------
83 ! D u m m y A r g u m e n t s
84 !-----------------------------------------------
85  REAL(dp), INTENT(IN) :: xcstate(neqs), bnorm
86  REAL(dp), INTENT(OUT) :: fsq_nl
87 !-----------------------------------------------
88 !undo internal gmres normalization
89 
90  lactive0: IF (lactive) THEN
91  CALL saxpby1lastns(bnorm, xcstate, one, x0, pxc)
92  CALL last_ntype_par
93  CALL padsides(pxc)
94  END IF lactive0
95 
96  CALL funct3d_par(lscreen0, ier_flag_res)
97  IF (lactive) CALL last_ns_par
98 
99  fsq_nl = fsqr + fsqz + fsql
100  nfcn = nfcn + 1
101 
102  END SUBROUTINE getnlforce_par
103  !------------------------------------------------
104  !
105  !------------------------------------------------
106  SUBROUTINE last_ns_par
107  USE xstuff
108 
109  REAL(dp), ALLOCATABLE, DIMENSION(:) :: tmp
110  ALLOCATE (tmp(ntmaxblocksize*ns))
111 
112  CALL tolastns(pgc,tmp)
113  CALL copylastns(tmp,pgc)
114 
115  CALL tolastns(pxcdot,tmp)
116  CALL copylastns(tmp,pxcdot)
117 
118  CALL tolastns(pxc,tmp)
119  CALL copylastns(tmp,pxc)
120 
121  CALL tolastns(pxsave,tmp)
122  CALL copylastns(tmp,pxsave)
123 
124  DEALLOCATE(tmp)
125 
126  END SUBROUTINE last_ns_par
127  !------------------------------------------------
128 
129  !------------------------------------------------
130  SUBROUTINE last_ntype_par
131  USE xstuff
132 
133  REAL(dp), ALLOCATABLE, DIMENSION(:) :: tmp
134  ALLOCATE (tmp(ntmaxblocksize*ns))
135 
136  CALL tolastntype(pgc,tmp)
137  CALL copylastntype(tmp,pgc)
138 
139  CALL tolastntype(pxcdot,tmp)
140  CALL copylastntype(tmp,pxcdot)
141 
142  CALL tolastntype(pxc,tmp)
143  CALL copylastntype(tmp,pxc)
144 
145  CALL tolastntype(pxsave,tmp)
146  CALL copylastntype(tmp,pxsave)
147 
148  DEALLOCATE(tmp)
149  END SUBROUTINE last_ntype_par
150  !------------------------------------------------
151 
152  !------------------------------------------------
153  SUBROUTINE gmres_fun_par (ier_flag, itype, lscreen)
154  USE precon2d, ONLY: ictrl_prec2d, block_precond_par
155  USE xstuff
156  USE vmec_main, ONLY: fsqr, fsqz, fsql, ftolv
157  USE gmres_lib, ONLY: gmres_par, gmres_info
158 !-----------------------------------------------
159 ! D u m m y A r g u m e n t s
160 !-----------------------------------------------
161  INTEGER, INTENT(IN) :: itype
162  INTEGER, INTENT(OUT) :: ier_flag
163  LOGICAL, INTENT(IN) :: lscreen
164 !-----------------------------------------------
165 ! L o c a l V a r i a b l e s
166 !-----------------------------------------------
167  TYPE (gmres_info) :: gi
168  INTEGER :: n, m, l
169  INTEGER :: icntl(9), info(3)
170  REAL(dp) :: cntl(5), fact, fact_min, fsq_min, fsq2,
171  & fsqr_min, fsqz_min, fsql_min
172  CHARACTER(LEN=*), PARAMETER :: qmr_message =
173  & 'Beginning GMRES iterations'
174  INTEGER, PARAMETER :: noPrec=0, leftprec=1, rightprec=2
175 !-----------------------------------------------
176  lgmrescall = .true.
177  n = neqs
178 !
179 ! CHOOSE TYPE OF SOLVER
180 !
181  IF (itype == 2) THEN
182  CALL gmresr_fun (ier_flag)
183  RETURN
184  ELSE IF (itype == 3) THEN
185  CALL qmr_fun
186  RETURN
187  END IF
188 
189 
190  IF (lfirst) THEN
191  lfirst = .false.
192  IF (grank.EQ.0) THEN
193  WRITE (*,'(2x,a,/)') qmr_message
194  WRITE (nthreed, '(2x,a,/)') qmr_message
195  END IF
196  END IF
197 
198 !******************************************************
199 !* Initialize the control parameters to default value
200 !******************************************************
201 
202  CALL init_dgmres(icntl,cntl)
203 
204 !************************
205 ! Tune some parameters
206 !************************
207 
208 ! Tolerance
209  cntl(1) = 1.e-3_dp
210 ! cntl(1) = 1.e-4_dp
211 ! Write errors to fort.21
212 ! icntl(1) = 21 !21
213 ! Write warnings to fort.21
214  icntl(2) = 0 !21
215 ! Save the convergence history in file fort.20
216  icntl(3) = 20
217 ! No preconditioning
218  icntl(4) = noprec
219 ! Left preconditioning (doesn't work well with no col-scaling)
220 ! icntl(4) = leftPrec
221 ! ICGS orthogonalization
222  icntl(5) = 3
223 ! icntl(5) = 0
224 ! Initial guess
225  icntl(6) = 0
226 ! icntl(6) = 1
227 ! Maximum number of iterations at each step (~ns/5)
228 ! icntl(7) = 15
229  icntl(7) = 20
230 ! Stops to peek at progress during rev com loop
231  icntl(9) = 1
232 
233 
234 !********************************
235 !* Choose the restart parameter
236 !********************************
237 ! write(*,*) 'Restart <', ldstrt
238 ! read(*,*) m
239 !
240 ! m <= n
241 !
242  m = 20
243 !
244 ! Load gmres_info structure
245 !
246  info = 0
247  gi%m=m; gi%icntl=icntl; gi%cntl=cntl; gi%info = info
248  gi%ftol = ftolv
249 
250 
251  ALLOCATE(gi%rcounts(nranks),gi%disp(nranks))
252  gi%startglobrow=tlglob
253  gi%endglobrow=trglob
254  gi%iam=rank
255  gi%nprocs=nranks
256  gi%rcounts=ntblkrcounts
257  gi%disp=ntblkdisp
258  gi%mblk_size=ntmaxblocksize
259 
260  gi%my_comm = ns_comm
261  gi%my_comm_world = runvmec_comm_world
262  gi%lactive = lactive
263 
264  gi%lverbose = lscreen
265 
266  l = ictrl_prec2d
267  IF (icntl(4) .NE. noprec) ictrl_prec2d = -1
268  CALL funct3d_par(lscreen0, ier_flag_res)
269  ictrl_prec2d = l
270  nfcn = nfcn+1
271 
272 !STORE INITIAL POINT AND INITIAL FORCE (AT INIT PT)
273 !SO DEVIATIONS FROM THEM CAN BE COMPUTED REPEATEDLY
274  CALL copylastntype(pxc, pxsave)
275  CALL copylastntype(pgc, pxcdot)
276 
277 !RHS: RETURN RESULT OF SOLVING LINEARIZED A*x = -gc IN XCDOT
278 ! AND IS DISTRIBUTED OVER ALL PROCESSORS
279  CALL copylastntype(pgc, pgc, -one)
280 
281  CALL last_ns_par
282 
283  CALL gmres_par(n, gi, matvec_par, block_precond_par,
284  & getnlforce_par, pxcdot, pgc)
285 
286  CALL last_ntype_par
287 
288 ! ier_flag = gi%info(1)
289 ! ictrl_prec2d = 1
290  ier_flag = 0
291  fact = 1; fact_min = fact
292  fsq_min = gi%ftol
293  fsqr_min = fsqr; fsqz_min = fsqz; fsql_min = fsql
294 
295 ! SIMPLE LINESEARCH SCALING SCAN
296 
297  1010 FORMAT(1x,'LINE SEARCH - SCAN ||X|| FOR MIN FSQ_NL',/,
298  & '-------------',/,
299  & 1x,'ITER',7x,'FSQ_NL',10x,'||X||',9x,'MAX|X|')
300 
301  CALL mpi_bcast(fsq_min, 1, mpi_real8, 0, runvmec_comm_world,
302  & mpi_err)
303 
304  DO m = 1, 5
305  fact = fact*sqrt(0.5_dp)
306  CALL saxpbylastntype(fact, pxcdot, one, pxsave, pxc)
307 
308  CALL funct3d_par(lscreen0, ier_flag_res)
309 
310  fsq2 = fsqr+fsqz+fsql
311 
312  IF (fsq2 .LT. fsq_min) THEN
313  fsq_min = fsq2
314  fact_min = fact
315  fsqr_min = fsqr; fsqz_min = fsqz; fsql_min = fsql
316  IF (grank .EQ. 0) print 1020, fact, fsq2
317  ELSE
318  EXIT
319  END IF
320  END DO
321 
322  1020 FORMAT(2x,'GMRES_FUN, TIME_STEP: ',1p,e10.3, ' FSQ_MIN: ',1pe10.3)
323 
324  fsqr = fsqr_min; fsqz = fsqz_min; fsql = fsql_min
325  IF (ictrl_prec2d .EQ. 1) THEN
326  CALL saxlastntype(pxcdot,pcol_scale,pxcdot)
327  END IF
328 
329  CALL saxpbylastntype(fact_min, pxcdot, one, pxsave, pxc)
330  CALL copylastntype(pxc, pxsave)
331 
332  DEALLOCATE(gi%rcounts,gi%disp)
333  lgmrescall=.false.
334 
335  END SUBROUTINE gmres_fun_par
336 
337  SUBROUTINE getnlforce(xcstate, fsq_nl, bnorm)
338  USE xstuff, ONLY: xc, gc, x0=>xsave
339 !-----------------------------------------------
340 ! D u m m y A r g u m e n t s
341 !-----------------------------------------------
342  REAL(dp),INTENT(IN) :: xcstate(neqs), bnorm
343  REAL(dp),INTENT(OUT) :: fsq_nl
344 !-----------------------------------------------
345 !undo internal gmres normalization
346  xc(1:neqs) = x0(1:neqs) + bnorm*xcstate(1:neqs)
347 
348  CALL funct3d(lscreen0, ier_flag_res)
349  fsq_nl = fsqr+fsqz+fsql
350 
351  nfcn = nfcn + 1
352 
353  END SUBROUTINE getnlforce
354 
355  SUBROUTINE matvec (p, Ap, ndim)
356  USE xstuff, ONLY: xc, x0=>xsave, gc0=>xcdot, gc
357 C-----------------------------------------------
358 C D u m m y A r g u m e n t s
359 C-----------------------------------------------
360  INTEGER, INTENT(in) :: ndim
361  REAL(dp), INTENT(in), DIMENSION(ndim) :: p
362  REAL(dp), INTENT(out), DIMENSION(ndim) :: Ap
363 C-----------------------------------------------
364 C L o c a l V a r i a b l e s
365 C-----------------------------------------------
366  INTEGER :: l
367  REAL(dp) :: delta, pmax
368 C-----------------------------------------------
369 !
370 ! Computes linearized matrix product A*p = [F(x0+delta*p) - F(x0)]/delta, about point x0
371 ! Must scale p so delta*max|p| ~ sqrt(epsilon) to get accurate numerical derivative
372 !
373 ! Ap = -p
374 ! GOTO 90
375 
376  delta = sqrt(epsilon(delta))
377  pmax = sqrt(sum(p(1:ndim)**2))
378  delta = delta/max(delta, pmax)
379 
380  xc(1:ndim) = x0(1:ndim) + delta*p(1:ndim)
381  CALL funct3d(lscreen0, ier_flag_res)
382  ap = (gc(1:ndim) - gc0(1:ndim))/delta
383 
384  IF (ier_flag_res .NE. 0) THEN
385  print *,'IN MATVEC, IER_FLAG = ', ier_flag_res
386  END IF
387 
388  90 CONTINUE
389  nfcn = nfcn + 1
390 
391  END SUBROUTINE matvec
392 
393  SUBROUTINE gmres_fun (ier_flag, itype)
394  USE precon2d, ONLY: block_precond
395  USE xstuff
396  USE vmec_main, ONLY: fsqr, fsqz, fsql, ftolv
397  USE gmres_lib, ONLY: gmres_ser, gmres_info
398 !-----------------------------------------------
399 ! D u m m y A r g u m e n t s
400 !-----------------------------------------------
401  INTEGER, INTENT(IN) :: itype
402  INTEGER, INTENT(OUT) :: ier_flag
403 !-----------------------------------------------
404 ! L o c a l V a r i a b l e s
405 !-----------------------------------------------
406  TYPE (gmres_info) :: gi
407  INTEGER :: n, m, l
408  INTEGER :: icntl(9), info(3)
409  REAL(dp) :: cntl(5), fact, fact_min, fsq_min, fsq2,
410  & fsqr_min, fsqz_min, fsql_min
411  CHARACTER(LEN=*), PARAMETER :: qmr_message =
412  & 'Beginning GMRES iterations'
413  INTEGER, PARAMETER :: noPrec=0, leftprec=1, rightprec=2
414 !-----------------------------------------------
415  n = neqs
416 
417 !
418 ! CHOOSE TYPE OF SOLVER
419 !
420  IF (itype == 2) THEN
421  CALL gmresr_fun (ier_flag)
422  RETURN
423  ELSE IF (itype == 3) THEN
424  CALL qmr_fun
425  RETURN
426  END IF
427 
428 
429  IF (lfirst) THEN
430  lfirst = .false.
431  WRITE (*,'(2x,a,/)') qmr_message
432  WRITE (nthreed, '(2x,a,/)') qmr_message
433  END IF
434 
435 !******************************************************
436 !* Initialize the control parameters to default value
437 !******************************************************
438 
439  CALL init_dgmres(icntl,cntl)
440 
441 !************************
442 ! Tune some parameters
443 !************************
444 
445 ! Tolerance
446  cntl(1) = 1.e-3_dp
447 ! cntl(1) = 1.e-4_dp
448 ! Write errors to fort.21
449 ! icntl(1) = 21 !21
450 ! Write warnings to fort.21
451  icntl(2) = 0 !21
452 ! Save the convergence history in file fort.20
453  icntl(3) = 20
454 ! No preconditioning
455  icntl(4) = noprec
456 ! Left preconditioning (doesn't work well with no col-scaling)
457 ! icntl(4) = leftPrec
458 ! ICGS orthogonalization
459  icntl(5) = 3
460 ! icntl(5) = 0
461 ! Initial guess
462  icntl(6) = 0
463 ! icntl(6) = 1
464 ! Maximum number of iterations at each step (~ns/5)
465 ! icntl(7) = 15
466  icntl(7) = 20
467 ! Stops to peek at progress during rev com loop
468  icntl(9) = 1
469 
470 
471 !********************************
472 !* Choose the restart parameter
473 !********************************
474 ! write(*,*) 'Restart <', ldstrt
475 ! read(*,*) m
476 !
477 ! m <= n
478 !
479  m = 20
480 !
481 ! Load gmres_info structure
482 !
483  info = 0
484  gi%m=m; gi%icntl=icntl; gi%cntl=cntl; gi%info = info
485  gi%ftol = ftolv
486 
487 !Store initial gc
488  l = ictrl_prec2d
489  IF (icntl(4) .NE. noprec) ictrl_prec2d = -1
490  CALL funct3d(lscreen0, ier_flag_res)
491  ictrl_prec2d = l
492  nfcn = nfcn+1
493 
494 !
495 !STORE INITIAL POINT AND INITIAL FORCE (AT INIT PT)
496 !SO DEVIATIONS FROM THEM CAN BE COMPUTED REPEATEDLY
497  xcdot = gc
498  xsave = xc
499 
500 !RHS: RETURN RESULT OF A*X = -gc IN XCDOT
501  gc = -gc
502 
503  CALL gmres_ser(n, gi, matvec, block_precond, getnlforce,
504  & xcdot, gc)
505 
506 100 CONTINUE
507 
508 ! ier_flag = gi%info(1)
509 ! ictrl_prec2d = 1
510  ier_flag = 0
511  fact = 1
512  fact_min = fact
513  fsq_min = huge(fsq_min)
514 
515 ! SIMPLE LINESEARCH SCALING SCAN
516  DO m = 1, 5
517 
518  xc(1:n) = xsave(1:n) + fact*xcdot(1:n)
519 
520  CALL funct3d(lscreen0, ier_flag_res)
521 
522  fsq2 = fsqr+fsqz+fsql
523 
524  IF (fsq2 .LT. fsq_min) THEN
525  fsq_min = fsq2
526  fact_min = fact
527  fsqr_min = fsqr; fsqz_min = fsqz; fsql_min = fsql
528  ELSE
529  EXIT
530  END IF
531  fact = fact/2._dp
532 
533  END DO
534 
535 ! PRINT 1010, fact_min, fsq_min
536 ! 1010 FORMAT(2x,'GMRES_FUN, TIME_STEP: ',1p,e10.3, ' FSQ_MIN: ',1pe10.3)
537 
538  xc(1:n) = xsave(1:n) + fact_min*xcdot(1:n)
539  fsqr = fsqr_min; fsqz = fsqz_min; fsql = fsql_min
540  xsave = xc
541 
542  END SUBROUTINE gmres_fun
543 
544  SUBROUTINE gmresr_fun (ier_flag)
545  USE xstuff
546 C-----------------------------------------------
547 C D u m m y A r g u m e n t s
548 C-----------------------------------------------
549  INTEGER :: ier_flag
550 C-----------------------------------------------
551 C L o c a l V a r i a b l e s
552 C-----------------------------------------------
553  INTEGER :: ndim, jtrunc, mgmres, maxits, lwork
554  LOGICAL :: oktest
555  REAL(dp) :: eps, resid
556  REAL(dp), ALLOCATABLE, DIMENSION(:) :: work, delx, brhs
557  CHARACTER(len=3), PARAMETER :: stc="rel"
558  CHARACTER(LEN=*), PARAMETER :: qmr_message =
559  & 'Beginning GMRESR iterations'
560 C-----------------------------------------------
561  IF (lfirst) THEN
562  lfirst = .false.
563  WRITE (*,'(2x,a,/)') qmr_message
564  WRITE (nthreed, '(2x,a,/)') qmr_message
565  END IF
566 
567  oktest = .false.
568  ndim = neqs
569  jtrunc = 10
570  mgmres = 20
571  maxits = 10
572  lwork = ndim*(2*jtrunc + mgmres + 2)
573  eps = .3_dp
574 
575  ALLOCATE(work(lwork), delx(ndim), brhs(ndim), stat=ier_flag_res)
576  IF (ier_flag_res .ne. 0) stop 'Allocation failed in gmresr'
577 
578  brhs = -gc(1:ndim)
579  delx = 0
580 
581  CALL gmresr(oktest, ndim, jtrunc, mgmres, brhs, delx, work,
582  & eps, stc, maxits, resid, matvec, ier_flag_res)
583 
584  xc(1:ndim) = xsave(1:ndim) + delx(1:ndim)
585 
586  DEALLOCATE (work, delx, brhs)
587 
588  ier_flag = 0
589 
590  END SUBROUTINE gmresr_fun
591 
592  SUBROUTINE qmr_fun
593  USE vmec_dim, ONLY: ns, mpol1, ntor1
594  USE vmec_params, ONLY: ntmax
595  USE vmec_main, ONLY: lfreeb
596  USE xstuff
597 C-----------------------------------------------
598 C L o c a l V a r i a b l e s
599 C-----------------------------------------------
600  INTEGER :: ndim, nlen, nlim, ierr, info(4)
601  INTEGER :: revcom, colx, colb
602  INTEGER :: nty, ntyp, mt, mp, nt, np, jp, js
603  REAL(dp), DIMENSION(neqs,9) :: vecs
604  REAL(dp) :: tol = 1.e-3_dp
605  CHARACTER(LEN=*), PARAMETER :: qmr_message =
606  1 'Beginning TF-QMR iterations'
607  LOGICAL, PARAMETER :: ldump_fort33 = .false.
608 C-----------------------------------------------
609  ndim = SIZE(vecs,1)
610  nlen = ndim
611  nlim = 10
612  xcdot = gc
613  xsave = xc
614 
615  IF (lfirst) THEN
616  lfirst = .false.
617  WRITE (*,'(2x,a,/)') qmr_message
618  WRITE (nthreed, '(2x,a,/)') qmr_message
619  IF (ldump_fort33) THEN
620 
621 ! CHECK THAT INITIALLY, PRECONDITIONER YIELDS (APPROXIMATE) IDENTITY MATRIX
622 ! OUTER LOOP: SUM OF XC PERTURBATION
623 ! INNER LOOP: GETS ALLL THE FORCES IN RESPONSE TO EACH OUTER LOOP PERTURBATION
624  ierr = 0
625  DO nty = 1, 3*ntmax
626  WRITE(33, '(a,i4)') "NTYPE' (XC-pert) = ",nty
627  DO mt = 0, mpol1
628  WRITE(33, '(a,i4)') "M' = ",mt
629  DO nt = 0, ntor1-1
630  WRITE(33, '(a,i4)') "N' = ",nt
631  DO js = 1, ns
632  ierr = ierr+1
633  IF (ierr .gt. ndim) EXIT
634  IF (mod(ierr,50).eq.0) print '(2x,a,f8.2,a)', 'Progress: ',
635  1 real(100*ierr)/ndim, ' %'
636  IF (js.eq.ns .and. .not.lfreeb) cycle
637  colx = 1; colb = 3
638  vecs(:,colx) = 0; vecs(ierr,colx) = 1
639  CALL matvec(vecs(1,colx), vecs(1,colb), ndim)
640  WRITE (33, '(a,i4,2x,a,i5,2x,a,1p,e12.2)') "js' = ", js,
641  1 ' ipert = ',ierr,' Ap[ipert,ipert] = ', vecs(ierr, colb)
642  colx = 0
643  DO ntyp = 1, 3*ntmax
644  DO mp = 0, mpol1
645  DO np = 0, ntor1-1
646  DO jp = 1, ns
647  colx = colx + 1
648  IF (colx .gt. ndim) cycle
649  IF (colx.eq.ierr .or.
650  1 abs(vecs(colx,colb)).lt.0.05_dp) cycle
651  WRITE (33, 123)'ntype = ', ntyp,' m = ',mp,
652  1 ' n = ', np,' js = ', jp,' iforce = ',colx,
653  2 ' Ap[iforce,ipert] = ', vecs(colx,colb)
654  END DO
655  END DO
656  END DO
657  END DO
658  END DO
659  END DO
660  END DO
661  END DO
662 
663  print '(/,2x,a,/)','Jacobian check in file FORT.33'
664 
665  END IF
666 
667  END IF
668  123 FORMAT(4x,4(a,i4),a,i6,a,1p,e12.3)
669 !
670 ! INITIALIZE vecs
671 !
672  vecs(:ndim,2) = -gc(:ndim)
673  vecs(:ndim,3) = gc(:ndim)
674 
675  ierr = 100000
676  info = 0
677  info(1) = ierr
678 
679  10 CALL dutfx (ndim,nlen,nlim,vecs,tol,info)
680  revcom = info(2)
681  colx = info(3)
682  colb = info(4)
683  IF (revcom .eq. 1) THEN
684  CALL matvec (vecs(1,colx), vecs(1,colb), ndim)
685  GO TO 10
686  END IF
687 
688  xc(1:ndim) = xsave(1:ndim) + vecs(1:ndim,1)
689 
690  END SUBROUTINE qmr_fun
691 
692  END MODULE gmres_mod
693 
694  SUBROUTINE truncate(num, iprec0)
695  USE stel_kinds, ONLY: dp
696  IMPLICIT NONE
697 ! NEEDED TO RESOLVE CALL IN gmres_par
698 !-----------------------------------------------
699 ! D u m m y A r g u m e n t s
700 !-----------------------------------------------
701  INTEGER, INTENT(IN) :: iprec0
702  REAL(dp), INTENT(INOUT) :: num
703 !-----------------------------------------------
704 !-----------------------------------------------
705 ! L o c a l V a r i a b l e s
706 !-----------------------------------------------
707  CHARACTER*24 :: chnum, tchnum
708 !-----------------------------------------------
709 !
710 ! TRUNCATES double-precision to precision iprec0 digits, keeping exponent range of double
711 ! WRITE TO INTERNAL FILE TO DO TRUNCATION
712 !
713 !UNCOMMENT THESE LINES TO ACTIVATE
714 ! WRITE (chnum, '(a,i2,a,i2,a)') '(1p,e',iprec0+7,'.',iprec0,')'
715 ! WRITE (tchnum, chnum) num
716 
717 ! READ (tchnum, chnum) num
718 
719  END SUBROUTINE truncate
gmres_lib::gmres_info
Definition: gmres_lib.f:7
blocktridiagonalsolver
Solver for block tri-diagonal matrices. [Kalyan S. Perumalla, ORNL, 2009-2011].
Definition: blocktridiagonalsolver.f90:8
parallel_vmec_module::copylastntype
Definition: parallel_vmec_module.f90:76