bluemira.equilibria.flux_surfaces

Flux surface utility classes and calculations

Classes

FluxSurface

Flux surface base class.

ClosedFluxSurface

Utility class for closed flux surfaces.

OpenFluxSurface

Utility class for handling open flux surface geometries.

PartialOpenFluxSurface

Utility class for a partial open flux surface, i.e. an open flux surface that has

CoreResults

Dataclass for core results.

FieldLine

Field line object.

FieldLineTracer

Field line tracing tool.

Functions

_flux_surface_dl(x, dx, dz, Bp, Bt)

analyse_plasma_core(→ CoreResults)

Analyse plasma core parameters across the normalised 1-D flux coordinate.

calculate_connection_length_flt(→ float)

Calculate the parallel connection length from a starting point to a flux-intercepting

calculate_connection_length_fs(→ float)

Calculate the parallel connection length from a starting point to a flux-intercepting

poloidal_angle(→ float)

From glancing angle (gamma) to poloidal angle.

Module Contents

bluemira.equilibria.flux_surfaces._flux_surface_dl(x, dx, dz, Bp, Bt)
class bluemira.equilibria.flux_surfaces.FluxSurface(geometry: bluemira.geometry.coordinates.Coordinates)

Flux surface base class.

Parameters:

geometry (bluemira.geometry.coordinates.Coordinates) – Flux surface geometry object

__slots__ = ('coords',)
coords
property x_start: float

Start radial coordinate of the FluxSurface.

Return type:

float

property z_start: float

Start vertical coordinate of the FluxSurface.

Return type:

float

property x_end: float

End radial coordinate of the FluxSurface.

Return type:

float

property z_end: float

End vertical coordinate of the FluxSurface.

Return type:

float

_dl(eq)
connection_length(eq: bluemira.equilibria.equilibrium.Equilibrium) float

Calculate the parallel connection length along a field line (i.e. flux surface).

Parameters:

eq (bluemira.equilibria.equilibrium.Equilibrium) – Equilibrium from which the FluxSurface was extracted

Returns:

Connection length from the start of the flux surface to the end of the flux surface

Return type:

float

plot(ax: matplotlib.pyplot.Axes | None = None, **kwargs)

Plot the FluxSurface.

Parameters:

ax (matplotlib.pyplot.Axes | None)

copy()

Make a deep copy of the FluxSurface.

Returns:

An instance of FluxSurface, with exactly the same class and coordinates, but sharing a different underlying copy of the data (Coordinates).

class bluemira.equilibria.flux_surfaces.ClosedFluxSurface(geometry: bluemira.geometry.coordinates.Coordinates)

Bases: FluxSurface

Inheritance diagram of bluemira.equilibria.flux_surfaces.ClosedFluxSurface

Utility class for closed flux surfaces.

Parameters:

geometry (bluemira.geometry.coordinates.Coordinates)

__slots__ = ('_p1', '_p2', '_p3', '_p4', '_z_centre')
_p1
_p2
_p3
_p4
_z_centre
property major_radius: float

Major radius of the ClosedFluxSurface.

Return type:

float

property minor_radius: float

Minor radius of the ClosedFluxSurface.

Return type:

float

property aspect_ratio: float

Aspect ratio of the ClosedFluxSurface.

Return type:

float

property kappa: float

Average elongation of the ClosedFluxSurface.

Return type:

float

property kappa_upper: float

Upper elongation of the ClosedFluxSurface.

Return type:

float

property kappa_lower: float

Lower elongation of the ClosedFluxSurface.

Return type:

float

property delta: float

Average triangularity of the ClosedFluxSurface.

Return type:

float

property delta_upper: float

Upper triangularity of the ClosedFluxSurface.

Return type:

float

property delta_lower: float

Lower triangularity of the ClosedFluxSurface.

Return type:

float

property zeta: float

Average squareness of the ClosedFluxSurface.

Return type:

float

property zeta_upper: float

Outer upper squareness of the ClosedFluxSurface.

Return type:

float

property zeta_lower: float

Outer lower squareness of the ClosedFluxSurface.

Return type:

float

_zeta_calc(a, b, xa, za, xd, zd)

Actual squareness calculation

Notes

Squareness defined here w.r.t an ellipse intersection along a projected line

property area: float

Enclosed area of the ClosedFluxSurface.

Return type:

float

property volume: float

Volume of the ClosedFluxSurface.

Return type:

float

shafranov_shift(eq: bluemira.equilibria.equilibrium.Equilibrium) tuple[float, float]

Calculate the Shafranov shift of the ClosedFluxSurface.

Parameters:

eq (bluemira.equilibria.equilibrium.Equilibrium) – Equilibrium with which to calculate the safety factor

Returns:

  • dx_shaf – Radial Shafranov shift

  • dz_shaf – Vertical Shafranov shift

Return type:

tuple[float, float]

safety_factor(eq: bluemira.equilibria.equilibrium.Equilibrium) float

Calculate the cylindrical safety factor of the ClosedFluxSurface. The ratio of toroidal turns to a single full poloidal turn.

Parameters:

eq (bluemira.equilibria.equilibrium.Equilibrium) – Equilibrium with which to calculate the safety factor

Return type:

Cylindrical safety factor of the closed flux surface

class bluemira.equilibria.flux_surfaces.OpenFluxSurface(coords: bluemira.geometry.coordinates.Coordinates)

Bases: FluxSurface

Inheritance diagram of bluemira.equilibria.flux_surfaces.OpenFluxSurface

Utility class for handling open flux surface geometries.

Parameters:

coords (bluemira.geometry.coordinates.Coordinates)

__slots__ = ()
split(psi_point: bluemira.equilibria.find.PsiPoint, plane: bluemira.geometry.plane.BluemiraPlane | None = None) tuple[PartialOpenFluxSurface, PartialOpenFluxSurface]

Split an OpenFluxSurface into two separate PartialOpenFluxSurfaces about a horizontal plane.

N.B. The magnetic centre of the plasma (O-point) is often the value that is used for the PsiPoint and X-Y plane.

Parameters:
  • psi_point (bluemira.equilibria.find.PsiPoint) – Point at which to make the split.

  • plane (bluemira.geometry.plane.BluemiraPlane | None) – The x-y cutting plane. Will default to the psi_point x-y plane

Returns:

  • down – The downwards open flux surfaces from the splitting point

  • up – The upwards open flux surfaces from the splitting point

Return type:

tuple[PartialOpenFluxSurface, PartialOpenFluxSurface]

class bluemira.equilibria.flux_surfaces.PartialOpenFluxSurface(coords: bluemira.geometry.coordinates.Coordinates)

Bases: OpenFluxSurface

Inheritance diagram of bluemira.equilibria.flux_surfaces.PartialOpenFluxSurface

Utility class for a partial open flux surface, i.e. an open flux surface that has been split at the midplane and only has one intersection with the wall.

Parameters:

coords (bluemira.geometry.coordinates.Coordinates)

__slots__ = ('alpha',)
alpha = None
clip(first_wall: bluemira.geometry.coordinates.Coordinates)

Clip the PartialOpenFluxSurface to a first wall.

Parameters:

first_wall (bluemira.geometry.coordinates.Coordinates) – The geometry of the first wall to clip the OpenFluxSurface to

flux_expansion(eq: bluemira.equilibria.equilibrium.Equilibrium) float

Flux expansion of the PartialOpenFluxSurface.

Parameters:

eq (bluemira.equilibria.equilibrium.Equilibrium) – Equilibrium with which to calculate the flux expansion

Return type:

Target flux expansion

class bluemira.equilibria.flux_surfaces.CoreResults

Dataclass for core results.

psi_n: collections.abc.Iterable[float]
R_0: collections.abc.Iterable[float]
a: collections.abc.Iterable[float]
A: collections.abc.Iterable[float]
area: collections.abc.Iterable[float]
V: collections.abc.Iterable[float]
kappa: collections.abc.Iterable[float]
delta: collections.abc.Iterable[float]
zeta: collections.abc.Iterable[float]
kappa_upper: collections.abc.Iterable[float]
delta_upper: collections.abc.Iterable[float]
zeta_upper: collections.abc.Iterable[float]
kappa_lower: collections.abc.Iterable[float]
delta_lower: collections.abc.Iterable[float]
zeta_lower: collections.abc.Iterable[float]
q: collections.abc.Iterable[float]
Delta_shaf: collections.abc.Iterable[float]
__post_init__()

Setup plot units

to_dict(*, latex_unit: bool = False)

Add appropriate units to value names. Make latex ready if latex=true.

Returns:

Dictionary with updated keys for tables and plotting.

Parameters:

latex_unit (bool)

bluemira.equilibria.flux_surfaces.analyse_plasma_core(eq: bluemira.equilibria.equilibrium.Equilibrium, n_points: int = 50) CoreResults

Analyse plasma core parameters across the normalised 1-D flux coordinate.

Return type:

Results dataclass

Parameters:
class bluemira.equilibria.flux_surfaces.FieldLine(coords: bluemira.geometry.coordinates.Coordinates, connection_length: float)

Field line object.

Parameters:
coords
connection_length
plot(ax: matplotlib.pyplot.Axes | None = None, **kwargs)

Plot the FieldLine.

Parameters:

ax (matplotlib.pyplot.Axes | None) – Matplotlib axes onto which to plot

pointcare_plot(ax: matplotlib.pyplot.Axes | None = None)

Poincaré plot of the field line intersections with the half-xz-plane.

Parameters:

ax (matplotlib.pyplot.Axes | None) – Matplotlib axes onto which to plot

class bluemira.equilibria.flux_surfaces.FieldLineTracer(eq: bluemira.equilibria.equilibrium.Equilibrium, first_wall: bluemira.equilibria.grid.Grid | bluemira.geometry.coordinates.Coordinates | None = None)

Field line tracing tool.

Parameters:

Notes

Totally pinched some maths from Ben Dudson’s FreeGS here… Perhaps one day I can return the favours.

I needed it to compare the analytical connection length calculation with something, so I nicked this but changed the way the equation is solved.

Note that this will properly trace field lines through Coils as it doesn’t rely on the psi map (which is inaccurate inside Coils).

class CollisionTerminator(boundary: bluemira.equilibria.grid.Grid | bluemira.geometry.coordinates.Coordinates)

Private Event handling object for solve_ivp

Parameters:

boundary (Union[Grid, Coordinates]) – Boundary at which to stop tracing the field line.

boundary
terminal = True
__call__(_phi, xz, *_args)

Function handle for the CollisionTerminator

Returns:

The distance to the given xz point

_call_grid(xz)

Function handle for the CollisionTerminator in the case of a Grid. (slight speed improvement)

Returns:

the minimal distance to the grid

_call_coordinates(xz)

Function handle for the CollisionTerminator in the case of Coordinates.

Returns:

the minimal distance to the grid

eq
first_wall = None
trace_field_line(x: float, z: float, n_points: int = 200, *, forward: bool = True, n_turns_max: int = 20) FieldLine

Trace a single field line starting at a point.

Parameters:
  • x (float) – Radial coordinate of the starting point

  • z (float) – Vertical coordinate of the starting point

  • n_points (int) – Number of points along the field line

  • forward (bool) – Whether or not to step forward or backward (+B or -B)

  • n_turns_max (Union[int, float]) – Maximum number of toroidal turns to trace the field line

Returns:

Resulting field line

Return type:

FieldLine

_dxzl_dphi(_phi, xz, forward)

Credit: Dr. B. Dudson, FreeGS.

Returns:

The dx, dz, and dl

static _process_result(result)
bluemira.equilibria.flux_surfaces.calculate_connection_length_flt(eq: bluemira.equilibria.equilibrium.Equilibrium, x: float, z: float, first_wall: bluemira.geometry.coordinates.Coordinates | bluemira.equilibria.grid.Grid, *, forward: bool = True, n_points: int = 200, n_turns_max: int = 50) float

Calculate the parallel connection length from a starting point to a flux-intercepting surface using a field line tracer.

Parameters:
Returns:

  • Parallel connection length along the field line from the starting point to the

  • intersection point [m]

Return type:

float

Notes

More mathematically accurate, but needs additional configuration. Will not likely return a very accurate flux interception point. Also works for closed flux surfaces, but can’t tell the difference. Not sensitive to equilibrium grid discretisation. Will work correctly for flux surfaces passing through Coils, but really they should be intercepted beforehand!

bluemira.equilibria.flux_surfaces.calculate_connection_length_fs(eq: bluemira.equilibria.equilibrium.Equilibrium, x: float, z: float, first_wall: bluemira.geometry.coordinates.Coordinates, *, forward: bool = True, f_s: bluemira.geometry.coordinates.Coordinates | None = None) float

Calculate the parallel connection length from a starting point to a flux-intercepting surface using flux surface geometry.

Parameters:
Returns:

  • Parallel connection length along the field line from the starting point to the

  • intersection point [m]

Raises:

FluxSurfaceError – If the flux surface at the point in the equilibrium is not an open flux surface

Return type:

float

Notes

Less mathematically accurate. Will return exact intersection point. Sensitive to equilibrium grid discretisation. Presently does not correctly work for flux surfaces passing through Coils, but really they should be intercepted beforehand!

bluemira.equilibria.flux_surfaces.poloidal_angle(Bp_strike: float, Bt_strike: float, gamma: float) float

From glancing angle (gamma) to poloidal angle.

Parameters:
  • Bp_strike (float) – Poloidal magnetic field value at the desired point

  • Bt_strike (float) – Toroidal magnetic field value at the desired point

  • gamma (float) – Glancing angle at the strike point [deg]

Return type:

Poloidal angle at the strike point [deg]