bluemira.equilibria.coils._grouping

Coil and coil grouping objects

Classes

CoilGroup

Coil Grouping object

Circuit

A CoilGroup where all coils have the same current

SymmetricCircuit

A Circuit with positional symmetry

CoilSetOptimisationState

State of the optimisation of a CoilSet

CoilSet

CoilSet is a CoilGroup with the concept of control coils

Functions

symmetrise_coilset(→ CoilSet)

Symmetrise a CoilSet by converting any coils that are up-down symmetric about

Module Contents

bluemira.equilibria.coils._grouping.symmetrise_coilset(coilset: CoilSet, *, rtol: float | None = None, symmetrise_singular: bool = False) CoilSet

Symmetrise a CoilSet by converting any coils that are up-down symmetric about z=0 to SymmetricCircuits.

Parameters:
  • coilset (CoilSet) – CoilSet to symmetrise

  • rtol (float | None) – Relative tolerance used when comparing coil values. The values for the secondary coil in the pair will be set to be equal to the primary coil values if they are within rtol.

  • symmetrise_singular (bool) – make singular coils symmetric about z=0

Returns:

New CoilSet with SymmetricCircuits where appropriate

Raises:

EquilibriaError – Superposition of coils or unrecognised type

Return type:

CoilSet

class bluemira.equilibria.coils._grouping.CoilGroup(*coils: bluemira.equilibria.coils._coil.Coil | CoilGroup, psi_analytic: bool = False, Bx_analytic: bool = True, Bz_analytic: bool = True)

Bases: bluemira.equilibria.coils._field.CoilGroupFieldsMixin

Inheritance diagram of bluemira.equilibria.coils._grouping.CoilGroup

Coil Grouping object

Allow nested coils or groups of coils with access to the methods and properties in the same way to a vanilla Coil

Parameters:
__slots__ = ('_Bx_analytic', '_Bz_analytic', '_coils', '_pad_size', '_psi_analytic')
_coils = ()
__repr__()

Pretty print

n_coils(ctype: str | bluemira.base.constants.CoilType | None = None) int

Get number of coils

Parameters:

ctype (str | bluemira.base.constants.CoilType | None) – get number of coils of a specific type

Returns:

Number of coils

Return type:

int

plot(ax: matplotlib.axes.Axes | None = None, *, subcoil: bool = True, label: bool = False, force: collections.abc.Iterable | None = None, **kwargs) bluemira.equilibria.plotting.CoilGroupPlotter | None

Plot a CoilGroup

Parameters:
  • ax (matplotlib.axes.Axes | None) – Matplotlib axis object

  • subcoil (bool) – plot coil discretisations

  • label (bool) – show coil labels on plot

  • force (collections.abc.Iterable | None) – force arrows iterable

  • kwargs – passed to matplotlib’s Axes.plot

Return type:

bluemira.equilibria.plotting.CoilGroupPlotter | None

fix_sizes()

Fix the sizes of coils in CoilGroup

resize(currents: float | list | numpy.ndarray)

Resize coils based on their current if their size is not fixed

Parameters:

currents (float | list | numpy.ndarray)

_resize(currents: float | list | numpy.ndarray)

Resize coils based on their current

Notes

Ignores any protections on their size

Parameters:

currents (float | list | numpy.ndarray)

__run_func(func: str, *args, **kwargs)

Runs a function with no outputs that exists on a coil or coilgroup

This function aims to deal with the edge cases that are around nested coilgroups If kwargs are passed they will be passed to all function calls as is. If args are passed an attempt is made to push the right shaped argument to a given function.

Raises:

ValueError – Number of arguments not equal to number og coil groups

Parameters:

func (str)

add_coil(*coils: bluemira.equilibria.coils._coil.Coil | CoilGroup)

Add coils to the coil group

Parameters:

coils (bluemira.equilibria.coils._coil.Coil | CoilGroup)

remove_coil(*coil_name: str, _top_level: bool = True) list[str] | None

Remove coil from CoilGroup

Parameters:
  • coil_name (str) – coil(s) to remove

  • _top_level (bool) – FOR INTERNAL USE, flags if at top level of nested coilgroup stack

Returns:

Removed names if not at top level of nested stack

Raises:

EquilibriaError – Unknown coils

Return type:

list[str] | None

Notes

If a nested coilgroup is empty it is also removed from the parent coilgroup

classmethod from_group_vecs(eqdsk: eqdsk.EQDSKInterface) CoilGroup

Initialises an instance of CoilSet from group vectors.

This has been implemented as a dict operation, because it will occur for eqdsks only. Future dict instantiation methods will likely differ, hence the confusing name of this method.

There should always be a coilset but… if for some reason the coilset is missing, and the user has not provided ‘user_coils’ as an input for ‘from_eqdsk’, then a dummy coilset is used and a warning message is printed.

Parameters:

eqdsk (eqdsk.EQDSKInterface)

Return type:

CoilGroup

to_group_vecs() tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]

Output CoilGroup properties as numpy arrays

Returns:

  • x – The x-positions of coils

  • z – The z-positions of coils.

  • dx – The coil size in the x-direction.

  • dz – The coil size in the z-direction.

  • currents – The coil currents.

Return type:

tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray, numpy.ndarray]

__list_getter(attr: str) list

Get attributes from coils tuple

Parameters:

attr (str)

Return type:

list

__getter(attr: str) numpy.ndarray
Returns:

Attribute from coils and convert to flattened numpy array

Parameters:

attr (str)

Return type:

numpy.ndarray

__quad_getter(attr: str) numpy.ndarray
Returns:

Quadratures and autopad to create non ragged array

Parameters:

attr (str)

Return type:

numpy.ndarray

__setter(attr: str, values: bluemira.base.constants.CoilType | float | collections.abc.Iterable[bluemira.base.constants.CoilType | float], dtype: type | None = None)

Set attributes on coils

Raises:

ValueError – Number of elements < number of coils

Parameters:
__getitem__(item)

Get coils

__copy__()

Copy dunder method, needed because attribute setter fails for quadratures

__deepcopy__(memo)

Deepcopy dunder method, needed because attribute setter fails for quadratures

_pad_discretisation(_to_pad: list[numpy.ndarray])

Convert quadrature list of array to rectangular arrays. Padding quadrature arrays with zeros to allow array operations on rectangular matricies.

Parameters:

_to_pad (list[numpy.ndarray]) – x quadratures

Notes

Padding exists for coils with different discretisations or sizes within a coilgroup. There are a few extra calculations of the greens functions where padding exists in _combined_control().

_find_coil(name)

Find coil by name

Raises:

KeyError – Coil not found in group

_get_coiltype(*ctype: bluemira.base.constants.CoilType | str) list[bluemira.equilibria.coils._coil.Coil]

Find coil by type

Parameters:

ctype (bluemira.base.constants.CoilType | str)

Return type:

list[bluemira.equilibria.coils._coil.Coil]

all_coils() list[bluemira.equilibria.coils._coil.Coil]
Returns:

All coils as a flattened list (no CoilGroups)

Return type:

list[bluemira.equilibria.coils._coil.Coil]

_get_type_index(*ctype: bluemira.base.constants.CoilType | str) numpy.typing.NDArray[int]
Parameters:

ctype (bluemira.base.constants.CoilType | str)

Return type:

numpy.typing.NDArray[int]

get_coiltype(*ctype: str | bluemira.base.constants.CoilType) CoilGroup | None
Returns:

Coils matching coil type

Parameters:

ctype (str | bluemira.base.constants.CoilType)

Return type:

CoilGroup | None

assign_material(ctype, j_max, b_max)

Assign material J and B to Coilgroup

get_max_current(max_current: float = np.inf) numpy.ndarray

Get max currents

If a max current argument is provided and the max current isn’t set, the value will be as input.

Parameters:

max_current (float) – max current value if j_max == nan

Returns:

Maximum currents

Return type:

numpy.ndarray

property name: list

Get coil names

Return type:

list

property primary_coil: bluemira.equilibria.coils._coil.Coil

Get primary coil, which is arbitrarily taken to be the first coil in the group.

Will recurse if the first coil itself is a CoilGroup.

Return type:

bluemira.equilibria.coils._coil.Coil

get_coil_or_group_with_coil_name(coil_name: str) bluemira.equilibria.coils._coil.Coil | CoilGroup

Get the coil or coil group with the coil with coil_name in it.

This will be the lowest level group that contains the coil.

Parameters:

coil_name (str) – The coil name to search for

Returns:

The coil or coil group with the given coil name in it

Raises:

ValueError – No coil found with given name

Return type:

bluemira.equilibria.coils._coil.Coil | CoilGroup

property x: numpy.ndarray

Get coil x positions

Return type:

numpy.ndarray

property z: numpy.ndarray

Get coil z positions

Return type:

numpy.ndarray

property position

Get coil x, z positions

property ctype: list

Get coil types

Return type:

list

property dx: numpy.ndarray

Get coil widths (half)

Return type:

numpy.ndarray

property dz: numpy.ndarray

Get coil heights (half)

Return type:

numpy.ndarray

property current: numpy.ndarray

Get coil currents

Return type:

numpy.ndarray

property j_max: numpy.ndarray

Get coil max current density

Return type:

numpy.ndarray

property b_max: numpy.ndarray

Get coil max field

Return type:

numpy.ndarray

property resistance: numpy.ndarray

Get coil resistance

Return type:

numpy.ndarray

property discretisation: numpy.ndarray

Get coil discretisations

Return type:

numpy.ndarray

property n_turns: numpy.ndarray

Get coil number of turns

Return type:

numpy.ndarray

property area: numpy.ndarray

Get coil areas

Return type:

numpy.ndarray

property volume: numpy.ndarray

Get coil volumes

Return type:

numpy.ndarray

property x_boundary: numpy.ndarray

Get coil x coordinate boundary

Return type:

numpy.ndarray

property z_boundary: numpy.ndarray

Get coil z coordinate boundary

Return type:

numpy.ndarray

property _flag_sizefix: numpy.ndarray

Get coil current radius

Return type:

numpy.ndarray

property _current_radius: numpy.ndarray

Get coil current radius

Return type:

numpy.ndarray

property _quad_x

Get coil x quadratures

property _quad_z

Get coil z quadratures

property _quad_dx

Get coil dx quadratures

property _quad_dz

Get coil dz quadratures

property _quad_weighting

Get coil quadrature weightings

property _quad_boundary

Get coil quadrature boundaries

class bluemira.equilibria.coils._grouping.Circuit(*coils: bluemira.equilibria.coils._coil.Coil | CoilGroup, current: float | None = None, psi_analytic: bool = False, Bx_analytic: bool = True, Bz_analytic: bool = True)

Bases: CoilGroup

Inheritance diagram of bluemira.equilibria.coils._grouping.Circuit

A CoilGroup where all coils have the same current

Parameters:
  • coils (bluemira.equilibria.coils._coil.Coil | CoilGroup) – coils in circuit

  • current (float | None) – The current value, if not provided the first coil current is used

  • psi_analytic (bool)

  • Bx_analytic (bool)

  • Bz_analytic (bool)

__slots__ = ('_Bx_analytic', '_Bz_analytic', '_coils', '_pad_size', '_psi_analytic')
current

Get coil currents

_get_current()
property primary_group: bluemira.equilibria.coils._coil.Coil | CoilGroup

Get the first coil or group in the circuit as the ‘primary_group’

Return type:

bluemira.equilibria.coils._coil.Coil | CoilGroup

add_coil(*coils: bluemira.equilibria.coils._coil.Coil | CoilGroup)

Add coil to circuit forcing the same current

Parameters:

coils (bluemira.equilibria.coils._coil.Coil | CoilGroup)

class bluemira.equilibria.coils._grouping.SymmetricCircuit(*coils: bluemira.equilibria.coils._coil.Coil | CoilGroup, psi_analytic: bool = False, Bx_analytic: bool = True, Bz_analytic: bool = True)

Bases: Circuit

Inheritance diagram of bluemira.equilibria.coils._grouping.SymmetricCircuit

A Circuit with positional symmetry

Parameters:

Notes

Although two groups can be defined any movement of the coils is achieved by offsets to the mean position of the coilgroups.

Currently only symmetric about z = 0 see gh issue #210

__slots__ = ('_symmetry_line', '_shift', 'sym_mat', '_Bx_analytic', '_Bz_analytic', '_coils', '_pad_size',...
property symmetric_group: bluemira.equilibria.coils._coil.Coil | CoilGroup

Get the second coil or group as the ‘symmetric_group’

Return type:

bluemira.equilibria.coils._coil.Coil | CoilGroup

modify_symmetry(symmetry_line: numpy.ndarray)

Create a unit vector for the symmetry of the circuit

Parameters:

symmetry_line (numpy.ndarray) – two points making a symmetry line [[float, float], [float, float]]

_symmetry_matrix()

Symmetry matrix

\[\begin{split}\frac{1}{1 + m} \left[ {\begin{array}{cc} 1 - m^2 & 2m \\ 2m & -(1 - m^2) \\ \end{array} } \right]\end{split}\]
_symmetrise() numpy.ndarray

Calculate the change in position to the symmetric coil, twice the distance to the line of symmetry.

Returns:

The change in position

Return type:

numpy.ndarray

remove_coil(*coil_name: str, _top_level: bool = True) list[str] | None

Remove coil(s) from CoilSet

Parameters:
  • coil_name (str) – coil(s) to remove

  • _top_level (bool) – FOR INTERNAL USE, flags if at top level of nested coilgroup stack

Returns:

Removed coil names, if not at top level of nested stack

Raises:

ValueError – Cannot remove coils from a SymmetricCircuit with nested CoilGroups

Return type:

list[str] | None

_get_primary_group_x_centre() numpy.float64

Get the x centre of the first coil group

Return type:

numpy.float64

_get_primary_group_z_centre() numpy.float64

Get the z centre of the first coil group

Return type:

numpy.float64

_get_symmetric_group_x_centre() numpy.float64

Get the x centre of the first coil group

Return type:

numpy.float64

_get_symmetric_group_z_centre() numpy.float64

Get the z centre of the first coil group

Return type:

numpy.float64

_get_group_centre() numpy.ndarray

Get the centre of the first coil group

Return type:

numpy.ndarray

class bluemira.equilibria.coils._grouping.CoilSetOptimisationState

State of the optimisation of a CoilSet

Parameters:
  • currents – The current values of the coils

  • xs – The x positions of the coils

  • zs – The z positions of the coils

currents: numpy.ndarray
xs: numpy.ndarray
zs: numpy.ndarray
__post_init__()
property positions: numpy.ndarray

Get the positions as a (2, N) array

Return type:

numpy.ndarray

property positions_flat: numpy.ndarray

Get the positions as an array with xs and zs concatenated (xs then zs)

Return type:

numpy.ndarray

class bluemira.equilibria.coils._grouping.CoilSet(*coils: bluemira.equilibria.coils._coil.Coil | CoilGroup, control_names: list | bool | None = None, psi_analytic: bool = False, Bx_analytic: bool = True, Bz_analytic: bool = True)

Bases: bluemira.equilibria.coils._field.CoilSetFieldsMixin, CoilGroup

Inheritance diagram of bluemira.equilibria.coils._grouping.CoilSet

CoilSet is a CoilGroup with the concept of control coils

A CoilSet will return the total volume and area of the coils and the respective psi or field calculations can optionally sum over the coils or only sum over the control coils.

By default all coils are controlled

Parameters:
  • coils (bluemira.equilibria.coils._coil.Coil | CoilGroup) – The coils to be added to the set

  • control_names (list | bool | None) – List of coil names to be controlled

  • psi_analytic (bool)

  • Bx_analytic (bool)

  • Bz_analytic (bool)

__slots__ = ('_control', '_control_ind', '_Bx_analytic', '_Bz_analytic', '_coils', '_pad_size', '_psi_analytic')
property control: list[str]

Get control coil names

Return type:

list[str]

remove_coil(*coil_name: str, _top_level: bool = True) list[str] | None

Remove coil(s) from CoilSet

Parameters:
  • coil_name (str) – coil(s) to remove

  • _top_level (bool) – FOR INTERNAL USE, flags if at top level of nested coilgroup stack

Returns:

Removed coil names, if not at top level of nested stack

Return type:

list[str] | None

property n_control: float

Number of coils being actively controlled

Return type:

float

get_control_coils() CoilSet

Get control coils

Return type:

CoilSet

get_uncontrolled_coils() CoilSet
Returns:

Uncontrolled coils

Return type:

CoilSet

property area: float

Cross sectional area of CoilSet

Return type:

float

property volume: float

Volume of Coilset

Return type:

float

_sum(output: numpy.ndarray, *, sum_coils: bool = False, control: bool = False) numpy.ndarray

Get responses of coils optionally only control and/or sum over the responses

Parameters:
  • output (numpy.ndarray) – Output of calculation

  • sum_coils (bool) – sum over coils

  • control (bool) – operations on control coils only

Returns:

Summed response output

Return type:

numpy.ndarray

get_coiltype(*ctype: str | bluemira.base.constants.CoilType) CoilSet | None

Get coils by coils type

Parameters:

ctype (str | bluemira.base.constants.CoilType)

Return type:

CoilSet | None

classmethod from_group_vecs(eqdsk: eqdsk.EQDSKInterface, control_coiltypes=(CoilType.PF, CoilType.CS)) CoilGroup

Create CoilSet from eqdsk group vectors.

Automatically sets all coils that are not implicitly passive to control coils

Parameters:

eqdsk (eqdsk.EQDSKInterface)

Return type:

CoilGroup

get_optimisation_state(position_coil_names: list[str] | None = None, current_scale: float = 1.0) CoilSetOptimisationState

Get the state of the CoilSet for optimisation. If control coils are set then this is accounted for.

Parameters:
  • position_coil_names (list[str] | None) – The names of the coils to get the positions of

  • current_scale (float) – The scale of the currents

Returns:

The state of the CoilSet for optimisation

Return type:

CoilSetOptimisationState

set_optimisation_state(opt_currents: numpy.ndarray | None = None, coil_position_map: dict[str, numpy.ndarray] | None = None, current_scale: float = 1.0)

Set the state of the CoilSet, post optimisation. If control coils are set then this is accounted for.

Used in conjunction with get_optimisation_state.

Parameters:
  • opt_currents (numpy.ndarray | None) – The optimisation currents

  • coil_position_map (dict[str, numpy.ndarray] | None) – The map of coil names to positions: [x, z]

  • current_scale (float) – The scale of the currents

property n_current_optimisable_coils: int

Get the number of all current optimisable coils. If control coils are set then this is accounted for.

This will only count the primary coil in the case of a SymmetricCircuit pair or coils.

Return type:

int

property current_optimisable_coil_names: list[str]

Get the names of all current optimisable coils. If control coils are set then this is accounted for.

This will be the primary coil in the case of a SymmetricCircuit pair or coils.

Return type:

list[str]

property all_current_optimisable_coils: list[bluemira.equilibria.coils._coil.Coil]

Get a list of all coils that can be current optimised. If control coils are set then this is accounted for.

Return type:

list[bluemira.equilibria.coils._coil.Coil]

get_current_optimisable_coils(coil_names: list[str] | None = None) CoilSet

Get a coils that can be current optimised. If control coils are set then this is accounted for.

If coil_names is given, only the coils with those names are returned. Names in coil_names must be a subset of current optimisable coils.

Parameters:

coil_names (list[str] | None) – The names of the coils to get. If None, all current optimisable coils are returned.

Raises:

ValueError – If a name in coil_names in not in all_current_optimisable_coils.

Return type:

CoilSet

property _opt_currents_inds: list[int]

Get the indices of the coils that can be optimised. If control coils are set then this is accounted for.

These indices are used to extract the optimisable currents from the CoilSet and are based on the index of the coils in the name array.

Return type:

list[int]

property _contains_circuits: bool

A simple check to see if the CoilSet contains any Circuits.

Return type:

bool

property _opt_currents_expand_mat: numpy.ndarray

Get the optimisation currents expansion matrix.

This matrix is used to convert the optimisable currents to the full set of currents in the CoilSet.

Raises:

ValueError – Number of optimisable coils not equal number of groups/coils

Return type:

numpy.ndarray

property _opt_currents: numpy.ndarray

Get the currents for the optimisable coils. If control coils are set then this is accounted for.

Return type:

numpy.ndarray

property n_position_optimisable_coils: int

Get the number of coils that can be position optimised. If control coils are set then this is accounted for.

This will only count the primary coil in the case of a SymmetricCircuit pair or coils.

Return type:

int

property position_optimisable_coil_names: list[str]

Get the names of the coils that can be position optimised. If control coils are set then this is accounted for.

This will be the primary coil in the case of a SymmetricCircuit pair or coils.

Return type:

list[str]

property all_position_optimisable_coils: list[bluemira.equilibria.coils._coil.Coil]

Get the names of all coils that can be position optimised. If control coils are set then this is accounted for.

Return type:

list[bluemira.equilibria.coils._coil.Coil]

get_position_optimisable_coils(coil_names: list[str] | None = None) CoilSet

Get the coils that can be position optimised. If control coils are set then this is accounted for.

Parameters:

coil_names (list[str] | None) – The names of the coils to get the positions of. If None, all position optimisable coils are returned.

Raises:

ValueError – Coil’s position not optimisable

Return type:

CoilSet

_get_opt_positions(position_coil_names: list[str] | None = None) tuple[numpy.ndarray, numpy.ndarray]

Get the positions of the position optimisable coils.

Parameters:

position_coil_names (list[str] | None) – The names of the coils to get the positions of. If None, all position optimisable coils are returned.

Returns:

  • The x coordinates

  • The z coordinates

Return type:

tuple[numpy.ndarray, numpy.ndarray]

_set_opt_positions(coil_position_map: dict[str, numpy.ndarray]) None

Set the positions of the position optimisable coils.

Parameters:

coil_position_map (dict[str, numpy.ndarray])

Return type:

None