PB3D  [2.45]
Ideal linear high-n MHD stability in 3-D
driver_POST.f90
Go to the documentation of this file.
1 !------------------------------------------------------------------------------!
3 !------------------------------------------------------------------------------!
4 module driver_post
5 #include <PB3D_macros.h>
6 #include <wrappers.h>
7  use str_utilities
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, &
14  &mds_x, mds_sol
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)
25  integer, allocatable :: dum_ser(:)
26  integer :: rich_lvl_name
27  integer :: min_id(3), max_id(3)
28  integer :: last_unstable_id
29  integer :: n_par_tot
30  character(len=4) :: grid_name(3)
31  integer :: n_out(3,2)
32  type(sol_type) :: sol
33  type(vac_type) :: vac
34  type(grid_type) :: grid_eq_XYZ
35  type(grid_type) :: grid_eq_HEL
36  type(grid_type) :: grid_X_HEL
37  type(eq_2_type) :: eq_2_HEL
38  type(X_1_type) :: X_HEL
39  complex(dp), allocatable :: E_pot_int(:,:)
40  complex(dp), allocatable :: E_kin_int(:,:)
41 #if ldebug
42  logical :: debug_tor_dep_ripple = .false.
43 #endif
44 
45 contains
76  integer function init_post() result(ierr)
89  use vac_ops, only: vac_pot_plot
92  use grid_utilities, only: calc_eqd_grid
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 
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
552  use helena_ops, only: interp_hel_on_grid
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,&
744  &[plot_sol_xi,plot_sol_q])
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 
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 
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 
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
928  complex(dp), intent(in) :: e_pot_int(7)
929  complex(dp), intent(in) :: e_kin_int(2)
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 
1036  subroutine find_stab_ranges(sol,min_id,max_id,last_unstable_id)
1038 
1039  ! input / output
1040  type(sol_type), intent(in) :: sol
1041  integer, intent(inout) :: min_id(3)
1042  integer, intent(inout) :: max_id(3)
1043  integer, intent(inout) :: last_unstable_id
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 
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(:,:,:)
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 
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
1190  use pb3d_ops, only: reconstruct_pb3d_grid
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)
1200  real(dp), intent(inout), allocatable :: xyz_eq(:,:,:,:)
1201  real(dp), intent(inout), allocatable :: xyz_sol(:,:,:,:)
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
1261  n_theta = eq_jobs_lims(2,eq_job_nr)-eq_jobs_lims(1,eq_job_nr)+1
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
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
1564 end module driver_post
mpi_utilities::get_ser_var
Gather parallel variable in serial version on group master.
Definition: MPI_utilities.f90:55
pb3d_ops::reconstruct_pb3d_sol
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.
Definition: PB3D_ops.f90:1359
num_vars::plot_e_rec
logical, public plot_e_rec
whether to plot energy reconstruction in POST
Definition: num_vars.f90:111
num_vars::x_grid_style
integer, public x_grid_style
style for normal component of X grid (1: eq, 2: sol, 3: enriched)
Definition: num_vars.f90:99
num_vars::plot_sol_xi
logical, public plot_sol_xi
whether to plot plasma perturbation of solution in POST
Definition: num_vars.f90:108
num_vars::swap_angles
logical, public swap_angles
swap angles theta and zeta in plots (only for POST)
Definition: num_vars.f90:150
num_vars::plot_resonance
logical, public plot_resonance
whether to plot the q-profile or iota-profile with resonances
Definition: num_vars.f90:102
x_ops
Operations considering perturbation quantities.
Definition: X_ops.f90:4
eq_ops::divide_eq_jobs
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
num_vars::dp
integer, parameter, public dp
double precision
Definition: num_vars.f90:46
eq_ops::calc_eq_jobs_lims
integer function, public calc_eq_jobs_lims(n_par_X, n_div)
Calculate eq_jobs_lims.
Definition: eq_ops.f90:6701
eq_vars
Variables that have to do with equilibrium quantities and the grid used in the calculations:
Definition: eq_vars.f90:27
num_vars::n_sol_plotted
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
mpi_utilities
Numerical utilities related to MPI.
Definition: MPI_utilities.f90:20
num_vars
Numerical variables used by most other modules.
Definition: num_vars.f90:4
x_vars::mds_x
type(modes_type), public mds_x
modes variables for perturbation grid
Definition: X_vars.f90:124
eq_ops::delta_r_plot
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
num_vars::max_str_ln
integer, parameter, public max_str_ln
maximum length of strings
Definition: num_vars.f90:50
num_utilities::calc_aux_utilities
subroutine, public calc_aux_utilities(n_mod)
Initialize utilities for fast future reference, depending on program style.
Definition: num_utilities.f90:2063
x_ops::calc_res_surf
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
driver_post::setup_out_grids
integer function setup_out_grids(grids_out, XYZ_eq, XYZ_sol)
Sets up the output grids for a particular parallel job.
Definition: driver_POST.f90:1186
num_vars::plot_sol_q
logical, public plot_sol_q
whether to plot magnetic perturbation of solution in POST
Definition: num_vars.f90:109
rich_vars
Variables concerning Richardson extrapolation.
Definition: rich_vars.f90:4
vac_ops::vac_pot_plot
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
str_utilities::i2str
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
Definition: str_utilities.f90:18
eq_ops::calc_eq
Calculate the equilibrium quantities on a grid determined by straight field lines.
Definition: eq_ops.f90:48
num_vars::n_zeta_plot
integer, public n_zeta_plot
nr. of toroidal points in plot
Definition: num_vars.f90:157
driver_post::find_stab_ranges
subroutine find_stab_ranges(sol, min_id, max_id, last_unstable_id)
finds the plot ranges min_id and max_id.
Definition: driver_POST.f90:1037
eq_utilities::calc_inv_met
Calculate from and where and , according to .
Definition: eq_utilities.f90:61
x_ops::init_modes
integer function, public init_modes(grid_eq, eq)
Initializes some variables concerning the mode numbers.
Definition: X_ops.f90:919
num_vars::post_output_sol
logical, public post_output_sol
POST has outputs of solution.
Definition: num_vars.f90:147
num_vars::eq_job_nr
integer, public eq_job_nr
nr. of eq job
Definition: num_vars.f90:79
num_vars::iu
complex(dp), parameter, public iu
complex unit
Definition: num_vars.f90:85
eq_ops::b_plot
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
vmec_utilities::calc_trigon_factors
integer function, public calc_trigon_factors(theta, zeta, trigon_factors)
Calculate the trigonometric cosine and sine factors.
Definition: VMEC_utilities.f90:275
num_vars::max_theta_plot
real(dp), public max_theta_plot
max. of theta_plot
Definition: num_vars.f90:160
driver_post::write_decomp_log
integer function write_decomp_log(X_id, E_pot_int, E_kin_int)
Write to decomposition log file.
Definition: driver_POST.f90:922
num_vars::n_procs
integer, public n_procs
nr. of MPI processes
Definition: num_vars.f90:69
output_ops::print_ex_2d
Print 2-D output on a file.
Definition: output_ops.f90:47
grid_ops::calc_norm_range
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
str_utilities
Operations on strings.
Definition: str_utilities.f90:4
num_vars::plot_magn_grid
logical, public plot_magn_grid
whether to plot the grid in real coordinates
Definition: num_vars.f90:103
grid_vars::grid_type
Type for grids.
Definition: grid_vars.f90:59
num_vars::decomp_i
integer, parameter, public decomp_i
file number of output of EV decomposition
Definition: num_vars.f90:189
str_utilities::r2strt
elemental character(len=max_str_ln) function, public r2strt(k)
Convert a real (double) to string.
Definition: str_utilities.f90:54
num_vars::prog_name
character(len=4), public prog_name
name of program, used for info
Definition: num_vars.f90:54
pb3d_ops::reconstruct_pb3d_in
integer function, public reconstruct_pb3d_in(data_name)
Reconstructs the input variables from PB3D HDF5 output.
Definition: PB3D_ops.f90:41
driver_post::stop_post
subroutine, public stop_post()
Cleans up main driver for postprocessing.
Definition: driver_POST.f90:816
pb3d_ops::reconstruct_pb3d_vac
integer function, public reconstruct_pb3d_vac(vac, data_name, rich_lvl)
Reconstructs the vacuum variables from PB3D HDF5 output.
Definition: PB3D_ops.f90:1228
eq_vars::eq_1_type
flux equilibrium type
Definition: eq_vars.f90:63
eq_utilities
Numerical utilities related to equilibrium variables.
Definition: eq_utilities.f90:4
eq_ops::j_plot
integer function, public j_plot(grid_eq, eq_1, eq_2, rich_lvl, plot_fluxes, XYZ)
Plots the current.
Definition: eq_ops.f90:5803
num_vars::ltest
logical, public ltest
whether or not to call the testing routines
Definition: num_vars.f90:112
num_vars::min_zeta_plot
real(dp), public min_zeta_plot
min. of zeta_plot
Definition: num_vars.f90:161
vac_vars
Variables pertaining to the vacuum quantities.
Definition: vac_vars.f90:4
grid_vars::alpha
real(dp), dimension(:), allocatable, public alpha
field line label alpha
Definition: grid_vars.f90:28
sol_vars::sol_type
solution type
Definition: sol_vars.f90:30
num_vars::compare_tor_pos
logical, public compare_tor_pos
compare quantities at toroidal positions (only for POST)
Definition: num_vars.f90:151
grid_vars::n_r_sol
integer, public n_r_sol
nr. of normal points in solution grid
Definition: grid_vars.f90:22
vac_ops
Operations and variables pertaining to the vacuum response.
Definition: vac_ops.f90:23
eq_ops::calc_t_hf
Calculate , the transformation matrix between H(ELENA) and F(lux) coordinate systems.
Definition: eq_ops.f90:271
pb3d_ops::reconstruct_pb3d_eq_2
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
num_vars::min_theta_plot
real(dp), public min_theta_plot
min. of theta_plot
Definition: num_vars.f90:159
driver_post::init_post
integer function, public init_post()
Initializes the POST driver.
Definition: driver_POST.f90:77
grid_utilities::extend_grid_f
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.
Definition: grid_utilities.f90:1096
num_utilities::spline
Wrapper to the pspline library, making it easier to use for 1-D applications where speed is not the m...
Definition: num_utilities.f90:276
output_ops::draw_ex
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.
Definition: output_ops.f90:1079
grid_ops::magn_grid_plot
integer function, public magn_grid_plot(grid)
Plots the grid in real 3-D space.
Definition: grid_ops.f90:1115
output_ops::plot_hdf5
Prints variables vars with names var_names in an HDF5 file with name c file_name and accompanying XDM...
Definition: output_ops.f90:137
vmec_utilities
Numerical utilities related to the output of VMEC.
Definition: VMEC_utilities.f90:4
num_vars::min_r_plot
real(dp), public min_r_plot
min. of r_plot
Definition: num_vars.f90:163
num_vars::plot_b
logical, public plot_b
whether to plot the magnetic field in real coordinates
Definition: num_vars.f90:104
num_vars::eq_style
integer, public eq_style
either 1 (VMEC) or 2 (HELENA)
Definition: num_vars.f90:89
x_ops::setup_modes
integer function, public setup_modes(mds, grid_eq, grid, plot_name)
Sets up some variables concerning the mode numbers.
Definition: X_ops.f90:1060
x_vars
Variables pertaining to the perturbation quantities.
Definition: X_vars.f90:4
helena_ops::interp_hel_on_grid
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).
Definition: HELENA_ops.f90:550
num_vars::plot_j
logical, public plot_j
whether to plot the current in real coordinates
Definition: num_vars.f90:105
eq_vars::max_flux_f
real(dp), public max_flux_f
max. flux in Flux coordinates, set in calc_norm_range_PB3D_in
Definition: eq_vars.f90:50
helena_ops
Operations on HELENA variables.
Definition: HELENA_ops.f90:4
num_vars::plot_kappa
logical, public plot_kappa
whether to plot curvature
Definition: num_vars.f90:107
x_vars::modes_type
mode number type
Definition: X_vars.f90:36
mpi_utilities::wait_mpi
integer function, public wait_mpi()
Wait for all processes, wrapper to MPI barrier.
Definition: MPI_utilities.f90:744
grid_utilities::calc_eqd_grid
Calculate grid of equidistant points, where optionally the last point can be excluded.
Definition: grid_utilities.f90:75
x_vars::mds_sol
type(modes_type), public mds_sol
modes variables for solution grid
Definition: X_vars.f90:125
num_vars::no_output
logical, public no_output
no output shown
Definition: num_vars.f90:145
driver_post
Main driver of PostProcessing of program Peeling Ballooning in 3D.
Definition: driver_POST.f90:4
num_utilities
Numerical utilities.
Definition: num_utilities.f90:4
messages::writo
subroutine, public writo(input_str, persistent, error, warning, alert)
Write output to file identified by output_i.
Definition: messages.f90:275
pb3d_ops::reconstruct_pb3d_x_1
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
messages
Numerical utilities related to giving output.
Definition: messages.f90:4
helena_vars
Variables that have to do with HELENA quantities.
Definition: HELENA_vars.f90:4
pb3d_ops
Operations on PB3D output.
Definition: PB3D_ops.f90:8
x_ops::resonance_plot
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
num_vars::pi
real(dp), parameter, public pi
Definition: num_vars.f90:83
grid_utilities
Numerical utilities related to the grids and different coordinate systems.
Definition: grid_utilities.f90:4
grid_vars::max_alpha
real(dp), public max_alpha
max. of field-line label [ ] in field-aligned grid
Definition: grid_vars.f90:27
pb3d_ops::reconstruct_pb3d_eq_1
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
str_utilities::c2strt
elemental character(len=max_str_ln) function, public c2strt(k)
Convert a complex (double) to string.
Definition: str_utilities.f90:88
eq_ops::kappa_plot
integer function, public kappa_plot(grid_eq, eq_1, eq_2, rich_lvl, XYZ)
Plots the curvature.
Definition: eq_ops.f90:5971
vac_vars::vac_type
vacuum type
Definition: vac_vars.f90:46
sol_ops::plot_sol_vals
subroutine, public plot_sol_vals(sol, last_unstable_id)
Plots Eigenvalues.
Definition: sol_ops.f90:37
sol_ops
Operations on the solution vectors such as decompososing the energy, etc...
Definition: sol_ops.f90:4
grid_vars
Variables pertaining to the different grids used.
Definition: grid_vars.f90:4
pb3d_ops::reconstruct_pb3d_grid
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
num_vars::plot_vac_pot
logical, public plot_vac_pot
whether to plot vacuum potential in POST
Definition: num_vars.f90:110
messages::lvl_ud
subroutine, public lvl_ud(inc)
Increases/decreases lvl of output.
Definition: messages.f90:254
num_vars::max_r_plot
real(dp), public max_r_plot
max. of r_plot
Definition: num_vars.f90:164
num_vars::no_plots
logical, public no_plots
no plots made
Definition: num_vars.f90:140
driver_post::run_driver_post
integer function, public run_driver_post()
The main driver routine for postprocessing.
Definition: driver_POST.f90:542
num_vars::plot_grid_style
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
num_vars::output_name
character(len=3), parameter, public output_name
name of output file
Definition: num_vars.f90:55
num_vars::use_pol_flux_f
logical, public use_pol_flux_f
whether poloidal flux is used in F coords.
Definition: num_vars.f90:114
x_ops::calc_x
Calculates either vectorial or tensorial perturbation variables.
Definition: X_ops.f90:39
rich_vars::rich_lvl
integer, public rich_lvl
current level of Richardson extrapolation
Definition: rich_vars.f90:19
x_vars::x_1_type
vectorial perturbation type
Definition: X_vars.f90:51
sol_vars
Variables pertaining to the solution quantities.
Definition: sol_vars.f90:4
num_vars::eq_jobs_lims
integer, dimension(:,:), allocatable, public eq_jobs_lims
data about eq jobs: [ , ] for all jobs
Definition: num_vars.f90:77
grid_vars::min_alpha
real(dp), public min_alpha
min. of field-line label [ ] in field-aligned grid
Definition: grid_vars.f90:26
num_vars::post_output_full
logical, public post_output_full
POST has output on full grids.
Definition: num_vars.f90:146
grid_vars::n_alpha
integer, public n_alpha
nr. of field-lines
Definition: grid_vars.f90:23
output_ops
Operations concerning giving output, on the screen as well as in output files.
Definition: output_ops.f90:5
num_vars::plot_flux_q
logical, public plot_flux_q
whether to plot flux quantities in real coordinates
Definition: num_vars.f90:106
num_vars::max_zeta_plot
real(dp), public max_zeta_plot
max. of zeta_plot
Definition: num_vars.f90:162
num_vars::rank
integer, public rank
MPI rank.
Definition: num_vars.f90:68
eq_ops::flux_q_plot
integer function, public flux_q_plot(grid_eq, eq)
Plots the flux quantities in the solution grid.
Definition: eq_ops.f90:3810
grid_utilities::nufft
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.
Definition: grid_utilities.f90:2901
input_utilities::dealloc_in
subroutine, public dealloc_in()
Cleans up input from equilibrium codes.
Definition: input_utilities.f90:268
pb3d_ops::get_pb3d_grid_size
integer function, public get_pb3d_grid_size(n, grid_name, rich_lvl, tot_rich)
get grid size
Definition: PB3D_ops.f90:1454
sol_ops::plot_sol_vec
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
input_utilities
Numerical utilities related to input.
Definition: input_utilities.f90:4
num_vars::post_style
integer, public post_style
style for POST (1: extended grid, 2: B-aligned grid)
Definition: num_vars.f90:98
eq_vars::eq_2_type
metric equilibrium type
Definition: eq_vars.f90:114
sol_ops::plot_harmonics
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
helena_vars::nchi
integer, public nchi
nr. of poloidal points
Definition: HELENA_vars.f90:35
num_vars::n_theta_plot
integer, public n_theta_plot
nr. of poloidal points in plot
Definition: num_vars.f90:156
eq_ops
Operations on the equilibrium variables.
Definition: eq_ops.f90:4
driver_post::plot_sol_val_comp
subroutine plot_sol_val_comp(sol_val_comp)
Plots difference between Eigenvalues and energy fraction.
Definition: driver_POST.f90:1113
grid_utilities::calc_xyz_grid
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.
Definition: grid_utilities.f90:799
sol_ops::decompose_energy
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
driver_post::open_decomp_log
integer function open_decomp_log()
Opens the decomposition log file.
Definition: driver_POST.f90:841
grid_ops
Operations that have to do with the grids and different coordinate systems.
Definition: grid_ops.f90:4
num_vars::norm_disc_prec_x
integer, public norm_disc_prec_x
precision for normal discretization for perturbation
Definition: num_vars.f90:121