bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions

Spherical harmonics classes and calculations.

Classes

PointType

Class for use with collocation_points function.

Collocation

Dataclass for collocation point locations.

Functions

coil_harmonic_amplitude_matrix(→ numpy.ndarray)

Construct matrix from harmonic amplitudes at given coil locations.

harmonic_amplitude_marix(→ numpy.ndarray)

Construct matrix from harmonic amplitudes at given points (in spherical coords).

collocation_points(→ Collocation)

Create a set of collocation points for use wih spherical harmonic

fs_fit_metric(→ float)

Calculate the value of the metric used for evaluating the SH&TH approximation.

coils_outside_fs_sphere(→ tuple[list, float])

Find the coils located outside of the sphere containing the core plasma,

get_psi_harmonic_amplitudes(→ numpy.ndarray)

Calculate the Spherical Harmonic (SH) amplitudes/coefficients needed to produce

spherical_harmonic_approximation(→ tuple[list, ...)

Calculate the spherical harmonic (SH) amplitudes/coefficients

plot_psi_comparision(→ tuple[matplotlib.pyplot.Axes, ...)

Create plot comparing an original psi to psi obtained from harmonic approximation.

Module Contents

bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.coil_harmonic_amplitude_matrix(input_coils: bluemira.equilibria.coils.CoilSet, max_degree: int, r_t: float, sh_coil_names: list, sig_figures: int = 15) numpy.ndarray

Construct matrix from harmonic amplitudes at given coil locations.

To get an array of spherical harmonic amplitudes/coefficients (A_l) which can be used in a spherical harmonic approximation of the vacuum/coil contribution to the poloidal flux (psi) do:

A_l = matrix harmonic amplitudes @ vector of coil currents

A_l can be used as constraints in optimisation, see spherical_harmonics_constraint.

N.B. for a single filament (coil):

\[A_{l} = \frac{1}{2} \mu_{0} I_{f} \sin{\theta_{f}} (\frac{r_{t}}{r_{f}})^l \frac{P_{l} \cos{\theta_{f}}}{\sqrt{l(l+1)}}\]

Where l = degree, and :math: P_{l} cos{theta_{f}} are the associated Legendre polynomials of degree l and order (m) = 1.

Parameters:
  • input_coils (bluemira.equilibria.coils.CoilSet) – Bluemira CoilSet

  • max_degree (int) – Maximum degree of harmonic to calculate up to

  • r_t (float) – Typical length scale (e.g. radius at outer midplane)

  • sh_coil_names (list) – Names of the coils to use with SH approximation (always located outside bdry_r)

  • sig_figures (int) – Number of significant figures for rounding currents2harmonics values

Returns:

Matrix of harmonic amplitudes

Return type:

currents2harmonics

bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.harmonic_amplitude_marix(collocation_r: numpy.ndarray, collocation_theta: numpy.ndarray, r_t: float, sig_figures: int = 15) numpy.ndarray

Construct matrix from harmonic amplitudes at given points (in spherical coords).

The matrix is used in a spherical harmonic approximation of the vacuum/coil contribution to the poloidal flux (psi):

\[\psi = \sum{A_{l} \frac{r^{l+1}}{r_{t}^l} \sin{\theta_{f}} \frac{P_{l} \cos{\theta_{f}}}{\sqrt{l(l+1)}}}\]

Where l = degree, A_l are the spherical harmonic coefficients/amplitudes, and :math: P_{l} cos{theta_{f}} are the associated Legendre polynomials of degree l and order (m) = 1.

N.B. Vacuum Psi = Total Psi - Plasma Psi.

Parameters:
  • collocation_r (numpy.ndarray) – R values of collocation points

  • collocation_theta (numpy.ndarray) – Theta values of collocation points

  • r_t (float) – Typical length scale (e.g. radius at outer midplane)

  • sig_figures (int) – Number of significant figures for rounding harmonics2collocation values

Returns:

harmonics2collocation – Matrix of harmonic amplitudes (to get spherical harmonic coefficients use matrix @ coefficients = vector psi_vacuum at collocation points)

Return type:

np.array

class bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.PointType(*args, **kwds)

Bases: enum.Enum

Inheritance diagram of bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.PointType

Class for use with collocation_points function. User can choose how the collocation points are distributed.

ARC
ARC_PLUS_EXTREMA
RANDOM
RANDOM_PLUS_EXTREMA
GRID_POINTS
class bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.Collocation

Dataclass for collocation point locations.

r: numpy.ndarray
theta: numpy.ndarray
x: numpy.ndarray
z: numpy.ndarray
bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.collocation_points(plasma_boundary: bluemira.geometry.coordinates.Coordinates, point_type: PointType, n_points: int = 10, seed: int | None = None, grid_num: tuple[int, int] | None = None) Collocation

Create a set of collocation points for use wih spherical harmonic approximations. Points are found within the user-supplied boundary and should correspond to the LCFS (or similar) of a chosen equilibrium. Current functionality is for:

  • equispaced points on an arc of fixed radius,

  • equispaced points on an arc plus extrema,

  • random points within a circle enclosed by the boundary,

  • random points plus extrema,

  • a grid of points containing the boundary.

Parameters:
  • n_points (int) – Number of points/targets (not including extrema - these are added automatically if relevant). For use with point_type ‘arc’, ‘arc_plus_extrema’, ‘random’, ‘random_plus_extrema’, or ‘grid_num’. For ‘grid_num’ it will create an n_points by n_points grid (see grid_num for a non square grid.)

  • plasma_boundary (bluemira.geometry.coordinates.Coordinates) – XZ coordinates of the plasma boundary

  • point_type (PointType) – Method for creating a set of points: ‘arc’, ‘arc_plus_extrema’, ‘random’, or ‘random_plus_extrema’, ‘grid_points’

  • seed (int | None) – Seed value to use with a random point distribution, defaults to RNGSeeds.equilibria_harmonics.value. For use with ‘random’ or ‘random_plus_extrema’ point_type.

  • grid_num (tuple[int, int] | None) – Tuple with the number of desired grid points in the x and z direction. For use with ‘grid_points’ point_type.

Returns:

Collocation points

Return type:

Collocation

bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.fs_fit_metric(coords1: bluemira.geometry.coordinates.Coordinates, coords2: bluemira.geometry.coordinates.Coordinates) float

Calculate the value of the metric used for evaluating the SH&TH approximation. This is equal to 1 for non-intersecting flux surfaces, and 0 for identical surfaces. The flux surface of interest is usually the LCFS, or a closed flux surface that is close to the last closed flux surface., e.g., psi_norm = 0.95 or 0.98.

Parameters:
Returns:

Measure of how ‘good’ the approximation is. fit_metric_value = total area within one but not both FSs / (input FS area + approximation FS area)

Return type:

fit_metric_value

bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.coils_outside_fs_sphere(eq: bluemira.equilibria.equilibrium.Equilibrium, psi_norm: float | None = None) tuple[list, float]

Find the coils located outside of the sphere containing the core plasma, e.g., LCFS of the equilibrium state.

Parameters:
Returns:

  • c_names or not_too_close_coils – coil names selected appropriately for use of SH approximation

  • bdry_r – maximum radial value for fs of starting equilibria

  • psi_norm – Normalised flux value of the surface of interest. None value will default to LCFS.

Return type:

tuple[list, float]

bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.get_psi_harmonic_amplitudes(vacuum_psi: numpy.ndarray, grid: bluemira.equilibria.grid.Grid, collocation: Collocation, r_t: float, sig_figures: int = 15) numpy.ndarray

Calculate the Spherical Harmonic (SH) amplitudes/coefficients needed to produce a SH approximation of the vacuum (i.e. control coil) contribution to the poloidal flux (psi).The number of degrees used in the approximation is one less than the number of collocation points.

Parameters:
  • vacuum_psi (numpy.ndarray) – Psi contribution from coils that we wish to approximate

  • grid (bluemira.equilibria.grid.Grid) – Associated grid

  • collocation (Collocation) – Collocation points

  • r_t (float) – Typical length scale for spherical harmonic approximation (default = maximum x value of LCFS).

  • sig_figures (int) – Number of significant figures for rounding psi_harmonic_amplitudes values

Returns:

SH coefficients for given number of degrees

Return type:

psi_harmonic_amplitudes

bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.spherical_harmonic_approximation(eq: bluemira.equilibria.equilibrium.Equilibrium, n_points: int = 8, point_type: PointType = PointType.ARC_PLUS_EXTREMA, grid_num: tuple[int, int] | None = None, acceptable_fit_metric: float = 0.01, psi_norm: float | None = None, nlevels: int = 50, seed: int | None = None, sig_figures: int = 15, *, plot: bool = False) tuple[list, numpy.ndarray, int, float, numpy.ndarray, float, numpy.ndarray]

Calculate the spherical harmonic (SH) amplitudes/coefficients needed as a reference value for the ‘spherical_harmonics_constraint’ used in coilset optimisation.

Use a FS fit metric to determine the required number of degrees.

The number of degrees used in the approximation is one less than the number of collocation points.

Parameters:
  • eq (bluemira.equilibria.equilibrium.Equilibrium) – Equilibria to use as starting point for approximation. We will approximate psi using SHs - the aim is to keep the core plasma contribution fixed (using SH amplitudes as constraints) while being able to vary the vacuum (coil) contribution, so that we do not need to re-solve for the equilibria during optimisation.

  • n_points (int) – Number of desired collocation points (default=8) excluding extrema (always +4 automatically)

  • point_type (PointType) – Name that determines how the collocation points are selected, (default=”arc_plus_extrema”). The following options are available for collocation point distribution: - ‘arc’ = equispaced points on an arc of fixed radius, - ‘arc_plus_extrema’ = ‘arc’ plus the min and max points of either the LCFS or a flux surface with a chosen normalised flux value. in the x- and z-directions (4 points total), - ‘random’, - ‘random_plus_extrema’. - ‘grid_points’

  • grid_num (tuple[int, int] | None) – Number of points in x-direction and z-direction, to use with grid point distribution.

  • acceptable_fit_metric (float) – The default flux surface (FS) used for this metric is the LCFS. (psi_norm value is used to select an alternative) If the FS found using the SH approximation method perfectly matches the FS of the input equilibria then the fit metric = 0. A fit metric of 1 means that they do not overlap at all. fit_metric_value = total area within one but not both FSs / (input FS area + approximation FS area)

  • psi_norm (float | None) – Normalised flux value of the surface of interest. None value will default to LCFS.

  • nlevels (int) – Plot setting, higher n = greater number of contour lines

  • seed (int | None) – Seed value to use with random point distribution

  • sig_figures (int) – Number of significant figures for rounding during SH approximation

  • plot (bool) – Whether or not to plot the results

Returns:

  • sh_coil_names – Names of the coils to use with SH approximation (always located outside bdry_r)

  • coil_current_harmonic_amplitudes – SH coefficients/amplitudes for required number of degrees

  • degree – Number of degrees required for a SH approx with the desired fit metric

  • fit_metric_value – Fit metric achieved

  • approx_total_psi – Total psi obtained using the SH approximation

  • bdry_r – Approximation boundary - sphere containing core plasma for chosen equilibrium.

  • sh_eq.coilset.current – Coil currents found using the spherical harmonic approximation

Raises:

EquilibriaError – Problem not setup for harmonics

Return type:

tuple[list, numpy.ndarray, int, float, numpy.ndarray, float, numpy.ndarray]

Note

The coil_harmonic_amplitude_matrix often has a high sensitivity to small numbers. To address numerical reproducability across different machines:

  • Even harmonic amplitudes are set to zero.

  • Currents found using lstsq are rounded before being used to calculate the FS fit metric.

bluemira.equilibria.optimisation.harmonics.harmonics_approx_functions.plot_psi_comparision(grid: bluemira.equilibria.grid.Grid, eq: bluemira.equilibria.equilibrium.Equilibrium, vac_psi_app: numpy.ndarray, axes: list[matplotlib.pyplot.Axes] | None = None, nlevels: int = 50, original_flux_surface: bluemira.geometry.coordinates.Coordinates | None = None, approx_flux_surface: bluemira.geometry.coordinates.Coordinates | None = None, *, show: bool = True) tuple[matplotlib.pyplot.Axes, Ellipsis]

Create plot comparing an original psi to psi obtained from harmonic approximation.

Parameters:
Returns:

The Matplotlib Axes objects for each subplot.

Return type:

plot1, plot2, plot3, plot4

Raises:

ValueError – 4 plots must be provided