5 #include <PB3D_macros.h>
49 module procedure coord_f2e_r
51 module procedure coord_f2e_rtz
77 module procedure calc_eqd_grid_1d
79 module procedure calc_eqd_grid_3d
111 module procedure calc_tor_diff_0d
113 module procedure calc_tor_diff_2d
118 integer function coord_f2e_rtz(grid_eq,r_F,theta_F,zeta_F,r_E,&
119 &theta_E,zeta_E,r_F_array,r_E_array,ord)
result(ierr)
124 character(*),
parameter :: rout_name =
'coord_F2E_rtz'
128 real(dp),
intent(in) :: r_f(:)
129 real(dp),
intent(in) :: theta_f(:,:,:)
130 real(dp),
intent(in) :: zeta_f(:,:,:)
131 real(dp),
intent(inout) :: r_e(:)
132 real(dp),
intent(inout) :: theta_e(:,:,:)
133 real(dp),
intent(inout) :: zeta_e(:,:,:)
134 real(dp),
intent(in),
optional,
target :: r_f_array(:)
135 real(dp),
intent(in),
optional,
target :: r_e_array(:)
136 integer,
intent(in),
optional :: ord
139 character(len=max_str_ln) :: err_msg
141 real(dp),
allocatable :: l_v_c_loc(:,:)
142 real(dp),
allocatable :: l_v_s_loc(:,:)
149 dims = shape(theta_e)
153 if (
present(ord)) ord_loc = ord
156 if (dims(3).ne.
size(r_f) .or. dims(3).ne.
size(r_e))
then
158 err_msg =
'r_F and r_E need to have the correct dimensions'
161 if (
present(r_f_array).neqv.
present(r_e_array))
then
163 err_msg =
'both r_F_array and r_E_array have to be provided'
168 ierr = coord_f2e_r(grid_eq,r_f,r_e,r_f_array,r_e_array)
176 ierr = coord_f2e_vmec()
186 integer function coord_f2e_vmec()
result(ierr)
192 character(*),
parameter :: rout_name =
'coord_F2E_VMEC'
196 real(dp),
pointer :: loc_r_f(:) => null()
197 real(dp),
allocatable :: theta_e_guess_3d(:,:,:)
198 real(dp),
allocatable :: lam(:,:,:,:)
204 if (
present(r_f_array))
then
207 loc_r_f => grid_eq%loc_r_F
214 allocate(l_v_c_loc(mnmax_v,dims(3)))
215 allocate(l_v_s_loc(mnmax_v,dims(3)))
219 ierr =
spline(loc_r_f,l_v_c(id,grid_eq%i_min:grid_eq%i_max,0),&
222 ierr =
spline(loc_r_f,l_v_s(id,grid_eq%i_min:grid_eq%i_max,0),&
228 allocate(theta_e_guess_3d(dims(1),dims(2),dims(3)))
229 allocate(lam(dims(1),dims(2),dims(3),0:1))
236 ierr =
fourier2real(l_v_c_loc,l_v_s_loc,theta_f,zeta_e,&
237 &lam(:,:,:,id),sym=[is_asym_v,.true.],deriv=[id,0])
240 theta_e_guess_3d = theta_f - lam(:,:,:,0)/(1+lam(:,:,:,1))
245 &theta_e_guess_3d,output=.true.)
246 if (err_msg.ne.
'')
then
252 if (maxval(abs(fun_pol(dims,theta_e,0))).gt.tol_zero*100)
then
254 &fun_pol(dims,theta_e,0))
255 err_msg =
'In coord_F2E_VMEC, calculating whether f=0 as a &
256 &check, yields a deviation from 0 of '//trim(
r2strt(&
257 &maxval(abs(fun_pol(dims,theta_e,0)))))//
'. See output.'
264 end function coord_f2e_vmec
270 function fun_pol(dims,theta_E_in,dpol)
271 character(*),
parameter :: rout_name =
'fun_pol'
274 integer,
intent(in) :: dims(3)
275 real(dp),
intent(in) :: theta_e_in(dims(1),dims(2),dims(3))
276 integer,
intent(in) :: dpol
277 real(dp) :: fun_pol(dims(1),dims(2),dims(3))
280 real(dp) :: lam(dims(1),dims(2),dims(3))
286 ierr =
fourier2real(l_v_c_loc,l_v_s_loc,theta_e_in,zeta_e,lam,&
287 &sym=[is_asym_v,.true.],deriv=[dpol,0])
292 fun_pol = theta_f - theta_e_in - lam
293 else if (dpol.eq.1)
then
295 else if (dpol.gt.1)
then
299 end function coord_f2e_rtz
301 integer function coord_f2e_r(grid_eq,r_F,r_E,r_F_array,r_E_array) &
306 character(*),
parameter :: rout_name =
'coord_F2E_r'
310 real(dp),
intent(in) :: r_f(:)
311 real(dp),
intent(inout) :: r_e(:)
312 real(dp),
intent(in),
optional,
target :: r_f_array(:)
313 real(dp),
intent(in),
optional,
target :: r_e_array(:)
316 character(len=max_str_ln) :: err_msg
318 real(dp),
pointer :: loc_r_e(:) => null()
319 real(dp),
pointer :: loc_r_f(:) => null()
328 if (n_r.ne.
size(r_e))
then
330 err_msg =
'r_F and r_E need to have the correct dimensions'
333 if (
present(r_f_array).neqv.
present(r_e_array))
then
335 err_msg =
'both r_F_array and r_E_array have to be provided'
340 if (
present(r_f_array))
then
344 loc_r_e => grid_eq%loc_r_E
345 loc_r_f => grid_eq%loc_r_F
353 nullify(loc_r_e,loc_r_f)
354 end function coord_f2e_r
357 integer function coord_e2f_rtz(grid_eq,r_E,theta_E,zeta_E,r_F,&
358 &theta_F,zeta_F,r_E_array,r_F_array)
result(ierr)
361 character(*),
parameter :: rout_name =
'coord_E2F_rtz'
365 real(dp),
intent(in) :: r_e(:)
366 real(dp),
intent(in) :: theta_e(:,:,:)
367 real(dp),
intent(in) :: zeta_e(:,:,:)
368 real(dp),
intent(inout) :: r_f(:)
369 real(dp),
intent(inout) :: theta_f(:,:,:)
370 real(dp),
intent(inout) :: zeta_f(:,:,:)
371 real(dp),
intent(in),
optional,
target :: r_e_array(:)
372 real(dp),
intent(in),
optional,
target :: r_f_array(:)
375 character(len=max_str_ln) :: err_msg
382 dims = shape(theta_f)
385 if (dims(3).ne.
size(r_f) .or. dims(3).ne.
size(r_e))
then
387 err_msg =
'r_F and r_E need to have the correct dimensions'
390 if (
present(r_f_array).neqv.
present(r_e_array))
then
392 err_msg =
'both r_F_array and r_E_array have to be provided'
397 ierr =
coord_e2f_r(grid_eq,r_e,r_f,r_e_array,r_f_array)
405 ierr = coord_e2f_vmec()
415 integer function coord_e2f_vmec()
result(ierr)
421 character(*),
parameter :: rout_name =
'coord_E2F_VMEC'
425 real(dp),
allocatable :: l_v_c_loc(:,:), l_v_s_loc(:,:)
426 real(dp),
allocatable :: lam(:,:,:)
427 real(dp),
pointer :: loc_r_e(:) => null()
433 if (
present(r_e_array))
then
436 loc_r_e => grid_eq%loc_r_E
443 allocate(l_v_c_loc(mnmax_v,dims(3)))
444 allocate(l_v_s_loc(mnmax_v,dims(3)))
445 allocate(lam(dims(1),dims(2),dims(3)))
449 ierr =
spline(loc_r_e,
l_v_c(id,grid_eq%i_min:grid_eq%i_max,0),&
452 ierr =
spline(loc_r_e,
l_v_s(id,grid_eq%i_min:grid_eq%i_max,0),&
458 ierr =
fourier2real(l_v_c_loc,l_v_s_loc,theta_e,zeta_e,lam,&
459 &sym=[is_asym_v,.true.])
464 theta_f = theta_e + lam
468 end function coord_e2f_vmec
471 integer function coord_e2f_r(grid_eq,r_E,r_F,r_E_array,r_F_array) &
476 character(*),
parameter :: rout_name =
'coord_E2F_r'
480 real(dp),
intent(in) :: r_e(:)
481 real(dp),
intent(inout) :: r_f(:)
482 real(dp),
intent(in),
optional,
target :: r_e_array(:)
483 real(dp),
intent(in),
optional,
target :: r_f_array(:)
486 character(len=max_str_ln) :: err_msg
488 real(dp),
pointer :: loc_r_e(:) => null()
489 real(dp),
pointer :: loc_r_f(:) => null()
498 if (n_r.ne.
size(r_f))
then
500 err_msg =
'r_E and r_F need to have the correct dimensions'
503 if (
present(r_e_array).neqv.
present(r_f_array))
then
505 err_msg =
'both r_E_array and r_F_array have to be provided'
510 if (
present(r_f_array))
then
514 loc_r_e => grid_eq%loc_r_E
515 loc_r_f => grid_eq%loc_r_F
523 nullify(loc_r_e,loc_r_f)
527 integer function calc_eqd_grid_3d(var,min_grid,max_grid,grid_dim,&
528 &excl_last)
result(ierr)
529 character(*),
parameter :: rout_name =
'calc_eqd_grid_3D'
532 real(
dp),
intent(inout) :: var(:,:,:)
533 real(
dp),
intent(in) :: min_grid
534 real(
dp),
intent(in) :: max_grid
535 integer,
intent(in) :: grid_dim
536 logical,
intent(in),
optional :: excl_last
540 character(len=max_str_ln) :: err_msg
541 logical :: excl_last_loc
543 integer :: grid_size_mod
549 if (grid_dim.lt.1 .or. grid_dim.gt.3)
then
551 err_msg =
'grid_dim has to point to a dimension going from 1 to 3'
556 grid_size =
size(var,grid_dim)
559 if (grid_size.lt.1)
then
560 err_msg =
'The angular array has to have a length of at &
567 excl_last_loc = .false.
568 if (
present(excl_last)) excl_last_loc = excl_last
571 if (excl_last_loc)
then
572 grid_size_mod = grid_size + 1
574 grid_size_mod = grid_size
581 if (grid_size.eq.1)
then
584 if (grid_dim.eq.1)
then
586 var(id,:,:) = min_grid + &
587 &(max_grid-min_grid)*(id-1)/(grid_size_mod-1)
589 else if (grid_dim.eq.2)
then
591 var(:,id,:) = min_grid + &
592 &(max_grid-min_grid)*(id-1)/(grid_size_mod-1)
596 var(:,:,id) = min_grid + &
597 &(max_grid-min_grid)*(id-1)/(grid_size_mod-1)
601 end function calc_eqd_grid_3d
603 integer function calc_eqd_grid_1d(var,min_grid,max_grid,excl_last) &
605 character(*),
parameter :: rout_name =
'calc_eqd_grid_1D'
608 real(
dp),
intent(inout) :: var(:)
609 real(
dp),
intent(in) :: min_grid
610 real(
dp),
intent(in) :: max_grid
611 logical,
intent(in),
optional :: excl_last
614 real(
dp),
allocatable :: var_3d(:,:,:)
620 allocate(var_3d(
size(var),1,1))
623 ierr = calc_eqd_grid_3d(var_3d,min_grid,max_grid,1,excl_last)
628 end function calc_eqd_grid_1d
631 integer function calc_tor_diff_2d(v_com,theta,norm_disc_prec,absolute,r) &
636 character(*),
parameter :: rout_name =
'calc_tor_diff_2D'
639 real(dp),
intent(inout) :: v_com(:,:,:,:,:)
640 real(dp),
intent(in) :: theta(:,:,:)
641 integer,
intent(in) :: norm_disc_prec
642 logical,
intent(in),
optional :: absolute
643 real(dp),
intent(in),
optional :: r(:)
646 integer :: id, jd, kd, ld
649 real(dp),
allocatable :: theta_eqd(:)
650 real(dp),
allocatable :: v_com_interp(:,:)
651 real(dp),
allocatable :: theta_ord(:)
652 real(dp),
allocatable :: v_com_ord(:)
653 logical :: absolute_loc
659 n_pol =
size(theta,1)-1
660 allocate(theta_eqd(n_pol))
661 allocate(v_com_interp(n_pol,3))
662 absolute_loc = .false.
663 if (
present(absolute)) absolute_loc = absolute
665 norm:
do kd = 1,
size(v_com,3)
670 do id = 1,
size(v_com,4)
671 do ld = 1,
size(v_com,5)
676 &v_com(1:n_pol,jd,kd,id,ld),theta_ord,v_com_ord,&
680 istat =
spline(theta_ord,v_com_ord,theta_eqd,&
681 &v_com_interp(:,jd),ord=min(norm_disc_prec,3),&
683 deallocate(theta_ord,v_com_ord)
686 call display_interp_warning(r)
687 v_com(:,2,kd,:,:) = 0._dp
693 v_com_interp(:,2) = &
694 &(v_com_interp(:,3)-v_com_interp(:,1))
695 if (.not.absolute_loc) &
696 &v_com_interp(:,2) = v_com_interp(:,2)/&
698 &
tol_zero,abs(v_com_interp(:,3)+v_com_interp(:,1))),&
699 &v_com_interp(:,3)+v_com_interp(:,1))
703 &theta_ord,v_com_ord,norm_disc_prec)
707 istat =
spline(theta_ord,v_com_ord,theta(:,2,kd),&
708 &v_com(:,2,kd,id,ld),min(norm_disc_prec,3),&
710 deallocate(theta_ord,v_com_ord)
713 call display_interp_warning(r)
714 v_com(:,2,kd,:,:) = 0._dp
724 subroutine display_interp_warning(r)
726 real(dp),
intent(in),
optional :: r(:)
729 call writo(
'Cannot interpolate geometrical &
730 &theta at normal position '//&
731 &trim(
r2str(r(kd))),warning=.true.)
733 call writo(
'Cannot interpolate geometrical &
734 &theta',warning=.true.)
737 call writo(
'Are you sure the origin is chosen &
739 call writo(
'Skipping this normal position')
741 end subroutine display_interp_warning
742 end function calc_tor_diff_2d
744 integer function calc_tor_diff_0d(v_mag,theta,norm_disc_prec,absolute,r) &
746 character(*),
parameter :: rout_name =
'calc_tor_diff_0D'
749 real(
dp),
intent(inout) :: v_mag(:,:,:)
750 real(
dp),
intent(in) :: theta(:,:,:)
751 integer,
intent(in) :: norm_disc_prec
752 logical,
intent(in),
optional :: absolute
753 real(
dp),
intent(in),
optional :: r(:)
756 real(
dp),
allocatable :: v_com_loc(:,:,:,:,:)
762 allocate(v_com_loc(
size(v_mag,1),
size(v_mag,2),
size(v_mag,3),1,1))
763 v_com_loc(:,:,:,1,1) = v_mag
766 ierr = calc_tor_diff_2d(v_com_loc,theta,norm_disc_prec,&
767 &absolute=absolute,r=r)
771 v_mag = v_com_loc(:,:,:,1,1)
772 end function calc_tor_diff_0d
798 integer function calc_xyz_grid(grid_eq,grid_XYZ,X,Y,Z,L,R)
result(ierr)
803 character(*),
parameter :: rout_name =
'calc_XYZ_grid'
808 real(dp),
intent(inout) :: x(:,:,:)
809 real(dp),
intent(inout) :: y(:,:,:)
810 real(dp),
intent(inout) :: z(:,:,:)
811 real(dp),
intent(inout),
optional :: l(:,:,:)
812 real(dp),
intent(inout),
optional :: r(:,:,:)
815 character(len=max_str_ln) :: err_msg
821 if (
size(x,1).ne.grid_xyz%n(1) .or.
size(x,2).ne.grid_xyz%n(2) .or. &
822 &
size(x,3).ne.grid_xyz%loc_n_r)
then
824 err_msg =
'X needs to have the correct dimensions'
827 if (
size(y,1).ne.grid_xyz%n(1) .or.
size(y,2).ne.grid_xyz%n(2) .or. &
828 &
size(y,3).ne.grid_xyz%loc_n_r)
then
830 err_msg =
'Y needs to have the correct dimensions'
833 if (
size(z,1).ne.grid_xyz%n(1) .or.
size(z,2).ne.grid_xyz%n(2) .or. &
834 &
size(z,3).ne.grid_xyz%loc_n_r)
then
836 err_msg =
'Z needs to have the correct dimensions'
840 if (
size(l,1).ne.grid_xyz%n(1) .or.
size(l,2).ne.grid_xyz%n(2) &
841 &.or.
size(l,3).ne.grid_xyz%loc_n_r)
then
843 err_msg =
'L needs to have the correct dimensions'
853 ierr = calc_xyz_grid_vmec(grid_eq,grid_xyz,x,y,z,l=l,r=r)
856 ierr = calc_xyz_grid_hel(grid_eq,grid_xyz,x,y,z,r=r)
865 if (
present(r)) r = r*
r_0
870 integer function calc_xyz_grid_vmec(grid_eq,grid_XYZ,X,Y,Z,L,R) &
878 character(*),
parameter :: rout_name =
'calc_XYZ_grid_VMEC'
883 real(dp),
intent(inout) :: x(:,:,:), y(:,:,:), z(:,:,:)
884 real(dp),
intent(inout),
optional :: l(:,:,:)
885 real(dp),
intent(inout),
optional :: r(:,:,:)
889 real(dp),
allocatable :: r_v_c_int(:,:), r_v_s_int(:,:)
890 real(dp),
allocatable :: z_v_c_int(:,:), z_v_s_int(:,:)
891 real(dp),
allocatable :: l_v_c_int(:,:), l_v_s_int(:,:)
892 real(dp),
allocatable :: r_loc(:,:,:)
893 character(len=max_str_ln) :: err_msg
899 if (.not.
allocated(grid_xyz%trigon_factors))
then
901 err_msg =
'trigon factors of grid_XYZ need to be allocated'
906 allocate(r_v_c_int(mnmax_v,grid_xyz%loc_n_r))
907 allocate(r_v_s_int(mnmax_v,grid_xyz%loc_n_r))
908 allocate(z_v_c_int(mnmax_v,grid_xyz%loc_n_r))
909 allocate(z_v_s_int(mnmax_v,grid_xyz%loc_n_r))
911 allocate(l_v_c_int(mnmax_v,grid_xyz%loc_n_r))
912 allocate(l_v_s_int(mnmax_v,grid_xyz%loc_n_r))
917 ierr =
spline(grid_eq%r_E,
r_v_c(id,:,0),grid_xyz%loc_r_E,&
920 ierr =
spline(grid_eq%r_E,
r_v_s(id,:,0),grid_xyz%loc_r_E,&
923 ierr =
spline(grid_eq%r_E,
z_v_c(id,:,0),grid_xyz%loc_r_E,&
926 ierr =
spline(grid_eq%r_E,
z_v_s(id,:,0),grid_xyz%loc_r_E,&
930 ierr =
spline(grid_eq%r_E,
l_v_c(id,:,0),grid_xyz%loc_r_E,&
933 ierr =
spline(grid_eq%r_E,
l_v_s(id,:,0),grid_xyz%loc_r_E,&
940 allocate(r_loc(grid_xyz%n(1),grid_xyz%n(2),grid_xyz%loc_n_r))
943 ierr =
fourier2real(r_v_c_int,r_v_s_int,grid_xyz%trigon_factors,&
944 &r_loc,sym=[.true.,is_asym_v])
946 ierr =
fourier2real(z_v_c_int,z_v_s_int,grid_xyz%trigon_factors,z,&
947 &sym=[is_asym_v,.true.])
951 &grid_xyz%trigon_factors,l,sym=[is_asym_v,.true.])
954 if (
present(r)) r = r_loc
958 x = r_loc*cos(grid_xyz%zeta_E)
959 y = r_loc*sin(grid_xyz%zeta_E)
962 deallocate(r_v_c_int,r_v_s_int,z_v_c_int,z_v_s_int)
963 if (
present(l))
deallocate(l_v_c_int,l_v_s_int)
965 end function calc_xyz_grid_vmec
969 integer function calc_xyz_grid_hel(grid_eq,grid_XYZ,X,Y,Z,R) &
975 character(*),
parameter :: rout_name =
'calc_XYZ_grid_HEL'
980 real(dp),
intent(inout) :: x(:,:,:), y(:,:,:), z(:,:,:)
981 real(dp),
intent(inout),
optional :: r(:,:,:)
984 integer :: id, jd, kd
987 real(dp) :: bcs_val(2,3)
988 real(dp),
allocatable :: r_h_int(:,:), z_h_int(:,:)
989 real(dp),
allocatable :: r_loc(:,:,:)
990 real(dp) :: theta_loc
1007 allocate(r_loc(grid_xyz%n(1),grid_xyz%n(2),grid_xyz%loc_n_r))
1010 allocate(r_h_int(
nchi,grid_xyz%loc_n_r))
1011 allocate(z_h_int(
nchi,grid_xyz%loc_n_r))
1016 ierr =
spline(grid_eq%r_E,
r_h(id,:),grid_xyz%loc_r_E,&
1018 &bcs_val=bcs_val(:,3))
1020 ierr =
spline(grid_eq%r_E,
z_h(id,:),grid_xyz%loc_r_E,&
1022 &bcs_val=bcs_val(:,3))
1029 do kd = 1,grid_xyz%loc_n_r
1031 do jd = 1,grid_xyz%n(2)
1033 do id = 1,grid_xyz%n(1)
1035 theta_loc = grid_xyz%theta_E(id,jd,kd)
1039 if (theta_loc.lt.0._dp)
then
1040 do while (theta_loc.lt.0._dp)
1041 theta_loc = theta_loc + 2*pi
1043 else if (theta_loc.gt.2*pi)
then
1044 do while (theta_loc.gt.2._dp*pi)
1045 theta_loc = theta_loc - 2*pi
1050 if (
ias.eq.0 .and. theta_loc.gt.pi)
then
1051 theta_loc = 2*pi-theta_loc
1060 &bcs=bcs(:,1),bcs_val=bcs_val(:,1))
1062 ierr =
spline(
chi_h,pmone*z_h_int(:,kd),[theta_loc],&
1064 &bcs=bcs(:,2),bcs_val=bcs_val(:,2))
1069 if (
present(r)) r = r_loc
1073 x = r_loc*cos(-grid_xyz%zeta_E)
1074 y = r_loc*sin(-grid_xyz%zeta_E)
1078 end function calc_xyz_grid_hel
1094 integer function extend_grid_f(grid_in,grid_ext,grid_eq,n_theta_plot,&
1095 &n_zeta_plot,lim_theta_plot,lim_zeta_plot)
result(ierr)
1100 character(*),
parameter :: rout_name =
'extend_grid_F'
1104 type(
grid_type),
intent(inout) :: grid_ext
1105 type(
grid_type),
intent(in),
optional :: grid_eq
1108 real(dp),
intent(in),
optional :: lim_theta_plot(2)
1109 real(dp),
intent(in),
optional :: lim_zeta_plot(2)
1113 integer :: n_theta_plot_loc
1114 integer :: n_zeta_plot_loc
1115 real(dp) :: lim_theta_plot_loc(2)
1116 real(dp) :: lim_zeta_plot_loc(2)
1122 n_theta_plot_loc = n_theta
1124 n_zeta_plot_loc = n_zeta
1127 if (
present(lim_theta_plot)) lim_theta_plot_loc = lim_theta_plot
1129 if (
present(lim_zeta_plot)) lim_zeta_plot_loc = lim_zeta_plot
1132 call writo(
'Theta limits: '//trim(
r2strt(lim_theta_plot_loc(1)))//&
1133 &
'pi .. '//trim(
r2strt(lim_theta_plot_loc(2)))//
'pi')
1134 call writo(
'Zeta limits: '//trim(
r2strt(lim_zeta_plot_loc(1)))//&
1135 &
'pi .. '//trim(
r2strt(lim_zeta_plot_loc(2)))//
'pi')
1139 ierr = grid_ext%init([n_theta_plot_loc,n_zeta_plot_loc,grid_in%n(3)],&
1140 &[grid_in%i_min,grid_in%i_max])
1142 grid_ext%r_F = grid_in%r_F
1143 grid_ext%loc_r_F = grid_in%loc_r_F
1144 ierr =
calc_eqd_grid(grid_ext%theta_F,lim_theta_plot_loc(1)*pi,&
1145 &lim_theta_plot_loc(2)*pi,1)
1147 ierr =
calc_eqd_grid(grid_ext%zeta_F,lim_zeta_plot_loc(1)*pi,&
1148 &lim_zeta_plot_loc(2)*pi,2)
1152 if (
present(grid_eq))
then
1153 call writo(
'convert F to E coordinates')
1157 grid_ext%r_E = grid_in%r_E
1161 &grid_ext%loc_r_F,grid_ext%theta_F,grid_ext%zeta_F,&
1162 &grid_ext%loc_r_E,grid_ext%theta_E,grid_ext%zeta_E)
1166 ierr =
trim_grid(grid_ext,grid_ext_trim)
1170 call grid_ext_trim%dealloc()
1188 integer function copy_grid(grid_A,grid_B,lims_B,i_lim)
result(ierr)
1189 character(*),
parameter :: rout_name =
'copy_grid'
1193 class(
grid_type),
intent(inout) :: grid_b
1194 integer,
intent(in),
optional :: lims_b(3,2)
1195 integer,
intent(in),
optional :: i_lim(2)
1199 integer :: lims_b_loc(3,2)
1200 integer :: i_lim_loc(2)
1206 lims_b_loc(1,:) = [1,grid_a%n(1)]
1207 lims_b_loc(2,:) = [1,grid_a%n(2)]
1208 lims_b_loc(3,:) = [1,grid_a%n(3)]
1209 if (
present(lims_b)) lims_b_loc = lims_b
1210 n_b = lims_b_loc(:,2)-lims_b_loc(:,1)+1
1211 where (lims_b_loc(:,1).eq.lims_b_loc(:,2) &
1212 &.and. lims_b_loc(:,1).eq.[0,0,0]) n_b = 0
1213 i_lim_loc = lims_b_loc(3,:)
1214 if (
present(i_lim)) i_lim_loc = lims_b_loc(3,1) - 1 + i_lim
1216 if (n_b(1).gt.grid_a%n(1) .or. n_b(2).gt.grid_a%n(2) .or. &
1217 &n_b(3).gt.grid_a%n(3))
then
1218 write(*,*)
'n_B' ,n_b
1219 write(*,*)
'grid_A', grid_a%n
1221 chckerr(
'lims_B is too large')
1223 if (i_lim_loc(1).gt.grid_a%n(3) .or. i_lim_loc(2).gt.grid_a%n(3))
then
1225 chckerr(
'normal limits too wide')
1229 ierr = grid_b%init(n_b,i_lim)
1233 grid_b%r_F = grid_a%r_F(lims_b_loc(3,1):lims_b_loc(3,2))
1234 grid_b%r_E = grid_a%r_E(lims_b_loc(3,1):lims_b_loc(3,2))
1235 grid_b%loc_r_F = grid_a%r_F(i_lim_loc(1):i_lim_loc(2))
1236 grid_b%loc_r_E = grid_a%r_E(i_lim_loc(1):i_lim_loc(2))
1237 if (n_b(1).ne.0 .and. n_b(2).ne.0)
then
1238 if (grid_a%divided)
then
1240 chckerr(
'grid_A cannot be divided')
1242 grid_b%theta_F = grid_a%theta_F(lims_b_loc(1,1):lims_b_loc(1,2),&
1243 &lims_b_loc(2,1):lims_b_loc(2,2),i_lim_loc(1):i_lim_loc(2))
1244 grid_b%theta_E = grid_a%theta_E(lims_b_loc(1,1):lims_b_loc(1,2),&
1245 &lims_b_loc(2,1):lims_b_loc(2,2),i_lim_loc(1):i_lim_loc(2))
1246 grid_b%zeta_F = grid_a%zeta_F(lims_b_loc(1,1):lims_b_loc(1,2),&
1247 &lims_b_loc(2,1):lims_b_loc(2,2),i_lim_loc(1):i_lim_loc(2))
1248 grid_b%zeta_E = grid_a%zeta_E(lims_b_loc(1,1):lims_b_loc(1,2),&
1249 &lims_b_loc(2,1):lims_b_loc(2,2),i_lim_loc(1):i_lim_loc(2))
1319 integer function calc_int_vol(ang_1,ang_2,norm,J,f,f_int)
result(ierr)
1324 character(*),
parameter :: rout_name =
'calc_int_vol'
1327 real(dp),
intent(in) :: ang_1(:,:,:)
1328 real(dp),
intent(in) :: ang_2(:,:,:)
1329 real(dp),
intent(in) :: norm(:)
1330 real(dp),
intent(in) :: j(:,:,:)
1331 complex(dp),
intent(in) :: f(:,:,:,:)
1332 complex(dp),
intent(inout) :: f_int(:)
1335 integer :: id, jd, kd, ld
1339 real(dp),
allocatable :: transf_j(:,:,:,:)
1340 real(dp),
allocatable :: transf_j_tot(:,:,:)
1341 complex(dp),
allocatable :: jf(:,:,:,:)
1342 character(len=max_str_ln) :: err_msg
1343 integer :: i_a(3), i_b(3)
1346 character(len=max_str_ln),
allocatable :: var_names(:,:)
1347 complex(dp),
allocatable :: f_int_alt(:)
1348 complex(dp),
allocatable :: f_int_alt_1d(:,:)
1349 complex(dp),
allocatable :: f_int_alt_2d(:,:,:)
1350 complex(dp),
allocatable :: f_int_alt_alt(:)
1351 integer :: loc_norm(2)
1361 if (
size(f_int).ne.nn_mod)
then
1363 err_msg =
'f and f_int need to have the same storage convention'
1366 if (
size(ang_1).ne.
size(ang_2) .or.
size(ang_1,3).ne.
size(norm))
then
1368 err_msg =
'The angular variables have to be compatible'
1371 if (
size(norm).eq.1)
then
1373 err_msg =
'The normal grid size has to be greater than one'
1381 dim_1 = dims(1:2).eq.1
1384 allocate(jf(max(dims(1)-1,1),max(dims(2)-1,1),dims(3)-1,nn_mod))
1385 allocate(transf_j(max(dims(1)-1,1),max(dims(2)-1,1),dims(3)-1,5))
1386 allocate(transf_j_tot(max(dims(1)-1,1),max(dims(2)-1,1),dims(3)-1))
1436 jf(:,:,:,ld) = jf(:,:,:,ld) + 0.125_dp * &
1437 &j(i_a(1):i_b(1),i_a(2):i_b(2),i_a(3):i_b(3)) * &
1438 &f(i_a(1):i_b(1),i_a(2):i_b(2),i_a(3):i_b(3),ld)
1442 transf_j(:,:,:,1) = 2*pi
1444 transf_j(:,:,:,4) = 0._dp
1448 transf_j(ld,:,:,1) = transf_j(ld,:,:,1) + &
1450 &ang_1(ld+1,i_a(2):i_b(2),i_a(3):i_b(3)) - &
1451 &ang_1(ld,i_a(2):i_b(2),i_a(3):i_b(3)) )
1453 transf_j(ld,:,:,4) = transf_j(ld,:,:,4) + &
1455 &ang_2(ld+1,i_a(2):i_b(2),i_a(3):i_b(3)) - &
1456 &ang_2(ld,i_a(2):i_b(2),i_a(3):i_b(3)) )
1461 transf_j(:,:,:,2) = 2*pi
1463 transf_j(:,:,:,3) = 0._dp
1467 transf_j(:,ld,:,2) = transf_j(:,ld,:,2) + &
1469 &ang_2(i_a(1):i_b(1),ld+1,i_a(3):i_b(3)) - &
1470 &ang_2(i_a(1):i_b(1),ld,i_a(3):i_b(3)) )
1472 transf_j(:,ld,:,3) = transf_j(:,ld,:,3) + &
1474 &ang_1(i_a(1):i_b(1),ld+1,i_a(3):i_b(3)) - &
1475 &ang_1(i_a(1):i_b(1),ld,i_a(3):i_b(3)) )
1480 transf_j(:,:,ld,5) = transf_j(:,:,ld,5) + 0.125_dp * ( &
1481 &norm(ld+1) - norm(ld) )
1488 transf_j_tot = (transf_j(:,:,:,1)*transf_j(:,:,:,2)-&
1489 &transf_j(:,:,:,3)*transf_j(:,:,:,4))*transf_j(:,:,:,5)
1494 f_int(ld) = sum(jf(:,:,:,ld)*transf_j_tot)
1499 call writo(
'Testing whether volume integral is calculated &
1503 allocate(var_names(nn_mod,2))
1504 var_names(:,1) =
'real part of integrand J f'
1505 var_names(:,2) =
'imaginary part of integrand J f'
1507 var_names(ld,1) = trim(var_names(ld,1))//
' '//trim(
i2str(ld))
1508 var_names(ld,2) = trim(var_names(ld,2))//
' '//trim(
i2str(ld))
1515 call plot_hdf5(
'transformation of Jacobians',&
1516 &
'TEST_transf_J_'//trim(
i2str(
rank)),transf_j_tot)
1520 allocate(f_int_alt(nn_mod))
1521 allocate(f_int_alt_1d(
size(f,3),nn_mod))
1522 allocate(f_int_alt_2d(
size(f,2),
size(f,3),nn_mod))
1523 allocate(f_int_alt_alt(nn_mod))
1525 f_int_alt_1d = 0._dp
1526 f_int_alt_2d = 0._dp
1527 f_int_alt_alt = 0._dp
1532 if (
size(f,1).gt.1)
then
1534 f_int_alt_2d(jd,kd,:) = f_int_alt_2d(jd,kd,:) + &
1535 &0.5*(j(id,jd,kd)*f(id,jd,kd,:)+&
1536 &j(id-1,jd,kd)*f(id-1,jd,kd,:))*&
1537 &(ang_1(id,jd,kd)-ang_1(id-1,jd,kd))
1540 f_int_alt_2d(jd,kd,:) = j(1,jd,kd)*f(1,jd,kd,:)
1547 if (
size(f,2).gt.1)
then
1549 f_int_alt_1d(kd,:) = f_int_alt_1d(kd,:) + &
1550 &0.5*(f_int_alt_2d(jd,kd,:)+&
1551 &f_int_alt_2d(jd-1,kd,:))*&
1552 &(ang_2(1,jd,kd)-ang_2(1,jd-1,kd))
1555 f_int_alt_1d(kd,:) = f_int_alt_2d(1,kd,:)
1560 if (
size(f,3).gt.1)
then
1562 f_int_alt(:) = f_int_alt(:) + &
1563 &0.5*(f_int_alt_1d(kd,:)+f_int_alt_1d(kd-1,:))*&
1564 &(norm(kd)-norm(kd-1))
1567 f_int_alt = f_int_alt_1d(1,:)
1571 loc_norm = [1,
size(f,3)]
1572 if (
rank.lt.
n_procs-1) loc_norm(2) = loc_norm(2)-1
1574 f_int_alt_alt(ld) = sum(j(:,:,loc_norm(1):loc_norm(2))*&
1575 &f(:,:,loc_norm(1):loc_norm(2),ld))
1577 if (
size(f,1).gt.1) f_int_alt_alt = f_int_alt_alt*&
1578 &(ang_1(2,1,1)-ang_1(1,1,1))
1579 if (
size(f,2).gt.1) f_int_alt_alt = f_int_alt_alt*&
1580 &(ang_2(1,2,1)-ang_2(1,1,1))
1581 if (
size(f,3).gt.1) f_int_alt_alt = f_int_alt_alt*&
1584 call writo(
'Resulting integral: ',persistent=.true.)
1588 &trim(
i2str(ld))//
': '//trim(
c2str(f_int(ld))),&
1591 &trim(
i2str(ld))//
': '//trim(
c2str(f_int_alt(ld))),&
1594 &trim(
i2str(ld))//
': '//trim(
c2str(f_int_alt_alt(ld))),&
1599 call writo(
'(Note that alternative calculations are only valid if &
1600 &independent coordinates!)')
1607 deallocate(jf,transf_j,transf_j_tot)
1635 integer function trim_grid(grid_in,grid_out,norm_id)
result(ierr)
1639 character(*),
parameter :: rout_name =
'trim_grid'
1643 type(
grid_type),
intent(inout) :: grid_out
1644 integer,
intent(inout),
optional :: norm_id(2)
1647 integer,
allocatable :: tot_i_min(:)
1648 integer,
allocatable :: tot_i_max(:)
1649 integer :: i_lim_out(2)
1656 if (grid_in%divided)
then
1658 ierr =
get_ser_var([grid_in%i_min],tot_i_min,scatter=.true.)
1662 ierr =
get_ser_var([grid_in%i_max],tot_i_max,scatter=.true.)
1668 i_lim_out(1) = max(tot_i_min(1),tot_i_min(
rank+1)+&
1669 &ceiling((tot_i_max(
rank)-tot_i_min(
rank+1)+1._dp)/2))
1671 i_lim_out(1) = tot_i_min(1)
1674 i_lim_out(2) = min(tot_i_max(
n_procs),tot_i_max(
rank+1)-&
1675 &floor((tot_i_max(
rank+1)-tot_i_min(
rank+2)+1._dp)/2))
1677 i_lim_out(2) = tot_i_max(
n_procs)
1681 i_lim_out(1) = max(min(i_lim_out(1),grid_in%i_max),grid_in%i_min)
1682 i_lim_out(2) = max(min(i_lim_out(2),grid_in%i_max),grid_in%i_min)
1686 ierr =
get_ser_var([i_lim_out(1)],tot_i_min,scatter=.true.)
1688 ierr =
get_ser_var([i_lim_out(2)],tot_i_max,scatter=.true.)
1692 n_out(1) = grid_in%n(1)
1693 n_out(2) = grid_in%n(2)
1694 n_out(3) = tot_i_max(
n_procs)-tot_i_min(1)+1
1697 ierr = grid_out%init(n_out,i_lim_out-tot_i_min(1)+1,divided=.true.)
1702 i_lim_out = i_lim_out - grid_in%i_min + 1
1703 if (
present(norm_id)) norm_id = i_lim_out
1709 i_lim_out = [grid_in%i_min,grid_in%i_max]
1710 if (
present(norm_id)) norm_id = i_lim_out
1713 i_lim_out = i_lim_out-i_lim_out(1)+1
1716 ierr = grid_out%init(n_out,i_lim_out)
1721 if (grid_in%n(1).ne.0 .and. grid_in%n(2).ne.0)
then
1722 grid_out%theta_E = grid_in%theta_E(:,:,i_lim_out(1):i_lim_out(2))
1723 grid_out%zeta_E = grid_in%zeta_E(:,:,i_lim_out(1):i_lim_out(2))
1724 grid_out%theta_F = grid_in%theta_F(:,:,i_lim_out(1):i_lim_out(2))
1725 grid_out%zeta_F = grid_in%zeta_F(:,:,i_lim_out(1):i_lim_out(2))
1727 if (grid_in%divided)
then
1728 grid_out%loc_r_E = grid_in%loc_r_E(i_lim_out(1):i_lim_out(2))
1729 grid_out%loc_r_F = grid_in%loc_r_F(i_lim_out(1):i_lim_out(2))
1733 if (grid_in%divided)
then
1734 grid_out%r_E = grid_in%r_E(tot_i_min(1):tot_i_max(
n_procs))
1735 grid_out%r_F = grid_in%r_F(tot_i_min(1):tot_i_max(
n_procs))
1737 grid_out%r_E = grid_in%r_E
1738 grid_out%r_F = grid_in%r_F
1742 if (
allocated(grid_in%trigon_factors))
then
1743 allocate(grid_out%trigon_factors(&
1744 &
size(grid_in%trigon_factors,1),&
1745 &
size(grid_in%trigon_factors,2),&
1746 &
size(grid_in%trigon_factors,3),&
1747 &grid_out%loc_n_r,2))
1748 grid_out%trigon_factors = &
1749 &grid_in%trigon_factors(:,:,:,i_lim_out(1):i_lim_out(2),:)
1763 integer function untrim_grid(grid_in,grid_out,size_ghost)
result(ierr)
1767 character(*),
parameter :: rout_name =
'untrim_grid'
1771 type(
grid_type),
intent(inout) :: grid_out
1772 integer,
intent(in) :: size_ghost
1775 integer :: i_lim_in(2)
1776 integer :: i_lim_out(2)
1777 integer,
allocatable :: tot_loc_n_r(:)
1778 integer :: size_ghost_loc
1784 ierr =
get_ser_var([grid_in%loc_n_r],tot_loc_n_r,scatter=.true.)
1788 size_ghost_loc = min(size_ghost,minval(tot_loc_n_r)-1)
1791 i_lim_in = [grid_in%i_min,grid_in%i_max]
1792 i_lim_out = i_lim_in
1793 if (
rank.lt.
n_procs-1) i_lim_out(2) = i_lim_out(2)+size_ghost_loc
1796 ierr = grid_out%init(grid_in%n,i_lim_out)
1800 if (grid_in%n(1).ne.0 .and. grid_in%n(2).ne.0)
then
1801 grid_out%theta_e(:,:,1:grid_in%loc_n_r) = grid_in%theta_e
1802 grid_out%zeta_e(:,:,1:grid_in%loc_n_r) = grid_in%zeta_e
1803 grid_out%theta_f(:,:,1:grid_in%loc_n_r) = grid_in%theta_f
1804 grid_out%zeta_f(:,:,1:grid_in%loc_n_r) = grid_in%zeta_f
1814 if (grid_in%divided)
then
1815 grid_out%loc_r_e = grid_in%r_e(i_lim_out(1):i_lim_out(2))
1816 grid_out%loc_r_f = grid_in%r_f(i_lim_out(1):i_lim_out(2))
1818 grid_out%r_e = grid_in%r_e
1819 grid_out%r_f = grid_in%r_f
1856 integer function calc_vec_comp(grid,grid_eq,eq_1,eq_2,v_com,norm_disc_prec,&
1857 &v_mag,base_name,max_transf,v_flux_tor,v_flux_pol,XYZ,compare_tor_pos) &
1870 character(*),
parameter :: rout_name =
'calc_vec_comp'
1877 real(dp),
intent(inout) :: v_com(:,:,:,:,:)
1878 integer,
intent(in) :: norm_disc_prec
1879 real(dp),
intent(inout),
optional :: v_mag(:,:,:)
1880 character(len=*),
intent(in),
optional :: base_name
1881 integer,
intent(in),
optional :: max_transf
1882 real(dp),
intent(inout),
allocatable,
optional :: v_flux_pol(:,:)
1883 real(dp),
intent(inout),
allocatable,
optional :: v_flux_tor(:,:)
1884 real(dp),
intent(in),
optional :: xyz(:,:,:,:)
1889 integer :: max_transf_loc
1890 integer :: id, jd, kd, ld
1891 integer :: plot_dim(4)
1892 integer :: plot_offset(4)
1894 integer :: tor_id(2)
1895 integer :: norm_id(2)
1896 logical :: cont_plot
1898 logical :: compare_tor_pos_loc
1899 character(len=max_str_ln) :: description(3)
1900 character(len=max_str_ln) :: file_names(3)
1901 character(len=max_str_ln) :: var_names(3,2)
1902 character(len=5) :: coord_names(3)
1903 character(len=max_str_ln) :: err_msg
1904 real(dp) :: norm_len
1905 real(dp),
allocatable :: q_saf(:,:)
1906 real(dp),
allocatable :: jac(:,:,:)
1907 real(dp),
allocatable :: xyzr(:,:,:,:)
1908 real(dp),
allocatable :: theta_geo(:,:,:)
1909 real(dp),
allocatable :: x(:,:,:,:), y(:,:,:,:), z(:,:,:,:)
1910 real(dp),
allocatable :: v_temp(:,:,:,:,:)
1911 real(dp),
allocatable :: v_ser_temp(:)
1912 real(dp),
allocatable :: v_ser_temp_int(:)
1913 real(dp),
allocatable :: t_ba(:,:,:,:,:,:,:), t_ab(:,:,:,:,:,:,:)
1914 real(dp),
allocatable :: d1r(:,:,:), d2r(:,:,:)
1915 real(dp),
allocatable :: d1z(:,:,:), d2z(:,:,:)
1921 call writo(
'Prepare calculation of vector components')
1926 if (
present(max_transf))
then
1927 if (max_transf.ge.1 .and. max_transf.le.5) &
1928 &max_transf_loc = max_transf
1931 if (
present(base_name))
then
1932 if (trim(base_name).ne.
'') do_plot = .true.
1943 ierr =
trim_grid(grid,grid_trim,norm_id)
1947 allocate(xyzr(grid%n(1),grid%n(2),grid%loc_n_r,4))
1948 ierr =
calc_xyz_grid(grid_eq,grid,xyzr(:,:,:,1),xyzr(:,:,:,2),&
1949 &xyzr(:,:,:,3),r=xyzr(:,:,:,4))
1953 compare_tor_pos_loc = compare_tor_pos_glob
1957 if (compare_tor_pos_loc)
then
1958 allocate(theta_geo(grid%n(1),grid%n(2),grid%loc_n_r))
1959 theta_geo = atan2(xyzr(:,:,:,3)-
rz_0(2),xyzr(:,:,:,4)-
rz_0(1))
1960 where (theta_geo.lt.0) theta_geo = theta_geo + 2*pi
1966 plot_dim = [grid_trim%n,3]
1967 plot_offset = [0,0,grid_trim%i_min-1,0]
1968 tor_id = [1,
size(v_com,2)]
1969 if (compare_tor_pos_loc)
then
1970 if (plot_dim(2).ne.3)
then
1972 err_msg =
'When comparing toroidal positions, need to &
1973 &have 3 toroidal points (one in the middle)'
1985 if (compare_tor_pos_loc)
then
1987 err_msg =
'When comparing toroidal positions, cannot have &
1988 &multiple equilibrium jobs'
1994 if (
eq_style.eq.1 .and. .not.
allocated(grid%trigon_factors))
then
1996 err_msg =
'trigonometric factors not allocated'
2001 if (compare_tor_pos_loc)
call writo(
'Comparing toroidal positions')
2004 allocate(x(grid_trim%n(1),grid_trim%n(2),grid_trim%loc_n_r,1))
2005 allocate(y(grid_trim%n(1),grid_trim%n(2),grid_trim%loc_n_r,1))
2006 allocate(z(grid_trim%n(1),grid_trim%n(2),grid_trim%loc_n_r,1))
2007 if (
present(xyz))
then
2008 x(:,:,:,1) = xyz(:,:,norm_id(1):norm_id(2),1)
2009 y(:,:,:,1) = xyz(:,:,norm_id(1):norm_id(2),2)
2010 z(:,:,:,1) = xyz(:,:,norm_id(1):norm_id(2),3)
2012 x(:,:,:,1) = xyzr(:,:,norm_id(1):norm_id(2),1)
2013 y(:,:,:,1) = xyzr(:,:,norm_id(1):norm_id(2),2)
2014 z(:,:,:,1) = xyzr(:,:,norm_id(1):norm_id(2),3)
2019 allocate(v_temp(grid%n(1),grid%n(2),grid%loc_n_r,3,2))
2020 allocate(t_ba(grid%n(1),grid%n(2),grid%loc_n_r,9,0:0,0:0,0:0))
2021 allocate(t_ab(grid%n(1),grid%n(2),grid%loc_n_r,9,0:0,0:0,0:0))
2022 allocate(q_saf(grid%loc_n_r,0:1))
2023 if ((
present(v_flux_tor) .or.
present(v_flux_pol)) .and. &
2024 &.not.compare_tor_pos_loc)
then
2025 allocate(jac(grid%n(1),grid%n(2),grid%loc_n_r))
2026 if (
rank.eq.0 .and. .not.cont_plot)
then
2027 if (
present(v_flux_tor))
then
2028 allocate(v_flux_tor(grid_trim%n(3),plot_dim(2)))
2031 if (
present(v_flux_pol))
then
2032 allocate(v_flux_pol(grid_trim%n(3),plot_dim(1)))
2041 call writo(
'Flux coordinates')
2043 if (
present(v_mag))
then
2046 v_mag = v_mag + v_com(:,:,:,id,1)*v_com(:,:,:,id,2)
2055 if (do_plot .and. .not.compare_tor_pos_loc)
then
2056 coord_names(1) =
'alpha'
2057 coord_names(2) =
'psi'
2059 coord_names(3) =
'theta'
2061 coord_names(3) =
'zeta'
2063 var_names = trim(base_name)
2065 var_names(id,1) = trim(var_names(id,1))//
'_sub_'//&
2066 &trim(coord_names(id))
2067 var_names(id,2) = trim(var_names(id,2))//
'_sup_'//&
2068 &trim(coord_names(id))
2070 description(1) =
'covariant components of the magnetic field in &
2072 description(2) =
'contravariant components of the magnetic field &
2073 &in Flux coordinates'
2074 description(3) =
'magnitude of the magnetic field in Flux &
2076 file_names(1) = trim(base_name)//
'_F_sub'
2077 file_names(2) = trim(base_name)//
'_F_sup'
2078 file_names(3) = trim(base_name)//
'_F_mag'
2080 v_com(:,:,:,1,1) = v_com(:,:,:,1,1) *
r_0
2081 v_com(:,:,:,2,1) = v_com(:,:,:,2,1) / (
r_0*
b_0)
2082 v_com(:,:,:,3,1) = v_com(:,:,:,3,1) *
r_0
2083 v_com(:,:,:,1,2) = v_com(:,:,:,1,2) /
r_0
2084 v_com(:,:,:,2,2) = v_com(:,:,:,2,2) * (
r_0*
b_0)
2085 v_com(:,:,:,3,2) = v_com(:,:,:,3,2) /
r_0
2088 call plot_hdf5(var_names(:,id),trim(file_names(id)),&
2089 &v_com(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2),:,id),&
2090 &tot_dim=plot_dim,loc_offset=plot_offset,&
2091 &x=x(:,tor_id(1):tor_id(2),:,:),&
2092 &y=y(:,tor_id(1):tor_id(2),:,:),&
2093 &z=z(:,tor_id(1):tor_id(2),:,:),&
2094 &cont_plot=cont_plot,descr=description(id))
2096 if (
present(v_mag))
then
2097 call plot_hdf5(trim(base_name),trim(file_names(3)),&
2098 &v_mag(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2)),&
2099 &tot_dim=plot_dim(1:3),loc_offset=plot_offset(1:3),&
2100 &x=x(:,tor_id(1):tor_id(2),:,1),&
2101 &y=y(:,tor_id(1):tor_id(2),:,1),&
2102 &z=z(:,tor_id(1):tor_id(2),:,1),&
2103 &cont_plot=cont_plot,descr=description(3))
2122 call writo(
'magnetic coordinates')
2127 ierr =
spline(grid_eq%loc_r_F,eq_1%q_saf_FD(:,id),grid%loc_r_F,&
2128 &q_saf(:,id),ord=norm_disc_prec)
2131 c_loc =
c([1,1],.false.)
2133 t_ba(:,:,:,c_loc,0,0,0) = -grid%theta_F
2134 do kd = 1,grid%loc_n_r
2135 t_ba(:,:,kd,c_loc,0,0,0) = t_ba(:,:,kd,c_loc,0,0,0)*q_saf(kd,1)
2136 t_ba(:,:,kd,
c([2,1],.false.),0,0,0) = -q_saf(kd,0)
2138 t_ba(:,:,:,
c([3,1],.false.),0,0,0) = 1._dp
2139 t_ba(:,:,:,
c([1,2],.false.),0,0,0) = 1._dp
2140 t_ba(:,:,:,
c([2,3],.false.),0,0,0) = 1._dp
2142 t_ba(:,:,:,c_loc,0,0,0) = -grid%zeta_F
2143 do kd = 1,grid%loc_n_r
2144 t_ba(:,:,kd,c_loc,0,0,0) = &
2145 &t_ba(:,:,kd,c_loc,0,0,0)*q_saf(kd,1)/q_saf(kd,0)
2146 t_ba(:,:,kd,
c([2,1],.false.),0,0,0) = 1._dp/q_saf(kd,0)
2147 t_ba(:,:,kd,
c([1,2],.false.),0,0,0) = q_saf(kd,0)
2149 t_ba(:,:,:,
c([2,1],.false.),0,0,0) = -1._dp
2150 t_ba(:,:,:,
c([3,3],.false.),0,0,0) = 1._dp
2157 v_com(:,:,:,jd,1) = v_com(:,:,:,jd,1) + t_ba(:,:,:,&
2158 &
c([jd,id],.false.),0,0,0) * v_temp(:,:,:,id,1)
2159 v_com(:,:,:,jd,2) = v_com(:,:,:,jd,2) + t_ab(:,:,:,&
2160 &
c([id,jd],.false.),0,0,0) * v_temp(:,:,:,id,2)
2163 if (
present(v_mag))
then
2166 v_mag = v_mag + v_com(:,:,:,id,1)*v_com(:,:,:,id,2)
2173 coord_names(1) =
'psi'
2174 coord_names(2) =
'theta'
2175 coord_names(3) =
'zeta'
2176 var_names = trim(base_name)
2178 var_names(id,1) = trim(var_names(id,1))//
'_sub_'//&
2179 &trim(coord_names(id))
2180 var_names(id,2) = trim(var_names(id,2))//
'_sup_'//&
2181 &trim(coord_names(id))
2183 description(1) =
'covariant components of the magnetic field in &
2184 &Magnetic coordinates'
2185 description(2) =
'contravariant components of the magnetic field &
2186 &in Magnetic coordinates'
2187 description(3) =
'magnitude of the magnetic field in Magnetic &
2189 file_names(1) = trim(base_name)//
'_M_sub'
2190 file_names(2) = trim(base_name)//
'_M_sup'
2191 file_names(3) = trim(base_name)//
'_M_mag'
2192 if (compare_tor_pos_loc)
then
2194 file_names(id) = trim(file_names(id))//
'_COMP'
2198 v_com(:,:,:,1,1) = v_com(:,:,:,1,1) / (
r_0*
b_0)
2199 v_com(:,:,:,2,1) = v_com(:,:,:,2,1) *
r_0
2200 v_com(:,:,:,3,1) = v_com(:,:,:,3,1) *
r_0
2201 v_com(:,:,:,1,2) = v_com(:,:,:,1,2) * (
r_0*
b_0)
2202 v_com(:,:,:,2,2) = v_com(:,:,:,2,2) /
r_0
2203 v_com(:,:,:,3,2) = v_com(:,:,:,3,2) /
r_0
2205 if (compare_tor_pos_loc)
then
2210 call plot_hdf5(var_names(:,id),trim(file_names(id)),&
2211 &v_com(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2),:,id),&
2212 &tot_dim=plot_dim,loc_offset=plot_offset,&
2213 &x=x(:,tor_id(1):tor_id(2),:,:),&
2214 &y=y(:,tor_id(1):tor_id(2),:,:),&
2215 &z=z(:,tor_id(1):tor_id(2),:,:),&
2216 &cont_plot=cont_plot,descr=description(id))
2218 if (
present(v_mag))
then
2219 if (compare_tor_pos_loc)
then
2223 call plot_hdf5(trim(base_name),trim(file_names(3)),&
2224 &v_mag(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2)),&
2225 &tot_dim=plot_dim(1:3),loc_offset=plot_offset(1:3),&
2226 &x=x(:,tor_id(1):tor_id(2),:,1),&
2227 &y=y(:,tor_id(1):tor_id(2),:,1),&
2228 &z=z(:,tor_id(1):tor_id(2),:,1),&
2229 &cont_plot=cont_plot,descr=description(3))
2233 if ((
present(v_flux_tor) .or.
present(v_flux_pol)) .and. &
2234 &.not.compare_tor_pos_loc)
then
2236 if (maxval(grid%theta_F(grid%n(1),:,:)).lt.&
2237 &minval(grid%theta_F(1,:,:)))
then
2238 call writo(
'theta of the grid monotomically decreases in Flux &
2239 &quantities.',alert=.true.)
2241 call writo(
'This inverts the sign of the toroidal flux.')
2242 call writo(
'Remember that the grid limits are prescribed &
2243 &in Flux quantities.')
2246 if (maxval(grid%zeta_F(:,grid%n(2),:)).lt.&
2247 &minval(grid%zeta_F(:,1,:)))
then
2248 call writo(
'zeta of the grid monotomically decreases in Flux &
2249 &quantities.',alert=.true.)
2251 call writo(
'This inverts the sign of the poloidal flux.')
2252 call writo(
'Remember that the grid limits are prescribed &
2253 &in Flux quantities.')
2254 if (
eq_style.eq.1)
call writo(
'For VMEC, these are inverse.')
2257 if (grid_trim%r_F(grid_trim%n(3)).lt.grid_trim%r_F(1))
then
2258 call writo(
'r of the grid monotomically decreases in Flux &
2259 &quantities.',alert=.true.)
2261 call writo(
'This inverts the sign of the fluxes.')
2262 call writo(
'Remember that the grid limits are prescribed &
2263 &in Flux quantities.')
2266 if (abs(minval(grid_trim%r_F)).gt.
tol_zero)
then
2267 call writo(
'r of the grid does not start at zero.',alert=.true.)
2269 call writo(
'This leaves out part of the fluxes.')
2274 allocate(v_ser_temp_int(grid_trim%n(3)))
2277 var_names(1,2) =
'integrated poloidal flux of '//trim(base_name)
2278 var_names(2,2) =
'integrated toroidal flux of '//trim(base_name)
2279 file_names(1) = trim(base_name)//
'_flux_pol_int'
2280 file_names(2) = trim(base_name)//
'_flux_tor_int'
2285 call writo(
'Instead of calculating fluxes, returning &
2286 &integrals in the angular variables.',alert=.true.)
2288 call writo(
'Useful to check whether Maxwell holds.')
2289 call writo(
'i.e. whether loop integral of J returns &
2291 call writo(
'Note that the J-variables now refer to B and &
2293 call writo(
'Don''t forget the contribution of the toroidal &
2294 &field B_zeta on axis, times 2piR.')
2295 call writo(
'Don''t forget the vacuum permeability!')
2300 do jd = 1,grid_eq%n(2)
2301 do id = 1,grid_eq%n(1)
2302 ierr =
spline(grid_eq%loc_r_F,&
2303 &eq_2%jac_FD(id,jd,:,0,0,0),grid%loc_r_F,&
2304 &jac(id,jd,:),ord=norm_disc_prec)
2309 v_com(:,:,:,2,2) = v_com(:,:,:,2,2)*jac
2310 v_com(:,:,:,3,2) = v_com(:,:,:,3,2)*jac
2317 if (
present(v_flux_tor) .and. grid_trim%n(1).gt.1 .and. &
2318 &.not.compare_tor_pos_loc)
then
2320 do jd = 1,grid_trim%n(2)
2325 do kd = norm_id(1),norm_id(2)
2326 ierr =
calc_int(v_com(:,jd,kd,2,1),&
2327 &grid%theta_F(:,jd,kd),v_com(:,jd,kd,2,2))
2333 &norm_id(1):norm_id(2),2,2),v_ser_temp)
2339 v_flux_tor(:,jd) = v_flux_tor(:,jd) + v_ser_temp
2341 v_flux_tor(:,jd+plot_offset(1)) = v_ser_temp
2347 do kd = norm_id(1),norm_id(2)
2348 ierr =
calc_int(v_com(:,jd,kd,3,2),&
2349 &grid%theta_F(:,jd,kd),v_com(:,jd,kd,3,1))
2355 &norm_id(1):norm_id(2),3,1),v_ser_temp)
2361 &grid_trim%r_F(norm_id(1):),v_ser_temp_int)
2364 &v_ser_temp_int*
psi_0
2366 v_flux_tor(:,jd) = v_flux_tor(:,jd) + &
2369 v_flux_tor(:,jd+plot_offset(1)) = v_ser_temp_int
2378 if (
rank.eq.0 .and. do_plot .and. &
2381 &trim(file_names(2)),v_flux_tor,&
2382 &x=reshape(grid_trim%r_F(norm_id(1):)*2*pi/max_flux_f,&
2383 &[grid_trim%n(3),1]),draw=.false.)
2384 call draw_ex([var_names(2,2)],trim(file_names(2)),&
2385 &plot_dim(2),1,.false.)
2390 if (
present(v_flux_pol) .and. grid_trim%n(2).gt.1 .and. &
2391 &.not.compare_tor_pos_loc)
then
2393 do id = 1,grid_trim%n(1)
2398 do kd = norm_id(1),norm_id(2)
2399 ierr =
calc_int(v_com(id,:,kd,3,1),&
2400 &grid%zeta_F(id,:,kd),v_com(id,:,kd,3,2))
2406 &norm_id(1):norm_id(2),3,2),v_ser_temp)
2412 v_flux_pol(:,id+plot_offset(1)) = v_ser_temp
2414 v_flux_pol(:,id) = v_flux_pol(:,id) + v_ser_temp
2420 do kd = norm_id(1),norm_id(2)
2421 ierr =
calc_int(v_com(id,:,kd,2,2),&
2422 &grid%zeta_F(id,:,kd),v_com(id,:,kd,2,1))
2428 &norm_id(1):norm_id(2),2,1),v_ser_temp)
2434 &grid_trim%r_F(norm_id(1):),v_ser_temp_int)
2437 &v_ser_temp_int*
psi_0
2439 v_flux_pol(:,id+plot_offset(1)) = v_ser_temp_int
2441 v_flux_pol(:,id) = v_flux_pol(:,id) + &
2451 if (
rank.eq.0 .and. do_plot .and. &
2454 &trim(file_names(1)),v_flux_pol,&
2455 &x=reshape(grid_trim%r_F(norm_id(1):)*2*pi/max_flux_f,&
2456 &[grid_trim%n(3),1]),draw=.false.)
2457 call draw_ex([var_names(1,2)],trim(file_names(1)),&
2458 &plot_dim(1),1,.false.)
2463 deallocate(v_ser_temp)
2464 if (
rank.eq.0)
deallocate(v_ser_temp_int)
2469 if (max_transf_loc.eq.2)
return
2477 call writo(
'Equilibrium coordinates')
2480 do jd = 1,grid_eq%n(2)
2481 do id = 1,grid_eq%n(1)
2482 ierr =
spline(grid_eq%loc_r_F,&
2483 &eq_2%T_FE(id,jd,:,ld,0,0,0),grid%loc_r_F,&
2484 &t_ab(id,jd,:,ld,0,0,0),ord=norm_disc_prec)
2486 ierr =
spline(grid_eq%loc_r_F,&
2487 &eq_2%T_EF(id,jd,:,ld,0,0,0),grid%loc_r_F,&
2488 &t_ba(id,jd,:,ld,0,0,0),ord=norm_disc_prec)
2496 v_com(:,:,:,jd,1) = v_com(:,:,:,jd,1) + &
2497 &t_ba(:,:,:,
c([jd,id],.false.),0,0,0) * &
2499 v_com(:,:,:,jd,2) = v_com(:,:,:,jd,2) + &
2500 &t_ab(:,:,:,
c([id,jd],.false.),0,0,0) * &
2504 if (
present(v_mag))
then
2507 v_mag = v_mag + v_com(:,:,:,id,1)*v_com(:,:,:,id,2)
2519 coord_names(1) =
'r'
2520 coord_names(2) =
'theta'
2521 coord_names(3) =
'phi'
2522 description(1) =
'covariant components of the magnetic &
2523 &field in VMEC coordinates'
2524 description(2) =
'contravariant components of the magnetic &
2525 &field in VMEC coordinates'
2526 description(3) =
'magnitude of the magnetic field in VMEC &
2528 file_names(1) = trim(base_name)//
'_V_sub'
2529 file_names(2) = trim(base_name)//
'_V_sup'
2530 file_names(3) = trim(base_name)//
'_V_mag'
2532 coord_names(1) =
'psi'
2533 coord_names(2) =
'theta'
2534 coord_names(3) =
'phi'
2535 description(1) =
'covariant components of the magnetic &
2536 &field in HELENA coordinates'
2537 description(2) =
'contravariant components of the magnetic &
2538 &field in HELENA coordinates'
2539 description(3) =
'magnitude of the magnetic field in &
2540 &HELENA coordinates'
2541 file_names(1) = trim(base_name)//
'_H_sub'
2542 file_names(2) = trim(base_name)//
'_H_sup'
2543 file_names(3) = trim(base_name)//
'_H_mag'
2545 if (compare_tor_pos_loc)
then
2547 file_names(id) = trim(file_names(id))//
'_COMP'
2550 var_names = trim(base_name)
2552 var_names(id,1) = trim(var_names(id,1))//
'_sub_'//&
2553 &trim(coord_names(id))
2554 var_names(id,2) = trim(var_names(id,2))//
'_sup_'//&
2555 &trim(coord_names(id))
2558 v_com(:,:,:,1,1) = v_com(:,:,:,1,1) *
r_0
2559 v_com(:,:,:,2,1) = v_com(:,:,:,2,1) *
r_0
2560 v_com(:,:,:,3,1) = v_com(:,:,:,3,1) *
r_0
2561 v_com(:,:,:,1,2) = v_com(:,:,:,1,2) /
r_0
2562 v_com(:,:,:,2,2) = v_com(:,:,:,2,2) /
r_0
2563 v_com(:,:,:,3,2) = v_com(:,:,:,3,2) /
r_0
2565 if (compare_tor_pos_loc)
then
2570 call plot_hdf5(var_names(:,id),trim(file_names(id)),&
2571 &v_com(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2),:,id),&
2572 &tot_dim=plot_dim,loc_offset=plot_offset,&
2573 &x=x(:,tor_id(1):tor_id(2),:,:),&
2574 &y=y(:,tor_id(1):tor_id(2),:,:),&
2575 &z=z(:,tor_id(1):tor_id(2),:,:),&
2576 &cont_plot=cont_plot,descr=description(id))
2578 if (
present(v_mag))
then
2579 if (compare_tor_pos_loc)
then
2583 call plot_hdf5(trim(base_name),trim(file_names(3)),&
2584 &v_mag(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2)),&
2585 &tot_dim=plot_dim(1:3),loc_offset=plot_offset(1:3),&
2586 &x=x(:,tor_id(1):tor_id(2),:,1),&
2587 &y=y(:,tor_id(1):tor_id(2),:,1),&
2588 &z=z(:,tor_id(1):tor_id(2),:,1),&
2589 &cont_plot=cont_plot,descr=description(3))
2595 if (max_transf_loc.eq.3)
return
2608 call writo(
'Cylindrical coordinates')
2615 do jd = 1,grid_eq%n(2)
2616 do id = 1,grid_eq%n(1)
2617 ierr =
spline(grid_eq%loc_r_F,&
2618 &eq_2%T_VC(id,jd,:,ld,0,0,0),grid%loc_r_F,&
2619 &t_ab(id,jd,:,ld,0,0,0),ord=norm_disc_prec)
2627 allocate(d1r(grid%n(1),grid%n(2),grid%loc_n_r))
2628 allocate(d2r(grid%n(1),grid%n(2),grid%loc_n_r))
2629 allocate(d1z(grid%n(1),grid%n(2),grid%loc_n_r))
2630 allocate(d2z(grid%n(1),grid%n(2),grid%loc_n_r))
2633 ierr =
spline(grid%loc_r_E,xyzr(id,jd,:,4)/norm_len,&
2634 &grid%loc_r_E,d1r(id,jd,:),ord=norm_disc_prec,&
2637 ierr =
spline(grid%loc_r_E,xyzr(id,jd,:,3)/norm_len,&
2638 &grid%loc_r_E,d1z(id,jd,:),ord=norm_disc_prec,&
2643 do kd = 1,grid%loc_n_r
2645 ierr =
spline(grid%theta_E(:,jd,kd),&
2646 &xyzr(:,jd,kd,4)/norm_len,grid%theta_E(:,jd,kd),&
2647 &d2r(:,jd,kd),ord=norm_disc_prec,deriv=1)
2649 ierr =
spline(grid%theta_E(:,jd,kd),&
2650 &xyzr(:,jd,kd,3)/norm_len,grid%theta_E(:,jd,kd),&
2651 &d2z(:,jd,kd),ord=norm_disc_prec,deriv=1)
2655 t_ab(:,:,:,
c([1,1],.false.),0,0,0) = d1r
2656 t_ab(:,:,:,
c([1,3],.false.),0,0,0) = d1z
2657 t_ab(:,:,:,
c([2,1],.false.),0,0,0) = d2r
2658 t_ab(:,:,:,
c([2,3],.false.),0,0,0) = d2z
2659 t_ab(:,:,:,
c([3,2],.false.),0,0,0) = -1._dp
2660 deallocate(d1r,d2r,d1z,d2z)
2667 v_com(:,:,:,jd,1) = v_com(:,:,:,jd,1) + t_ba(:,:,:,&
2668 &
c([jd,id],.false.),0,0,0) * v_temp(:,:,:,id,1)
2669 v_com(:,:,:,jd,2) = v_com(:,:,:,jd,2) + t_ab(:,:,:,&
2670 &
c([id,jd],.false.),0,0,0) * v_temp(:,:,:,id,2)
2673 if (
present(v_mag))
then
2676 v_mag = v_mag + v_com(:,:,:,id,1)*v_com(:,:,:,id,2)
2686 description(1) =
'covariant components of the magnetic field in &
2687 &cylindrical coordinates'
2688 description(2) =
'contravariant components of the magnetic field &
2689 &in cylindrical coordinates'
2690 description(3) =
'magnitude of the magnetic field in cylindrical &
2692 file_names(1) = trim(base_name)//
'_C_sub'
2693 file_names(2) = trim(base_name)//
'_C_sup'
2694 file_names(3) = trim(base_name)//
'_C_mag'
2695 if (compare_tor_pos_loc)
then
2697 file_names(id) = trim(file_names(id))//
'_COMP'
2700 coord_names(1) =
'R'
2701 coord_names(2) =
'phi'
2702 coord_names(3) =
'Z'
2703 var_names = trim(base_name)
2705 var_names(id,1) = trim(var_names(id,1))//
'_sub_'//&
2706 &trim(coord_names(id))
2707 var_names(id,2) = trim(var_names(id,2))//
'_sup_'//&
2708 &trim(coord_names(id))
2712 v_com(:,:,:,2,1) = v_com(:,:,:,2,1) *
r_0
2715 v_com(:,:,:,2,2) = v_com(:,:,:,2,2) /
r_0
2718 if (compare_tor_pos_loc)
then
2723 call plot_hdf5(var_names(:,id),trim(file_names(id)),&
2724 &v_com(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2),:,id),&
2725 &tot_dim=plot_dim,loc_offset=plot_offset,&
2726 &x=x(:,tor_id(1):tor_id(2),:,:),&
2727 &y=y(:,tor_id(1):tor_id(2),:,:),&
2728 &z=z(:,tor_id(1):tor_id(2),:,:),&
2729 &cont_plot=cont_plot,descr=description(id))
2731 if (
present(v_mag))
then
2732 if (compare_tor_pos_loc)
then
2736 call plot_hdf5(trim(base_name),trim(file_names(3)),&
2737 &v_mag(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2)),&
2738 &tot_dim=plot_dim(1:3),loc_offset=plot_offset(1:3),&
2739 &x=x(:,tor_id(1):tor_id(2),:,1),&
2740 &y=y(:,tor_id(1):tor_id(2),:,1),&
2741 &z=z(:,tor_id(1):tor_id(2),:,1),&
2742 &cont_plot=cont_plot,descr=description(3))
2748 if (max_transf_loc.eq.4)
return
2757 call writo(
'Cartesian coordinates')
2761 t_ab(:,:,:,
c([1,1],.false.),0,0,0) = cos(-grid%zeta_F)
2762 t_ab(:,:,:,
c([1,2],.false.),0,0,0) = sin(-grid%zeta_F)
2763 t_ab(:,:,:,
c([2,1],.false.),0,0,0) = -xyzr(:,:,:,4)/norm_len*&
2765 t_ab(:,:,:,
c([2,2],.false.),0,0,0) = xyzr(:,:,:,4)/norm_len*&
2767 t_ab(:,:,:,
c([3,3],.false.),0,0,0) = 1._dp
2773 v_com(:,:,:,jd,1) = v_com(:,:,:,jd,1) + t_ba(:,:,:,&
2774 &
c([jd,id],.false.),0,0,0) * v_temp(:,:,:,id,1)
2775 v_com(:,:,:,jd,2) = v_com(:,:,:,jd,2) + t_ab(:,:,:,&
2776 &
c([id,jd],.false.),0,0,0) * v_temp(:,:,:,id,2)
2779 if (
present(v_mag))
then
2782 v_mag = v_mag + v_com(:,:,:,id,1)*v_com(:,:,:,id,2)
2789 description(1) =
'covariant components of the magnetic field in &
2790 &cartesian coordinates'
2791 description(2) =
'contravariant components of the magnetic field &
2792 &in cartesian coordinates'
2793 description(3) =
'magnitude of the magnetic field in cartesian &
2795 file_names(1) = trim(base_name)//
'_X_sub'
2796 file_names(2) = trim(base_name)//
'_X_sup'
2797 file_names(3) = trim(base_name)//
'_X_mag'
2798 if (compare_tor_pos_loc)
then
2800 file_names(id) = trim(file_names(id))//
'_COMP'
2803 coord_names(1) =
'X'
2804 coord_names(2) =
'Y'
2805 coord_names(3) =
'Z'
2806 var_names = trim(base_name)
2808 var_names(id,1) = trim(var_names(id,1))//
'_sub_'//&
2809 &trim(coord_names(id))
2810 var_names(id,2) = trim(var_names(id,2))//
'_sup_'//&
2811 &trim(coord_names(id))
2813 if (compare_tor_pos_loc)
then
2818 call plot_hdf5(var_names(:,id),trim(file_names(id)),&
2819 &v_com(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2),:,id),&
2820 &tot_dim=plot_dim,loc_offset=plot_offset,&
2821 &x=x(:,tor_id(1):tor_id(2),:,:),&
2822 &y=y(:,tor_id(1):tor_id(2),:,:),&
2823 &z=z(:,tor_id(1):tor_id(2),:,:),&
2824 &cont_plot=cont_plot,descr=description(id))
2826 if (
present(v_mag))
then
2827 if (compare_tor_pos_loc)
then
2831 call plot_hdf5(trim(base_name),trim(file_names(3)),&
2832 &v_mag(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2)),&
2833 &tot_dim=plot_dim(1:3),loc_offset=plot_offset(1:3),&
2834 &x=x(:,tor_id(1):tor_id(2),:,1),&
2835 &y=y(:,tor_id(1):tor_id(2),:,1),&
2836 &z=z(:,tor_id(1):tor_id(2),:,1),&
2837 &cont_plot=cont_plot,descr=description(3))
2841 call plot_hdf5([trim(base_name)],trim(base_name)//
'_vec',&
2842 &v_com(:,tor_id(1):tor_id(2),norm_id(1):norm_id(2),:,1),&
2843 &tot_dim=plot_dim,loc_offset=plot_offset,&
2844 &x=x(:,tor_id(1):tor_id(2),:,:),y=y(:,tor_id(1):tor_id(2),:,:),&
2845 &z=z(:,tor_id(1):tor_id(2),:,:),col=4,cont_plot=cont_plot,&
2846 &descr=
'magnetic field vector')
2852 call grid_trim%dealloc()
2864 character(*),
parameter :: rout_name =
'calc_n_par_X_rich'
2867 integer,
intent(inout) :: n_par_x_rich
2868 logical,
intent(in),
optional :: only_half_grid
2871 character(len=max_str_ln) :: err_msg
2878 if (
present(only_half_grid))
then
2879 if (only_half_grid)
then
2884 err_msg =
'Need odd number of points'
2900 integer function nufft(x,f,f_F,plot_name)
result(ierr)
2903 character(*),
parameter :: rout_name =
'nufft'
2906 real(
dp),
intent(in) :: x(:)
2907 real(
dp),
intent(in) :: f(:)
2908 real(
dp),
intent(inout),
allocatable :: f_f(:,:)
2909 character(len=*),
intent(in),
optional :: plot_name
2915 logical :: print_log = .false.
2916 real(
dp),
allocatable :: x_loc(:)
2917 real(
dp),
allocatable :: work(:)
2918 real(
dp),
allocatable :: f_loc(:)
2919 real(
dp),
allocatable :: f_int(:)
2920 character(len=max_str_ln) :: plot_title(2)
2923 if (
size(x).ne.
size(f))
then
2925 chckerr(
'x and f must have same size')
2927 if (maxval(x)-minval(x).gt.2*
pi)
then
2929 chckerr(
'x is not a fundamental interval')
2939 allocate(f_int(n_x))
2940 ierr =
spline(x_loc,f_loc,[((id-1._dp)/n_x*2*
pi,id=1,n_x)],f_int,&
2960 allocate(work(3*n_x+15))
2963 call dffti(n_x,work)
2964 call dfftf(n_x,f_int,work)
2968 f_int(:) = f_int(:)*2/n_x
2969 f_int(1) = f_int(1)/2
2972 if (
allocated(f_f))
deallocate(f_f)
2973 allocate(f_f(m_f+1,2))
2976 f_f(2:m_f+1,1) = f_int(2:2*m_f:2)
2977 f_f(2:m_f+1,2) = -f_int(3:2*m_f+1:2)
2980 if (
present(plot_name))
then
2981 plot_title = [
'cos',
'sin']
2982 call print_ex_2d(plot_title,plot_name,f_f,draw=.false.)
2983 call draw_ex(plot_title,plot_name,2,1,.false.)
2985 plot_title = [
'cos [log]',
'sin [log]']
2986 call print_ex_2d(plot_title,trim(plot_name)//
'_log',&
2987 &log10(abs(f_f)),draw=.false.)
2988 call draw_ex(plot_title,trim(plot_name)//
'_log',2,1,.false.)
2996 real(
dp),
intent(in) :: r_f(:)
2997 real(
dp),
intent(in) :: lim_r(2)
2998 integer,
intent(inout) :: lim_id(2)
3003 real(
dp),
parameter :: tol = 1.e-6
3009 if (r_f(1).lt.r_f(n_r))
then
3011 if (r_f(id).le.minval(lim_r)-tol) lim_id(1) = id
3012 if (r_f(n_r-id+1).ge.maxval(lim_r)+tol) &
3013 &lim_id(2) = n_r-id+1
3017 if (r_f(id).ge.maxval(lim_r)+tol) lim_id(1) = id
3018 if (r_f(n_r-id+1).le.minval(lim_r)-tol) &
3019 &lim_id(2) = n_r-id+1
3038 integer function calc_arc_angle(grid,eq_1,eq_2,arc,use_E)
result(ierr)
3044 character(*),
parameter :: rout_name =
'calc_arc_angle'
3050 real(dp),
intent(inout),
allocatable :: arc(:,:,:)
3051 logical,
intent(in),
optional :: use_e
3055 logical :: use_e_loc
3062 if (
present(use_e)) use_e_loc = use_e
3065 allocate(arc(grid%n(1),grid%n(2),grid%loc_n_r))
3066 do kd = 1,grid%loc_n_r
3070 &eq_2%g_E(:,jd,kd,
c([2,2],.true.),0,0,0)**(0.5),&
3071 &grid%theta_E(:,jd,kd),arc(:,jd,kd))
3074 arc(:,jd,kd) = grid%theta_E(1,jd,kd) + &
3075 &arc(:,jd,kd) / arc(grid%n(1),jd,kd) * &
3076 &(grid%theta_E(grid%n(1),jd,kd)-grid%theta_E(1,jd,kd))
3081 &eq_2%g_FD(:,jd,kd,
c([3,3],.true.),0,0,0) - &
3082 &eq_2%g_FD(:,jd,kd,
c([1,3],.true.),0,0,0) * &
3083 &2*eq_1%q_saf_FD(kd,0) + &
3084 &eq_2%g_FD(:,jd,kd,
c([1,1],.true.),0,0,0) * &
3085 &eq_1%q_saf_FD(kd,0)**2)**(0.5),&
3086 &grid%theta_F(:,jd,kd),arc(:,jd,kd))
3091 &(-eq_2%g_FD(:,jd,kd,
c([1,1],.true.),0,0,0))&
3092 &**(0.5),grid%theta_F(:,jd,kd),arc(:,jd,kd))
3096 arc(:,jd,kd) = grid%theta_F(1,jd,kd) + &
3097 &arc(:,jd,kd) / arc(grid%n(1),jd,kd) * &
3098 &(grid%theta_F(grid%n(1),jd,kd)-grid%theta_F(1,jd,kd))