PB3D [2.47]
Ideal linear high-n MHD stability in 3-D
Loading...
Searching...
No Matches
driver_POST.f90
Go to the documentation of this file.
1!------------------------------------------------------------------------------!
2!> Main driver of PostProcessing of program Peeling Ballooning in 3D.
3!------------------------------------------------------------------------------!
5#include <PB3D_macros.h>
6#include <wrappers.h>
8 use output_ops
9 use messages
10 use num_vars, only: max_str_ln, dp, iu, pi
11 use grid_vars, only: grid_type
12 use eq_vars, only: eq_1_type, eq_2_type
13 use x_vars, only: x_1_type, modes_type, &
15 use sol_vars, only: sol_type
16 use vac_vars, only: vac_type
17 use rich_vars, only: rich_lvl
18
19 implicit none
20 private
22
23 ! local variables
24 integer :: lims_norm(2,3) !< normal \c i_limit of eq, X and sol variables
25 integer, allocatable :: dum_ser(:) !< serial dummy variable
26 integer :: rich_lvl_name !< either the Richardson level or zero, to append to names
27 integer :: min_id(3), max_id(3) !< min. and max. index of range 1, 2 and 3
28 integer :: last_unstable_id !< index of last unstable EV
29 integer :: n_par_tot !< total \c n(1) for all equilibrium jobs together
30 character(len=4) :: grid_name(3) !< names of grids
31 integer :: n_out(3,2) !< total grid sizes for eq and X grids
32 type(sol_type) :: sol !< solution variables
33 type(vac_type) :: vac !< vacuum variables
34 type(grid_type) :: grid_eq_XYZ !< eq grid for XYZ calculations
35 type(grid_type) :: grid_eq_HEL !< HELENA eq grid
36 type(grid_type) :: grid_X_HEL !< HELENA X grid
37 type(eq_2_type) :: eq_2_HEL !< metric equilibrium for HELENA tables
38 type(X_1_type) :: X_HEL !< vectorial perturbation variables for HELENA tables
39 complex(dp), allocatable :: E_pot_int(:,:) !< \f$\int E_{\text{pot}} \text{d}V\f$ for requested solutions
40 complex(dp), allocatable :: E_kin_int(:,:) !< \f$\int E_{\text{kin}} \text{d}V\f$ for requested solutions
41#if ldebug
42 logical :: debug_tor_dep_ripple = .false. !< plot debug information for toroidal dependency of ripple \ldebug
43#endif
44
45contains
46 !> Initializes the POST driver.
47 !!
48 !! - set up preliminary variables
49 !! * global variables
50 !! * read grids (full)
51 !! * \c eq_1 (full) and \c n \& \c m (full)
52 !! - set up output grids:
53 !! * <tt> POST_style = 1</tt>: extended grid
54 !! * <tt> POST_style = 2</tt>: field-aligned grid
55 !! - clean up
56 !! - set up final variables
57 !! * normal limits
58 !! * read grids (divided), \c eq_1 (divided) and \c sol (divided)
59 !! variables
60 !! - 1-D output plots
61 !! * resonance plot
62 !! * flux quantities plot
63 !! * magnetic grid plot
64 !! - prepare Eigenvalue plots
65 !! * calculates resonant surfaces
66 !! * plots Eigenvalues
67 !! * finds stability ranges for all Eigenvalues to be plot
68 !! * plots harmonics for every Eigenvalue
69 !! * calculates the parallel ranges of the equilibrium jobs
70 !! - clean up
71 !!
72 !! In the actual driver, more detailed plots are possibly made for all
73 !! requested Eigenvalues if \c full_output.
74 !!
75 !! \return ierr
76 integer function init_post() result(ierr)
89 use vac_ops, only: vac_pot_plot
93 use helena_vars, only: nchi
96
97 character(*), parameter :: rout_name = 'init_POST'
98
99 ! local variables
100 type(grid_type), target :: grid_eq ! equilibrium grid
101 type(grid_type), pointer :: grid_eq_b ! field-aligned equilibrium grid
102 type(grid_type) :: grid_x ! perturbation grid
103 type(grid_type) :: grid_sol ! solution grid
104 type(eq_1_type) :: eq_1 ! flux equilibrium
105 integer :: n_div ! number of divisions of parallel points
106 integer :: id, jd ! counters
107 integer :: var_size_without_par(2) ! size without parallel dimension for eq_2 and X_1 variables
108 integer :: lim_loc(3,2) ! grid ranges for local equilibrium job
109 integer :: n_div_max ! maximum divisions of equilibrium jobs
110 real(dp), allocatable :: res_surf(:,:) ! resonant surfaces
111 real(dp), allocatable :: r_f_x(:) ! normal points in perturbation grid
112 character(len=max_str_ln) :: err_msg ! error message
113
114 ! initialize ierr
115 ierr = 0
116
117 ! user output
118 select case (post_style)
119 case (1) ! extended grid
120 call writo('The post-processing will be done in an extended &
121 &grid')
122 call lvl_ud(1)
123 call writo('range in r: '//trim(r2strt(min_r_plot))//' .. '//&
124 &trim(r2strt(max_r_plot)))
125 call writo('range in θ: '//trim(r2strt(min_theta_plot))//&
126 &' .. '//trim(r2strt(max_theta_plot))//', '//&
127 &trim(i2str(n_theta_plot))//' points')
128 call writo('range in ζ: '//trim(r2strt(min_zeta_plot))//&
129 &' .. '//trim(r2strt(max_zeta_plot))//', '//&
130 &trim(i2str(n_zeta_plot))//' points')
131 call lvl_ud(-1)
132 case (2) ! field-aligned grid
133 call writo('The post-processing will be done in the PB3D grid')
134 call lvl_ud(1)
135 call writo('range in r: '//trim(r2strt(min_r_plot))//' .. '//&
136 &trim(r2strt(max_r_plot)))
137 call lvl_ud(-1)
138 end select
139
140 ! user output
141 call writo('Setting up preliminary variables')
142 call lvl_ud(1)
143
144 ! some preliminary things
145 ierr = reconstruct_pb3d_in('in') ! reconstruct miscellaneous PB3D output variables
146 chckerr('')
147
148 ! set up alpha
149 allocate(alpha(n_alpha))
150 ierr = calc_eqd_grid(alpha,min_alpha*pi,max_alpha*pi,excl_last=.true.)
151 chckerr('')
152
153 ! set up whether Richardson level has to be appended to the name
154 select case (eq_style)
155 case (1) ! VMEC
156 rich_lvl_name = rich_lvl ! append richardson level
157 case (2) ! HELENA
158 rich_lvl_name = 0 ! do not append name
159 end select
160
161 ! set up grid names
162 select case (eq_style)
163 case (1) ! VMEC
164 ! take the standard grids
165 grid_name(1) = 'eq'
166 grid_name(2) = 'X'
167 grid_name(3) = 'sol'
168 case (2) ! HELENA
169 ! take the field-aligned grids
170 grid_name(1) = 'eq_B'
171 grid_name(2) = 'X_B'
172 grid_name(3) = 'sol'
173 end select
174
175 ! limits to exclude angular part
176 lim_loc(1,:) = [0,0]
177 lim_loc(2,:) = [0,0]
178 lim_loc(3,:) = [1,-1]
179
180 ! reconstruct normal part of full equilibrium, perturbation and solution
181 ! grids
182 ierr = reconstruct_pb3d_grid(grid_eq,'eq',rich_lvl=rich_lvl_name,&
183 &tot_rich=.true.,lim_pos=lim_loc)
184 chckerr('')
185 ierr = reconstruct_pb3d_grid(grid_x,'X',rich_lvl=rich_lvl_name,&
186 &tot_rich=.true.,lim_pos=lim_loc)
187 chckerr('')
188 ierr = reconstruct_pb3d_grid(grid_sol,'sol')
189 chckerr('')
190
191 ! set up modes variables in full grids
192 ! Note: This is needed as many routines count on this, for example
193 ! 'set_nm_X' in X_vars, also used to initialize a solution variable,
194 ! etc.
195 ierr = reconstruct_pb3d_eq_1(grid_eq,eq_1,'eq_1')
196 chckerr('')
197 ierr = init_modes(grid_eq,eq_1)
198 chckerr('')
199 ierr = setup_modes(mds_x,grid_eq,grid_x,plot_name='X_POST')
200 chckerr('')
201 ierr = setup_modes(mds_sol,grid_eq,grid_sol,plot_name='sol_POST')
202 chckerr('')
203
204 ! user output
205 call lvl_ud(-1)
206 call writo('Preliminary variables set up')
207
208 ! user output
209 call writo('Dividing grids over MPI processes')
210 call lvl_ud(1)
211
212 ! set eq, X and sol limits, using r_F of the grids
213 allocate(r_f_x(grid_x%n(3))) ! r_F_X needs to be allocatable for calc_norm_range
214 r_f_x = grid_x%r_F
215 ierr = calc_norm_range('POST',eq_limits=lims_norm(:,1),&
216 &x_limits=lims_norm(:,2),sol_limits=lims_norm(:,3),&
217 &r_f_eq=grid_eq%r_F,r_f_x=r_f_x,r_f_sol=grid_sol%r_F)
218 chckerr('')
219 deallocate(r_f_x)
220 call writo('normal grid limits:')
221 call lvl_ud(1)
222 call writo('proc '//trim(i2str(rank))//' - equilibrium: '//&
223 &trim(i2str(lims_norm(1,1)))//' .. '//trim(i2str(lims_norm(2,1))),&
224 &persistent=.true.)
225 call writo('proc '//trim(i2str(rank))//' - perturbation: '//&
226 &trim(i2str(lims_norm(1,2)))//' .. '//trim(i2str(lims_norm(2,2))),&
227 &persistent=.true.)
228 call writo('proc '//trim(i2str(rank))//' - solution: '//&
229 &trim(i2str(lims_norm(1,3)))//' .. '//trim(i2str(lims_norm(2,3))),&
230 &persistent=.true.)
231 call lvl_ud(-1)
232
233 ! synchronize outputs
234 ierr = wait_mpi()
235 chckerr('')
236
237 ! user output
238 call lvl_ud(-1)
239 call writo('Grids divided over MPI processes')
240
241 ! clean up
242 call grid_eq%dealloc()
243 call grid_x%dealloc()
244 call grid_sol%dealloc()
245 call eq_1%dealloc()
246
247 ! user output
248 call writo('Setting up final variables')
249 call lvl_ud(1)
250
251 ! reconstruct variables
252 ierr = reconstruct_pb3d_grid(grid_eq,'eq',rich_lvl=rich_lvl_name,&
253 &tot_rich=.true.,grid_limits=lims_norm(:,1))
254 chckerr('')
255 ierr = reconstruct_pb3d_grid(grid_x,'X',rich_lvl=rich_lvl_name,&
256 &tot_rich=.true.,grid_limits=lims_norm(:,2))
257 chckerr('')
258 ierr = reconstruct_pb3d_grid(grid_sol,'sol',grid_limits=lims_norm(:,3))
259 chckerr('')
260 ierr = reconstruct_pb3d_eq_1(grid_eq,eq_1,'eq_1')
261 chckerr('')
262 if (post_output_sol) then
263 ierr = reconstruct_pb3d_sol(mds_sol,grid_sol,sol,'sol',&
265 chckerr('')
266 ierr = 2
267 chckerr('Vacuum has not been implemented yet!')
268 ierr = reconstruct_pb3d_vac(vac,'vac',rich_lvl=rich_lvl_name)
269 chckerr('')
270 end if
271
272 ! user output
273 call lvl_ud(-1)
274 call writo('Final variables set up')
275
276 ! user output
277 call writo('1-D PB3D output plots')
278 call lvl_ud(1)
279
280 if (plot_resonance) then
281 ierr = resonance_plot(mds_sol,grid_eq,eq_1)
282 chckerr('')
283 else
284 call writo('Resonance plot not requested')
285 end if
286 if (plot_flux_q) then
287 ierr = flux_q_plot(grid_eq,eq_1)
288 chckerr('')
289 else
290 call writo('Flux quantities plot not requested')
291 end if
292 if (plot_magn_grid) then
293 select case (eq_style)
294 case (1) ! VMEC
295 grid_eq_b => grid_eq
296 case (2) ! HELENA
297 allocate(grid_eq_b)
298 ierr = reconstruct_pb3d_grid(grid_eq_b,'eq_B',&
299 &rich_lvl=rich_lvl,tot_rich=.true.,&
300 &grid_limits=lims_norm(:,1))
301 chckerr('')
302 end select
303 ierr = magn_grid_plot(grid_eq_b)
304 chckerr('')
305 if (eq_style.eq.2) then
306 call grid_eq_b%dealloc()
307 deallocate(grid_eq_b)
308 end if
309 nullify(grid_eq_b)
310 else
311 call writo('Magnetic grid plot not requested')
312 end if
313
314 ierr = wait_mpi()
315 chckerr('')
316
317 ! user output
318 call lvl_ud(-1)
319 call writo('1-D outputs plots done')
320
321 ! user output
322 call writo('Prepare 3-D plots')
323 call lvl_ud(1)
324
325 ! calculate resonant surfaces on solution grid
326 call writo('Calculate resonant surfaces')
327 call lvl_ud(1)
328 ierr = calc_res_surf(mds_sol,grid_eq,eq_1,res_surf,info=.false.)
329 call lvl_ud(-1)
330
331 ! plot solution on solution grid
332 if (post_output_sol) then
333 call writo('Plot the Eigenvalues')
334 call lvl_ud(1)
335 call plot_sol_vals(sol,last_unstable_id)
336 call lvl_ud(-1)
337
338 ! find stability regions
339 call writo('Find stability ranges')
340 call lvl_ud(1)
341 call find_stab_ranges(sol,min_id,max_id,last_unstable_id)
342 call lvl_ud(-1)
343
344 ! plots harmonics for every Eigenvalue, looping over three ranges
345 call writo('Plot the Harmonics')
346 call lvl_ud(1)
347 do jd = 1,3
348 if (min_id(jd).le.max_id(jd)) call &
349 &writo('RANGE '//trim(i2str(jd))//': modes '//&
350 &trim(i2str(min_id(jd)))//'..'//trim(i2str(max_id(jd))))
351 call lvl_ud(1)
352
353 ! indices in each range
354 do id = min_id(jd),max_id(jd)
355 ! user output
356 call writo('Mode '//trim(i2str(id))//'/'//&
357 &trim(i2str(size(sol%val)))//', with eigenvalue '&
358 &//trim(c2strt(sol%val(id))))
359 call lvl_ud(1)
360 ierr = plot_harmonics(mds_sol,grid_sol,sol,id,res_surf)
361 chckerr('')
362
363 ! user output
364 call lvl_ud(-1)
365 call writo('Mode '//trim(i2str(id))//'/'//&
366 &trim(i2str(size(sol%val)))//' finished')
367
368 ! vacuum plots if requested
369 write(*,*) '¡¡¡¡¡ NO VACUUM !!!!!'
370 plot_vac_pot = .false.
371 if (plot_vac_pot) then
372 ! user output
373 call writo('Start vacuum plot for this solution')
374 call lvl_ud(1)
375
376 ! plot vacuum potential
377 ierr = vac_pot_plot(grid_sol,vac,sol,id)
378 chckerr('')
379
380 ! user output
381 call lvl_ud(-1)
382 call writo('Done with vacuum plot')
383 end if
384 end do
385
386 call lvl_ud(-1)
387 if (min_id(jd).le.max_id(jd)) call &
388 &writo('RANGE '//trim(i2str(jd))//' plotted')
389 end do
390 call lvl_ud(-1)
391 end if
392
393 ! Divide the equilibrium jobs (see subroutine "calc_memory" inside
394 ! "divide_eq_jobs"), only necessary when full output.
395 ! The results are saved in the global variables eq_jobs_lims for every
396 ! eq_job.
397 ! If full output not requested, allocate eq_jobs_lims to zero size, so
398 ! that the driver is never run.
399 if (post_output_full) then
400 ! set total grid sizes
401 do id = 1,2
402 ierr = get_pb3d_grid_size(n_out(:,id),grid_name(id),&
403 &rich_lvl=rich_lvl,tot_rich=.true.)
404 chckerr('')
405 if (post_style.eq.1) n_out(1:2,id) = [n_theta_plot,n_zeta_plot]
406 end do
407
408 ! test if angular grid sizes are compatible
409 if (n_out(1,1).ne.n_out(1,2) .or. n_out(2,1).ne.n_out(2,2)) then
410 ierr = 1
411 call writo('grid sizes for output grids not compatible. This &
412 &is assumed in the calculation of the equilibrium jobs.')
413 call writo('If this has changed, adapt and generalize &
414 &"divide_eq_jobs" appropriately.')
415 err_msg = 'Take into account how the ranges transfer from &
416 &grid to grid'
417 chckerr(err_msg)
418 end if
419
420 ! set size of all variables, without parallel dimension
421 allocate(dum_ser(2*n_procs))
422 ierr = get_ser_var(lims_norm(:,1),dum_ser,scatter=.true.) ! normal limits of equilibrium grid
423 chckerr('')
424 var_size_without_par(1) = dum_ser(2*n_procs)-dum_ser(1)+1 ! maximum range
425 ierr = get_ser_var(lims_norm(:,2),dum_ser,scatter=.true.) ! normal limits of perturbation grid
426 chckerr('')
427 var_size_without_par(2) = dum_ser(2*n_procs)-dum_ser(1)+1 ! maximum range
428 select case (x_grid_style)
429 case (1,3) ! equilibrium or enriched
430 var_size_without_par(2) = var_size_without_par(2) + n_r_sol
431 case (2) ! solution
432 ! do nothing
433 end select
434 deallocate(dum_ser)
435
436 n_div_max = n_out(1,1)-1
437 if (compare_tor_pos) n_div_max = 1
438 select case (eq_style)
439 case (1) ! VMEC
440 ! divide equilibrium jobs
441 ierr = divide_eq_jobs(product(n_out(1:2,1)),&
442 &var_size_without_par,n_div,n_div_max=n_div_max)
443 chckerr('')
444 case (2) ! HELENA
445 ! divide equilibrium jobs
446 ierr = divide_eq_jobs(product(n_out(1:2,1)),&
447 &var_size_without_par,n_div,n_div_max=n_div_max,&
448 &n_par_x_base=nchi)
449 chckerr('')
450 end select
451
452 ! calculate equilibrium job limits
453 ierr = calc_eq_jobs_lims(n_out(1,1),n_div)
454 chckerr('')
455
456 ! set up total number of parallel points
457 n_par_tot = maxval(eq_jobs_lims(2,:))-minval(eq_jobs_lims(1,:))+1
458 else
459 allocate(eq_jobs_lims(2,0))
460 end if
461
462 ! Calculate variables on HELENA output grid if full output and HELENA
463 ! for later interpolation
464 if (post_output_full .and. eq_style.eq.2) then
465 ! user output
466 call writo('Reconstructing HELENA output for later interpolation')
467 call lvl_ud(1)
468
469 ierr = reconstruct_pb3d_grid(grid_eq_hel,'eq',&
470 &grid_limits=lims_norm(:,1))
471 chckerr('')
472 ierr = reconstruct_pb3d_grid(grid_x_hel,'X',&
473 &grid_limits=lims_norm(:,2))
474 chckerr('')
475 ierr = reconstruct_pb3d_eq_2(grid_eq_hel,eq_2_hel,'eq_2')
476 chckerr('')
477 ierr = reconstruct_pb3d_x_1(mds_x,grid_x_hel,x_hel,'X_1')
478 chckerr('')
479
480 ! user output
481 call lvl_ud(-1)
482 call writo('HELENA output reconstructed for later interpolation')
483 end if
484
485 ! reconstruct normal part of full eq grid for XYZ reconstruction
486 if (post_output_full .and. plot_grid_style.eq.0 .or. &
487 &plot_grid_style.eq.3) then
488 ! user output
489 call writo('Reconstructing full eq grid for XYZ reconstruction')
490 call lvl_ud(1)
491
492 ierr = reconstruct_pb3d_grid(grid_eq_xyz,'eq',&
493 &rich_lvl=rich_lvl_name,tot_rich=.true.,lim_pos=lim_loc)
494 chckerr('')
495
496 ! user output
497 call lvl_ud(-1)
498 call writo('Full eq grid reconstructed for XYZ reconstruction')
499 end if
500
501 ! user output
502 call lvl_ud(-1)
503 call writo('3-D plots prepared')
504
505 ! clean up
506 call grid_eq%dealloc()
507 call grid_x%dealloc()
508 call grid_sol%dealloc()
509 call eq_1%dealloc()
510 end function init_post
511
512 !> The main driver routine for postprocessing.
513 !!
514 !! \note The PB3D output is given on different grids for different styles of
515 !! the equilibrium model:
516 !! - VMEC: field-aligned grid on which EV problem has been solved.
517 !! - HELENA: output grid on which equilibrium and metric variables are
518 !! tabulated.
519 !!
520 !! Furthermore, if Richardson extrapolation is used, the VMEC grids and
521 !! variables are contained in multiple HDF5 variables.
522 !! These variables are needed here both in a field-aligned and a plot grid.
523 !!
524 !! A consequence of the above is that for VMEC the field-aligned output is
525 !! already given, but the output on the plot grid has to be calculated from
526 !! scratch, while for HELENA both outputs have to be interpolated from the
527 !! output tables.
528 !!
529 !! The general workflow is as follows:
530 !! - take a subset of the output grids for the current equilibrium job.
531 !! - for <tt>POST_style = 1</tt> (extended grid):
532 !! * VMEC: recalculate variables
533 !! * HEL: interpolate variables
534 !! for <tt>POST_style = 2</tt> (B-aligned grid):
535 !! * VMEC: read subset of variables
536 !! * HEL: interpolate variables
537 !! - create helper variables
538 !! - create plots and outputs
539 !!
540 !! \return ierr
541 integer function run_driver_post() result(ierr)
547 use eq_ops, only: calc_eq, calc_t_hf, b_plot, j_plot, &
549 use eq_utilities, only: calc_inv_met
550 use x_ops, only: calc_x
554#if ldebug
555 use num_vars, only: ltest
556#endif
557
558 character(*), parameter :: rout_name = 'run_driver_POST'
559
560 ! local variables
561 type(grid_type) :: grids(3) ! local output eq, X and sol grid, with limited parallel range and divided normal range
562 type(eq_1_type) :: eq_1 ! flux equilibrium
563 type(eq_2_type) :: eq_2 ! metric equilibrium
564 type(x_1_type) :: x ! vectorial perturbation variables
565 integer :: id, jd ! counter
566 integer :: n_ev_out ! how many EV's are treated
567 integer :: i_ev_out ! counter
568 logical :: no_plots_loc ! local copy of no_plots
569 logical :: no_output_loc ! local copy of no_output
570 logical :: last_eq_job ! last parallel job
571 real(dp), allocatable :: xyz_eq(:,:,:,:) ! X, Y and Z on equilibrium output grid
572 real(dp), allocatable :: xyz_sol(:,:,:,:) ! X, Y and Z on solution output grid
573 complex(dp), allocatable :: sol_val_comp(:,:,:) ! solution eigenvalue for requested solutions
574#if ldebug
575 logical :: ltest_loc ! local copy of ltest
576#endif
577
578 ! initialize ierr
579 ierr = 0
580
581 ! user output
582 call writo('Parallel range for this job:')
583 call lvl_ud(1)
584 call writo(trim(i2str(eq_jobs_lims(1,eq_job_nr)))//'..'//&
585 &trim(i2str(eq_jobs_lims(2,eq_job_nr)))//' of '//'1..'//&
586 &trim(i2str(n_par_tot)))
587 call lvl_ud(-1)
588
589 ! some variables
590 last_eq_job = eq_job_nr.eq.size(eq_jobs_lims,2)
591 n_ev_out = sum(max_id-min_id+1)
592
593 ! set up restricted output grids for this equilibrium job
594 ierr = setup_out_grids(grids,xyz_eq,xyz_sol)
595 chckerr('')
596
597 ! set up output eq_1, eq_2 and X_1, depending on equilibrium style
598 ierr = calc_eq(grids(1),eq_1)
599 chckerr('')
600 select case (eq_style)
601 case (1) ! VMEC
602 ! user output
603 call writo('Calculate variables on output grid')
604 call lvl_ud(1)
605
606 ! back up no_plots and no_output and set to .true.
607 no_plots_loc = no_plots; no_plots = .true.
608 no_output_loc = no_output; no_output = .true.
609#if ldebug
610 ltest_loc = ltest; ltest = .false.
611#endif
612
613 ! Calculate the metric equilibrium quantitities
614 ierr = calc_eq(grids(1),eq_1,eq_2)
615 chckerr('')
616
617 ! calculate X variables, vector phase
618 ierr = calc_x(mds_x,grids(1),grids(2),eq_1,eq_2,x)
619 chckerr('')
620
621 ! reset no_plots and no_output
622 no_plots = no_plots_loc
623 no_output = no_output_loc
624#if ldebug
625 ltest = ltest_loc
626#endif
627
628 ! user output
629 call lvl_ud(-1)
630 call writo('Variables calculated on output grid')
631 case (2) ! HELENA
632 ! user output
633 call writo('Interpolate variables angularly on output grid')
634 call lvl_ud(1)
635
636 call eq_2%init(grids(1),setup_e=.true.,setup_f=.true.)
637 call x%init(mds_x,grids(2))
638 ierr = interp_hel_on_grid(grid_eq_hel,grids(1),&
639 &eq_2=eq_2_hel,eq_2_out=eq_2,eq_1=eq_1,&
640 &grid_name='output equilibrium grid')
641 chckerr('')
642 ierr = interp_hel_on_grid(grid_x_hel,grids(2),x_1=x_hel,&
643 &x_1_out=x,grid_name='output perturbation grid')
644 chckerr('')
645
646 ! also set up transformation matrices for plots
647 ierr = calc_t_hf(grids(1),eq_1,eq_2,[0,0,0])
648 chckerr('')
649 ierr = calc_inv_met(eq_2%T_FE,eq_2%T_EF,[0,0,0])
650 chckerr('')
651
652 ! user output
653 call lvl_ud(-1)
654 call writo('Variables interpolated angularly on output grid')
655 end select
656
657 ! user output
658 call writo('Initialize 3-D plots')
659 call lvl_ud(1)
660
661 ! initialize integrated energies and open decompose log file if first
662 ! equilibrium job and energy reconstruction requested
663 if (plot_e_rec .and. eq_job_nr.eq.1) then
664 allocate(e_pot_int(7,n_ev_out))
665 allocate(e_kin_int(2,n_ev_out))
666 e_pot_int = 0._dp
667 e_kin_int = 0._dp
668
669 ierr = open_decomp_log()
670 chckerr('')
671 end if
672
673 ! user output
674 call lvl_ud(-1)
675 call writo('3-D plots initialized')
676
677 ! user output
678 call writo('3-D PB3D output plots')
679 call lvl_ud(1)
680
681 ! plot displacement vector if comparing toroidal positions
682 if (compare_tor_pos) then
683 call writo('Plot the displacement vector')
684 call lvl_ud(1)
685 ierr = delta_r_plot(grids(1),eq_1,eq_2,xyz_eq)
686 chckerr('')
687 call lvl_ud(-1)
688 end if
689
690 ! plot magnetic field if requested
691 if (plot_b) then
692 call writo('Plot the magnetic field')
693 call lvl_ud(1)
694 ierr = b_plot(grids(1),eq_1,eq_2,plot_fluxes=post_style.eq.1,&
695 &xyz=xyz_eq)
696 chckerr('')
697 call lvl_ud(-1)
698 end if
699
700 ! plot current if requested
701 if (plot_j) then
702 call writo('Plot the current')
703 call lvl_ud(1)
704 ierr = j_plot(grids(1),eq_1,eq_2,plot_fluxes=post_style.eq.1,&
705 &xyz=xyz_eq)
706 chckerr('')
707 call lvl_ud(-1)
708 end if
709
710 ! plot magnetic field if requested
711 if (plot_kappa) then
712 call writo('Plot the curvature')
713 call lvl_ud(1)
714 ierr = kappa_plot(grids(1),eq_1,eq_2,xyz=xyz_eq)
715 chckerr('')
716 call lvl_ud(-1)
717 end if
718
719 if (post_output_sol) then
720 ! user output
721 call writo('Solution plots for different ranges')
722 call lvl_ud(1)
723
724 ! loop over three ranges
725 i_ev_out = 1
726 if (last_eq_job) allocate(sol_val_comp(2,2,n_ev_out))
727 do jd = 1,3
728 if (min_id(jd).le.max_id(jd)) call &
729 &writo('RANGE '//trim(i2str(jd))//': modes '//&
730 &trim(i2str(min_id(jd)))//'..'//trim(i2str(max_id(jd))))
731 call lvl_ud(1)
732
733 ! indices in each range
734 do id = min_id(jd),max_id(jd)
735 ! user output
736 call writo('Mode '//trim(i2str(id))//'/'//&
737 &trim(i2str(size(sol%val)))//', with eigenvalue '&
738 &//trim(c2strt(sol%val(id))))
739 call lvl_ud(1)
740
741 ! plot solution vector
742 ierr = plot_sol_vec(mds_x,mds_sol,grids(1),grids(2),&
743 &grids(3),eq_1,eq_2,x,sol,xyz_sol,id,&
745 chckerr('')
746
747 if (plot_e_rec) then
748 ! user output
749 call writo('Decompose the energy into its terms')
750 call lvl_ud(1)
751 ierr = decompose_energy(mds_x,mds_sol,grids(1),grids(2),&
752 &grids(3),eq_1,eq_2,x,sol,vac,id,&
753 &b_aligned=post_style.eq.2,xyz=xyz_sol,&
754 &e_pot_int=e_pot_int(:,i_ev_out),&
755 &e_kin_int=e_kin_int(:,i_ev_out))
756 chckerr('')
757 call lvl_ud(-1)
758
759 ! write to log file and save difference between
760 ! Eigenvalue and energy fraction if last parallel job
761 if (last_eq_job) then
762 ierr = write_decomp_log(id,e_pot_int(:,i_ev_out),&
763 &e_kin_int(:,i_ev_out))
764 chckerr('')
765
766 sol_val_comp(:,1,i_ev_out) = id*1._dp
767 sol_val_comp(:,2,i_ev_out) = [sol%val(id),&
768 &sum(e_pot_int(:,i_ev_out))/&
769 &sum(e_kin_int(:,i_ev_out))]
770 end if
771
772 ! increment counter
773 i_ev_out = i_ev_out + 1
774 end if
775
776 ! user output
777 call lvl_ud(-1)
778 call writo('Mode '//trim(i2str(id))//'/'//&
779 &trim(i2str(size(sol%val)))//' finished')
780 end do
781
782 call lvl_ud(-1)
783 if (min_id(jd).le.max_id(jd)) call &
784 &writo('RANGE '//trim(i2str(jd))//' plotted')
785 end do
786
787 ! plot difference between Eigenvalue and energy fraction if last
788 ! parallel job
789 if (last_eq_job) then
790 call plot_sol_val_comp(sol_val_comp)
791 end if
792
793 ! user output
794 call lvl_ud(-1)
795 call writo('Solution for different ranges plotted')
796 end if
797
798 ! user output
799 call lvl_ud(-1)
800 call writo('3-D output plots done')
801
802 ! clean up
803 call writo('Clean up')
804 call lvl_ud(1)
805 call grids(1)%dealloc()
806 call grids(2)%dealloc()
807 call grids(3)%dealloc()
808 call eq_1%dealloc()
809 call eq_2%dealloc()
810 call x%dealloc()
811 call lvl_ud(-1)
812 end function run_driver_post
813
814 !> Cleans up main driver for postprocessing.
815 subroutine stop_post()
818 use input_utilities, only: dealloc_in
819
820 call dealloc_in()
821 if (post_output_sol) then
822 call sol%dealloc()
823 call vac%dealloc()
824 end if
825 if (post_output_full .and. eq_style.eq.2) then
826 call grid_eq_hel%dealloc()
827 call grid_x_hel%dealloc()
828 call eq_2_hel%dealloc()
829 call x_hel%dealloc()
830 end if
831 if (post_output_full .and. plot_grid_style.eq.0 .or. &
832 &plot_grid_style.eq.3) then
833 call grid_eq_xyz%dealloc()
834 end if
835 end subroutine stop_post
836
837 !> Opens the decomposition log file.
838 !!
839 !! \return ierr
840 integer function open_decomp_log() result(ierr)
842 &decomp_i
843 use rich_vars, only: rich_lvl
844
845 character(*), parameter :: rout_name = 'open_decomp_log'
846
847 ! local variables
848 character(len=max_str_ln) :: format_head ! header format
849 character(len=max_str_ln) :: full_output_name ! full name
850 character(len=max_str_ln) :: grid_name ! name of grid on which calculations are done
851 character(len=2*max_str_ln) :: temp_output_str ! temporary output string
852
853 ! initialize ierr
854 ierr = 0
855
856 ! set up output name
857 select case (post_style)
858 case (1) ! extended grid
859 grid_name = 'extended'
860 case (2) ! field-aligned grid
861 grid_name = 'field-aligned'
862 end select
863
864 call writo('Open decomposition log file')
865 call lvl_ud(1)
866 if (rank.eq.0) then
867 ! set format strings
868 format_head = '("# ",7(A23," "))'
869 ! open output file for the log
870 full_output_name = prog_name//'_'//trim(output_name)//'_EN_R'//&
871 &trim(i2str(rich_lvl))//'.txt'
872 open(unit=decomp_i,status='replace',file=full_output_name,&
873 &iostat=ierr)
874 chckerr('Cannot open EN output file')
875 call writo('Log file opened in '//trim(full_output_name))
876 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
877 &'# Energy decomposition using the solution Eigenvectors'
878 chckerr('Failed to write')
879 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
880 &'# (Output on the '//trim(grid_name)//' grid)'
881 chckerr('Failed to write')
882 write(temp_output_str,format_head) &
883 &'RE Eigenvalue ', 'RE E_pot/E_kin ', &
884 &'RE E_pot ', 'RE E_kin '
885 write(unit=decomp_i,fmt='(A)',iostat=ierr) trim(temp_output_str)
886 chckerr('Failed to write')
887 write(temp_output_str,format_head) &
888 &'IM Eigenvalue ', 'IM E_pot/E_kin ', &
889 &'IM E_pot ', 'IM E_kin '
890 write(unit=decomp_i,fmt='(A)',iostat=ierr) trim(temp_output_str)
891 chckerr('Failed to write')
892 write(temp_output_str,format_head) &
893 &'RE E_kin_n ', 'RE E_kin_g '
894 write(unit=decomp_i,fmt='(A)',iostat=ierr) trim(temp_output_str)
895 chckerr('Failed to write')
896 write(temp_output_str,format_head) &
897 &'IM E_kin_n ', 'IM E_kin_g '
898 write(unit=decomp_i,fmt='(A)',iostat=ierr) trim(temp_output_str)
899 chckerr('Failed to write')
900 write(temp_output_str,format_head) &
901 &'RE E_pot line_bending_n', 'RE E_pot line_bending_g', &
902 &'RE E_pot ballooning_n ', 'RE E_pot ballooning_g ', &
903 &'RE E_pot kink_n ', 'RE E_pot kink_g ', &
904 &'RE E_pot vac '
905 write(unit=decomp_i,fmt='(A)',iostat=ierr) trim(temp_output_str)
906 chckerr('Failed to write')
907 write(temp_output_str,format_head) &
908 &'IM E_pot line_bending_n', 'IM E_pot line_bending_g', &
909 &'IM E_pot ballooning_n ', 'IM E_pot ballooning_g ', &
910 &'IM E_pot kink_n ', 'IM E_pot kink_g ', &
911 &'IM E_pot vac '
912 write(unit=decomp_i,fmt='(A)',iostat=ierr) trim(temp_output_str)
913 chckerr('Failed to write')
914 end if
915 call lvl_ud(-1)
916 end function open_decomp_log
917
918 !> Write to decomposition log file.
919 !!
920 !! \return ierr
921 integer function write_decomp_log(X_id,E_pot_int,E_kin_int) result(ierr)
922 use num_vars, only: decomp_i, rank
923
924 character(*), parameter :: rout_name = 'write_decomp_log'
925
926 ! input / output
927 integer, intent(in) :: x_id !< nr. of Eigenvalue
928 complex(dp), intent(in) :: e_pot_int(7) !< E_pot integrated for requested solutions
929 complex(dp), intent(in) :: e_kin_int(2) !< E_kin integrated for requested solutions
930
931 ! local variables
932 character(len=max_str_ln) :: format_val ! format
933 character(len=2*max_str_ln) :: temp_output_str ! temporary output string
934
935 ! initialize ierr
936 ierr = 0
937
938 ! user output
939 call writo('Write to log file')
940 call lvl_ud(1)
941
942 ! only master
943 if (rank.eq.0) then
944 ! set up format string:
945 ! row 1: EV, E_pot/E_kin
946 ! row 2: E_pot, E_kin
947 ! row 3: E_kin(1), E_kin(2)
948 ! row 4: E_pot(1), E_pot(2)
949 ! row 5: E_pot(3), E_pot(4)
950 ! row 6: E_pot(5), E_pot(6)
951 format_val = '(" ",7(ES23.16," "))'
952
953 ! write header
954 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
955 &'# Eigenvalue '//trim(i2str(x_id))
956 chckerr('Failed to write')
957
958 ! write values
959 write(temp_output_str,format_val) &
960 &rp(sol%val(x_id)),&
961 &rp(sum(e_pot_int)/sum(e_kin_int)),&
962 &rp(sum(e_pot_int)),&
963 &rp(sum(e_kin_int))
964 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
965 &trim(temp_output_str)
966 chckerr('Failed to write')
967 write(temp_output_str,format_val) &
968 &ip(sol%val(x_id)),&
969 &ip(sum(e_pot_int)/sum(e_kin_int)), &
970 &ip(sum(e_pot_int)),&
971 &ip(sum(e_kin_int))
972 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
973 &trim(temp_output_str)
974 chckerr('Failed to write')
975 write(temp_output_str,format_val) &
976 &rp(e_kin_int(1)),&
977 &rp(e_kin_int(2))
978 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
979 &trim(temp_output_str)
980 chckerr('Failed to write')
981 write(temp_output_str,format_val) &
982 &ip(e_kin_int(1)),&
983 &ip(e_kin_int(2))
984 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
985 &trim(temp_output_str)
986 chckerr('Failed to write')
987 write(temp_output_str,format_val) &
988 &rp(e_pot_int(1)),&
989 &rp(e_pot_int(2)),&
990 &rp(e_pot_int(3)),&
991 &rp(e_pot_int(4)),&
992 &rp(e_pot_int(5)),&
993 &rp(e_pot_int(6)),&
994 &rp(e_pot_int(7))
995 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
996 &trim(temp_output_str)
997 chckerr('Failed to write')
998 write(temp_output_str,format_val) &
999 &ip(e_pot_int(1)),&
1000 &ip(e_pot_int(2)),&
1001 &ip(e_pot_int(3)),&
1002 &ip(e_pot_int(4)),&
1003 &ip(e_pot_int(5)),&
1004 &ip(e_pot_int(6)),&
1005 &ip(e_pot_int(7))
1006 write(unit=decomp_i,fmt='(A)',iostat=ierr) &
1007 &trim(temp_output_str)
1008 chckerr('Failed to write')
1009
1010 close(decomp_i)
1011 end if
1012
1013 call lvl_ud(-1)
1014 end function write_decomp_log
1015
1016 !> finds the plot ranges \c min_id and \c max_id.
1017 !!
1018 !! There are three ranges, calculated using n_sol_plotted, which indicates:
1019 !! 1. how many of the first EV's in the unstable range
1020 !! 2. how many of the last EV's in the unstable range
1021 !! 3. how many of the first EV's in the stable range
1022 !! 4. how many of the last EV's in the stable range
1023 !!
1024 !! have to be plotted.
1025 !!
1026 !! This yields maximally three different ranges: One starting at the first
1027 !! unstable EV, one centered around the zero of the EV's and one ending at
1028 !! the last EV. These ranges can be disjoint but do not have to be.\n
1029 !! Also, it is possible that a range does not exist, for example if there
1030 !! are no unstable EV's.
1031 !!
1032 !! \note A negative value for the elements in n_sol_plotted means "all
1033 !! values in range":
1034 !! 1. or 2. full unstable range
1035 !! 3. or 4. full stable range
1036 subroutine find_stab_ranges(sol,min_id,max_id,last_unstable_id)
1037 use num_vars, only: n_sol_plotted
1038
1039 ! input / output
1040 type(sol_type), intent(in) :: sol !< solution variables
1041 integer, intent(inout) :: min_id(3) !< min. index of range 1, 2 and 3
1042 integer, intent(inout) :: max_id(3) !< max. index of range 1, 2 and 3
1043 integer, intent(inout) :: last_unstable_id !< index of last unstable EV
1044
1045 ! local variables
1046 integer :: id ! counter
1047 integer :: n_sol_found ! how many solutions found and saved
1048
1049 ! set local variables
1050 n_sol_found = size(sol%val)
1051
1052 ! find last unstable index (if ends with 0, no unstable EV)
1053 last_unstable_id = 0
1054 do id = 1,n_sol_found
1055 if (rp(sol%val(id)).lt.0._dp) last_unstable_id = id
1056 end do
1057 ! set up min. and max. of range 1
1058 if (last_unstable_id.gt.0) then ! there is an unstable range
1059 if (n_sol_plotted(1).ge.0) then
1060 min_id(1) = 1 ! start from most unstable EV
1061 max_id(1) = min(n_sol_plotted(1),last_unstable_id) ! end with n_sol_plotted(1) first unstable values if available
1062 else
1063 min_id(1) = 1 ! start from most unstable EV
1064 max_id(1) = last_unstable_id ! end with last unstable EV
1065 end if
1066 else ! no unstable range
1067 min_id(1) = 1 ! no unstable values to plot
1068 max_id(1) = 0 ! no unstable values to plot
1069 end if
1070 ! set up min. and max. of range 2
1071 if (last_unstable_id.gt.0) then ! there is an unstable range
1072 if (n_sol_plotted(2).ge.0) then
1073 min_id(2) = last_unstable_id - n_sol_plotted(2) + 1 ! start from n_sol_plotted(2) last unstable values
1074 else
1075 min_id(2) = 1 ! start from 1
1076 end if
1077 if (n_sol_plotted(3).ge.0) then
1078 max_id(2) = min(last_unstable_id + n_sol_plotted(3),n_sol_found)! end with n_sol_plotted(3) first stable values if available
1079 else
1080 max_id(2) = n_sol_found ! end with last EV
1081 end if
1082 else ! no unstable range
1083 min_id(2) = 1 ! start from first EV (stable)
1084 if (n_sol_plotted(3).ge.0) then
1085 max_id(2) = min(n_sol_plotted(3),n_sol_found) ! end with n_sol_plotted(3) first stable values if available
1086 else
1087 max_id(2) = n_sol_found ! end with last EV
1088 end if
1089 end if
1090 ! set up min. and max. of range 3
1091 if (n_sol_plotted(4).ge.0) then
1092 min_id(3) = n_sol_found - n_sol_plotted(4) + 1 ! start from n_sol_plotted(4) last stable values
1093 else
1094 min_id(3) = last_unstable_id + 1 ! start from n_sol_plotted(4) last stable values
1095 end if
1096 max_id(3) = n_sol_found ! end with most stable EV
1097 ! merge ranges 2 and 3 if overlap
1098 if (min_id(3).le.max_id(2)) then
1099 max_id(2) = max_id(3) ! range 3 merged with range 2
1100 min_id(3) = 1 ! range 3 not used any more
1101 max_id(3) = 0 ! range 3 not used any more
1102 end if
1103 ! merge ranges 1 and 2 if overlap
1104 if (min_id(2).le.max_id(1)) then
1105 max_id(1) = max_id(2) ! range 2 merged with range 1
1106 min_id(2) = 1 ! range 2 not used any more
1107 max_id(2) = 0 ! range 2 not used any more
1108 end if
1109 end subroutine find_stab_ranges
1110
1111 !> Plots difference between Eigenvalues and energy fraction.
1112 subroutine plot_sol_val_comp(sol_val_comp)
1113 use num_vars, only: rank
1114
1115 ! input /output
1116 complex(dp), intent(inout) :: sol_val_comp(:,:,:) !< fraction between total \f$E_{\text{pot}}\f$ and \f$E_{\text{kin}}\f$, compared with EV
1117
1118 ! local variables
1119 character(len=max_str_ln) :: plot_title(2) ! title for plots
1120 character(len=max_str_ln) :: plot_name ! file name for plots
1121
1122 if (rank.eq.0 .and. size(sol_val_comp,3).gt.0) then
1123 ! real part
1124 plot_title = ['RE sol_val','E_frac ']
1125 plot_name = 'sol_val_comp_RE'
1126 call print_ex_2d(plot_title,plot_name,&
1127 &rp(sol_val_comp(:,1,:)),&
1128 &x=rp(sol_val_comp(:,2,:)),draw=.false.)
1129 call draw_ex(plot_title,plot_name,size(sol_val_comp,3),1,.false.)
1130 plot_title(1) = 'rel diff between RE sol_val and E_frac'
1131 plot_name = 'sol_val_comp_RE_rel_diff'
1132 call print_ex_2d(plot_title(1),plot_name,rp(&
1133 &(sol_val_comp(1,2,:)-sol_val_comp(2,2,:))/&
1134 &sol_val_comp(1,2,:)),x=rp(sol_val_comp(1,1,:)),&
1135 &draw=.false.)
1136 call draw_ex(plot_title(1:1),plot_name,1,1,.false.)
1137 plot_title(1) = 'rel diff between RE sol_val and E_frac [log]'
1138 plot_name = 'sol_val_comp_RE_rel_diff_log'
1139 call print_ex_2d(plot_title(1),plot_name,log10(abs(rp(&
1140 &(sol_val_comp(1,2,:)-sol_val_comp(2,2,:))/&
1141 &sol_val_comp(1,2,:)))),x=rp(sol_val_comp(1,1,:)),&
1142 &draw=.false.)
1143 call draw_ex(plot_title(1:1),plot_name,1,1,.false.)
1144
1145 ! imaginary part
1146 plot_title = ['IM sol_val','E_frac ']
1147 plot_name = 'sol_val_comp_IM'
1148 call print_ex_2d(plot_title,plot_name,&
1149 &rp(sol_val_comp(:,1,:)),x=ip(sol_val_comp(:,2,:)),draw=.false.)
1150 call draw_ex(plot_title,plot_name,size(sol_val_comp,3),1,.false.)
1151 plot_title(1) = 'rel diff between IM sol_val and E_frac'
1152 plot_name = 'sol_val_comp_IM_rel_diff'
1153 call print_ex_2d(plot_title(1),plot_name,ip(&
1154 &(sol_val_comp(1,2,:)-sol_val_comp(2,2,:))/&
1155 &sol_val_comp(1,2,:)),x=rp(sol_val_comp(1,1,:)),&
1156 &draw=.false.)
1157 call draw_ex(plot_title(1:1),plot_name,1,1,.false.)
1158 plot_title(1) = 'rel diff between IM sol_val and E_frac [log]'
1159 plot_name = 'sol_val_comp_IM_rel_diff_log'
1160 call print_ex_2d(plot_title(1),plot_name,log10(abs(ip(&
1161 &(sol_val_comp(1,2,:)-sol_val_comp(2,2,:))/&
1162 &sol_val_comp(1,2,:)))),x=rp(sol_val_comp(1,1,:)),&
1163 &draw=.false.)
1164 call draw_ex(plot_title(1:1),plot_name,1,1,.false.)
1165 end if
1166 end subroutine plot_sol_val_comp
1167
1168 !> Sets up the output grids for a particular parallel job.
1169 !!
1170 !! Three grids are returned:
1171 !! * eq
1172 !! * X
1173 !! * sol
1174 !!
1175 !! The normal coordinates of these grids correspond to the one used in PB3D.
1176 !! For X this is determined by \c x_grid_style.
1177 !!
1178 !! The angular components of the eq and X grids is determined by \c
1179 !! post_style:
1180 !! * 1: extended grid with \c min_theta_plot, \c max_theta_plot, \c
1181 !! min_zeta_plot and \c max_zeta_plot.
1182 !! * 2: PB3D grid.
1183 !!
1184 !! \return ierr
1185 integer function setup_out_grids(grids_out,XYZ_eq,XYZ_sol) result(ierr)
1188 use num_utilities, only: spline
1189 use grid_utilities, only: extend_grid_f
1191 use num_vars, only: rank, n_procs
1192#if ldebug
1193 use grid_utilities, only: nufft
1194#endif
1195
1196 character(*), parameter :: rout_name = 'setup_out_grids'
1197
1198 ! input / output
1199 type(grid_type), intent(inout) :: grids_out(3) !< eq, X and sol output grids (full parallel and normal range)
1200 real(dp), intent(inout), allocatable :: xyz_eq(:,:,:,:) !< \c X, \c Y and \c Z on output equilibrium grid
1201 real(dp), intent(inout), allocatable :: xyz_sol(:,:,:,:) !< \c X, \c Y and \c Z on output solution grid
1202
1203 ! local variables
1204 type(grid_type) :: grid_eq ! equilibrium grid
1205 type(grid_type) :: grid_x ! perturbation grid
1206 integer :: n_theta ! nr. of points in theta for extended grid
1207 integer :: id, jd, ld ! counters
1208 integer :: lim_loc(3,2,3) ! grid ranges for local equilibrium job (last index: eq, X, sol)
1209 real(dp) :: lim_theta(2) ! theta limits
1210 real(dp), allocatable :: r_geo(:,:,:) ! geometrical radius
1211 real(dp), allocatable :: xy(:,:,:) ! x and y
1212 real(dp), allocatable :: f(:,:,:) ! Fourier components
1213 real(dp), allocatable :: f_loc(:,:) ! local f
1214 real(dp), allocatable :: xyz_x(:,:,:,:) ! X, Y and Z on output perturbation grid
1215
1216 ! initialize ierr
1217 ierr = 0
1218
1219 call writo('Set up output grid')
1220 call lvl_ud(1)
1221
1222 select case (post_style)
1223 case (1) ! extended grid
1224 ! limits to exclude angular part
1225 call writo('Set up limits')
1226 ! eq
1227 lim_loc(1,:,1) = [0,0]
1228 lim_loc(2,:,1) = [0,0]
1229 lim_loc(3,:,1) = [1,-1]
1230 ! X
1231 lim_loc(1,:,2) = [0,0]
1232 lim_loc(2,:,2) = [0,0]
1233 lim_loc(3,:,2) = [1,-1]
1234 ! sol
1235 lim_loc(1,:,3) = [0,0]
1236 lim_loc(2,:,3) = [0,0]
1237 lim_loc(3,:,3) = [1,-1]
1238
1239 ! reconstruct equilibrium, perturbation and solution grids
1240 call writo('Reconstruct PB3D variables')
1241 ierr = reconstruct_pb3d_grid(grid_eq,'eq',&
1242 &rich_lvl=rich_lvl_name,lim_pos=lim_loc(:,:,1),&
1243 &grid_limits=lims_norm(:,1))
1244 chckerr('')
1245 ierr = reconstruct_pb3d_grid(grid_x,'X',&
1246 &rich_lvl=rich_lvl_name,lim_pos=lim_loc(:,:,2),&
1247 &grid_limits=lims_norm(:,2))
1248 chckerr('')
1249 ierr = reconstruct_pb3d_grid(grids_out(3),'sol',&
1250 &lim_pos=lim_loc(:,:,3),grid_limits=lims_norm(:,3))
1251 chckerr('')
1252
1253 ! theta limits
1254 if (n_par_tot.gt.1) then
1255 lim_theta = min_theta_plot + &
1256 &(eq_jobs_lims(:,eq_job_nr)-1._dp)*&
1257 &(max_theta_plot-min_theta_plot)/(n_par_tot-1._dp)
1258 else
1259 lim_theta = min_theta_plot
1260 end if
1262
1263 ! extend eq and X grid
1264 call writo('Extend equilibrium grid')
1265 call lvl_ud(1)
1266 ierr = extend_grid_f(grid_eq,grids_out(1),n_theta_plot=n_theta,&
1267 &lim_theta_plot=lim_theta,grid_eq=grid_eq) ! extend eq grid and convert to F
1268 chckerr('')
1269 call lvl_ud(-1)
1270
1271 call writo('Extend perturbation grid')
1272 call lvl_ud(1)
1273 ierr = grids_out(2)%init([n_theta,n_out(2:3,2)],&
1274 &i_lim=[grid_x%i_min,grid_x%i_max])
1275 chckerr('')
1276 grids_out(2)%r_F = grid_x%r_F
1277 grids_out(2)%r_E = grid_x%r_E
1278 grids_out(2)%loc_r_F = grid_x%loc_r_F
1279 grids_out(2)%loc_r_E = grid_x%loc_r_E
1280 select case (x_grid_style)
1281 case (1) ! equilibrium
1282 ! copy angular variables
1283 grids_out(2)%theta_F = grids_out(1)%theta_F
1284 grids_out(2)%theta_E = grids_out(1)%theta_E
1285 grids_out(2)%zeta_F = grids_out(1)%zeta_F
1286 grids_out(2)%zeta_E = grids_out(1)%zeta_E
1287 case (2,3) ! solution or enriched
1288 ! interpolate angular variables
1289 do jd = 1,grids_out(1)%n(2)
1290 do id = 1,grids_out(1)%n(1)
1291 ierr = spline(grids_out(1)%loc_r_F,&
1292 &grids_out(1)%theta_F(id,jd,:),&
1293 &grids_out(2)%loc_r_F,&
1294 &grids_out(2)%theta_F(id,jd,:),&
1295 &ord=norm_disc_prec_x)
1296 chckerr('')
1297 ierr = spline(grids_out(1)%loc_r_F,&
1298 &grids_out(1)%theta_E(id,jd,:),&
1299 &grids_out(2)%loc_r_F,&
1300 &grids_out(2)%theta_E(id,jd,:),&
1301 &ord=norm_disc_prec_x)
1302 chckerr('')
1303 ierr = spline(grids_out(1)%loc_r_F,&
1304 &grids_out(1)%zeta_F(id,jd,:),&
1305 &grids_out(2)%loc_r_F,&
1306 &grids_out(2)%zeta_F(id,jd,:),&
1307 &ord=norm_disc_prec_x)
1308 chckerr('')
1309 ierr = spline(grids_out(1)%loc_r_F,&
1310 &grids_out(1)%zeta_E(id,jd,:),&
1311 &grids_out(2)%loc_r_F,&
1312 &grids_out(2)%zeta_E(id,jd,:),&
1313 &ord=norm_disc_prec_x)
1314 chckerr('')
1315 end do
1316 end do
1317 end select
1318 call lvl_ud(-1)
1319
1320 ! clean up
1321 call grid_eq%dealloc()
1322 call grid_x%dealloc()
1323 case (2) ! field-aligned grid
1324 ! limits to take subset of angular part
1325 call writo('Set up limits')
1326 ! eq
1327 lim_loc(1,:,1) = eq_jobs_lims(:,eq_job_nr)
1328 lim_loc(2,:,1) = [1,-1]
1329 lim_loc(3,:,1) = [1,-1]
1330 ! X
1331 lim_loc(1,:,2) = eq_jobs_lims(:,eq_job_nr)
1332 lim_loc(2,:,2) = [1,-1]
1333 lim_loc(3,:,2) = [1,-1]
1334 ! sol
1335 lim_loc(1,:,3) = [0,0]
1336 lim_loc(2,:,3) = [0,0]
1337 lim_loc(3,:,3) = [1,-1]
1338
1339 ! reconstruct equilibrium, perturbation and solution grids
1340 call writo('Reconstruct PB3D variables')
1341 ierr = reconstruct_pb3d_grid(grids_out(1),trim(grid_name(1)),&
1342 &rich_lvl=rich_lvl,tot_rich=.true.,&
1343 &lim_pos=lim_loc(:,:,1),grid_limits=lims_norm(:,1))
1344 chckerr('')
1345 ierr = reconstruct_pb3d_grid(grids_out(2),trim(grid_name(2)),&
1346 &rich_lvl=rich_lvl,tot_rich=.true.,&
1347 &lim_pos=lim_loc(:,:,2),grid_limits=lims_norm(:,2))
1348 chckerr('')
1349 ierr = reconstruct_pb3d_grid(grids_out(3),trim(grid_name(3)),&
1350 &lim_pos=lim_loc(:,:,3),grid_limits=lims_norm(:,3))
1351 chckerr('')
1352 end select
1353
1354 call writo('Calculate X, Y and Z of equilibrium grid')
1355 call lvl_ud(1)
1356 ierr = calc_xyz_of_output_grid(grids_out(1),xyz_eq)
1357 chckerr('')
1358 call lvl_ud(-1)
1359
1360 call writo('Calculate X, Y and Z of perturbation grid')
1361 call lvl_ud(1)
1362 ierr = calc_xyz_of_output_grid(grids_out(2),xyz_x)
1363 chckerr('')
1364 call lvl_ud(-1)
1365
1366 call writo('Calculate X, Y and Z of solution grid')
1367 call lvl_ud(1)
1368 allocate(xyz_sol(grids_out(2)%n(1),grids_out(2)%n(2),&
1369 &grids_out(3)%loc_n_r,3))
1370 select case (x_grid_style)
1371 case (1,3) ! equilibrium or enriched
1372 ! setup normal interpolation data
1373 do ld = 1,3
1374 do jd = 1,grids_out(2)%n(2)
1375 do id = 1,grids_out(2)%n(1)
1376 ierr = spline(grids_out(2)%loc_r_F,&
1377 &xyz_x(id,jd,:,ld),grids_out(3)%loc_r_F,&
1378 &xyz_sol(id,jd,:,ld),ord=norm_disc_prec_x)
1379 chckerr('')
1380 end do
1381 end do
1382 end do
1383 case (2) ! solution
1384 xyz_sol = xyz_x
1385 end select
1386 call lvl_ud(-1)
1387
1388#if ldebug
1389 ! Plot toroidal dependency of ripple.
1390 ! Note: Hard-code NFP.
1391 if (debug_tor_dep_ripple .and. rank.eq.n_procs-1) then
1392 call plot_hdf5(['X','Y','Z'],'XYZ',xyz_eq)
1393 allocate(r_geo(grids_out(1)%n(1),grids_out(1)%n(2),&
1394 &grids_out(1)%loc_n_r))
1395 r_geo = sqrt((xyz_eq(:,:,:,3)-0.56710)**2 + &
1396 &(xyz_eq(:,:,:,1)-6.4297)**2)
1397 call plot_hdf5('r_geo','r_geo_TEMP',r_geo,x=xyz_eq(:,:,:,1),&
1398 &y=xyz_eq(:,:,:,2),z=xyz_eq(:,:,:,3))
1399 allocate(xy(grids_out(1)%n(2),grids_out(1)%n(1),2))
1400 do id = 1,grids_out(1)%n(1)
1401 xy(:,id,1) = xyz_eq(id,:,grids_out(1)%loc_n_r,2)*18
1402 xy(:,id,2) = r_geo(id,:,grids_out(1)%loc_n_r) &
1403 &* grids_out(1)%n(2) / sum(r_geo(id,:,grids_out(1)%loc_n_r))
1404 end do
1405 call print_ex_2d(['r_geo'],'r_geo',xy(:,:,2),x=xy(:,:,1),&
1406 &draw=.false.)
1407 call draw_ex(['r_geo'],'r_geo',grids_out(1)%n(1),1,.false.,&
1408 &ex_plot_style=1)
1409 do id = 1,grids_out(1)%n(1)
1410 ierr = nufft(xy(1:size(xy,1)-1,id,1),xy(1:size(xy,1)-1,id,2),&
1411 &f_loc)
1412 chckerr('')
1413 if (id.eq.1) &
1414 &allocate(f(size(f_loc,1),size(f_loc,2),grids_out(1)%n(1)))
1415 f(:,:,id) = f_loc
1416 end do
1417 call print_ex_2d(['r_geo_cos'],'r_geo_cos',f(:,1,:),&
1418 &draw=.false.)
1419 call draw_ex(['r_geo_cos'],'r_geo_cos',grids_out(1)%n(1),1,.false.,&
1420 &ex_plot_style=1)
1421 call print_ex_2d(['r_geo_sin'],'r_geo_sin',f(:,2,:),&
1422 &draw=.false.)
1423 call draw_ex(['r_geo_sin'],'r_geo_sin',grids_out(1)%n(1),1,.false.,&
1424 &ex_plot_style=1)
1425 end if
1426#endif
1427
1428 call lvl_ud(-1)
1429 contains
1430 ! Calculate XYZ of output grid, depending on plot_grid style:
1431 ! 0: 3-D geometry
1432 ! 1: slab geometry
1433 ! 2: slab geometry with wrapping of angles
1434 ! 3: 3-D geometry with straightened toroidal coordinate
1435 !> \private
1436 integer function calc_xyz_of_output_grid(grid,XYZ) result(ierr)
1437 use grid_utilities, only: calc_xyz_grid
1440 use eq_vars, only: max_flux_f
1441 use grid_vars, only: alpha, n_alpha
1443 use mpi_utilities, only: wait_mpi
1444
1445 character(*), parameter :: rout_name = 'calc_XYZ_of_output_grid'
1446
1447 ! input / output
1448 type(grid_type), intent(inout) :: grid ! output grid for which to calculate XYZ
1449 real(dp), allocatable :: xyz(:,:,:,:) ! X, Y and Z on output grid
1450
1451 ! local variables
1452 real(dp), allocatable :: r(:,:,:) ! R on output grid
1453 character(len=max_str_ln) :: err_msg ! error message
1454 integer :: jd, kd ! counters
1455
1456 ! initialize ierr
1457 ierr = 0
1458
1459 ! if VMEC, calculate trigonometric factors of output grid
1460 if (eq_style.eq.1) then
1461 ierr = calc_trigon_factors(grid%theta_E,grid%zeta_E,&
1462 &grid%trigon_factors)
1463 chckerr('')
1464 end if
1465
1466 ! set up XYZ
1467 allocate(xyz(grid%n(1),grid%n(2),grid%loc_n_r,3))
1468 select case (plot_grid_style)
1469 case (0) ! 3-D geometry
1470 ! user output
1471 call writo('Plots are done in 3-D geometry')
1472 call lvl_ud(1)
1473
1474 ierr = calc_xyz_grid(grid_eq_xyz,grid,&
1475 &xyz(:,:,:,1),xyz(:,:,:,2),xyz(:,:,:,3))
1476 chckerr('')
1477 !!! To plot the cross-section
1478 !!call print_ex_2D(['cross_section'],'cross_section_'//&
1479 !!&trim(i2str(eq_job_nr))//'_'//trim(i2str(rank)),&
1480 !!&XYZ(:,1,:,3),x=XYZ(:,1,:,1),draw=.false.)
1481 !!call draw_ex(['cross_section'],'cross_section_'//&
1482 !!&trim(i2str(eq_job_nr))//'_'//trim(i2str(rank)),&
1483 !!&size(XYZ,3),1,.false.)
1484
1485 call lvl_ud(-1)
1486 case (3) ! 3-D geometry with straightened toroidal coordinate
1487 ! user output
1488 call writo('Plots are done in an unwrapped torus')
1489 call lvl_ud(1)
1490
1491 allocate(r(grid%n(1),grid%n(2),grid%loc_n_r))
1492 ierr = calc_xyz_grid(grid_eq_xyz,grid,&
1493 &xyz(:,:,:,1),xyz(:,:,:,2),xyz(:,:,:,3),r=r)
1494 chckerr('')
1495 xyz(:,:,:,1) = r ! set X to R coordinate
1496 xyz(:,:,:,2) = grid%zeta_F ! set Y to toroidal coordinate
1497 !!! To plot the cross-section
1498 !!call print_ex_2D(['cross_section'],'cross_section_'//&
1499 !!&trim(i2str(eq_job_nr))//'_'//trim(i2str(rank)),&
1500 !!&XYZ(:,1,:,3),x=XYZ(:,1,:,1),draw=.false.)
1501 !!call draw_ex(['cross_section'],'cross_section_'//&
1502 !!&trim(i2str(eq_job_nr))//'_'//trim(i2str(rank)),&
1503 !!&size(XYZ,3),1,.false.)
1504
1505 call lvl_ud(-1)
1506 case (1,2) ! slab geometry (with or without wrapping to fundamental interval)
1507 ! user output
1508 call writo('Plots are done in slab geometry')
1509 call lvl_ud(1)
1510
1511 ! set angular coordinates
1512 select case (post_style)
1513 case (1) ! extended grid: both theta and zeta need to be chosen, not alpha
1514 if (use_pol_flux_f) then
1515 xyz(:,:,:,1) = grid%theta_F/pi
1516 xyz(:,:,:,2) = grid%zeta_F/pi
1517 else
1518 xyz(:,:,:,1) = grid%zeta_F/pi
1519 xyz(:,:,:,2) = grid%theta_F/pi
1520 end if
1521 case (2) ! field-aligned grid: alpha in combination with parallel angle
1522 if (swap_angles) then
1523 call writo('For plotting, the angular &
1524 &coordinates are swapped: theta <-> zeta')
1525 if (use_pol_flux_f) then
1526 xyz(:,:,:,1) = grid%zeta_F/pi
1527 else
1528 xyz(:,:,:,1) = grid%theta_F/pi
1529 end if
1530 else
1531 if (use_pol_flux_f) then
1532 xyz(:,:,:,1) = grid%theta_F/pi
1533 else
1534 xyz(:,:,:,1) = grid%zeta_F/pi
1535 end if
1536 end if
1537 do jd = 1,n_alpha
1538 xyz(:,jd,:,2) = alpha(jd)
1539 end do
1540 end select
1541
1542 ! set normal coordinate
1543 do kd = 1,grid%loc_n_r
1544 xyz(:,:,kd,3) = grid%loc_r_F(kd)/max_flux_f*2*pi
1545 end do
1546
1547 ! limit to fundamental interval -1..1 if plot grid style 2
1548 if (plot_grid_style.eq.2) xyz(:,:,:,1:2) = &
1549 &modulo(xyz(:,:,:,1:2)+1._dp,2._dp)-1._dp
1550
1551 call lvl_ud(-1)
1552 case default
1553 err_msg = 'No style "'//trim(i2str(plot_grid_style))//&
1554 &'" for plot_grid_style'
1555 ierr = 1
1556 chckerr(err_msg)
1557 end select
1558
1559 ! synchronize
1560 ierr = wait_mpi()
1561 chckerr('')
1562 end function calc_xyz_of_output_grid
1563 end function setup_out_grids
1564end module driver_post
Calculate the equilibrium quantities on a grid determined by straight field lines.
Definition eq_ops.f90:48
Calculate , the transformation matrix between H(ELENA) and F(lux) coordinate systems.
Definition eq_ops.f90:271
Calculate from and where and , according to weyens3d.
Calculate grid of equidistant points, where optionally the last point can be excluded.
Gather parallel variable in serial version on group master.
Wrapper to the pspline library, making it easier to use for 1-D applications where speed is not the m...
Prints variables vars with names var_names in an HDF5 file with name c file_name and accompanying XDM...
Print 2-D output on a file.
Calculates either vectorial or tensorial perturbation variables.
Definition X_ops.f90:39
Main driver of PostProcessing of program Peeling Ballooning in 3D.
integer function, public run_driver_post()
The main driver routine for postprocessing.
subroutine, public stop_post()
Cleans up main driver for postprocessing.
integer function, public init_post()
Initializes the POST driver.
Operations on the equilibrium variables.
Definition eq_ops.f90:4
integer function, public delta_r_plot(grid_eq, eq_1, eq_2, xyz, rich_lvl)
Plots HALF of the change in the position vectors for 2 different toroidal positions,...
Definition eq_ops.f90:6173
integer function, public kappa_plot(grid_eq, eq_1, eq_2, rich_lvl, xyz)
Plots the curvature.
Definition eq_ops.f90:5971
integer function, public divide_eq_jobs(n_par_x, arr_size, n_div, n_div_max, n_par_x_base, range_name)
Divides the equilibrium jobs.
Definition eq_ops.f90:6566
integer function, public calc_eq_jobs_lims(n_par_x, n_div)
Calculate eq_jobs_lims.
Definition eq_ops.f90:6701
integer function, public j_plot(grid_eq, eq_1, eq_2, rich_lvl, plot_fluxes, xyz)
Plots the current.
Definition eq_ops.f90:5803
integer function, public b_plot(grid_eq, eq_1, eq_2, rich_lvl, plot_fluxes, xyz)
Plots the magnetic fields.
Definition eq_ops.f90:5700
integer function, public flux_q_plot(grid_eq, eq)
Plots the flux quantities in the solution grid.
Definition eq_ops.f90:3810
Numerical utilities related to equilibrium variables.
Variables that have to do with equilibrium quantities and the grid used in the calculations:
Definition eq_vars.f90:27
real(dp), public max_flux_f
max. flux in Flux coordinates, set in calc_norm_range_PB3D_in
Definition eq_vars.f90:50
Operations that have to do with the grids and different coordinate systems.
Definition grid_ops.f90:4
integer function, public calc_norm_range(style, in_limits, eq_limits, x_limits, sol_limits, r_f_eq, r_f_x, r_f_sol, jq)
Calculates normal range for the input grid, the equilibrium grid and/or the solution grid.
Definition grid_ops.f90:46
integer function, public magn_grid_plot(grid)
Plots the grid in real 3-D space.
Numerical utilities related to the grids and different coordinate systems.
integer function, public extend_grid_f(grid_in, grid_ext, grid_eq, n_theta_plot, n_zeta_plot, lim_theta_plot, lim_zeta_plot)
Extend a grid angularly.
integer function, public calc_xyz_grid(grid_eq, grid_xyz, x, y, z, l, r)
Calculates , and on a grid grid_XYZ, determined through its E(quilibrium) coordinates.
integer function, public nufft(x, f, f_f, plot_name)
calculates the cosine and sine mode numbers of a function defined on a non-regular grid.
Variables pertaining to the different grids used.
Definition grid_vars.f90:4
real(dp), dimension(:), allocatable, public alpha
field line label alpha
Definition grid_vars.f90:28
integer, public n_alpha
nr. of field-lines
Definition grid_vars.f90:23
real(dp), public max_alpha
max. of field-line label [ ] in field-aligned grid
Definition grid_vars.f90:27
real(dp), public min_alpha
min. of field-line label [ ] in field-aligned grid
Definition grid_vars.f90:26
integer, public n_r_sol
nr. of normal points in solution grid
Definition grid_vars.f90:22
Operations on HELENA variables.
Definition HELENA_ops.f90:4
integer function, public interp_hel_on_grid(grid_in, grid_out, eq_2, x_1, x_2, eq_2_out, x_1_out, x_2_out, eq_1, grid_name)
Interpolate variables resulting from HELENA equilibria to another grid (angularly).
Variables that have to do with HELENA quantities.
integer, public nchi
nr. of poloidal points
Numerical utilities related to input.
subroutine, public dealloc_in()
Cleans up input from equilibrium codes.
Numerical utilities related to giving output.
Definition messages.f90:4
subroutine, public lvl_ud(inc)
Increases/decreases lvl of output.
Definition messages.f90:254
subroutine, public writo(input_str, persistent, error, warning, alert)
Write output to file identified by output_i.
Definition messages.f90:275
Numerical utilities related to MPI.
integer function, public wait_mpi()
Wait for all processes, wrapper to MPI barrier.
Numerical utilities.
integer, dimension(:,:), allocatable, public f
1-D array indices of Fourier mode combination indices
subroutine, public calc_aux_utilities(n_mod)
Initialize utilities for fast future reference, depending on program style.
Numerical variables used by most other modules.
Definition num_vars.f90:4
integer, parameter, public dp
double precision
Definition num_vars.f90:46
logical, public ltest
whether or not to call the testing routines
Definition num_vars.f90:112
integer, public post_style
style for POST (1: extended grid, 2: B-aligned grid)
Definition num_vars.f90:98
logical, public plot_b
whether to plot the magnetic field in real coordinates
Definition num_vars.f90:104
integer, public n_theta_plot
nr. of poloidal points in plot
Definition num_vars.f90:156
integer, public plot_grid_style
style for POST plot grid (0: 3-D plots, 1: slab plots, 2: slab plots with folding,...
Definition num_vars.f90:169
character(len=3), parameter, public output_name
name of output file
Definition num_vars.f90:55
logical, public plot_kappa
whether to plot curvature
Definition num_vars.f90:107
real(dp), public max_r_plot
max. of r_plot
Definition num_vars.f90:164
real(dp), public min_theta_plot
min. of theta_plot
Definition num_vars.f90:159
real(dp), parameter, public pi
Definition num_vars.f90:83
real(dp), public max_zeta_plot
max. of zeta_plot
Definition num_vars.f90:162
logical, public compare_tor_pos
compare quantities at toroidal positions (only for POST)
Definition num_vars.f90:151
logical, public no_output
no output shown
Definition num_vars.f90:145
integer, public n_procs
nr. of MPI processes
Definition num_vars.f90:69
logical, public plot_flux_q
whether to plot flux quantities in real coordinates
Definition num_vars.f90:106
complex(dp), parameter, public iu
complex unit
Definition num_vars.f90:85
integer, parameter, public max_str_ln
maximum length of strings
Definition num_vars.f90:50
logical, public plot_sol_q
whether to plot magnetic perturbation of solution in POST
Definition num_vars.f90:109
logical, public post_output_sol
POST has outputs of solution.
Definition num_vars.f90:147
logical, public plot_vac_pot
whether to plot vacuum potential in POST
Definition num_vars.f90:110
integer, public n_zeta_plot
nr. of toroidal points in plot
Definition num_vars.f90:157
logical, public plot_resonance
whether to plot the q-profile or iota-profile with resonances
Definition num_vars.f90:102
integer, dimension(:,:), allocatable, public eq_jobs_lims
data about eq jobs: [ , ] for all jobs
Definition num_vars.f90:77
integer, public x_grid_style
style for normal component of X grid (1: eq, 2: sol, 3: enriched)
Definition num_vars.f90:99
character(len=4), public prog_name
name of program, used for info
Definition num_vars.f90:54
real(dp), public min_zeta_plot
min. of zeta_plot
Definition num_vars.f90:161
logical, public post_output_full
POST has output on full grids.
Definition num_vars.f90:146
integer, public eq_style
either 1 (VMEC) or 2 (HELENA)
Definition num_vars.f90:89
integer, parameter, public decomp_i
file number of output of EV decomposition
Definition num_vars.f90:189
integer, dimension(4), public n_sol_plotted
how many solutions to be plot (first unstable, last unstable, first stable, last stable)
Definition num_vars.f90:171
logical, public plot_j
whether to plot the current in real coordinates
Definition num_vars.f90:105
integer, public ex_plot_style
external plot style (1: GNUPlot, 2: Bokeh for 2D, Mayavi for 3D)
Definition num_vars.f90:175
real(dp), public min_r_plot
min. of r_plot
Definition num_vars.f90:163
integer, public rank
MPI rank.
Definition num_vars.f90:68
logical, public plot_sol_xi
whether to plot plasma perturbation of solution in POST
Definition num_vars.f90:108
integer, public norm_disc_prec_x
precision for normal discretization for perturbation
Definition num_vars.f90:121
logical, public plot_magn_grid
whether to plot the grid in real coordinates
Definition num_vars.f90:103
logical, public swap_angles
swap angles theta and zeta in plots (only for POST)
Definition num_vars.f90:150
real(dp), public max_theta_plot
max. of theta_plot
Definition num_vars.f90:160
integer, public eq_job_nr
nr. of eq job
Definition num_vars.f90:79
logical, public use_pol_flux_f
whether poloidal flux is used in F coords.
Definition num_vars.f90:114
logical, public plot_e_rec
whether to plot energy reconstruction in POST
Definition num_vars.f90:111
logical, public no_plots
no plots made
Definition num_vars.f90:140
Operations concerning giving output, on the screen as well as in output files.
Definition output_ops.f90:5
subroutine, public draw_ex(var_names, draw_name, nplt, draw_dim, plot_on_screen, ex_plot_style, data_name, draw_ops, extra_ops, is_animated, ranges, delay, persistent)
Use external program to draw a plot.
Operations on PB3D output.
Definition PB3D_ops.f90:8
integer function, public reconstruct_pb3d_vac(vac, data_name, rich_lvl)
Reconstructs the vacuum variables from PB3D HDF5 output.
integer function, public reconstruct_pb3d_eq_1(grid_eq, eq, data_name, lim_pos)
Reconstructs the equilibrium variables from PB3D HDF5 output.
Definition PB3D_ops.f90:597
integer function, public reconstruct_pb3d_grid(grid, data_name, rich_lvl, tot_rich, lim_pos, grid_limits)
Reconstructs grid variables from PB3D HDF5 output.
Definition PB3D_ops.f90:442
integer function, public get_pb3d_grid_size(n, grid_name, rich_lvl, tot_rich)
get grid size
integer function, public reconstruct_pb3d_x_1(mds, grid_x, x, data_name, rich_lvl, tot_rich, lim_sec_x, lim_pos)
Reconstructs the vectorial perturbation variables from PB3D HDF5 output.
Definition PB3D_ops.f90:833
integer function, public reconstruct_pb3d_eq_2(grid_eq, eq, data_name, rich_lvl, tot_rich, lim_pos)
Reconstructs the equilibrium variables from PB3D HDF5 output.
Definition PB3D_ops.f90:695
integer function, public reconstruct_pb3d_in(data_name)
Reconstructs the input variables from PB3D HDF5 output.
Definition PB3D_ops.f90:41
integer function, public reconstruct_pb3d_sol(mds, grid_sol, sol, data_name, rich_lvl, lim_sec_sol, lim_pos)
Reconstructs the solution variables from PB3D HDF5 output.
Variables concerning Richardson extrapolation.
Definition rich_vars.f90:4
integer, public rich_lvl
current level of Richardson extrapolation
Definition rich_vars.f90:19
Operations on the solution vectors such as decompososing the energy, etc...
Definition sol_ops.f90:4
subroutine, public plot_sol_vals(sol, last_unstable_id)
Plots Eigenvalues.
Definition sol_ops.f90:37
integer function, public decompose_energy(mds_x, mds_sol, grid_eq, grid_x, grid_sol, eq_1, eq_2, x, sol, vac, x_id, b_aligned, xyz, e_pot_int, e_kin_int)
Decomposes the plasma potential and kinetic energy in its individual terms for an individual Eigenval...
Definition sol_ops.f90:991
integer function, public plot_sol_vec(mds_x, mds_sol, grid_eq, grid_x, grid_sol, eq_1, eq_2, x, sol, xyz, x_id, plot_var)
Plots Eigenvectors.
Definition sol_ops.f90:116
integer function, public plot_harmonics(mds, grid_sol, sol, x_id, res_surf)
Plots the harmonics and their maximum in 2-D.
Definition sol_ops.f90:646
Variables pertaining to the solution quantities.
Definition sol_vars.f90:4
Operations on strings.
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
elemental character(len=max_str_ln) function, public c2strt(k)
Convert a complex (double) to string.
elemental character(len=max_str_ln) function, public r2strt(k)
Convert a real (double) to string.
Operations and variables pertaining to the vacuum response.
Definition vac_ops.f90:23
integer function, public vac_pot_plot(grid_sol, vac, sol, x_id)
Calculate vacuum potential at some positions that are not resonant.
Definition vac_ops.f90:1857
Variables pertaining to the vacuum quantities.
Definition vac_vars.f90:4
Numerical utilities related to the output of VMEC.
integer function, public calc_trigon_factors(theta, zeta, trigon_factors)
Calculate the trigonometric cosine and sine factors.
Operations considering perturbation quantities.
Definition X_ops.f90:4
integer function, public calc_res_surf(mds, grid_eq, eq, res_surf, info, jq)
Calculates resonating flux surfaces for the perturbation modes.
Definition X_ops.f90:1638
integer function, public setup_modes(mds, grid_eq, grid, plot_name)
Sets up some variables concerning the mode numbers.
Definition X_ops.f90:1060
integer function, public init_modes(grid_eq, eq)
Initializes some variables concerning the mode numbers.
Definition X_ops.f90:919
integer function, public resonance_plot(mds, grid_eq, eq)
plot -profile or -profile in flux coordinates with or indicated if requested.
Definition X_ops.f90:1814
Variables pertaining to the perturbation quantities.
Definition X_vars.f90:4
type(modes_type), public mds_x
modes variables for perturbation grid
Definition X_vars.f90:124
type(modes_type), public mds_sol
modes variables for solution grid
Definition X_vars.f90:125
flux equilibrium type
Definition eq_vars.f90:63
metric equilibrium type
Definition eq_vars.f90:114
Type for grids.
Definition grid_vars.f90:59
solution type
Definition sol_vars.f90:30
vacuum type
Definition vac_vars.f90:46
mode number type
Definition X_vars.f90:36
vectorial perturbation type
Definition X_vars.f90:51