V3FIT
eqsolve.f
1  SUBROUTINE eqsolve(ier_flag, lscreen)
2  USE vmec_main
3  USE vmec_params, ONLY: ntmax, ns4, jac75_flag, norm_term_flag,
4  & bad_jacobian_flag, more_iter_flag,
5  & successful_term_flag
6  USE precon2d, ONLY: scratchfile, lswap2disk, ictrl_prec2d
7  USE directaccess, ONLY: deletedafile
8  USE gmres_mod, ONLY: nfcn
9  USE realspace
10  USE xstuff
11 ! Add below JDH 2010-08-03
12  USE vmec_history
13  USE parallel_include_module
14  USE parallel_vmec_module, ONLY: zerolastntype
15  USE vacmod, ONLY: nuv, nuv3
16  IMPLICIT NONE
17 !-----------------------------------------------
18 ! D u m m y A r g u m e n t s
19 !-----------------------------------------------
20  INTEGER :: ier_flag
21  LOGICAL :: lscreen
22 !-----------------------------------------------
23 ! L o c a l P a r a m e t e r s
24 !-----------------------------------------------
25  REAL(dp), PARAMETER :: p98 = 0.98_dp, p96 = 0.96_dp
26 !-----------------------------------------------
27 ! L o c a l V a r i a b l e s
28 !-----------------------------------------------
29  REAL(dp) :: w1, r00s, w0, wdota, r0dot, teqsolon, teqsoloff
30  LOGICAL :: liter_flag, lreset_internal
31 C-----------------------------------------------
32 !
33 ! INDEX OF LOCAL VARIABLES
34 !
35 ! iequi counter used to call -EQFOR- at end of run
36 ! ijacob counter for number of times jacobian changes sign
37 ! irst counter monitoring sign of jacobian; resets R, Z, and
38 ! Lambda when jacobian changes sign and decreases time step
39 ! signgs sign of Jacobian : must be =1 (right-handed) or =-1 (left-handed)
40 
41 ! iterj stores position in main iteration loop (j=1,2)
42 ! itfsq counter for storing FSQ into FSQT for plotting
43 ! ivac counts number of free-boundary iterations
44 ! ndamp number of iterations over which damping is averaged
45 ! meven parity selection label for even poloidal modes of R and Z
46 ! modd parity selection label for odd poloidal modes of R and
47 ! gc stacked array of R, Z, Lambda Spectral force coefficients (see readin for stack order)
48 ! xc stacked array of scaled R, Z, Lambda Fourier coefficients
49 
50  CALL second0(teqsolon)
51 
52  liter_flag = iter2 .eq. 1
53  1000 CONTINUE
54 
55  itfsq = 0
56  w1 = zero
57  r00s = zero
58 
59 !
60 ! COMPUTE INITIAL R, Z AND MAGNETIC FLUX PROFILES
61 !
62  20 CONTINUE
63 !
64 ! RECOMPUTE INITIAL PROFILE, BUT WITH IMPROVED AXIS/OR RESTART
65 ! FROM INITIAL PROFILE, BUT WITH A SMALLER TIME-STEP
66 !
67  IF (irst .EQ. 2) THEN
68 
69  IF (parvmec) THEN
70  CALL zerolastntype(pxc)
71  CALL profil3d_par(pxc(1), pxc(1+irzloff), lreset_internal,
72  & .false.)
73  ELSE
74  xc = 0
75  CALL profil3d(xc(1),xc(1+irzloff),lreset_internal,.false.)
76  END IF
77 
78  irst = 1
79  IF (liter_flag) CALL restart_iter(delt0r)
80  END IF
81 ! IF (liter_flag) CALL restart_iter(delt0r)
82  liter_flag = .true.
83  ier_flag = norm_term_flag
84 
85 !
86 ! FORCE ITERATION LOOP
87 !
88  iter_loop: DO WHILE (liter_flag)
89 !
90 ! ADVANCE FOURIER AMPLITUDES OF R, Z, AND LAMBDA
91 !
92  CALL evolve (delt0r, ier_flag, liter_flag, lscreen)
93 
94  IF (ijacob .eq. 0 .and.
95  & (ier_flag .eq. bad_jacobian_flag .or.
96  & irst .eq. 4) .and.
97  & ns .ge.3) THEN
98  IF (lscreen) THEN
99  IF (ier_flag .eq. bad_jacobian_flag) THEN
100  IF (rank.EQ.0) WRITE (*,50)
101  END IF
102  IF (rank.EQ.0) WRITE (*,51)
103  END IF
104 
105  50 FORMAT(' INITIAL JACOBIAN CHANGED SIGN!')
106  51 FORMAT(' TRYING TO IMPROVE INITIAL MAGNETIC AXIS GUESS')
107 
108  IF (parvmec) THEN
109  CALL guess_axis_par (pr1, pz1, pru0, pzu0, lscreen)
110  ELSE
111  CALL guess_axis (r1, z1, ru0, zu0)
112  ENDIF
113 
114  lreset_internal = .true.
115  ijacob = 1
116  irst = 2
117  GOTO 20
118  ELSE IF (ier_flag .NE. norm_term_flag .AND.
119  1 ier_flag .NE. successful_term_flag) THEN
120  RETURN
121  END IF
122 
123 #ifdef _ANIMEC
124  w0 = wb + wpar/(gamma-one)
125 #else
126  w0 = wb + wp/(gamma - one)
127 #endif
128 
129 !
130 ! ADDITIONAL STOPPING CRITERION (set liter_flag to FALSE)
131 !
132  IF (ijacob .eq. 25) THEN
133  irst = 2
134  CALL restart_iter(delt0r)
135 ! delt0r = p98*delt !changed in restart
136  IF (lscreen) print 120, delt0r
137  irst = 1
138  GOTO 1000
139  ELSE IF (ijacob .eq. 50) THEN
140  irst = 2
141  CALL restart_iter(delt0r)
142 ! delt0r = p96*delt
143  IF (lscreen) print 120, delt0r
144  irst = 1
145  GOTO 1000
146  ELSE IF (ijacob .ge. 75) THEN
147  ier_flag = jac75_flag
148  liter_flag = .false.
149  ELSE IF (iter2.ge.niter .and. liter_flag) THEN
150  ier_flag = more_iter_flag
151  liter_flag = .false.
152  END IF
153 
154 ! Store force residual, wdot for plotting
155  wdota = abs(w0 - w1)/w0
156 
157  CALL mpi_bcast(r00, 1, mpi_real8, 0, ns_comm, mpi_err)
158 
159  r0dot = abs(r00 - r00s)/r00
160  r00s = r00
161  w1 = w0
162  IF (ivac .eq. 1) THEN
163  IF (grank .EQ. 0) THEN
164  IF (lscreen) print 110, iter2
165  WRITE (nthreed, 110) iter2
166  END IF
167  ivac = ivac + 1
168  ENDIF
169 
170 ! NOTE: PRINTOUT clobbers gc!
171 ! Increment time step and printout every nstep iterations
172  IF (mod(iter2,nstep) .eq. 0 .or.
173  & iter2 .eq. 1 .or.
174  & .not.liter_flag) THEN
175  CALL printout(iter2, delt0r, w0, lscreen)
176  END IF
177  iter2 = iter2 + 1
178  iterc = iterc + 1
179 ! JDH 2012-06-20 ^^^ iterc is a cumulative iteration counter. Used in V3FIT.
180 ! Never reset to 1
181 
182 ! JDH 2010-08-03: Call to vmec_history_store moved here from evolve.f
183 ! Stores fsq values and other, for later post-processing
184  IF (.not.parvmec) THEN
185  CALL vmec_history_store(delt0r)
186  END IF
187  CALL flush(6)
188 !
189 ! STORE FSQ FOR PLOTTING. EVENTUALLY, STORE FOR EACH RADIAL MESH
190 !
191  IF (mod(iter2,niter/nstore_seq + 1) .eq. 0 .and.
192  & ns .eq. ns_array(multi_ns_grid)) THEN
193  IF (itfsq .lt. nstore_seq) THEN
194  itfsq = itfsq + 1
195  fsqt(itfsq) = fsqr + fsqz
196  wdot(itfsq) = max(wdota,c1pm13)
197  END IF
198  END IF
199  END DO iter_loop
200 
201 !SPH (021711): V3FITA - SAVE STATE FOR RESTART IF PRECONDITIONER IS ON
202 
203  IF (l_v3fit) THEN
204 
205 !JDH 2011-09-14. Correct logic error.
206 
207 ! IF (ictrl_prec2d .eq. 0) THEN
208 ! lqmr = (itype_precon .ge. 2)
209 ! ELSE
210  IF (ictrl_prec2d .gt. 0) THEN
211  CALL restart_iter(delt0r)
212  END IF
213  END IF
214 
215  IF (lswap2disk) CALL deletedafile(scratchfile)
216 
217  IF (grank .EQ. 0) THEN
218  WRITE (nthreed, 60) w0*twopi**2, wdota, r0dot
219  IF (lrecon) WRITE (nthreed, 70) r00*fsqsum0/wb
220  IF (nfcn .GT. 0) WRITE (nthreed, 80) nfcn
221  END IF
222 
223  CALL second0(teqsoloff)
224  eqsolve_time = eqsolve_time + (teqsoloff-teqsolon)
225 
226  60 FORMAT(/,' MHD Energy = ',1p,e12.6,3x, 'd(ln W)/dt = ',1p,e9.3,
227  & 3x,'d(ln R0)/dt = ',e9.3)
228  70 FORMAT(' Average radial force balance: Int[FR(m=0)]',
229  & '/Int(B**2/R) = ',1p,e12.5,' (should tend to zero)'/)
230  80 FORMAT(' Function calls in GMRES: ',i5)
231  110 FORMAT(/,2x,'VACUUM PRESSURE TURNED ON AT ',i4,' ITERATIONS'/)
232  120 FORMAT(2x,'HAVING A CONVERGENCE PROBLEM: RESETTING DELT TO ',f8.3,
233  & /,2x,'If this does NOT resolve the problem, try changing ',
234  & '(decrease OR increase) the value of DELT')
235 
236  END SUBROUTINE eqsolve