13 USE v3_utilities,
ONLY:
assert
19 nfp=>nfp_i, mnmax=>mnmax_i, hs=>
hs_i
22 USE descriptor_mod,
ONLY: iam, nprocs
23 USE nscalingtools,
ONLY: sksdbg, parsolver, parfunctisl, mpi_err, &
24 startglobrow, endglobrow, rcounts, disp
34 INTEGER,
PARAMETER :: ndamp = 20
36 INTEGER,
PARAMETER :: ncongrad_steps = 100
38 INTEGER,
PARAMETER :: nprint_step = 1
54 REAL (dp) :: delt_cg = 1
64 REAL (dp) :: fsq_ratio
66 REAL (dp) :: fsq_ratio1
68 REAL (dp),
DIMENSION(ndamp) :: otau
70 REAL (dp),
DIMENSION(:),
ALLOCATABLE :: xcdot
87 SUBROUTINE converge_diagonal(wout_file, ftol)
89 USE perturbation,
ONLY: add_perturb, niter_max
90 USE dumping_mod,
ONLY: write_output
95 CHARACTER (len=*),
INTENT(in) :: wout_file
96 REAL(dp),
INTENT(IN) :: ftol
100 REAL (dp) :: fsq_block
105 REAL (dp),
PARAMETER :: fsq_prec = 1.e-10_dp
109 fsq_block = max(ftol, fsq_prec)
131 diag_evolve_time=diag_evolve_time+(t2-t1)
136 CALL write_output(wout_file,
niter, .false.)
139 l_iterate = fsq_ratio1 .le. 0.5_dp .and.
146 CALL add_perturb(
xc, getwmhd)
148 diag_add_pert_time=diag_add_pert_time+(t2-t1)
166 SUBROUTINE converge_blocks(wout_file, ftol)
168 USE perturbation,
ONLY: add_perturb, niter_max
169 USE dumping_mod,
ONLY: write_output
172 CHARACTER (len=*),
INTENT(in) :: wout_file
173 REAL (dp),
INTENT(in) :: ftol
182 REAL (dp),
PARAMETER :: fsq_prec = 1.e-10_dp
197 block_evolve_time = block_evolve_time + (t2 - t1)
202 CALL write_output (wout_file,
niter, .false.)
205 l_iterate =
niter .lt. niter_max .and.
208 IF (.not.l_conjmin .and. .not.l_gmres)
THEN
222 IF (
nprecon .gt. 2 .and. abs(1 - fsq_ratio1) .lt. 1.e-2_dp)
THEN
225 IF (nrow.EQ.3 .and. l_iterate)
THEN
239 CALL add_perturb(
xc, getwmhd)
241 block_add_pert_time = block_add_pert_time + (t2 - t1)
250 1000
FORMAT(
' CONJ GRADIENT UNABLE TO MAKE PROGRESS')
251 1001
FORMAT(
' FSQ RATIO: ',1p,e10.2,
' SIESTA CAN NOT CONVERGE FURTHER!'
258 SUBROUTINE init_evolution
259 USE hessian,
ONLY: levmarq_param0, levmarq_param, l_compute_hessian
260 USE quantities,
ONLY: jvsupsmncf,jvsupumnsf,jvsupvmnsf, &
261 jvsupsmnsf,jvsupumncf,jvsupvmncf, &
262 fsubsmncf, fsubumnsf, fsubvmnsf, &
263 fsubsmnsf, fsubumncf, fsubvmncf, &
296 fsqprev = -1; fsqprev1 = -1
307 levmarq_param = levmarq_param0
312 CALL assert(mnmax .eq. (1 + mpol)*(2*ntor + 1),
'WRONG mnmax!')
318 CALL assert(istat.eq.0,
'Allocate xc failed!')
321 CALL init_ptrs(
xc, jvsupsmncf, jvsupumnsf, jvsupvmnsf,
322 jvsupsmnsf, jvsupumncf, jvsupvmncf)
325 CALL assert(istat.eq.0,
'Allocate gc failed!')
329 CALL init_ptrs(
gc, fsubsmncf, fsubumnsf, fsubvmnsf,
330 fsubsmnsf, fsubumncf, fsubvmncf)
332 l_compute_hessian = .false.
351 USE quantities,
ONLY: jvsupsmncf, jvsupumnsf, jvsupvmnsf, &
352 jvsupsmnsf, jvsupumncf, jvsupvmncf, &
353 fsubsmncf, fsubumnsf, fsubvmnsf, &
354 fsubsmnsf, fsubumncf, fsubvmncf
355 USE gmres,
ONLY: gmres_fun
359 USE perturbation,
ONLY: niter_max
360 USE diagnostics_mod,
ONLY: bgradp_rms, toroidal_flux0, bgradp, &
364 USE timer_mod,
ONLY: gmres_time
366 USE vmec_info,
ONLY: vmec_curtor
387 INTEGER,
DIMENSION(2) :: tnum_funct
388 CHARACTER(LEN=20) :: str_resistive
391 REAL (dp),
DIMENSION(1),
PARAMETER :: levscan = (/ 0.25_dp /)
398 IF (
niter .le. 1)
THEN
421 IF (fsq_ratio1 .gt. 0.25_dp .and.
422 fsq_ratio1 .lt. 1.5_dp)
THEN
425 IF (fsq_ratio1 .gt. 1.5_dp)
THEN
428 IF (fsq_ratio1 .gt. 10._dp)
THEN
431 levm_loc = max(0.1_dp, min(10._dp, f2*levm_loc))
436 IF (levmarq_param0 .eq. zero)
THEN
440 IF (mupar0 .eq. zero)
THEN
445 levmarq_param = max(0.3_dp, levmarq_param0)
451 IF (
niter .gt. 1)
THEN
459 IF (ldiagonal .OR. lblock)
THEN
462 CALL compute_hessian_blocks(funct_island, ldiagonal)
464 CALL second0(skstoff)
466 comp_diag_elements_time = comp_diag_elements_time
470 compute_hessian_time = compute_hessian_time + (skstoff - skston
486 IF (
niter .eq. 1)
THEN
491 CALL second0(skstoff)
492 evolve_funct_island_time = evolve_funct_island_time
496 ELSE IF (l_gmres)
THEN
505 CALL second0(skstoff)
506 gmres_time = gmres_time + (skstoff - skston)
509 IF (.not.l_gmres .and.
niter .gt. 1)
THEN
515 levmarq_param = levscan(i - 1)*lm0
516 IF (levmarq_param .gt. levmarq_param0)
THEN
517 levmarq_param = levmarq_param0*1.e-2_dp
519 IF (levmarq_param .le.
levm_ped)
THEN
523 WRITE (*,1000) levmarq_param
525 CALL refactorhessian(levmarq_param)
528 CALL conjugate_grad(
ftol)
536 CALL second0(skstoff)
537 conj_grad_time = conj_grad_time + (skstoff - skston)
540 v2tot = sqrt(hs*sum(
xc*
xc))
542 lprint = mod(
niter, nprint_step) .eq. 0 .or.
niter .eq. 1
548 IF (
fsq_total .lt. zero .and. iam .eq. 0)
THEN
551 IF (fsqprev .gt. zero)
THEN
567 CALL mpi_allreduce(mpi_in_place, tnum_funct, 2, mpi_integer,
568 mpi_max, siesta_comm, mpi_err)
569 nfun_calls = (tnum_funct(1) + tnum_funct(2))
574 IF (
niter .eq. 1)
THEN
575 CALL bgradp(startglobrow, endglobrow)
584 CALL mpi_allreduce(mpi_in_place,
siesta_curtor, 1, mpi_real8,
585 mpi_sum, siesta_comm, mpi_err)
588 IF (
niter .gt. 1 .and. iam .eq. 0)
THEN
590 IF (.not.
lverbose .and. iprint .eq. 6)
THEN
595 CALL write_bounds(jvsupsmncf, fsubsmncf,
'X^S-max:',
'F_S-max:'
596 CALL write_bounds(jvsupumnsf, fsubumnsf,
'X^U-max:',
'F_U-max:'
597 CALL write_bounds(jvsupvmnsf, fsubvmnsf,
'X^V-max:',
'F_V-max:'
600 IF (.not.
lverbose .and. iprint .eq. 6)
THEN
605 CALL write_bounds(jvsupsmnsf, fsubsmnsf,
'X^S-max:',
'F_S-max:'
606 CALL write_bounds(jvsupumncf, fsubumncf,
'X^U-max:',
'F_U-max:'
607 CALL write_bounds(jvsupvmncf, fsubvmncf,
'X^V-max:',
'F_V-max:'
612 (
bs0(i), i=2,6), (
bu0(i), i=2,6)
615 (
bs0(i), i=8,12), (
bu0(i), i=8,12)
621 IF (.not.
lverbose .and. iprint .eq. 6)
THEN
629 IF ((.not.
lverbose .and. iprint .eq. 6) .or. iam .ne. 0)
THEN
632 IF (
niter .EQ. 1)
THEN
634 str_resistive =
"RESISTIVE RUN "
636 str_resistive =
"NON-RESISTIVE RUN "
641 WRITE (iprint, 65) levmarq_param0, mupar0
642 WRITE (iprint, 70)
neqs, ns, mpol, ntor, nu_i, nv_i,
665 CALL second0(skstoff)
666 evolve_restart_file_time=evolve_restart_file_time+(skstoff-skston)
674 CALL second0(skstoff)
675 evolve_add_resistive_e_time=evolve_add_resistive_e_time+(skstoff-skston
677 1000
FORMAT(/,
' Refactoring Hessian: LM = ',1pe12.3)
678 1001
FORMAT(
'Fsq_Total = ', 1pe12.3,
' < 0!')
679 1002
FORMAT(
'SYMMETRIC DISPLACEMENTS AND FORCES')
680 1003
FORMAT(
'ASYMMETRIC DISPLACEMENTS AND FORCES')
681 1004
FORMAT(
' |B^s-r12*B^u|/|B^s+r12*B^u| (m=1,r->0, sym) : ',1pe10.3,
682 ' |J^s-r12*J^u|/|J^s+r12*J^u| (m=1,r->0, sym) : ',1pe10.3,
683 ' JBSUPSH(JS=2-6,M=1)/r12 (sym): ',1p5e10.3,/,
684 ' JBSUPUH(JS=2-6,M=1) : ',1p5e10.3)
685 1005
FORMAT(
' |B^s+r12*B^u|/|B^s-r12*B^u| (m=1,r->0, asym) : ',1pe10.3,
686 ' |J^s+r12*J^u|/|J^s-r12*J^u| (m=1,r->0, asym) : ',1pe10.3,
687 '-JBSUPSH(JS=2-6,M=1)/r12 (asym): ',1p5e10.3,/,
688 ' JBSUPUH(JS=2-6,M=1) : ',1p5e10.3)
689 1006
FORMAT(1x, a,
' ETA_FACTOR: ',1pe10.2,
' LASYM: ',l1,
690 ' L_PUSH_S: ',l1,
' L_PUSH_U: ',l1,
' L_PUSH_V: ',l1,
693 50
FORMAT(
' WMHD: ', 1pe13.6,
' <BETA>: ',1pe11.4,
694 ' TFLUX: ',1pe11.4,
' B.GRAD-P (rms): ', 1pe11.4,/,21(
'-'))
695 60
FORMAT(
' DELTA_T: ',1pe10.2,
' ETA_K: ',
696 1pe10.2,
' HESSIAN SYM: ', l1)
697 65
FORMAT(
' LEVMARQ_PARAM: ',1pe10.2,
' MU_PAR: ',1pe10.2)
698 70
FORMAT(
' NEQS: ', i6,
' NS: ',i4,
' MPOL: ',i4,
' NTOR: ',i4,
699 ' NTHETA: ', i4,
' NZETA: ',i4,
' NGMRES-STEPS: ', i4,//,
700 ' NITER (W-W0)/W0*1E6 F2(MHD) F2(LIN)',
701 ' F2SUBS F2SUBU F2SUBV |V|rms NCALLS')
702 100
FORMAT(1x,i5,1x, 1pe12.4, 2x, 1x,1pe10.3, 2x,9 (
'-'),
704 102
FORMAT(1x,i5,1x, 1pe12.4, 2x, 6(1x,1pe10.3),i9)
705 112
FORMAT(
' |B^s+r12*B^u|/|B^s-r12*B^u| (m=1,r->0, asym) : ',1pe10.3,
706 ' |J^s+r12*J^u|/|J^s-r12*J^u| (m=1,r->0, asym) : ',1pe10.3,
707 '-JBSUPSH(JS=2-6,M=1)/r12 (asym): ',1p5e10.3,/,
708 ' JBSUPUH(JS=2-6,M=1) : ',1p5e10.3)
709 1007
FORMAT(
' SIESTA Curtor : ',e12.4,
' VMEC Curtor : 'e12.4,/)
715 SUBROUTINE write_bounds(vsupXmn, fsubXmn, vlabel, flabel)
719 REAL(dp),
DIMENSION(0:mpol,-ntor:ntor,ns),
INTENT(IN) &
721 CHARACTER(LEN=*),
INTENT(IN) :: vlabel, flabel
725 INTEGER,
PARAMETER :: nm0=1, nn0=2, ns0=3
726 INTEGER :: imaxlocv(3), ilbound(3), imaxlocf(3), iprint
727 REAL(dp) :: vmax, fmax
730 ilbound = lbound(vsupxmn)-1
731 imaxlocv = maxloc(abs(vsupxmn)) + ilbound
732 vmax = vsupxmn(imaxlocv(1),imaxlocv(2),imaxlocv(3))
733 CALL assert(abs(vmax).EQ.maxval(abs(vsupxmn)),
'vmax WRONG')
734 imaxlocv = imaxlocv - ilbound
735 imaxlocf = maxloc(abs(fsubxmn)) + ilbound
736 fmax = fsubxmn(imaxlocf(1),imaxlocf(2),imaxlocf(3))
737 CALL assert(abs(fmax).EQ.maxval(abs(fsubxmn)),
'fmax WRONG')
738 imaxlocf = imaxlocf - ilbound
741 IF ((.NOT.
lverbose .AND. iprint.EQ.6) .OR. iam.NE.0) cycle
743 trim(vlabel),vmax,imaxlocv(ns0),imaxlocv(nm0)-1,
744 imaxlocv(nn0)-ntor-1,
745 trim(flabel),fmax,imaxlocf(ns0),imaxlocf(nm0)-1,
749 45
FORMAT(2(1x,a,1x,1pe10.2,
' AT JS: ',i4,
' M: ',i4,
' N: ',i4,2x))
751 END SUBROUTINE write_bounds
755 SUBROUTINE conjugate_grad (ftol)
757 USE hessian,
ONLY: mupar
766 REAL(dp),
PARAMETER :: p5 = 0.50_dp
767 INTEGER,
PARAMETER :: ndamp = 10
768 INTEGER :: icount, iter
769 REAL(dp) :: b1, fac, fsq_start, fsq_min0, fsq_save, fsq_conv,
771 REAL(dp),
ALLOCATABLE :: xcstart(:)
794 CALL assert(icount.eq.0,
'ALLOCATION FAILED IN CONJ_GRAD')
804 IF (iam .EQ. 0 .and.
lverbose) print 90
805 90
FORMAT(1x,
'CONJUGATE GRADIENT CONVERGENCE SUMMARY',
806 /,
' -------------',/,1x,
'ITER',7x,
'FSQ_NL',10x,
'||X||')
810 DO icount = 1, 10*ncongrad_steps
816 CALL update_taudamp (fsq_save, delt_cg)
818 IF (icount .EQ. 1)
THEN
825 ALLOCATE (xcstart(
SIZE(
gc)))
838 IF (iam.EQ.0 .AND. (icount.EQ.1 .OR. mod(icount,10).EQ.0) .and.
842 delt_cg = 0.95_dp*delt_cg
843 IF (delt_cg .LT. 0.001_dp)
EXIT
853 IF (mod(icount, 50) .EQ. 0)
THEN
854 IF (fsq_min0 .GT. fsq_conv/2)
EXIT
859 otav = sum(otau)/ndamp
860 dtau = delt_cg*otav/2
870 xcdot = fac*(b1*xcdot + delt_cg*
gc)
871 xc =
xc + delt_cg*xcdot
881 mupars = mupar; mupar = 0
887 l_conjmin = (fsq_min0 .LT. fsq_start)
894 IF (fsq_min0 .GT. 0.95_dp*fsq_start) l_conjmin=.false.
903 IF (iam.EQ.0 .AND. l_conjmin)
THEN
904 IF (
lverbose)
WRITE (6, 100) icount, fsq_start, fsq_min0
905 WRITE (
unit_out,100) icount, fsq_start, fsq_min0
910 DEALLOCATE (xcdot,
xc0, xcstart)
911 100
FORMAT(
' ITER_CG: ', i3,
' FSQ (START CG): ',1p,e12.3,
' FSQ (END CG): '
912 110
FORMAT(i5, 2(3x,1pe12.3))
914 END SUBROUTINE conjugate_grad
918 SUBROUTINE update_taudamp (fsq_save, delt_cg)
922 REAL(dp),
INTENT(INOUT) :: fsq_save, delt_cg
926 REAL(dp),
PARAMETER :: mintau = 0.15_dp
930 IF (fsq_save .GT. zero)
THEN
932 ratio = min(mintau, ratio)
933 otau(1:ndamp-1) = otau(2:ndamp)
934 otau(ndamp) = ratio/delt_cg
937 otau = mintau/delt_cg
940 END SUBROUTINE update_taudamp