PB3D
[2.45]
Ideal linear high-n MHD stability in 3-D
|
Operations considering perturbation quantities. More...
Interfaces and Types | |
interface | calc_x |
Calculates either vectorial or tensorial perturbation variables. More... | |
interface | print_output_x |
Print either vectorial or tensorial perturbation quantities of a certain order to an output file. More... | |
interface | redistribute_output_x |
Redistribute the perturbation variables. More... | |
Functions/Subroutines | |
integer function, public | init_modes (grid_eq, eq) |
Initializes some variables concerning the mode numbers. More... | |
integer function, public | setup_modes (mds, grid_eq, grid, plot_name) |
Sets up some variables concerning the mode numbers. More... | |
integer function, public | check_x_modes (grid_eq, eq) |
Checks whether the high-n approximation is valid: More... | |
integer function, public | calc_res_surf (mds, grid_eq, eq, res_surf, info, jq) |
Calculates resonating flux surfaces for the perturbation modes. More... | |
integer function, public | resonance_plot (mds, grid_eq, eq) |
plot \(q\)-profile or \(\iota\)-profile in flux coordinates with \(nq-m = 0\) or \(n-\iota m = 0\) indicated if requested. More... | |
integer function | calc_u (grid_eq, grid_X, eq_1, eq_2, X) |
Calculate \(U_m^0\), \(U_m^1\) or \(U_n^0\), \(U_n^1\). More... | |
integer function | calc_pv (grid_eq, grid_X, eq_1, eq_2, X_a, X_b, X, lim_sec_X) |
calculate \(\widetilde{PV}_{k,m}^i\) (pol. flux) or \(\widetilde{PV}_{l,n}^i\) (tor. flux) at all equilibrium loc_n_r values. More... | |
integer function | calc_kv (grid_eq, grid_X, eq_1, eq_2, X_a, X_b, X, lim_sec_X) |
calculate \(\widetilde{KV}_{k,m}^i\) (pol. flux) or \(\widetilde{KV}_{l,n}^i\) (tor. flux) at all equilibrium loc_n_r values. More... | |
integer function, public | calc_magn_ints (grid_eq, grid_X, eq, X, X_int, prev_style, lim_sec_X) |
Calculate the magnetic integrals from \(\widetilde{PV}_{k,m}^i\) and \(\widetilde{KV}_{k,m}^i\) in an equidistant grid where the step size can vary depending on the normal coordinate. More... | |
integer function, public | divide_x_jobs (arr_size) |
Divides the perturbation jobs. More... | |
integer function, public | print_debug_x_1 (mds, grid_X, X_1) |
Prints debug information for X_1 driver. More... | |
integer function, public | print_debug_x_2 (mds, grid_X, X_2_int) |
Prints debug information for X_2 driver. More... | |
Variables | |
logical, public | debug_check_x_modes_2 = .false. |
plot debug information for check_x_modes_2() More... | |
Operations considering perturbation quantities.
integer function x_ops::calc_kv | ( | type(grid_type), intent(in) | grid_eq, |
type(grid_type), intent(in) | grid_X, | ||
type(eq_1_type), intent(in) | eq_1, | ||
type(eq_2_type), intent(in), target | eq_2, | ||
type(x_1_type), intent(in) | X_a, | ||
type(x_1_type), intent(in) | X_b, | ||
type(x_2_type), intent(inout) | X, | ||
integer, dimension(2,2), intent(in), optional | lim_sec_X | ||
) |
calculate \(\widetilde{KV}_{k,m}^i\) (pol. flux) or \(\widetilde{KV}_{l,n}^i\) (tor. flux) at all equilibrium loc_n_r
values.
Like in calc_U(), use is made of variables Ti
that are set up in the equilibrium grid and are afterwards converted to Ti_X
in the perturbation grid, which needs to have the same angular coordinates as the equilibrium grid:
\[\begin{aligned} T_1 &= \rho \mathcal{J}^2 \frac{h^{22}}{\mu_0} g_{33} \\ T_2 &= \rho \frac{1}{h^{22}} \ , \end{aligned}\]
with \(T_i\) = Ti
.
The interpolated Ti_X are then used to calculate \(\widetilde{KV}_{k,m}^i\):
\[\begin{aligned} \widetilde{KV}_{k,m}^0 &= T_1 U_k^{0*} U_m^0 + T_2 \\ \widetilde{KV}_{k,m}^1 &= T_1 U_k^{0*} U_m^1 \\ \widetilde{KV}_{k,m}^2 &= T_1 U_k^{1*} U_m^1 \ , \end{aligned}\]
where
\[DU_k^i = i (nq-m) U_k^i + \frac{\partial U_k^i}{\partial\theta} . \]
This is valid for poloidal Flux coordinates and where \(n\) is to be replaced by \(m\) and \((nq-m)\) by \((n-\iota m)\) for toroidal Flux coordinates.
[in] | grid_eq | equilibrium grid |
[in] | grid_x | perturbation grid |
[in] | eq_1 | flux equilibrium |
[in] | eq_2 | metric equilibrium |
[in] | x_a | vectorial perturbation variables of dimension 2 |
[in] | x_b | vectorial perturbation variables of dimension 2 |
[in,out] | x | tensorial perturbation variables |
[in] | lim_sec_x | limits of m_X (pol flux) or n_X (tor flux) for both dimensions |
Definition at line 2879 of file X_ops.f90.
integer function, public x_ops::calc_magn_ints | ( | type(grid_type), intent(in) | grid_eq, |
type(grid_type), intent(in) | grid_X, | ||
type(eq_2_type), intent(in), target | eq, | ||
type(x_2_type), intent(in) | X, | ||
type(x_2_type), intent(inout) | X_int, | ||
integer, intent(in), optional | prev_style, | ||
integer, dimension(2,2), intent(in), optional | lim_sec_X | ||
) |
Calculate the magnetic integrals from \(\widetilde{PV}_{k,m}^i\) and \(\widetilde{KV}_{k,m}^i\) in an equidistant grid where the step size can vary depending on the normal coordinate.
All the variables should thus be field-line oriented. The result is saved in the first index of the X variables, the other can be ignored.
Using prev_style
, the results of this calculation on X can be combined with the ones already present in X_int
.
prev_style=0
: Overwrite [def].prev_style=1
: Add to current integral.prev_style=2
: Divide by 2 and add to current integral. Also modify the indices of the current integral:magn_int_style
= 1: 1 2 2 2 2 2 1 -> 2 2 2 2 2 2
,magn_int_style
= 2: 1 3 3 2 3 3 1 -> 3 2 3 3 2 3
.prev_style=3
: Add to current integral. Also modify the indices of the current integral as in prev_style
= 2.Therefore, it is to be used in order. For example:
Afterwards, it would cycle through 2 and 3, as style 0 and 1 are only for the first Richardson level.
X_2
, but it is assumed that the first index has dimension 1, the rest is ignored.min_n_par_X
)use_pol_flux_F
[6].[in] | grid_eq | equilibrium grid |
[in] | grid_x | perturbation grid |
[in] | eq | metric equilibrium |
[in] | x | tensorial perturbation variables |
[in,out] | x_int | interpolated tensorial perturbation variables, containing all mode combinations |
[in] | prev_style | style to treat X_prev |
[in] | lim_sec_x | limits of m_X (pol flux) or n_X (tor flux) for both dimensions |
Definition at line 3081 of file X_ops.f90.
integer function x_ops::calc_pv | ( | type(grid_type), intent(in) | grid_eq, |
type(grid_type), intent(in) | grid_X, | ||
type(eq_1_type), intent(in), target | eq_1, | ||
type(eq_2_type), intent(in), target | eq_2, | ||
type(x_1_type), intent(in) | X_a, | ||
type(x_1_type), intent(in) | X_b, | ||
type(x_2_type), intent(inout) | X, | ||
integer, dimension(2,2), intent(in), optional | lim_sec_X | ||
) |
calculate \(\widetilde{PV}_{k,m}^i\) (pol. flux) or \(\widetilde{PV}_{l,n}^i\) (tor. flux) at all equilibrium loc_n_r
values.
Like in calc_U(), use is made of variables Ti
that are set up in the equilibrium grid and are afterwards converted to Ti_X
in the perturbation grid, which needs to have the same angular coordinates as the equilibrium grid:
\[\begin{aligned} T_1 &= \frac{h^{22}}{\mu_0} g_{33} \\ T_2 &= \mathcal{J}S + \mu_0 \sigma \frac{g_{33}}{\mathcal{J}} h^{22} \\ T_3 &= \frac{\sigma}{\mathcal{J}} T_2 \\ T_4 &= \frac{1}{\mu_0} \mathcal{J}^2 h^{22} \\ T_5 &= 2 p' \kappa_n \ , \end{aligned}\]
with \(T_i\) = Ti
.
The interpolated Ti_X are then used to calculate \(\widetilde{PV}_{k,m}^i\):
\[\begin{aligned} \widetilde{PV}_{k,m}^0 &= T_1(DU_k^{0*} - T_2)(DU_m^0 - T_2) - T_3 + (nq-m)(nq-k)T_4 - T_5 \\ \widetilde{PV}_{k,m}^1 &= T_1(DU_k^{0*} - T_2) DU_m^1 \\ \widetilde{PV}_{k,m}^2 &= T_1 DU_k^{1*} DU_m^1 \ , \end{aligned}\]
where
\[DU_k^i = i (nq-m) U_k^i + \frac{\partial U_k^i}{\partial\theta} . \]
This is valid for poloidal Flux coordinates and where \(n\) is to be replaced by \(m\) and \((nq-m)\) by \((n-\iota m)\) for toroidal Flux coordinates.
[in] | grid_eq | equilibrium grid |
[in] | grid_x | perturbation grid |
[in] | eq_1 | flux equilibrium |
[in] | eq_2 | metric equilibrium |
[in] | x_a | vectorial perturbation variables of dimension 2 |
[in] | x_b | vectorial perturbation variables of dimension 2 |
[in,out] | x | tensorial perturbation variables |
[in] | lim_sec_x | limits of m_X (pol flux) or n_X (tor flux) for both dimensions |
Definition at line 2646 of file X_ops.f90.
integer function, public x_ops::calc_res_surf | ( | type(modes_type), intent(in) | mds, |
type(grid_type), intent(in) | grid_eq, | ||
type(eq_1_type), intent(in) | eq, | ||
real(dp), dimension(:,:), intent(inout), allocatable | res_surf, | ||
logical, intent(in), optional | info, | ||
real(dp), dimension(:), intent(inout), optional, allocatable | jq | ||
) |
Calculates resonating flux surfaces for the perturbation modes.
The output consists of mode number, resonating normal position and the fraction \(\frac{m}{n}\) or \(\frac{n}{m}\). for those modes for which a solution is found that is within the plasma range.
It contains three pieces of information:
(:,1)
: the mode index(:,2)
: the radial position in Flux coordinates(:,3)
: the fraction \(\frac{m}{n}\) or \(\frac{n}{m}\)for every single mode in sec
of mds
, which can be tabulated in an arbitrary grid, not necessarily the equilibrium one.
Optionally, the total safety factor or rotational transform can be returned to the master.
Also, information can be displayed with \info.
[in] | mds | general modes variables |
[in] | grid_eq | equilibrium grid_eq |
[in] | eq | flux equilibrium |
[in,out] | res_surf | resonant surface |
[in] | info | if info is displayed |
[in,out] | jq | either safety factor or rotational transform |
Definition at line 1638 of file X_ops.f90.
integer function x_ops::calc_u | ( | type(grid_type), intent(in) | grid_eq, |
type(grid_type), intent(in) | grid_X, | ||
type(eq_1_type), intent(in), target | eq_1, | ||
type(eq_2_type), intent(in), target | eq_2, | ||
type(x_1_type), intent(inout) | X | ||
) |
Calculate \(U_m^0\), \(U_m^1\) or \(U_n^0\), \(U_n^1\).
This is done at eq loc_n_r
values of the normal coordinate, n_par
values of the parallel coordinate and size_X
values of the poloidal mode number, or of the toroidal mode number, as well as the poloidal derivatives
Use is made of variables Ti
that are set up in the equilibrium grid and are afterwards converted to Ti_X
in the perturbation grid, which needs to have the same angular coordinates as the equilibrium grid:
\[\begin{aligned} T_1 &= \frac{B_\alpha}{B_\theta} \\ T_2 &= \Theta^\alpha + q' \theta \\ T_3 &= \frac{B_\alpha}{B_\theta} q' + \frac{\mathcal{J}^2}{B_\theta} \mu_0 p' \\ T_4 &= \frac{B_\alpha}{B_\theta} q' \theta - \frac{B_\psi}{B_\theta} \\ T_5 &= \frac{B_\alpha}{B_\theta} \frac{\partial \Theta^\theta}{\partial \theta} - \frac{\partial\Theta^\theta}{\partial \alpha} \\ T_6 &= \frac{B_\alpha}{B_\theta} \Theta^\theta \ , \end{aligned}\]
with \(T_i\) = Ti
.
which is valid for poloidal Flux coordinates.
For toroidal Flux coordinates, \(q'\) has to be replaced by \(-\iota'\) and \(\theta\) by \(\zeta\).
The interpolated Ti_X
are then used to calculate \(U\):
\[\begin{aligned} U_0 =& -T_2 &\text{(order 1)}\\ &+ \frac{i}{n}\left(T_3 + i(nq-m) T_4\right) &\text{(order 2)}\\ &+ \left(\frac{i}{n}\right)^2 i(nq-m) \left(-T_5 - (nq-m) T_6\right) &\text{(order 3)}\\ U_1 =& \frac{i}{n} &\text{(order 1)}\\ &+ \left(\frac{i}{n}\right)^2 i(nq-m)(-T_1) &\text{(order 2)} . \end{aligned}\]
This is valid for poloidal Flux coordinates and where \(n\) is to be replaced by \(m\) and \((nq-m)\) by \((n-\iota m)\) for toroidal Flux coordinates.
For VMEC, these factors are also derived in the parallel coordinate.
[in] | grid_eq | equilibrium grid variables |
[in] | grid_x | perturbation grid variables |
[in] | eq_1 | flux equilibrium |
[in] | eq_2 | metric equilibrium |
[in,out] | x | vectorial perturbation variables |
Definition at line 2097 of file X_ops.f90.
integer function, public x_ops::check_x_modes | ( | type(grid_type), intent(in) | grid_eq, |
type(eq_1_type), intent(in) | eq | ||
) |
Checks whether the high-n approximation is valid:
This depends on the X_style:
For X_style 1 (prescribed): every mode should resonate at least somewhere in the whole normal range:
where \(T\) = tol
<< 1.
This condition is determined by the sign of \(q\) (or \(\iota\)) and given by:
for poloidal flux.
For toroidal flux, \(q\) should be replaced by \(\iota\) and \(\frac{m}{n}\) by \(\frac{n}{m}\).
For X_style
2 (fast): the resonance has been taken care of, but it remains to be checked whether the number of modes is efficient.
[in] | grid_eq | equilibrium grid |
[in] | eq | flux equilibrium |
Definition at line 1350 of file X_ops.f90.
integer function, public x_ops::divide_x_jobs | ( | integer, intent(in) | arr_size | ) |
Divides the perturbation jobs.
This concerns the calculation of the magnetic integrals of blocks of tensorial perturbation variables. These are set up using the equilibrium and vectorial perturbation variables that are stored in memory, but only the integrated tensorial result is stored in memory, with negligible variables size.
The size of the (k,m) pairs to be calculated is determined by looking at what fits in memory when the equilibrium and vectorial perturbation variables are stored in memory first.
[in] | arr_size | array size (using loc_n_r) |
Definition at line 3364 of file X_ops.f90.
integer function, public x_ops::init_modes | ( | type(grid_type), intent(in) | grid_eq, |
type(eq_1_type), intent(in) | eq | ||
) |
Initializes some variables concerning the mode numbers.
Setup minimum and maximum of mode numbers at every flux surface in equilibrium coordinates
min_n_X
, max_n_X
min_m_X
, max_m_X
,It functions depending on the X_style
used: 1 (prescribed) or 2 (fast). For the fast style, at every flux surface the range of modes is sought that resonates most:
where \(N\) = n_mod_X
.
However, at the same time, both m
and n
have to be larger, in absolute value, than min_sec_X
. Therefore, the range of width n_mod_X
can be shifted upwards.
[in] | grid_eq | equilibrium grid |
[in] | eq | flux equilibrium |
Definition at line 919 of file X_ops.f90.
integer function, public x_ops::print_debug_x_1 | ( | type(modes_type), intent(in) | mds, |
type(grid_type), intent(in) | grid_X, | ||
type(x_1_type), intent(in) | X_1 | ||
) |
integer function, public x_ops::print_debug_x_2 | ( | type(modes_type), intent(in) | mds, |
type(grid_type), intent(in) | grid_X, | ||
type(x_2_type), intent(in) | X_2_int | ||
) |
integer function, public x_ops::resonance_plot | ( | type(modes_type), intent(in) | mds, |
type(grid_type), intent(in) | grid_eq, | ||
type(eq_1_type), intent(in) | eq | ||
) |
plot \(q\)-profile or \(\iota\)-profile in flux coordinates with \(nq-m = 0\) or \(n-\iota m = 0\) indicated if requested.
The plot will be done in the grid in which mds
is tabulated, which is not necessarily the equilibrium one.
[in] | mds | general modes variables |
[in] | grid_eq | equilibrium grid |
[in] | eq | flux equilibrium |
Definition at line 1814 of file X_ops.f90.
integer function, public x_ops::setup_modes | ( | type(modes_type), intent(inout), target | mds, |
type(grid_type), intent(in) | grid_eq, | ||
type(grid_type), intent(in) | grid, | ||
character(len=*), intent(in), optional | plot_name | ||
) |
Sets up some variables concerning the mode numbers.
Apart from the mode numbers
n
, m
,also the variables of the secondary modes
are set up in the coordinates of the grid passed. The normal values of this grid are saved as well, in
All variables are tabulated in the full normal grid. The mode indices, however, are chosen so that there is maximum overlap between different normal positions. This is trivial for X_style
1 (prescribed), but for X_style
2 (fast), this is best explained by an example:
1 10 11 12 <- start 2 10 11 12 <- no change in limits 2 13 11 12 <- limits shift up by one 3 13 11 12 <- no change in limits 4 13 14 12 <- limits shift up by one 5 16 14 15 <- limits shift up by two 6 13 14 15 <- limits shift down by one
This procedure makes use of the global variables
min_m_X
, max_m_X, min_n_X, max_m_Xthat have to be set up using init_nm_x().
Optionally, n
and m
can be plot.
[in,out] | mds | modes variables |
[in] | grid_eq | equilibrium grid |
[in] | grid | grid at which to calculate modes |
[in] | plot_name | name to be used when plotting n and m |
Definition at line 1060 of file X_ops.f90.