Components¶
device_inductance.coils ¶
Coil
dataclass
¶
An axisymmetric magnet, which may not have a rectangular cross-section
extent
cached
property
¶
[m] rmin, rmax, zmin, zmax extent of filament centers
filaments
instance-attribute
¶
Discretized circular filaments describing the coil's winding pattern
grids
cached
property
¶
Generate a grid that spans the winding pack, landing exactly on the windings if possible.
local_field_interpolators
cached
property
¶
Build interpolators over the solved local fields, if available
local_fields
cached
property
¶
Solve the local self-field flux and flux density per amp by mapping the coil section to a continuous current density distribution and solving the continuous flux field via 4th-order finite difference, then extracting the B-field from the flux field via 4th-order finite difference.
Returns:
| Type | Description |
|---|---|
LocalFields
|
Structure containing local field map components and interpolators |
meshes
cached
property
¶
Generate a meshgrid that spans the winding pack, landing exactly on the windings if possible.
name
instance-attribute
¶
This name should match the name used in the device description ODS
resistance
instance-attribute
¶
[ohm] total effective resistance of the coil; for superconducting coils, this will be small
self_inductance
instance-attribute
¶
[H] total scalar self-inductance of this coil
CoilFilament
dataclass
¶
A discretized element of an axisymmetric magnet. Self-inductance is calculated based on conductor geometry.
device_inductance.circuits ¶
device_inductance.structures ¶
filament ¶
The lowest-level discretization of conducting structure.
PassiveStructureFilament
dataclass
¶
PassiveStructureFilament(
parent_name: str,
r: float,
z: float,
area: float,
resistance: float,
self_inductance: float,
polygon: Polygon,
)
A chunk of a cylindrically-symmetric passive conductor
self_inductance
instance-attribute
¶
[H] self-inductance assuming one full loop
heuristics ¶
MAX_EDGE_LENGTH_M
module-attribute
¶
Default maximum length of an edge in the lowest-level discretization
poly_angle ¶
poly_angle(
p: Polygon,
centroid: tuple[float, float],
max_edge_length_m: float = MAX_EDGE_LENGTH_M,
) -> float
Get peak winding number in [rad] of the polygon boundary w.r.t. the centroid. This is not necessarily the same as the maximum angle subtended by the polygon, but is a good heuristic for it, and runs in O(N) instead of O(N^2).
Source code in src/device_inductance/structures/heuristics.py
unroundness ¶
[dimensionless] ratio of perimeter to perimeter of a circle with the same area. Gives a heuristic estimate for how un-like a circle the shape is.
Source code in src/device_inductance/structures/heuristics.py
winding_number ¶
Calculate winding number about x, y, and z axes, w.r.t. the filament centroid. This estimates the angle subtended by each segment of the coil path, which is 2*pi radians per full revolution, and may be either positive or negative depending on the orientation of the coil winding path.
The choice of sign convention is arbitrary, as these results exist to compare to each other, and for no other purpose.
Source code in src/device_inductance/structures/heuristics.py
input ¶
CONTACT_DETECTION_DISTANCE
module-attribute
¶
[m] distance under which two passive structure objects are considered to be in electrical contact
PassiveStructureInput
dataclass
¶
First level of structure discretization within device_inductance. Some discretization may have already been performed upstream.
loop ¶
Top-level discretization of conducting structure.
PassiveStructureLoop
dataclass
¶
PassiveStructureLoop(
parent_name: str,
polygon: Polygon,
filaments: list[PassiveStructureFilament],
)
A logical chunk of structure material that may be the result of slicing a larger object into smaller pieces. Composed of one or more filaments.
ns
cached
property
¶
[dimensionless] (Fractional) number of turns of each filament, weighted according to their cross-sectional area as a fraction of this loop's total.
polygon
instance-attribute
¶
Shape of the enclosing polygon before sub-discretization
resistance
cached
property
¶
[ohm] Total loop resistance; effective parallel resistance over all filaments
from_input
classmethod
¶
from_input(
inp: PassiveStructureInput,
slicer: RadialSlicer,
angle_thresh_deg: float = 20.0,
unroundness_thresh: float = 2.0,
) -> list[PassiveStructureLoop]
Make one or more PassiveStructureLoop from an input element. The input element may be subdivided into multiple loops if it subtends a large angle relative to the centroid and has a large perimeter-to-area ratio in the section plane.
Source code in src/device_inductance/structures/loop.py
from_poly
classmethod
¶
from_poly(
parent_name: str,
polygon: Polygon,
resistivity: float,
max_edge_length_m: float = MAX_EDGE_LENGTH_M,
) -> PassiveStructureLoop
Discretize a structure that is reasonably well-associated with a single centroid and may be the result of earlier sub-division of a larger structure, but may not be fully discretized yet.
Source code in src/device_inductance/structures/loop.py
mutual_inductance ¶
[H] Mutual inductance between two loops.
If self passed as other, the precalculated self-inductance is returned.
Source code in src/device_inductance/structures/loop.py
slicer ¶
Tool for cutting a polyogon into pie-slice chunks
RadialSlicer ¶
RadialSlicer(
n_slices: int,
extent: tuple[float, float, float, float],
centroid: tuple[float, float],
)
Tool for cutting a polyogon into pie-slice chunks
Source code in src/device_inductance/structures/slicer.py
centroid
instance-attribute
¶
Centroid used to generate the slices
polygons
instance-attribute
¶
Contiguous but non-overlapping slices spanning the provided extent
slice ¶
Cut polygon p into as many as n_slices new
polygons or as few as 1 polygon, if no cuts are needed.
Source code in src/device_inductance/structures/slicer.py
device_inductance.sensors ¶
FullFluxLoop
dataclass
¶
Flux sensor wrapped around the entire toroid, encompassing all the poloidal projected area from this point inward. Idealized here as attached to an ideal integrator s.t. it senses flux integrated in time instead of rate of change. ::
, - ~ ~ ~ - ,
, ' ' ,
, , phi
, A_pol , ^
, , |
, -----------> * p1 x
, R , Z
, ,
, ,
, , '
' - , _ _ _ , '
||
_||_
- +
response ¶
Ideal integrated response to a given flux field
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grids
|
tuple[NDArray, NDArray]
|
[m] 1D arrays describing rectilinear mesh |
required |
psi
|
NDArray
|
[Wb], 2D array of rate of change of poloidal flux |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the sensor is not inside the mesh |
Returns:
| Type | Description |
|---|---|
float
|
[Wb] ideal integrated response |
Source code in src/device_inductance/sensors.py
PartialFluxLoop
dataclass
¶
PartialFluxLoop(
name: str,
r0: float,
phi0: float,
z0: float,
r1: float,
phi1: float,
z1: float,
n_discretization: int = 1000,
)
Flux sensor defined in terms of the opposite corners of a rectangle wrapped part-way around the toroid, enclosing some poloidal projected area but no toroidal projected area. Idealized here as attached to an ideal integrator s.t. it senses flux integrated in time instead of rate of change.
::
Z
* --------- * p2 ^
| | |
| | x ---> phi
p1 * --------- * R
The normal vector is taken as clockwise from the vector formed by the first and second points.
o (r1, z1)
|
|------> normal
|
|
o (r0, z0)
discretized_rz_section
cached
property
¶
Generate evenly-sampled points along the r-z section of the loop and the projected area associated with each point.
Because the projected area at each point is different, 1D trapezoid integration is inconvenient; instead, points are sampled entirely inside the span of the section, not including the endpoints, in order to support a Riemann sum over dot(B, dA) using a finer resolution.
n_discretization
class-attribute
instance-attribute
¶
Number of points to use for integrating the flux field. Meant to be a constant that is tuned manually to target an acceptable error level.
normal_vector
property
¶
[dimensionless] (r, z) components of the normal vector of the surface enclosed by the loop
response ¶
Ideal integrated response to a given local B-field
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grids
|
tuple[NDArray, NDArray]
|
[m] 1D arrays describing rectilinear mesh |
required |
br
|
NDArray
|
[T] |
required |
bz
|
NDArray
|
[T] |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the sensor is not inside the mesh |
Returns:
| Type | Description |
|---|---|
float
|
[Wb] ideal integrated flux through the loop |
Source code in src/device_inductance/sensors.py
PoloidalFieldProbe
dataclass
¶
A poloidal B-field sensor at a point in space; aka Mirnov probe or pickup coil. Idealized here as attached to an ideal integrator s.t. it senses B integrated in time instead of rate of change.
In reality, the hardware senses dB/dt on some vector in the poloidal plane, but this is not so useful in a digital context without high-bandwidth integration.
poloidal_angle
instance-attribute
¶
[rad] poloidal orientation (about phi), clockwise from +R-axis
unit_vector
property
¶
Get the unit vector in the rz plane that the measurement is projected on. Uses cocos-11 coordinate system, with poloidal angle clockwise about into-the-board toroidal direction, starting from the outboard (r=1, z=0) direction.
response ¶
Ideal integrated response to a given local B-field. This is the sum of local B-field components, not the normed field!
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grids
|
tuple[NDArray, NDArray]
|
[m] 1D arrays describing rectilinear mesh |
required |
br
|
NDArray
|
[T] |
required |
bz
|
NDArray
|
[T] |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the sensor is not inside the mesh |
Returns:
| Type | Description |
|---|---|
float
|
[T] ideal integrated B-field, sum of components projected on the axis of the probe |