5#include <PB3D_macros.h>
45 &sol_limits,r_F_eq,r_F_X,r_F_sol,jq)
result(ierr)
47 character(*),
parameter :: rout_name =
'calc_norm_range'
50 character(len=*),
intent(in) :: style
51 integer,
intent(inout),
optional :: in_limits(2)
52 integer,
intent(inout),
optional :: eq_limits(2)
53 integer,
intent(inout),
optional :: x_limits(2)
54 integer,
intent(inout),
optional :: sol_limits(2)
55 real(
dp),
intent(inout),
optional :: r_f_eq(:)
56 real(
dp),
intent(inout),
allocatable,
optional :: r_f_x(:)
57 real(
dp),
intent(inout),
optional :: r_f_sol(:)
58 real(
dp),
intent(in),
optional :: jq(:)
61 character(len=max_str_ln) :: err_msg
69 if (
present(in_limits))
then
74 err_msg =
'for PB3D: in, in_limits need to be provided'
78 if (
present(eq_limits))
then
82 err_msg =
'for PB3D: eq, eq_limits need to be provided'
86 if (
present(eq_limits).and.
present(x_limits).and.&
87 &
present(r_f_eq).and.
present(r_f_x).and.(
present(jq)))
then
93 err_msg =
'for PB3D: X, eq_limits, X_limits, r_F_eq, &
94 &r_F_X and jq need to be provided'
98 if (
present(sol_limits).and.
present(r_f_sol))
then
103 err_msg =
'for PB3D: sol, sol_limits and r_F_sol need to &
108 if (
present(eq_limits) .and.
present(x_limits) .and. &
109 &
present(sol_limits) .and.
present(r_f_eq) .and. &
110 &
present(r_f_x) .and.
present(r_f_sol))
then
112 &r_f_eq,r_f_x,r_f_sol)
115 err_msg =
'for POST, eq_limits, X_limits, sol_limits, &
116 &r_F_eq, r_F_X and r_F_sol need to be provided'
121 err_msg =
'Incorrect style "'//trim(style)//
'"'
146 character(*),
parameter :: rout_name =
'calc_norm_range_PB3D_in'
149 integer,
intent(inout) :: in_limits(2)
152 real(
dp),
allocatable :: flux_f(:), flux_e(:)
153 real(
dp) :: tot_min_r_in_f_con
154 real(
dp) :: tot_max_r_in_f_con
155 real(
dp) :: tot_min_r_in_e_con(1)
156 real(
dp) :: tot_max_r_in_e_con(1)
157 real(
dp) :: tot_min_r_in_e_dis
158 real(
dp) :: tot_max_r_in_e_dis
215 ierr =
spline(flux_f,flux_e,[tot_min_r_in_f_con],&
217 ierr =
spline(flux_f,flux_e,[tot_max_r_in_f_con],&
227 ierr =
con2dis(tot_min_r_in_e_con(1),tot_min_r_in_e_dis,flux_e)
229 ierr =
con2dis(tot_max_r_in_e_con(1),tot_max_r_in_e_dis,flux_e)
232 in_limits(1) = floor(tot_min_r_in_e_dis)
233 in_limits(2) = ceiling(tot_max_r_in_e_dis)
250 integer,
intent(inout) :: eq_limits(2)
257 if (
rank.gt.0) eq_limits(1) = eq_limits(1)+1
284 &r_F_X,jq)
result(ierr)
292 character(*),
parameter :: rout_name =
'calc_norm_range_PB3D_X'
295 integer,
intent(in) :: eq_limits(2)
296 integer,
intent(inout) :: x_limits(2)
297 real(
dp),
intent(in) :: r_f_eq(:)
298 real(
dp),
intent(inout),
allocatable :: r_f_x(:)
299 real(
dp),
intent(in) :: jq(:)
303 integer,
allocatable :: div(:)
304 real(
dp),
allocatable :: r_f_plot(:,:)
317 call writo(
'Using the equilibrium grid')
326 call writo(
'Using the solution grid')
329 allocate(div(
size(r_f_eq)-1))
330 do kd = 1,
size(r_f_eq)-1
336 allocate(r_f_x(
size(r_f_eq)+sum(div)))
337 do kd = 1,
size(r_f_eq)-1
339 &r_f_x(kd+sum(div(1:kd-1)):kd+sum(div(1:kd))),&
340 &r_f_eq(kd),r_f_eq(kd+1),excl_last=.true.)
343 r_f_x(
size(r_f_x)) = r_f_eq(
size(r_f_eq))
346 x_limits(1) = eq_limits(1)+sum(div(1:eq_limits(1)-1))
347 x_limits(2) = eq_limits(2)+sum(div(1:eq_limits(2)-1))
351 allocate(r_f_plot(
size(r_f_x),4))
352 r_f_plot(1:
size(r_f_eq),1) = r_f_eq
353 r_f_plot(1:
size(r_f_eq),3) = [(kd,kd=1,
size(r_f_eq))]
354 r_f_plot(
size(r_f_eq)+1:
size(r_f_x),1) = &
355 &r_f_eq(
size(r_f_eq))
356 r_f_plot(
size(r_f_eq)+1:
size(r_f_x),3) =
size(r_f_eq)
357 r_f_plot(:,2) = r_f_x
358 r_f_plot(:,4) = [(kd,kd=1,
size(r_f_x))]
361 &r_f_plot(:,3:4),x=r_f_plot(:,1:2),draw=.false.)
362 call draw_ex([
'eq',
'X '],
'r_F_X',2,1,&
367 call writo(
'Enriching the equilibrium grid to have jq &
370 if (any(div.gt.0))
then
371 call writo(
'Added '//trim(
i2str(sum(div)))//
' points')
373 call writo(
'But it was not necessary to add points')
394 character(*),
parameter :: rout_name =
'calc_norm_range_PB3D_sol'
397 integer,
intent(inout) :: sol_limits(2)
398 real(
dp),
intent(inout) :: r_f_sol(:)
399 integer,
intent(in),
optional ::
n_procs
403 integer,
allocatable :: loc_n_r_sol(:)
404 integer :: n_procs_loc
414 allocate(loc_n_r_sol(n_procs_loc))
415 loc_n_r_sol =
n_r_sol/n_procs_loc
416 loc_n_r_sol(1:mod(
n_r_sol,n_procs_loc)) = &
417 &loc_n_r_sol(1:mod(
n_r_sol,n_procs_loc)) + 1
420 if (
rank.lt.n_procs_loc)
then
422 &[sum(loc_n_r_sol(1:
rank))+1,sum(loc_n_r_sol(1:
rank+1))]
460 integer,
intent(inout) :: eq_limits(2)
461 integer,
intent(inout) :: X_limits(2)
462 integer,
intent(inout) :: sol_limits(2)
463 real(dp),
intent(in) :: r_F_eq(:)
464 real(dp),
intent(in) :: r_F_X(:)
465 real(dp),
intent(in) :: r_F_sol(:)
468 integer :: sol_limits_tot(2)
470 integer,
allocatable :: loc_n_r_sol(:)
471 real(dp) :: min_sol, max_sol
484 n_r_sol = sol_limits_tot(2)-sol_limits_tot(1)+1
489 loc_n_r_sol(1:mod(n_r_sol,
n_procs)) = &
490 &loc_n_r_sol(1:mod(n_r_sol,
n_procs)) + 1
493 sol_limits = [sum(loc_n_r_sol(1:
rank))+1,sum(loc_n_r_sol(1:
rank+1))]
494 sol_limits = sol_limits + sol_limits_tot(1) - 1
498 min_sol = minval(r_f_sol(sol_limits(1):sol_limits(2)))
499 max_sol = maxval(r_f_sol(sol_limits(1):sol_limits(2)))
507 x_limits = sol_limits
534 character(*),
parameter :: rout_name =
'setup_grid_eq'
537 type(
grid_type),
intent(inout) :: grid_eq
538 integer,
intent(in) :: eq_limits(2)
554 &
' normal and '//trim(
i2str(
n_par_x))//
' parallel points')
562 call writo(
'Identical to the equilibrium input grid')
567 call writo(
'Will be interpolated to a field-aligned grid &
571 ierr = grid_eq%init([
nchi,1,
n_r_eq],eq_limits)
575 do id = 1,grid_eq%n(1)
576 grid_eq%theta_E(id,:,:) =
chi_h(id)
578 grid_eq%zeta_E = 0._dp
581 grid_eq%theta_F = grid_eq%theta_E
582 grid_eq%zeta_F = grid_eq%zeta_E
604 character(*),
parameter :: rout_name =
'setup_grid_eq_B'
607 type(
grid_type),
intent(inout) :: grid_eq
608 type(
grid_type),
intent(inout) :: grid_eq_b
609 type(eq_1_type),
intent(in) :: eq
610 logical,
intent(in),
optional :: only_half_grid
613 character(len=max_str_ln) :: err_msg
625 err_msg =
'The grid is already field-aligned for VMEC'
631 &[grid_eq%i_min,grid_eq%i_max])
635 grid_eq_b%loc_r_E = grid_eq%loc_r_E
636 grid_eq_b%loc_r_F = grid_eq%loc_r_F
637 grid_eq_b%r_E = grid_eq%r_E
638 grid_eq_b%r_F = grid_eq%r_F
654 integer function setup_grid_x(grid_eq,grid_X,r_F_X,X_limits)
result(ierr)
659 character(*),
parameter :: rout_name =
'setup_grid_X'
662 type(grid_type),
intent(in) :: grid_eq
663 type(grid_type),
intent(inout) :: grid_x
664 real(
dp),
intent(in),
allocatable :: r_f_x(:)
665 integer,
intent(in) :: x_limits(2)
676 ierr = grid_eq%copy(grid_x)
680 ierr = grid_x%init([grid_eq%n(1:2),
size(r_f_x)],x_limits)
685 grid_x%loc_r_F = r_f_x(x_limits(1):x_limits(2))
688 ierr =
coord_f2e(grid_eq,grid_x%r_F,grid_x%r_E,&
689 &r_f_array=grid_eq%r_F,r_e_array=grid_eq%r_E)
691 ierr =
coord_f2e(grid_eq,grid_x%loc_r_F,grid_x%loc_r_E,&
692 &r_f_array=grid_eq%r_F,r_e_array=grid_eq%r_E)
696 do jd = 1,grid_eq%n(2)
697 do id = 1,grid_eq%n(1)
698 ierr =
spline(grid_eq%loc_r_F,grid_eq%theta_E(id,jd,:),&
699 &grid_x%loc_r_F,grid_x%theta_E(id,jd,:),&
702 ierr =
spline(grid_eq%loc_r_F,grid_eq%zeta_E(id,jd,:),&
703 &grid_x%loc_r_F,grid_x%zeta_E(id,jd,:),&
706 ierr =
spline(grid_eq%loc_r_F,grid_eq%theta_F(id,jd,:),&
707 &grid_x%loc_r_F,grid_x%theta_F(id,jd,:),&
710 ierr =
spline(grid_eq%loc_r_F,grid_eq%zeta_F(id,jd,:),&
711 &grid_x%loc_r_F,grid_x%zeta_F(id,jd,:),&
727 &sol_limits)
result(ierr)
732 character(*),
parameter :: rout_name =
'setup_grid_sol'
735 type(grid_type),
intent(in) :: grid_eq
736 type(grid_type),
intent(in) :: grid_x
737 type(grid_type),
intent(inout) :: grid_sol
738 real(
dp),
intent(in) :: r_f_sol(:)
739 integer,
intent(in) :: sol_limits(2)
745 call writo(trim(
i2str(
size(r_f_sol)))//
' normal points')
750 ierr = grid_sol%init([0,0,
size(r_f_sol)],sol_limits,&
755 grid_sol%r_F = r_f_sol
756 grid_sol%loc_r_F = r_f_sol(sol_limits(1):sol_limits(2))
759 ierr =
coord_f2e(grid_eq,grid_sol%r_F,grid_sol%r_E,&
760 &r_f_array=grid_eq%r_F,r_e_array=grid_eq%r_E)
762 ierr =
coord_f2e(grid_eq,grid_sol%loc_r_F,grid_sol%loc_r_E,&
763 &r_f_array=grid_eq%r_F,r_e_array=grid_eq%r_E)
768 ierr = grid_sol%init([0,0,grid_x%n(3)],&
769 &[grid_x%i_min,grid_x%i_max],grid_x%divided)
771 grid_sol%r_F = grid_x%r_F
772 grid_sol%loc_r_F = grid_x%r_F(sol_limits(1):sol_limits(2))
773 grid_sol%r_E = grid_x%r_E
774 grid_sol%loc_r_E = grid_x%r_E(sol_limits(1):sol_limits(2))
810 character(*),
parameter :: rout_name =
'calc_ang_grid_eq_B'
813 type(
grid_type),
intent(inout) :: grid_eq
814 type(
eq_1_type),
intent(in),
target :: eq
815 logical,
intent(in),
optional :: only_half_grid
818 character(len=max_str_ln) :: err_msg
819 real(
dp),
allocatable :: r_e_loc(:)
820 real(
dp),
pointer :: flux_f(:) => null()
821 real(
dp),
pointer :: flux_e(:) => null()
822 real(
dp) :: r_f_factor, r_e_factor
824 integer :: id, jd, kd
825 integer :: n_par_x_loc
826 logical :: only_half_grid_loc
827 real(
dp),
allocatable :: theta_f_loc(:,:,:)
828 real(
dp),
allocatable :: zeta_f_loc(:,:,:)
836 only_half_grid_loc = .false.
837 if (
present(only_half_grid)) only_half_grid_loc = only_half_grid
844 call writo(
'for '//trim(
i2str(grid_eq%n(3)))//&
851 if (only_half_grid_loc)
call writo(
'for this Richardson level, only &
852 &the even points are setup up')
866 flux_e => eq%flux_p_E(:,0)
868 flux_e => eq%flux_t_E(:,0)
873 flux_e => eq%flux_p_E(:,0)
880 flux_f => eq%flux_p_E(:,0)
883 flux_f => eq%flux_t_E(:,0)
884 r_f_factor = pmone*2*
pi
895 do kd = 1,grid_eq%loc_n_r
896 zeta_f_loc(:,:,kd) = pmone*eq%q_saf_E(kd,0)*&
900 zeta_f_loc(:,jd,:) = zeta_f_loc(:,jd,:) +
alpha(jd)
906 do kd = 1,grid_eq%loc_n_r
907 theta_f_loc(:,:,kd) = pmone*eq%rot_t_E(kd,0)*&
911 theta_f_loc(:,jd,:) = theta_f_loc(:,jd,:) -
alpha(jd)
916 if (only_half_grid_loc)
then
919 &theta_f_loc(2*id,:,:)
921 &zeta_f_loc(2*id,:,:)
931 allocate(r_e_loc(
size(flux_f)))
936 call writo(
'convert F to E coordinates')
938 ierr =
coord_f2e(grid_eq,grid_eq%loc_r_F,grid_eq%theta_F,&
939 &grid_eq%zeta_F,r_e_loc,grid_eq%theta_E,grid_eq%zeta_E,&
940 &r_f_array=flux_f/r_f_factor,r_e_array=flux_e/r_e_factor)
945 if (maxval(abs(grid_eq%loc_r_E-r_e_loc)).gt.10*
tol_zero)
then
947 err_msg =
'loc_r_E of equilibrium grid is not recovered'
954 deallocate(theta_f_loc,zeta_f_loc)
955 allocate(theta_f_loc(grid_eq%n(1),grid_eq%n(2),grid_eq%loc_n_r))
956 allocate(zeta_f_loc(grid_eq%n(1),grid_eq%n(2),grid_eq%loc_n_r))
957 ierr =
coord_e2f(grid_eq,grid_eq%loc_r_E,grid_eq%theta_E,&
958 &grid_eq%zeta_E,grid_eq%loc_r_F,theta_f_loc,zeta_f_loc,&
959 &r_e_array=flux_e/r_e_factor,r_f_array=flux_f/r_f_factor)
964 &grid_eq%n,[0,0,grid_eq%i_min-1],
'test whether F variable are &
965 &recovered',output_message=.true.)
967 &grid_eq%n,[0,0,grid_eq%i_min-1],
'test whether F variable are &
968 &recovered',output_message=.true.)
974 nullify(flux_f,flux_e)
1000 character(*),
parameter :: rout_name =
'redistribute_output_grid'
1004 type(
grid_type),
intent(inout) :: grid_out
1005 logical,
intent(in),
optional :: no_outer_trim
1009 integer :: eq_limits(2)
1010 integer :: sol_limits(2)
1012 integer :: i_lim_tot(2)
1013 integer :: i_lim_out(2)
1014 integer :: lims(2), lims_dis(2)
1015 real(
dp),
allocatable :: r_f_sol(:)
1016 real(
dp),
allocatable :: temp_var(:)
1017 integer,
allocatable :: temp_lim(:)
1018 integer,
allocatable :: eq_limits_tot(:,:)
1019 logical :: no_outer_trim_loc
1026 ierr =
calc_norm_range(
'PB3D_sol',sol_limits=sol_limits,r_f_sol=r_f_sol)
1034 allocate(eq_limits_tot(2,
n_procs))
1036 ierr =
get_ser_var(eq_limits(id:id),temp_lim,scatter=.true.)
1038 eq_limits_tot(id,:) = temp_lim
1042 no_outer_trim_loc = .false.
1043 if (
present(no_outer_trim)) no_outer_trim_loc = no_outer_trim
1044 if (no_outer_trim_loc)
then
1046 i_lim_tot = [1,n_out(3)]
1047 i_lim_out = eq_limits
1049 n_out(1:2) = grid%n(1:2)
1050 n_out(3) = eq_limits_tot(2,
n_procs)-eq_limits_tot(1,1)+1
1051 i_lim_tot = [eq_limits_tot(1,1),eq_limits_tot(2,
n_procs)]
1052 i_lim_out = eq_limits-eq_limits_tot(1,1)+1
1054 ierr = grid_out%init(n_out,i_lim_out)
1058 lims(1) = product(grid%n(1:2))*(grid%i_min-1)+1
1059 lims(2) = product(grid%n(1:2))*grid%i_max
1060 lims_dis(1) = product(grid%n(1:2))*(eq_limits(1)-1)+1
1061 lims_dis(2) = product(grid%n(1:2))*eq_limits(2)
1062 allocate(temp_var(lims_dis(2)-lims_dis(1)+1))
1066 grid_out%r_F = grid%r_F(i_lim_tot(1):i_lim_tot(2))
1068 grid_out%r_E = grid%r_E(i_lim_tot(1):i_lim_tot(2))
1073 &temp_var,lims,lims_dis)
1075 grid_out%theta_F = reshape(temp_var,shape(grid_out%theta_F))
1078 &temp_var,lims,lims_dis)
1080 grid_out%zeta_F = reshape(temp_var,shape(grid_out%zeta_F))
1083 &temp_var,lims,lims_dis)
1085 grid_out%theta_E = reshape(temp_var,shape(grid_out%theta_E))
1088 &temp_var,lims,lims_dis)
1090 grid_out%zeta_E = reshape(temp_var,shape(grid_out%zeta_E))
1092 if (grid_out%divided)
then
1093 grid_out%loc_r_F = grid_out%r_F(grid_out%i_min:grid_out%i_max)
1094 grid_out%loc_r_E = grid_out%r_E(grid_out%i_min:grid_out%i_max)
1121 character(*),
parameter :: rout_name =
'magn_grid_plot'
1124 type(grid_type),
intent(in) :: grid
1127 real(
dp),
allocatable :: x_1(:,:,:), y_1(:,:,:), z_1(:,:,:)
1128 real(
dp),
allocatable :: x_2(:,:,:), y_2(:,:,:), z_2(:,:,:)
1129 real(
dp),
pointer :: x_1_tot(:,:,:) => null()
1130 real(
dp),
pointer :: y_1_tot(:,:,:) => null()
1131 real(
dp),
pointer :: z_1_tot(:,:,:) => null()
1132 real(
dp),
pointer :: x_2_tot(:,:,:) => null()
1133 real(
dp),
pointer :: y_2_tot(:,:,:) => null()
1134 real(
dp),
pointer :: z_2_tot(:,:,:) => null()
1135 type(grid_type) :: grid_ext
1136 type(grid_type) :: grid_plot
1137 integer :: n_theta_plot_old
1138 integer :: n_zeta_plot_old
1139 real(
dp) :: min_theta_plot_old, max_theta_plot_old
1140 real(
dp) :: min_zeta_plot_old, max_zeta_plot_old
1141 character(len=max_str_ln) :: anim_name
1149 call writo(
'Plotting magnetic field and flux surfaces')
1188 &grid_plot%trigon_factors)
1193 anim_name =
'Magnetic field in flux surfaces'
1196 call writo(
'writing flux surfaces')
1199 allocate(x_1(grid_plot%n(1),grid_plot%n(2),grid_plot%loc_n_r))
1200 allocate(y_1(grid_plot%n(1),grid_plot%n(2),grid_plot%loc_n_r))
1201 allocate(z_1(grid_plot%n(1),grid_plot%n(2),grid_plot%loc_n_r))
1206 call grid_plot%dealloc()
1213 call get_full_xyz(x_1,y_1,z_1,x_1_tot,y_1_tot,z_1_tot,
'flux surfaces')
1216 call writo(
'writing field lines')
1225 &grid_plot%trigon_factors)
1230 allocate(x_2(grid_plot%n(1),grid_plot%n(2),grid_plot%loc_n_r))
1231 allocate(y_2(grid_plot%n(1),grid_plot%n(2),grid_plot%loc_n_r))
1232 allocate(z_2(grid_plot%n(1),grid_plot%n(2),grid_plot%loc_n_r))
1237 call grid_plot%dealloc()
1238 call grid_ext%dealloc()
1245 call get_full_xyz(x_2,y_2,z_2,x_2_tot,y_2_tot,z_2_tot,
'field lines')
1247 ierr = magn_grid_plot_hdf5(x_1_tot,x_2_tot,y_1_tot,y_2_tot,&
1248 &z_1_tot,z_2_tot,anim_name)
1252 deallocate(x_1,y_1,z_1)
1253 deallocate(x_2,y_2,z_2)
1254 nullify(x_1_tot,y_1_tot,z_1_tot)
1255 nullify(x_2_tot,y_2_tot,z_2_tot)
1259 call writo(
'Done plotting magnetic field and flux surfaces')
1263 subroutine get_full_xyz(X,Y,Z,X_tot,Y_tot,Z_tot,merge_name)
1267 real(
dp),
intent(in),
target :: x(:,:,:), y(:,:,:), z(:,:,:)
1268 real(
dp),
intent(inout),
pointer :: x_tot(:,:,:)
1269 real(
dp),
intent(inout),
pointer :: y_tot(:,:,:)
1270 real(
dp),
intent(inout),
pointer :: z_tot(:,:,:)
1271 character(len=*) :: merge_name
1274 real(
dp),
allocatable :: ser_xyz_loc(:)
1275 integer,
allocatable :: tot_dim(:)
1278 if (grid%divided)
then
1280 call writo(
'Merging local plots for '//merge_name)
1288 allocate(x_tot(
size(x,1),
size(x,2),sum(tot_dim)))
1289 allocate(y_tot(
size(x,1),
size(x,2),sum(tot_dim)))
1290 allocate(z_tot(
size(x,1),
size(x,2),sum(tot_dim)))
1293 allocate(ser_xyz_loc(
size(x(:,:,1))*sum(tot_dim)))
1294 ierr =
get_ser_var(reshape(x,[
size(x)]),ser_xyz_loc)
1296 if (
rank.eq.0) x_tot = reshape(ser_xyz_loc,shape(x_tot))
1297 ierr =
get_ser_var(reshape(y,[
size(y)]),ser_xyz_loc)
1299 if (
rank.eq.0) y_tot = reshape(ser_xyz_loc,shape(y_tot))
1300 ierr =
get_ser_var(reshape(z,[
size(z)]),ser_xyz_loc)
1302 if (
rank.eq.0) z_tot = reshape(ser_xyz_loc,shape(z_tot))
1308 end subroutine get_full_xyz
1312 integer function magn_grid_plot_hdf5(X_1,X_2,Y_1,Y_2,Z_1,Z_2,&
1313 &anim_name)
result(ierr)
1322 character(*),
parameter :: rout_name =
'magn_grid_plot_HDF5'
1325 real(
dp),
intent(in),
pointer :: x_1(:,:,:), y_1(:,:,:), z_1(:,:,:)
1326 real(
dp),
intent(in),
pointer :: x_2(:,:,:), y_2(:,:,:), z_2(:,:,:)
1327 character(len=*),
intent(in) :: anim_name
1330 character(len=max_str_ln) :: plot_title(2)
1331 character(len=max_str_ln) :: file_name
1340 integer :: loc_dim(3,2)
1349 call writo(
'Drawing animation with HDF5')
1353 loc_dim(:,1) = [
size(x_1,1),
size(x_1,2),1]
1354 loc_dim(:,2) = [
size(x_2,1),1,1]
1355 n_r =
size(x_1,3) - 1
1358 plot_title(1) =
'Magnetic Flux Surfaces'
1359 plot_title(2) =
'Magnetic Field Lines'
1360 file_name =
'field_lines_in_flux_surfaces_R_'//&
1365 &descr=anim_name,ind_plot=.true.)
1371 allocate(space_col_grids(n_r))
1382 &
'X_surf_'//trim(
i2str(id)),x_1(:,:,id:id),loc_dim(:,1))
1387 &
'Y_surf_'//trim(
i2str(id)),y_1(:,:,id:id),loc_dim(:,1))
1392 &
'Z_surf_'//trim(
i2str(id)),z_1(:,:,id:id),loc_dim(:,1))
1400 &grid_top=top,grid_geom=geom,reset=.true.)
1411 &
'X_field_'//trim(
i2str(id))//
'_'//trim(
i2str(jd)),&
1412 &x_2(:,jd:jd,id+1:id+1),loc_dim(:,2))
1417 &
'Y_field_'//trim(
i2str(id))//
'_'//trim(
i2str(jd)),&
1418 &y_2(:,jd:jd,id+1:id+1),loc_dim(:,2))
1423 &
'Z_field_'//trim(
i2str(id))//
'_'//trim(
i2str(jd)),&
1424 &z_2(:,jd:jd,id+1:id+1),loc_dim(:,2))
1432 &grid_top=top,grid_geom=geom,reset=.true.)
1439 &
'spatial collection',3,grid_time=id*1._dp,&
1440 &grid_grids=grids,reset=.true.)
1446 &grid_grids=space_col_grids,reset=.true.)
1471 end function magn_grid_plot_hdf5
1488 &par_div,remove_previous_arrs)
result(ierr)
1495 character(*),
parameter :: rout_name =
'print_output_grid'
1498 type(grid_type),
intent(in) :: grid
1499 character(len=*),
intent(in) :: grid_name
1500 character(len=*),
intent(in) :: data_name
1501 integer,
intent(in),
optional :: rich_lvl
1502 logical,
intent(in),
optional :: par_div
1503 logical,
intent(in),
optional :: remove_previous_arrs
1507 integer :: par_id(2)
1508 type(grid_type) :: grid_trim
1509 type(
var_1d_type),
allocatable,
target :: grid_1d(:)
1510 type(
var_1d_type),
pointer :: grid_1d_loc => null()
1512 logical :: par_div_loc
1518 call writo(
'Write '//trim(grid_name)//
' grid variables to output &
1527 par_div_loc = .false.
1528 if (
present(par_div)) par_div_loc = par_div
1532 par_id = [1,n_tot(1)]
1533 if (grid_trim%n(1).gt.0 .and. par_div_loc)
then
1545 grid_1d_loc => grid_1d(id); id = id+1
1546 grid_1d_loc%var_name =
'n'
1547 allocate(grid_1d_loc%tot_i_min(1),grid_1d_loc%tot_i_max(1))
1548 allocate(grid_1d_loc%loc_i_min(1),grid_1d_loc%loc_i_max(1))
1549 grid_1d_loc%tot_i_min = [1]
1550 grid_1d_loc%tot_i_max = [3]
1551 grid_1d_loc%loc_i_min = [1]
1552 grid_1d_loc%loc_i_max = [3]
1553 allocate(grid_1d_loc%p(3))
1554 grid_1d_loc%p = n_tot
1557 grid_1d_loc => grid_1d(id); id = id+1
1558 grid_1d_loc%var_name =
'r_F'
1559 allocate(grid_1d_loc%tot_i_min(1),grid_1d_loc%tot_i_max(1))
1560 allocate(grid_1d_loc%loc_i_min(1),grid_1d_loc%loc_i_max(1))
1561 grid_1d_loc%tot_i_min = [1]
1562 grid_1d_loc%tot_i_max = [n_tot(3)]
1563 grid_1d_loc%loc_i_min = [grid_trim%i_min]
1564 grid_1d_loc%loc_i_max = [grid_trim%i_max]
1565 allocate(grid_1d_loc%p(
size(grid_trim%loc_r_F)))
1566 grid_1d_loc%p = grid_trim%loc_r_F
1569 grid_1d_loc => grid_1d(id); id = id+1
1570 grid_1d_loc%var_name =
'r_E'
1571 allocate(grid_1d_loc%tot_i_min(1),grid_1d_loc%tot_i_max(1))
1572 allocate(grid_1d_loc%loc_i_min(1),grid_1d_loc%loc_i_max(1))
1573 grid_1d_loc%tot_i_min = [1]
1574 grid_1d_loc%tot_i_max = [n_tot(3)]
1575 grid_1d_loc%loc_i_min = [grid_trim%i_min]
1576 grid_1d_loc%loc_i_max = [grid_trim%i_max]
1577 allocate(grid_1d_loc%p(
size(grid_trim%loc_r_E)))
1578 grid_1d_loc%p = grid_trim%loc_r_E
1581 if (product(grid%n(1:2)).ne.0)
then
1583 grid_1d_loc => grid_1d(id); id = id+1
1584 grid_1d_loc%var_name =
'theta_F'
1585 allocate(grid_1d_loc%tot_i_min(3),grid_1d_loc%tot_i_max(3))
1586 allocate(grid_1d_loc%loc_i_min(3),grid_1d_loc%loc_i_max(3))
1587 grid_1d_loc%tot_i_min = [1,1,1]
1588 grid_1d_loc%tot_i_max = n_tot
1589 grid_1d_loc%loc_i_min = [par_id(1),1,grid_trim%i_min]
1590 grid_1d_loc%loc_i_max = [par_id(2),n_tot(2),grid_trim%i_max]
1591 allocate(grid_1d_loc%p(
size(grid_trim%theta_F)))
1592 grid_1d_loc%p = reshape(grid_trim%theta_F,[
size(grid_trim%theta_F)])
1595 grid_1d_loc => grid_1d(id); id = id+1
1596 grid_1d_loc%var_name =
'theta_E'
1597 allocate(grid_1d_loc%tot_i_min(3),grid_1d_loc%tot_i_max(3))
1598 allocate(grid_1d_loc%loc_i_min(3),grid_1d_loc%loc_i_max(3))
1599 grid_1d_loc%tot_i_min = [1,1,1]
1600 grid_1d_loc%tot_i_max = n_tot
1601 grid_1d_loc%loc_i_min = [par_id(1),1,grid_trim%i_min]
1602 grid_1d_loc%loc_i_max = [par_id(2),n_tot(2),grid_trim%i_max]
1603 allocate(grid_1d_loc%p(
size(grid_trim%theta_E)))
1604 grid_1d_loc%p = reshape(grid_trim%theta_E,[
size(grid_trim%theta_E)])
1607 grid_1d_loc => grid_1d(id); id = id+1
1608 grid_1d_loc%var_name =
'zeta_F'
1609 allocate(grid_1d_loc%tot_i_min(3),grid_1d_loc%tot_i_max(3))
1610 allocate(grid_1d_loc%loc_i_min(3),grid_1d_loc%loc_i_max(3))
1611 grid_1d_loc%tot_i_min = [1,1,1]
1612 grid_1d_loc%tot_i_max = n_tot
1613 grid_1d_loc%loc_i_min = [par_id(1),1,grid_trim%i_min]
1614 grid_1d_loc%loc_i_max = [par_id(2),n_tot(2),grid_trim%i_max]
1615 allocate(grid_1d_loc%p(
size(grid_trim%zeta_F)))
1616 grid_1d_loc%p = reshape(grid_trim%zeta_F,[
size(grid_trim%zeta_F)])
1619 grid_1d_loc => grid_1d(id); id = id+1
1620 grid_1d_loc%var_name =
'zeta_E'
1621 allocate(grid_1d_loc%tot_i_min(3),grid_1d_loc%tot_i_max(3))
1622 allocate(grid_1d_loc%loc_i_min(3),grid_1d_loc%loc_i_max(3))
1623 grid_1d_loc%tot_i_min = [1,1,1]
1624 grid_1d_loc%tot_i_max = n_tot
1625 grid_1d_loc%loc_i_min = [par_id(1),1,grid_trim%i_min]
1626 grid_1d_loc%loc_i_max = [par_id(2),n_tot(2),grid_trim%i_max]
1627 allocate(grid_1d_loc%p(
size(grid_trim%zeta_E)))
1628 grid_1d_loc%p = reshape(grid_trim%zeta_E,[
size(grid_trim%zeta_E)])
1633 &
'grid_'//trim(data_name),rich_lvl=rich_lvl,&
1634 &ind_print=.not.grid_trim%divided,&
1635 &remove_previous_arrs=remove_previous_arrs)
1639 call grid_trim%dealloc()
1642 nullify(grid_1d_loc)
subroutine calc_norm_range_post(eq_limits, x_limits, sol_limits, r_f_eq, r_f_x, r_f_sol)
POST version.
integer function calc_norm_range_pb3d_sol(sol_limits, r_f_sol, n_procs)
PB3D solution version.
subroutine calc_norm_range_pb3d_eq(eq_limits)
PB3D equilibrium version.
integer function calc_norm_range_pb3d_in(in_limits)
PB3D input version.
integer function calc_norm_range_pb3d_x(eq_limits, x_limits, r_f_eq, r_f_x, jq)
PB3D perturbation version.
Calculate grid of equidistant points, where optionally the last point can be excluded.
Converts Equilibrium coordinates . to Flux coordinates .
Converts Flux coordinates to Equilibrium coordinates .
Deallocates XML_str_type.
Gather parallel variable in serial version on group master.
Convert between points from a continuous grid to a discrete grid.
Convert between points from a discrete grid to a continuous grid.
Rounds an arry of values to limits, with a tolerance that can optionally be modified.
Wrapper to the pspline library, making it easier to use for 1-D applications where speed is not the m...
Print 2-D output on a file.
Numerical utilities related to equilibrium variables.
subroutine, public print_info_eq(n_par_x_rich)
Prints information for equilibrium parallel job.
Variables that have to do with equilibrium quantities and the grid used in the calculations:
real(dp), public max_flux_f
max. flux in Flux coordinates, set in calc_norm_range_PB3D_in
real(dp), public max_flux_e
max. flux in Equilibrium coordinates, set in calc_norm_range_PB3D_in
Operations that have to do with the grids and different coordinate systems.
integer function, public calc_ang_grid_eq_b(grid_eq, eq, only_half_grid)
Calculate equilibrium grid that follows magnetic field lines.
integer function, public print_output_grid(grid, grid_name, data_name, rich_lvl, par_div, remove_previous_arrs)
Print grid variables to an output file.
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.
integer function, public redistribute_output_grid(grid, grid_out, no_outer_trim)
Redistribute a grid to match the normal distribution of solution grid.
integer function, public setup_grid_sol(grid_eq, grid_x, grid_sol, r_f_sol, sol_limits)
Sets up the general solution grid, in which the solution variables are calculated.
logical, public debug_calc_ang_grid_eq_b
plot debug information for calc_ang_grid_eq_b()
integer function, public setup_grid_eq_b(grid_eq, grid_eq_b, eq, only_half_grid)
Sets up the field-aligned equilibrium grid.
integer function, public magn_grid_plot(grid)
Plots the grid in real 3-D space.
integer function, public setup_grid_eq(grid_eq, eq_limits)
Sets up the equilibrium grid.
integer function, public setup_grid_x(grid_eq, grid_x, r_f_x, x_limits)
Sets up the general perturbation grid, in which the perturbation variables are calculated.
Numerical utilities related to the grids and different coordinate systems.
subroutine, public find_compr_range(r_f, lim_r, lim_id)
finds smallest range that comprises a minimum and maximum value.
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 trim_grid(grid_in, grid_out, norm_id)
Trim a grid, removing any overlap between the different regions.
integer function, public calc_n_par_x_rich(n_par_x_rich, only_half_grid)
Calculates the local number of parallel grid points for this Richardson level, taking into account th...
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.
Variables pertaining to the different grids used.
real(dp), dimension(:), allocatable, public alpha
field line label alpha
real(dp), public min_par_x
min. of parallel coordinate [ ] in field-aligned grid
integer, public n_alpha
nr. of field-lines
integer, public n_r_eq
nr. of normal points in equilibrium grid
real(dp), public max_par_x
max. of parallel coordinate [ ] in field-aligned grid
integer, public n_r_in
nr. of normal points in input grid
integer, public n_r_sol
nr. of normal points in solution grid
Operations on HDF5 and XDMF variables.
integer function, public print_hdf5_grid(grid_id, grid_name, grid_type, grid_time, grid_top, grid_geom, grid_atts, grid_grids, reset, ind_plot)
Prints an HDF5 grid.
integer function, public print_hdf5_arrs(vars, pb3d_name, head_name, rich_lvl, disp_info, ind_print, remove_previous_arrs)
Prints a series of arrays, in the form of an array of pointers, to an HDF5 file.
integer function, public add_hdf5_item(file_info, xdmf_item, reset, ind_plot)
Add an XDMF item to a HDF5 file.
integer function, public open_hdf5_file(file_info, file_name, sym_type, descr, ind_plot, cont_plot)
Opens an HDF5 file and accompanying xmf file and returns the handles.
subroutine, public print_hdf5_geom(geom_id, geom_type, geom_dataitems, reset, ind_plot)
Prints an HDF5 geometry.
integer function, public close_hdf5_file(file_info, ind_plot, cont_plot)
Closes an HDF5 file and writes the accompanying xmf file.
integer function, public print_hdf5_3d_data_item(dataitem_id, file_info, var_name, var, dim_tot, loc_dim, loc_offset, init_val, ind_plot, cont_plot)
Prints an HDF5 data item.
subroutine, public print_hdf5_top(top_id, top_type, top_n_elem, ind_plot)
Prints an HDF5 topology.
Variables pertaining to HDF5 and XDMF.
integer, parameter, public max_dim_var_1d
maximum dimension of var_1D
Variables that have to do with HELENA quantities.
integer, public nchi
nr. of poloidal points
real(dp), dimension(:), allocatable, public chi_h
poloidal angle
real(dp), dimension(:,:), allocatable, public flux_p_h
poloidal flux
real(dp), dimension(:,:), allocatable, public flux_t_h
toroidal flux
Numerical utilities related to giving output.
subroutine, public lvl_ud(inc)
Increases/decreases lvl of output.
subroutine, public writo(input_str, persistent, error, warning, alert)
Write output to file identified by output_i.
Numerical utilities related to MPI.
integer function, public redistribute_var(var, dis_var, lims, lims_dis)
Redistribute variables according to new limits.
Numerical variables used by most other modules.
integer, public sol_n_procs
nr. of MPI processes for solution with SLEPC
integer, parameter, public dp
double precision
integer, public n_theta_plot
nr. of poloidal points in plot
integer, public norm_disc_prec_sol
precision for normal discretization for solution
real(dp), public max_r_plot
max. of r_plot
real(dp), public min_theta_plot
min. of theta_plot
real(dp), parameter, public pi
real(dp), public max_zeta_plot
max. of zeta_plot
real(dp), public max_njq_change
maximum change of prim. mode number times saf. fac. / rot. transf. when using X_style 2 (fast)
integer, public n_procs
nr. of MPI processes
integer, parameter, public max_str_ln
maximum length of strings
integer, public n_zeta_plot
nr. of toroidal points in plot
integer, dimension(:,:), allocatable, public eq_jobs_lims
data about eq jobs: [ , ] for all jobs
integer, public x_grid_style
style for normal component of X grid (1: eq, 2: sol, 3: enriched)
real(dp), public min_zeta_plot
min. of zeta_plot
integer, public eq_style
either 1 (VMEC) or 2 (HELENA)
character(len=max_str_ln), public pb3d_name
name of PB3D output file
integer, public norm_disc_prec_eq
precision for normal discretization for equilibrium
real(dp), public min_r_plot
min. of r_plot
integer, public rank
MPI rank.
integer, public norm_disc_prec_x
precision for normal discretization for perturbation
real(dp), public max_theta_plot
max. of theta_plot
logical, public use_pol_flux_e
whether poloidal flux is used in E coords.
integer, public eq_job_nr
nr. of eq job
logical, public use_pol_flux_f
whether poloidal flux is used in F coords.
real(dp), public tol_zero
tolerance for zeros
logical, public no_plots
no plots made
Operations concerning giving output, on the screen as well as in output files.
subroutine, public plot_diff_hdf5(a, b, file_name, tot_dim, loc_offset, descr, output_message)
Takes two input vectors and plots these as well as the relative and absolute difference in a HDF5 fil...
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.
Variables concerning Richardson extrapolation.
integer, public rich_lvl
current level of Richardson extrapolation
integer, public n_par_x
nr. of parallel points in field-aligned grid
elemental character(len=max_str_ln) function, public i2str(k)
Convert an integer to string.
elemental character(len=max_str_ln) function, public r2strt(k)
Convert a real (double) to string.
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.
Variables that concern the output of VMEC.
real(dp), dimension(:,:), allocatable, public flux_t_v
toroidal flux
real(dp), dimension(:,:), allocatable, public flux_p_v
poloidal flux
Variables pertaining to the perturbation quantities.
real(dp), public max_r_sol
max. normal range for pert.
real(dp), public min_r_sol
min. normal range for pert.
integer, public prim_x
n_X (pol. flux) or m_X (tor. flux)
HDF5 data type, containing the information about HDF5 files.
1D equivalent of multidimensional variables, used for internal HDF5 storage.
XML strings used in XDMF.