V3FIT
All Classes Namespaces Files Functions Variables Enumerations Macros Pages
vmec.f
1  PROGRAM vmec
2  USE vmec_input
3  USE vmec_seq
4  USE safe_open_mod
5 ! USE precon2d, ONLY: ScratchFile
6  USE vparams, ONLY: nlog, nlog0, nthreed
7  USE vmec_params, ONLY: more_iter_flag,
8  & bad_jacobian_flag,
9  & restart_flag, readin_flag, timestep_flag,
10  & output_flag, cleanup_flag,
11  & norm_term_flag, successful_term_flag ! J Geiger: for more iterations and full 3D1-output
12  USE parallel_include_module
13  USE parallel_vmec_module, ONLY: myenvvariables,
14  & initializeparallel,
15  & finalizeparallel
16  IMPLICIT NONE
17 C-----------------------------------------------
18 C L o c a l P a r a m e t e r s
19 C-----------------------------------------------
20  INTEGER, PARAMETER :: nseq0 = 12
21  CHARACTER(LEN=*), PARAMETER ::
22  & increase_niter = "Try increasing NITER",
23  & bad_jacobian = "The jacobian was non-definite!",
24  & full_3d1output_request = "Full threed1-output request!"
25 C-----------------------------------------------
26 C L o c a l V a r i a b l e s
27 C-----------------------------------------------
28  INTEGER :: numargs, ierr_vmec, index_end,
29  & iopen, isnml, iread, iseq, index_seq,
30  & index_dat, iunit, ncount, nsteps, i
31  INTEGER :: ictrl(5)
32  CHARACTER(LEN=120) :: input_file, seq_ext, reset_file_name, arg
33  CHARACTER(LEN=120) :: log_file
34  CHARACTER(LEN=120), DIMENSION(10) :: command_arg
35  LOGICAL :: lscreen
36  INTEGER :: RVC_COMM
37 
38  REAL(dp) :: ton, toff
39  REAL(dp) :: totalton, totaltoff
40 
41 C-----------------------------------------------
42 !***
43 ! D I S C L A I M E R
44 !
45 ! You are using a beta version of the PROGRAM VMEC, which is currently
46 ! under development by S. P. Hirshman at the Fusion Energy Division,
47 ! Oak Ridge National Laboratory. Please report any problems or comments
48 ! to him. As a beta version, this program is subject to change
49 ! and improvement without notice.
50 !
51 ! 1. CODE SYNOPSIS
52 !
53 ! THIS PROGRAM - VMEC (Variational Moments Equilibrium Code) -
54 ! SOLVES THREE-DIMENSIONAL MHD EQUILIBRIUM EQUATIONS USING
55 ! FOURIER SPECTRAL (MOMENTS) METHODS. A CYLINDRICAL COORDINATE
56 ! REPRESENTATION IS USED (R-Z COORDINATES). THE POLOIDAL
57 ! ANGLE VARIABLE IS RENORMALIZED THROUGH THE STREAM FUNCTION
58 ! LAMBDA, WHICH IS SELF-CONSISTENTLY DETERMINED AND DIFFERENCED
59 ! VARIATIONALLY ON THE HALF-RADIAL MESH. THE POLOIDAL ANGLE IS
60 ! DETERMINED BY MINIMIZING <M> = m**2 S(m) , WHERE S(m) =
61 ! Rm**2 + Zm**2 . AN EVEN-ODD DECOMPOSITION IN THE POLOIDAL MODE
62 ! NO. OF R,Z, AND LAMDA IS USED TO IMPROVE RADIAL RESOLUTION.
63 ! A FREE-BOUNDARY OPTION IS AVAILABLE (FOR lfreeb=T), WITH A
64 ! USER-SUPPLIED DATA-FILE "MGRID" NEEDED TO COMPUTE THE PLASMA
65 ! VACUUM FIELD COMPONENTS BR, BPHI, BZ (see SUBROUTINE BECOIL)
66 !
67 ! THE MAGNETIC FIELD IS REPRESENTED INTERNALLY AS FOLLOWS:
68 !
69 ! B(s,u,v) = grad(phiT) X ( grad(u) + grad(lambda) ) +
70 !
71 ! iota(s) * grad(v) X grad(phiT)
72 !
73 ! WHERE phiT is the toroidal flux (called phi in code) and
74 ! u,v are the poloidal, toroidal angles, respectively.
75 !
76 ! 2. ADDITIONAL CODES REQUIRED
77 ! For the fixed boundary calculation, the user must provide the Fourier
78 ! coefficients for the plasma boundary (the last surface outside of which
79 ! the pressure gradient vanishes). For ALL but the simplest geometry, the
80 ! SCRUNCH code (available from R. Wieland), based on the DESCUR curve-fitting
81 ! code, can be used to produce the optimized VMEC Fourier representation for
82 ! an arbritrary closed boundary (it need not be a 'star-like' DOmain, nor
83 ! need it possess vertical, or 'stellarator', symmetry).
84 !
85 ! For the free boundary calculation, the MAKEGRID code (available upon
86 ! request) is needed to create a binary Green''s FUNCTION table for the
87 ! vacuum magnetic field(s) and, IF data analysis is to be done, flux and
88 ! field loops as well. The user provides a SUBROUTINE (BFIELD) which can be
89 ! called at an arbitrary spatial location and which should RETURN the three
90 ! cylindrical components of the vacuum field at that point. (Similary,
91 ! locations of diagnostic flux loops, Rogowski coils, etc. are required IF
92 ! equilibrium reconstruction is to be done.)
93 !
94 ! Plotting is handled by a stand-alone package, PROUT.NCARG (written by
95 ! R. M. Wieland). It uses NCAR-graphics calls and reads the primary VMEC output
96 ! file, WOUT.EXT, WHERE 'EXT' is the command-line extension of the INPUT file.
97 !
98 !
99 ! 3. UNIX SCRIPT SETUP PARAMETERS
100 ! The VMEC source code (vmec.lsqh) is actually a UNIX script file which uses
101 ! the C-precompiler to produce both the machine-specific Fortran source and a
102 ! make-file specific to ANY one of the following platforms:
103 !
104 ! IBM-RISC6000, CRAY, ALPHA (DEC-STATION), HP-UX WORKSTATION,
105 ! WINDOWS-NT, DEC-VMS
106 !
107 ! Additional platforms are easy to add to the existing script as required.
108 !
109 !
110 ! 4. FORTRAN PARAMETER STATEMENTS set by user
111 ! In the Fortran-90 version of VMEC these PARAMETER statements have
112 ! been replaced by dynamic memory allocation. So the user should set the
113 ! run-time parameters ns (through ns_array), mpol, ntor in the NAMELIST INDATA.
114 !
115 !
116 ! Added features since last edition (see vmec_params for revision history list)
117 ! 1. Implemented preconditioning algorithm for R,Z
118 ! 2. The physical (unpreconditioned) residuals are used
119 ! to determine the level of convergence
120 ! 3. The original (MOMCON) scaling of lambda is used, i.e.,
121 ! Bsupu = phip*(iota - lamda[sub]v)/SQRT(g). This is needed to
122 ! maintain consistency with the time-stepper for arbitrary PHIP.
123 !
124 ! WRITTEN BY S. P. HIRSHMAN (8/28/85 - REVISED 3/1/86) BASED ON
125 ! 1. S. P. Hirshman and J. C. Whitson, Phys. Fluids 26, 3553 (1983).
126 ! 2. S. P. Hirshman and H. K. Meier, Phys. Fluids 28, 1387 (1985).
127 ! 3. S. P. Hirshman and D. K. Lee, Comp. Phys. Comm. 39, 161 (1986).
128 !
129 
130 ! Local variables
131 !
132 ! ictrl: array(5) of control variables for running "runvmec" routine
133 ! see "runvmec" for a description
134 !
135 
136 !
137 ! Read in command-line arguments to get input file or sequence file,
138 ! screen display information, and restart information
139 !
140  INTERFACE
141  SUBROUTINE runvmec(ictrl_array, input_file0,
142  & lscreen, RVC_COMM, reset_file_name)
143  IMPLICIT NONE
144  INTEGER, INTENT(inout), TARGET :: ictrl_array(5)
145  LOGICAL, INTENT(in) :: lscreen
146  CHARACTER(LEN=*), INTENT(in) :: input_file0
147  INTEGER, INTENT(in), OPTIONAL :: RVC_COMM
148  CHARACTER(LEN=*), OPTIONAL :: reset_file_name
149  END SUBROUTINE runvmec
150  END INTERFACE
151 
152  CALL myenvvariables
153  CALL initializeparallel
154  CALL mpi_comm_dup(mpi_comm_world,rvc_comm,mpi_err)
155  CALL second0(totalton)
156  ton = totalton
157 
158  CALL getcarg(1, command_arg(1), numargs)
159  DO iseq = 2, numargs
160  CALL getcarg(iseq, command_arg(iseq), numargs)
161  END DO
162 
163  CALL second0(toff)
164  get_args_time = get_args_time + (toff -ton)
165 
166  lscreen = .false.
167  IF(grank.EQ.0) lscreen = .true.
168  reset_file_name = " "
169 
170  IF (numargs .lt. 1) THEN
171  stop 'Invalid command line'
172  ELSE IF (command_arg(1).eq.'-h' .or. command_arg(1).eq.'/h') THEN
173  print *,
174  & ' ENTER INPUT FILE NAME OR INPUT-FILE SUFFIX ON COMMAND LINE'
175  print *
176  print *,' For example: '
177  print *,' xvmec input.tftr OR xvmec tftr ',
178  & 'OR xvmec ../input.tftr'
179  print *
180  print *,' Sequence files, containing a list of input files',
181  & ' are also allowed. For example: '
182  print *,' xvmec input.tftr_runs'
183  print *
184  print *,' Here, input.tftr_runs contains a &VSEQ namelist',
185  & ' entry'
186  print *
187  print *,' Additional (optional) command arguments are',
188  & ' allowed:'
189  print *
190  print *,' xvmec <filename> [noscreen] [reset=reset_wout_file]'
191  print *
192  print *,' noscreen: supresses all output to screen ',
193  & ' (default, or "screen", displays output)'
194  print *,' name of reset wout file (defaults to none)'
195 
196  stop
197  ELSE
198  DO iseq = 2, min(numargs,10)
199  arg = command_arg(iseq)
200  IF (trim(arg) .eq. 'noscreen' .or. &
201  & trim(arg) .eq. 'NOSCREEN') THEN
202  lscreen = .false.
203  END IF
204  index_end = index(arg, "reset=")
205  index_seq = max(index(arg, "RESET="), index_end)
206  IF (index_seq .gt. 0) reset_file_name = arg(index_seq+6:)
207  END DO
208  END IF
209 
210 !
211 ! Determine type of file opened (sequential or input-data)
212 ! ARG1 (char var)
213 ! By DEFAULT, ARG1 obtained from the command
214 ! line is parsed as follows to determine the input data file(s):
215 ! a. Attempt to OPEN file ARG1 (full path + file name).
216 ! Look for the VSEQ NAMELIST to obtain nseq, nseq_select, and
217 ! extension array. If they exist and nseq>0, VMEC will run
218 ! sequentially using input determined from the array EXTENSION[i]
219 ! or input.EXTENSION[i]
220 ! b. If the command argument is not a sequence NAMELIST, THEN the data file
221 ! ARG1 or input.ARG1 is READ directly, with NSEQ=1.
222 !
223  arg = command_arg(1)
224  index_dat = index(arg,'.')
225  index_end = len_trim(arg)
226  IF (index_dat .gt. 0) THEN
227  seq_ext = arg(index_dat + 1:index_end)
228  input_file = trim(arg)
229  ELSE
230  seq_ext = trim(arg)
231  input_file = 'input.'//trim(seq_ext)
232  END IF
233 
234  nseq = 1
235  nseq_select(1) = 1
236  extension(1) = input_file
237 !
238 ! READ IN NAMELIST VSEQ TO GET ARRAY
239 ! OF INPUT FILE EXTENSIONS AND INDEXING ARRAY, NSEQ_SELECT
240 !
241  nlog = nlog0
242  iunit = nseq0
243  DO iseq = 1, 2
244  IF (iseq .EQ. 1) THEN
245  arg = input_file
246  ELSE
247  arg = seq_ext
248  END IF
249  CALL second0(ton)
250  CALL safe_open(iunit, iopen, trim(arg), 'old', 'formatted')
251  CALL second0(toff)
252  safe_open_time = safe_open_time + (toff - ton)
253  IF (iopen .eq. 0) THEN
254  DO ncount = 1, nseqmax
255  nseq_select(ncount) = ncount
256  END DO
257  CALL second0(ton)
258 
259  CALL read_namelist (iunit, isnml, 'vseq')
260 
261  CALL second0(toff)
262  read_namelist_time = read_namelist_time + (toff - ton)
263 !
264 ! OPEN FILE FOR STORING SEQUENTIAL RUN HISTORY
265 !
266  IF (isnml .eq. 0) THEN
267  IF (nseq .gt. nseqmax) stop 'NSEQ>NSEQMAX'
268  log_file = 'log.'//seq_ext
269  CALL second0(ton)
270 
271  CALL safe_open(nlog, iread, log_file, 'replace',
272  & 'formatted')
273 
274  CALL second0(toff)
275  safe_open_time = safe_open_time + (toff - ton)
276 
277  IF (iread .NE. 0) THEN
278  print *, log_file,
279  & ' LOG FILE IS INACCESSIBLE: IOSTAT= ',iread
280  stop 3
281  ELSE
282  EXIT !!Break out of loop
283  END IF
284  END IF
285  END IF
286  CLOSE (iunit)
287  END DO
288 
289 !
290 ! CALL EQUILIBRIUM SOLVER
291 !
292 ! nseq_select: If sequence file (VSEQ NAMELIST given with nseq >0)
293 ! array giving indices into EXTENSION array prescribing
294 ! the order in which the input files are run by VMEC
295 ! nseq: number of sequential VMEC runs to make
296 !
297 !
298 ! CALL VMEC WITH POSSIBLE SEQUENCE EXTENSION (SEQ_EXT)
299 ! AND ARRAY OF INPUT FILE EXTENSIONS (EXTENSION)
300 !
301  ictrl = 0
302 
303 ! GOTO 200 !ENABLE THIS STATEMENT TO TEST REVERSE-COMMUNICATION STOP/RESTART CODING
304 
305  seq: DO iseq = 1, nseq
306  index_seq = nseq_select(iseq)
307  ictrl(1) = restart_flag + readin_flag + timestep_flag
308  & + output_flag + cleanup_flag !Sets all flags
309  ictrl(2) = 0
310 ! ictrl(3) = 100
311 ! ictrl(4) = 2
312  ictrl(5) = iseq - 1
313  ncount = 0
314  IF (iseq .GT. 1) THEN
315  reset_file_name =
316 #ifdef NETCDF
317  & 'wout_' // trim(extension(index_seq-1)) // ".nc"
318 #else
319  & 'wout.' // trim(extension(index_seq-1))
320  WRITE (*,*) 'WARNING: Text based wout files are no ' \\
321  & 'longer maintained and may be removed in ' \\
322  & 'the future.'
323 #endif
324  END IF
325 !
326 ! SET UP A "REVERSE-COMMUNICATION" LOOP FOR RUNNING VMEC
327 !
328 
329  100 CONTINUE
330 
331  rvccallnum = 1
332  CALL runvmec(ictrl, extension(index_seq), lscreen, rvc_comm,
333  & reset_file_name)
334 
335  ierr_vmec = ictrl(2)
336 
337  SELECT CASE (ierr_vmec)
338  CASE (more_iter_flag) !Need a few more iterations to converge
339  IF (grank .EQ. 0) THEN
340  IF(lscreen) WRITE (6, '(1x,a)') increase_niter
341  WRITE (nthreed, '(1x,a)') increase_niter
342  WRITE (nthreed, '(1x,a)') "PARVMEC aborting..."
343  CALL flush(nthreed)
344  END IF
345 ! J Geiger: if lmoreiter and lfull3d1out are false
346 ! the o-lines (original) are the only
347 ! ones to be executed.
348  IF (lmoreiter) THEN ! J Geiger: --start--
349  DO i = 2, max_main_iterations ! Changes to run
350  ictrl(1) = timestep_flag ! some more iterations if requested
351  ictrl(3) = niter ! - this is the number of iterations
352  rvccallnum = 2
353  CALL runvmec(ictrl, extension(1), lscreen,
354  & rvc_comm, reset_file_name) ! - the second iteration run with ictrl(3) iterations
355  IF (ictrl(2) .EQ. more_iter_flag .and.
356  & grank .EQ. 0) THEN
357  WRITE (nthreed, '(1x,a)') increase_niter
358  IF(lscreen) WRITE (6, '(1x,a)') increase_niter
359  END IF
360  END DO
361  ictrl(1) = output_flag + cleanup_flag ! - Output, cleanup
362  IF (ictrl(2) .ne. successful_term_flag) THEN
363  ictrl(2)=successful_term_flag ! - force success flag to get full threed1-output!
364  END IF
365  ictrl(3) = 0 ! - this is the number of iterations
366  rvccallnum = 3
367  CALL runvmec(ictrl, extension(1), lscreen, rvc_comm,
368  & reset_file_name)
369  ELSE ! else-branch contains original code.
370 #if defined(MPI_OPT)
371  CALL mpi_barrier(rvc_comm, mpi_err)
372 #endif
373 
374  ictrl(1) = output_flag + cleanup_flag !Output, cleanup ! o-lines
375  ictrl(2) = 0 ! o-lines
376  IF (lfull3d1out) THEN
377  ictrl(2) = successful_term_flag
378  IF (grank .EQ. 0) THEN
379  WRITE(6,'(1x,a)') full_3d1output_request
380  WRITE(nthreed,'(1x,a)') full_3d1output_request
381  END IF
382  END IF
383 
384  rvctrigger = .true.
385  rvccallnum = 4
386  CALL runvmec(ictrl, extension(1), lscreen, rvc_comm, ! o-lines
387  & reset_file_name)
388  rvctrigger = .false.
389  END IF ! J Geiger: -- end --
390 
391  CASE (bad_jacobian_flag) !Bad jacobian even after axis reset and ns->3
392  IF (grank .EQ. 0) THEN
393  IF (lscreen) WRITE (6, '(/,1x,a)') bad_jacobian
394  WRITE (nthreed, '(/,1x,a)') bad_jacobian
395  END IF
396  CASE DEFAULT
397  END SELECT
398  END DO seq
399 
400  GOTO 300
401 
402 !REVERSE-COMMUNICATION TEST LOOP: SHOULD BE OFF FOR NORMAL VMEC2000 RUN
403 !ONLY SHOWS HOW TO IMPLEMENT EXTERNAL STOP/START OF VMEC
404  200 CONTINUE
405 
406  nsteps = 50
407  ictrl(1) = restart_flag + readin_flag !Initialization only
408  ictrl(3) = nsteps
409  ictrl(4) = 1 !Go to fine grid directly (assumes it is grid index=1)
410  rvccallnum = 5
411  CALL runvmec(ictrl, extension(1), lscreen, rvc_comm,
412  & reset_file_name)
413 
414  ictrl(1) = timestep_flag + output_flag !Set timestep flag (output_flag, too, if wout needed)
415  ictrl(1) = timestep_flag !Set timestep flag (output_flag, too, if wout needed)
416 
417  DO iopen = 1, 3 !Scan through grids (3, for this example)
418  ictrl(4) = iopen
419  DO ncount = 1, max(1,niter/nsteps)
420  rvccallnum=6
421  CALL runvmec(ictrl, extension(1), lscreen, rvc_comm,
422  & reset_file_name)
423  print *,' BREAK HERE'
424  ierr_vmec = ictrl(2)
425  IF (ierr_vmec .ne. more_iter_flag) EXIT
426  END DO
427  END DO
428 
429  ictrl(1) = output_flag+cleanup_flag !Output, cleanup
430  rvccallnum = 7
431  CALL runvmec(ictrl, extension(1), lscreen, rvc_comm,
432  & reset_file_name)
433 
434  300 CONTINUE
435 
436  CLOSE (nlog)
437 
438  CALL second0(totaltoff)
439  total_time = total_time + (totaltoff - totalton)
440  toff = totaltoff
441  IF (.NOT.lv3fitcall .AND. lactive) CALL writetimes('timings.txt')
442  CALL finalizeparallel
443 
444  END PROGRAM vmec