PB3D  [2.45]
Ideal linear high-n MHD stability in 3-D
Interfaces and Types | Functions/Subroutines | Variables
x_ops Module Reference

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...
 

Detailed Description

Operations considering perturbation quantities.

Function/Subroutine Documentation

◆ calc_kv()

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.

See also
See [15] .
Returns
ierr
Parameters
[in]grid_eqequilibrium grid
[in]grid_xperturbation grid
[in]eq_1flux equilibrium
[in]eq_2metric equilibrium
[in]x_avectorial perturbation variables of dimension 2
[in]x_bvectorial perturbation variables of dimension 2
[in,out]xtensorial perturbation variables
[in]lim_sec_xlimits of m_X (pol flux) or n_X (tor flux) for both dimensions

Definition at line 2879 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_magn_ints()

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:
    • for magn_int_style = 1: 1 2 2 2 2 2 1 -> 2 2 2 2 2 2,
    • for 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.
  • else: ignore previous magnetic integrals.

Therefore, it is to be used in order. For example:

  1. \(\phantom{\rightarrow}\) (R=1,E=1): style 0,
  2. \(\rightarrow\) (R=1,E=2): style 1,
  3. \(\rightarrow\) (R=2,E=1): style 2,
  4. \(\rightarrow\) (R=2,E=2): style 3.

Afterwards, it would cycle through 2 and 3, as style 0 and 1 are only for the first Richardson level.

Note
  1. The variable type for the integrated tensorial perturbation variables is also X_2, but it is assumed that the first index has dimension 1, the rest is ignored.
  2. Simpson's 3/8 rule converges faster than the trapezoidal rule, but normally needs a better starting point (i.e. higher min_n_par_X)
  3. For alpha style 1, Weyl's lemma is used to convert the surface integral into a line integral along the magnetic field. This means that the resulting line integral still needs to be multiplied by \(\frac{2\pi}{M}\), where \(M\) is the number of times the poloidal or toroidal angle completes a full \(2\pi\) tour, depending on use_pol_flux_F [6].
  4. For alpha style 2, this factor is just the step size in alpha.
See also
See x_vars.x_2_type.
Returns
ierr
Parameters
[in]grid_eqequilibrium grid
[in]grid_xperturbation grid
[in]eqmetric equilibrium
[in]xtensorial perturbation variables
[in,out]x_intinterpolated tensorial perturbation variables, containing all mode combinations
[in]prev_stylestyle to treat X_prev
[in]lim_sec_xlimits of m_X (pol flux) or n_X (tor flux) for both dimensions

Definition at line 3081 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_pv()

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.

See also
See [15] .
Returns
ierr
Parameters
[in]grid_eqequilibrium grid
[in]grid_xperturbation grid
[in]eq_1flux equilibrium
[in]eq_2metric equilibrium
[in]x_avectorial perturbation variables of dimension 2
[in]x_bvectorial perturbation variables of dimension 2
[in,out]xtensorial perturbation variables
[in]lim_sec_xlimits of m_X (pol flux) or n_X (tor flux) for both dimensions

Definition at line 2646 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_res_surf()

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.

Returns
ierr
Parameters
[in]mdsgeneral modes variables
[in]grid_eqequilibrium grid_eq
[in]eqflux equilibrium
[in,out]res_surfresonant surface
[in]infoif info is displayed
[in,out]jqeither safety factor or rotational transform

Definition at line 1638 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ calc_u()

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.

See also
See [15].
Returns
ierr
Parameters
[in]grid_eqequilibrium grid variables
[in]grid_xperturbation grid variables
[in]eq_1flux equilibrium
[in]eq_2metric equilibrium
[in,out]xvectorial perturbation variables

Definition at line 2097 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ check_x_modes()

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:

  • \(\frac{\left|nq-m\right|}{\left|n\right|} < T\) and \(\frac{\left|nq-m\right|}{\left|m\right|} < T\) for poloidal flux
  • \(\frac{\left|q-\iota m\right|}{\left|m\right|} < T\) and \(\frac{\left|n-\iota m\right|}{\left|n\right|} < T\) for toroidal flux

where \(T\) = tol << 1.

This condition is determined by the sign of \(q\) (or \(\iota\)) and given by:

  • \(\max\left(q_\text{min}-T,\frac{q_\text{min}}{1+T}\right) < \frac{m}{n} < \min\left(q_\text{max}+T,\frac{q_\text{max}}{1-T}\right)\), \(q>0\)
  • \(\max\left(q_\text{min}-T,\frac{q_\text{min}}{1-T}\right) < \frac{m}{n} < \min\left(q_\text{max}+T,\frac{q_\text{max}}{1+T}\right)\), \(q<0\)

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.

Returns
ierr
Parameters
[in]grid_eqequilibrium grid
[in]eqflux equilibrium

Definition at line 1350 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ divide_x_jobs()

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.

Returns
ierr
Parameters
[in]arr_sizearray size (using loc_n_r)

Definition at line 3364 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_modes()

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:

  • \(m = nq \pm \frac{N}{2}\) for poloidal flux
  • \(n = \iota m \pm \frac{N}{2}\) for toroidal flux

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.

Returns
ierr
Parameters
[in]grid_eqequilibrium grid
[in]eqflux equilibrium

Definition at line 919 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_debug_x_1()

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 
)

Prints debug information for X_1 driver.

Parameters
[in]mdsgeneral modes variables
[in]grid_xperturbation grid
[in]x_1vectorial X variables

Definition at line 3490 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ print_debug_x_2()

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 
)

Prints debug information for X_2 driver.

Parameters
[in]mdsgeneral modes variables
[in]grid_xperturbation grid
[in]x_2_inttensorial X variables

Definition at line 3633 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ resonance_plot()

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.

Returns
ierr
Parameters
[in]mdsgeneral modes variables
[in]grid_eqequilibrium grid
[in]eqflux equilibrium

Definition at line 1814 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setup_modes()

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

  • sec,

are set up in the coordinates of the grid passed. The normal values of this grid are saved as well, in

  • r_F.

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:

kd m1 m2 m3

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_X

that have to be set up using init_nm_x().

Optionally, n and m can be plot.

Returns
ierr
Parameters
[in,out]mdsmodes variables
[in]grid_eqequilibrium grid
[in]gridgrid at which to calculate modes
[in]plot_namename to be used when plotting n and m

Definition at line 1060 of file X_ops.f90.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ debug_check_x_modes_2

logical, public x_ops::debug_check_x_modes_2 = .false.

plot debug information for check_x_modes_2()

Note
Debug version only

Definition at line 26 of file X_ops.f90.