Process reference: electromagnetics
Generated from the docstrings of vaft.process.electromagnetics:
10 public functions. Each entry is what
vaft.process.describe("electromagnetics.<name>") prints.
All process categories
Overview
Two halves. The first builds free-space Green’s-function response matrices – the poloidal flux and field per unit current – for active coils, passive vessel loops and plasma filaments. The second integrates the passive circuit those matrices describe, giving the eddy currents a coil programme drives in the vessel.
Physics only. Nothing here reads a machine description: every geometry,
resistance and mutual-inductance matrix arrives as an argument, so the same
code serves any axisymmetric machine. The VEST geometry and the packaged
coupling matrices live in vaft.machine_mapping.
| Symbol | Meaning | Unit |
|---|---|---|
| psi | poloidal flux per unit source current | Wb/A |
| Br, Bz | field components per unit source current | T/A |
| R | loop resistance matrix, diagonal | ohm |
| M | passive-passive mutual inductance matrix | H |
| L | passive-active mutual inductance matrix | H |
| dt_sub | substep of the circuit integration | s |
Response matrices are per unit current, so a field is recovered by contracting one with a current history; nothing here carries a current of its own. Sources are ideal filaments unless a turn count says otherwise, and a turn count multiplies the response rather than changing the geometry.
The passive circuit is driven by the rate of change of the active current, not by the current itself, which is why a coil programme flat in time drives no eddy current however large it is.
The singularity where an observation point coincides with its source is
handled by evaluating either side of it and averaging, rather than by
excluding the point; see compute_br_bz_phi.
Functions
calc_grid | Assemble the response of every coil and passive loop on a rectangular grid. Convention |
compute_br_bz_phi | Field and flux of one unit-current ring at a set of observation points. Convention |
compute_impedance_matrices | Assemble the resistance and inductance matrices of the passive circuit. Convention |
compute_mutual_passive_active | Mutual inductance between passive loops and active coils, derived from geometry. Convention |
compute_point_response_matrices | Broadcast response of point sources at observation points, with exact kernels. Convention |
compute_response_matrix | Flux and field response at arbitrary observation points, per source. Convention |
compute_response_vector | The same response as the matrix form, with the arguments in the legacy order. Convention |
compute_vacuum_fields_1d | Contract current histories with response matrices into field histories. Convention |
solve_eddy_currents | Integrate the vessel eddy currents driven by a coil and plasma programme. Convention |
wall_propagator | The one-substep propagator of the passive circuit. Convention |
No function matches.
calc_grid
Machine-independentConvention-sensitive
source
calc_grid(xvar, zvar, coil_turns, coil_r, coil_z, loop_geometry_type, loop_outline_r, loop_outline_z, loop_rectangle_r, loop_rectangle_z)
Assemble the response of every coil and passive loop on a rectangular grid.
| Name | Type | Unit | Description |
|---|---|---|---|
xvar | array_like | m | Major-radius grid axis. |
zvar | array_like | m | Height grid axis. |
coil_turns | array_like | - | Turns of each active coil. |
coil_r | array_like | m | Major radius of each coil. |
coil_z | array_like | m | Height of each coil. |
loop_geometry_type | sequence | - | Which shape each passive loop is described by. |
loop_outline_r | sequence | m | Major radius of each outline-described loop’s vertices. |
loop_outline_z | sequence | m | Height of those vertices. |
loop_rectangle_r | sequence | m | Major radius of each rectangle-described loop. |
loop_rectangle_z | sequence | m | Height of those rectangles. |
| Returns | |||
| — | np.ndarray | - | Response per unit current with one row per grid point and one column per source, coils first and passive loops after. |
Convention
Rows run over the flattened grid and columns over the sources, coils before loops, which is the ordering every consumer of this matrix assumes. A loop described by an outline is reduced to its centroid before its response is taken, so an extended loop is treated as a filament at that point.
Applicability · Limitations · Provenance
Applicability
Machine-independent.
Limitations
The centroid reduction means a loop large compared with its distance to the grid is poorly represented. Builds the whole grid at once, so memory grows as the product of grid points and sources.
Provenance
compute_br_bz_phi, evaluated per source and stacked.
compute_br_bz_phi
Machine-independentConvention-sensitive
source
compute_br_bz_phi(r_obs, z_obs, r_src, z_src, shift=0.01)
Show source vaft/process/electromagnetics.py, lines 74–146
def compute_br_bz_phi(
r_obs: np.ndarray,
z_obs: np.ndarray,
r_src: float,
z_src: float,
shift: float = 0.01
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Field and flux of one unit-current ring at a set of observation points.
Parameters
----------
r_obs : array_like
Major radius of the observation points [m].
z_obs : array_like
Height of the observation points [m].
r_src : float
Major radius of the source ring [m].
z_src : float
Height of the source ring [m].
shift : float, optional
Offset used to step around the source singularity [m].
Returns
-------
tuple of np.ndarray
The radial and vertical field per unit current in tesla per ampere, and
the poloidal flux per unit current in weber per ampere [-].
Convention
----------
Per unit current, so the caller multiplies by an actual current. An
observation point sitting on the source has no finite response; rather than
excluding it, the response is evaluated at two points either side and
averaged, which keeps the returned array the same shape as the input and gives
a finite value whose error is second order in the offset.
Defaults
--------
``shift = 0.01`` is a numerical convenience. The averaging is applied only
within a third of it from the source, so a point comfortably away from the
ring is untouched.
Applicability
-------------
Machine-independent.
Limitations
-----------
Free space: no iron, no shielding, no image currents. The source is an ideal
filament, so the response very close to a real conductor of finite section is
not physical, which is what the offset is papering over rather than solving.
Provenance
----------
.. [1] The axisymmetric Green's functions in :mod:`vaft.formula.green`.
"""
distances = calculate_distance(r_obs, r_src, z_obs, z_src)
condition = distances < (shift / 3.0)
br1_shifted, bz1_shifted = green_br_bz(r_obs + shift, z_obs, r_src, z_src)
br2_shifted, bz2_shifted = green_br_bz(r_obs - shift, z_obs, r_src, z_src)
phi1_shifted = green_r(r_obs + shift, z_obs, r_src, z_src)
phi2_shifted = green_r(r_obs - shift, z_obs, r_src, z_src)
br_direct, bz_direct = green_br_bz(r_obs, z_obs, r_src, z_src)
phi_direct = green_r(r_obs, z_obs, r_src, z_src)
br_final = np.where(condition, (br1_shifted + br2_shifted) / 2.0, br_direct)
bz_final = np.where(condition, (bz1_shifted + bz2_shifted) / 2.0, bz_direct)
phi_final = np.where(condition, (phi1_shifted + phi2_shifted) / 2.0, phi_direct)
return br_final, bz_final, phi_finalField and flux of one unit-current ring at a set of observation points.
| Name | Type | Unit | Description |
|---|---|---|---|
r_obs | array_like | m | Major radius of the observation points. |
z_obs | array_like | m | Height of the observation points. |
r_src | float | m | Major radius of the source ring. |
z_src | float | m | Height of the source ring. |
shift | float, optional | m | Offset used to step around the source singularity. |
| Returns | |||
| — | tuple of np.ndarray | - | The radial and vertical field per unit current in tesla per ampere, and the poloidal flux per unit current in weber per ampere. |
Convention
Per unit current, so the caller multiplies by an actual current. An observation point sitting on the source has no finite response; rather than excluding it, the response is evaluated at two points either side and averaged, which keeps the returned array the same shape as the input and gives a finite value whose error is second order in the offset.
Defaults · Applicability · Limitations · Provenance
Defaults
shift = 0.01 is a numerical convenience. The averaging is applied only
within a third of it from the source, so a point comfortably away from the
ring is untouched.
Applicability
Machine-independent.
Limitations
Free space: no iron, no shielding, no image currents. The source is an ideal filament, so the response very close to a real conductor of finite section is not physical, which is what the offset is papering over rather than solving.
Provenance
- The axisymmetric Green’s functions in
vaft.formula.green.
compute_impedance_matrices
Machine-independentConvention-sensitive
source
compute_impedance_matrices(loop_resistances, passive_loop_geometry, coil_geometry, mutual_pp, mutual_pa, plasma_rz)
Assemble the resistance and inductance matrices of the passive circuit.
| Name | Type | Unit | Description |
|---|---|---|---|
loop_resistances | array_like | ohm | Resistance of each passive loop. |
passive_loop_geometry | sequence | - | Geometry of each passive loop. |
coil_geometry | sequence | - | Geometry of the active coils; superseded by the mutual matrix below. |
mutual_pp | array_like | H | Passive-to-passive mutual inductance. |
mutual_pa | array_like | H | Passive-to-active mutual inductance. |
plasma_rz | array_like | m | Plasma filament positions, coupled in when given. |
| Returns | |||
| — | tuple of np.ndarray | - | The diagonal resistance matrix in ohms, and the two inductance matrices in henries, the second widened by the plasma coupling when supplied. |
Convention
Resistance is diagonal: loops are resistively independent and coupled only inductively. The passive-to-active matrix is widened to the right by the plasma coupling when filaments are given, so the plasma enters the circuit as another driving current rather than as a separate term.
The coil geometry argument is kept for compatibility and is superseded by the supplied mutual matrix; passing geometry alone no longer determines the coupling.
Applicability · Limitations · Provenance
Applicability
Machine-independent.
Limitations
Takes the mutual matrices as given and cannot check they were computed for
this geometry, which is exactly the mismatch
compute_mutual_passive_active exists to resolve.
Provenance
- The circuit form the eddy-current solve integrates; see
solve_eddy_currents.
compute_mutual_passive_active
Machine-independentConvention-sensitive
source
compute_mutual_passive_active(passive_loop_geometry, coil_geometry)
Show source vaft/process/electromagnetics.py, lines 543–599
def compute_mutual_passive_active(
passive_loop_geometry: List[Tuple[str, float, float, float]],
coil_geometry: List[List[Tuple[float, float, int]]],
) -> np.ndarray:
"""Mutual inductance between passive loops and active coils, derived from geometry.
Parameters
----------
passive_loop_geometry : sequence
Geometry of each passive loop [-].
coil_geometry : sequence
Geometry and turns of each active coil [-].
Returns
-------
np.ndarray
Mutual inductance with one row per loop and one column per coil [H].
Convention
----------
Derived from the geometry given, which is what makes it a usable fallback when
a packaged coupling matrix does not apply. The packaged matrix represents a
historical coil geometry; a machine whose coils have since moved needs this
instead, and the two must not be mixed within one calculation.
Applicability
-------------
Machine-independent. The geometry is the argument; the packaged matrix it
substitutes for is VEST's.
Limitations
-----------
Filament idealization, so it is less accurate than a matrix computed from the
real conductor sections. Use it when the packaged matrix does not match the
geometry, not in preference to one that does.
Provenance
----------
.. [1] The Green's functions in :mod:`vaft.formula.green`; the packaged
alternative is the machine layer's ``em_coupling`` asset.
"""
coupling = np.zeros((len(passive_loop_geometry), len(coil_geometry)))
for i_loop, (_, r_loop, z_loop, coefficient) in enumerate(
passive_loop_geometry
):
for i_coil, elements in enumerate(coil_geometry):
if not elements:
raise ValueError(f"active coil {i_coil} has no geometry elements")
total_turns = sum(element[2] for element in elements)
mean_response = sum(
green_r(r_loop, z_loop, r_coil, z_coil)
for r_coil, z_coil, _ in elements
) / len(elements)
coupling[i_loop, i_coil] = coefficient * total_turns * mean_response
return couplingMutual inductance between passive loops and active coils, derived from geometry.
| Name | Type | Unit | Description |
|---|---|---|---|
passive_loop_geometry | sequence | - | Geometry of each passive loop. |
coil_geometry | sequence | - | Geometry and turns of each active coil. |
| Returns | |||
| — | np.ndarray | H | Mutual inductance with one row per loop and one column per coil. |
Convention
Derived from the geometry given, which is what makes it a usable fallback when a packaged coupling matrix does not apply. The packaged matrix represents a historical coil geometry; a machine whose coils have since moved needs this instead, and the two must not be mixed within one calculation.
Applicability · Limitations · Provenance
Applicability
Machine-independent. The geometry is the argument; the packaged matrix it substitutes for is VEST’s.
Limitations
Filament idealization, so it is less accurate than a matrix computed from the real conductor sections. Use it when the packaged matrix does not match the geometry, not in preference to one that does.
Provenance
- The Green’s functions in
vaft.formula.green; the packaged alternative is the machine layer’sem_couplingasset.
compute_point_response_matrices
Machine-independentConvention-sensitive
source
compute_point_response_matrices(obs_r, obs_z, src_r, src_z, turns=None, groups=None, n_groups=None, components=('psi', 'bz', 'br'))
Broadcast response of point sources at observation points, with exact kernels.
| Name | Type | Unit | Description |
|---|---|---|---|
obs_r | array_like | m | Major radius of the observation points. |
obs_z | array_like | m | Height of the observation points. |
src_r | array_like | m | Major radius of the sources. |
src_z | array_like | m | Height of the sources. |
turns | array_like, optional | - | Turn count weighting each source. |
groups | array_like, optional | - | Which output column each source contributes to. |
n_groups | int, optional | - | How many columns the grouping produces. |
components | sequence of str, optional | - | Which of the flux and the two field components to return. |
| Returns | |||
| — | dict of str to np.ndarray | - | One matrix per requested component, per unit current. |
Convention
Exact elliptic-integral kernels rather than the approximations elsewhere in this module, and fully broadcast rather than looped, which is what makes it the right choice for many sources at many points.
Grouping sums columns as it goes, so a set of filaments belonging to one circuit becomes a single column instead of being summed afterwards; on a real machine that turns several hundred filament columns into a handful of circuit ones. Turns weight each source before that sum.
Defaults · Applicability · Limitations · Provenance
Defaults
Returning all three components is a numerical convenience, not a physical choice, and narrowing it is worth doing: each field component costs roughly twice the flux pass.
Applicability
Machine-independent.
Limitations
A source coincident with an observation point has no finite response here;
unlike compute_br_bz_phi, nothing steps around the singularity. On
axis the kernels take their analytic limits.
Provenance
- The exact elliptic-integral Green’s functions in
vaft.formula.green.
compute_response_matrix
Machine-independentConvention-sensitive
source
compute_response_matrix(observation_points, coil_data, passive_loop_data, plasma_points=None)
Flux and field response at arbitrary observation points, per source.
| Name | Type | Unit | Description |
|---|---|---|---|
observation_points | array_like | m | Points at which to evaluate, as major radius and height pairs. |
coil_data | sequence | - | Active coil geometry and turns. |
passive_loop_data | sequence | - | Passive loop geometry. |
plasma_points | array_like, optional | m | Plasma filament positions. |
| Returns | |||
| — | tuple of np.ndarray | - | The flux, vertical field and radial field response, each with one row per observation point and one column per source. |
Convention
Unlike calc_grid, the observation points are arbitrary rather than a
rectangular mesh, which is what a diagnostic set of sensor positions needs.
Column order is coils, then passive loops, then plasma filaments when given.
Applicability · Limitations · Provenance
Applicability
Machine-independent.
Limitations
Same filament idealization as the rest of the module. Plasma filaments are positions only: this returns their response, not their currents.
Provenance
compute_br_bz_phi, evaluated per source.
compute_response_vector
Machine-independentConvention-sensitive
source
compute_response_vector(coil_data, passive_loop_data, plasma_points, observation_points)
Show source vaft/process/electromagnetics.py, lines 386–429
def compute_response_vector(
coil_data: List[Dict[str, Any]],
passive_loop_data: List[Dict[str, Any]],
plasma_points: List[List[float]],
observation_points: List[List[float]]
) -> Tuple[ndarray, ndarray, ndarray]:
"""The same response as the matrix form, with the arguments in the legacy order.
Parameters
----------
coil_data : sequence
Active coil geometry and turns [-].
passive_loop_data : sequence
Passive loop geometry [-].
plasma_points : array_like
Plasma filament positions [m].
observation_points : array_like
Points at which to evaluate [m].
Returns
-------
tuple of np.ndarray
Exactly what :func:`compute_response_matrix` returns [-].
Convention
----------
A thin wrapper that reorders its arguments and delegates. It exists because
the legacy call order put the observation points last; new code should call
the matrix form directly.
Applicability
-------------
Machine-independent.
Provenance
----------
.. [1] :func:`compute_response_matrix`, which does the work.
"""
return compute_response_matrix(
observation_points=observation_points,
coil_data=coil_data,
passive_loop_data=passive_loop_data,
plasma_points=plasma_points
)The same response as the matrix form, with the arguments in the legacy order.
| Name | Type | Unit | Description |
|---|---|---|---|
coil_data | sequence | - | Active coil geometry and turns. |
passive_loop_data | sequence | - | Passive loop geometry. |
plasma_points | array_like | m | Plasma filament positions. |
observation_points | array_like | m | Points at which to evaluate. |
| Returns | |||
| — | tuple of np.ndarray | - | Exactly what |
Convention
A thin wrapper that reorders its arguments and delegates. It exists because the legacy call order put the observation points last; new code should call the matrix form directly.
Applicability · Provenance
Applicability
Machine-independent.
Provenance
compute_response_matrix, which does the work.
compute_vacuum_fields_1d
Machine-independentConvention-sensitive
source
compute_vacuum_fields_1d(coil_plus_loop_currents, coil_plus_loop_psi_resp, coil_plus_loop_br_resp, coil_plus_loop_bz_resp)
Show source vaft/process/electromagnetics.py, lines 997–1057
def compute_vacuum_fields_1d(
coil_plus_loop_currents: np.ndarray, # shape (n_times, nb_coil+nb_loop)
coil_plus_loop_psi_resp: np.ndarray, # shape (n_points, nb_coil+nb_loop)
coil_plus_loop_br_resp: np.ndarray, # shape (n_points, nb_coil+nb_loop)
coil_plus_loop_bz_resp: np.ndarray, # shape (n_points, nb_coil+nb_loop)
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Contract current histories with response matrices into field histories.
Parameters
----------
coil_plus_loop_currents : array_like
Current history, one row per time and one column per source [A].
coil_plus_loop_psi_resp : array_like
Flux response per unit current [Wb/A].
coil_plus_loop_br_resp : array_like
Radial field response per unit current [T/A].
coil_plus_loop_bz_resp : array_like
Vertical field response per unit current [T/A].
Returns
-------
tuple of np.ndarray
Flux in weber and the two field components in tesla, each with one row per
time and one column per observation point [-].
Convention
----------
The linear step the response matrices exist for: each output is the current
history contracted against its own response. **Vacuum fields only** -- the
plasma's own contribution is not here unless it entered as a filament current
in the input.
Applicability
-------------
Machine-independent.
Limitations
-----------
Column order in the currents must match the response matrices' own, and
nothing checks it; a mismatched ordering gives plausible numbers that are
wrong.
Provenance
----------
.. [1] The response matrices built by :func:`compute_response_matrix` or
:func:`calc_grid`.
"""
n_times = coil_plus_loop_currents.shape[0]
n_points = coil_plus_loop_psi_resp.shape[0]
psi_out = np.zeros((n_times, n_points))
br_out = np.zeros((n_times, n_points))
bz_out = np.zeros((n_times, n_points))
for i_time in range(n_times):
ix = coil_plus_loop_currents[i_time] # shape (nb_coil+nb_loop,)
psi_out[i_time] = coil_plus_loop_psi_resp @ ix
br_out[i_time] = coil_plus_loop_br_resp @ ix
bz_out[i_time] = coil_plus_loop_bz_resp @ ix
return psi_out, br_out, bz_outContract current histories with response matrices into field histories.
| Name | Type | Unit | Description |
|---|---|---|---|
coil_plus_loop_currents | array_like | A | Current history, one row per time and one column per source. |
coil_plus_loop_psi_resp | array_like | Wb/A | Flux response per unit current. |
coil_plus_loop_br_resp | array_like | T/A | Radial field response per unit current. |
coil_plus_loop_bz_resp | array_like | T/A | Vertical field response per unit current. |
| Returns | |||
| — | tuple of np.ndarray | - | Flux in weber and the two field components in tesla, each with one row per time and one column per observation point. |
Convention
The linear step the response matrices exist for: each output is the current history contracted against its own response. Vacuum fields only – the plasma’s own contribution is not here unless it entered as a filament current in the input.
Applicability · Limitations · Provenance
Applicability
Machine-independent.
Limitations
Column order in the currents must match the response matrices’ own, and nothing checks it; a mismatched ordering gives plausible numbers that are wrong.
Provenance
- The response matrices built by
compute_response_matrixorcalc_grid.
solve_eddy_currents
Machine-independentConvention-sensitive
source
solve_eddy_currents(R_mat, L_mat, M_mat, coil_plasma_currents, time, dt_sub=5e-05, *, method='auto')
Integrate the vessel eddy currents driven by a coil and plasma programme.
| Name | Type | Unit | Description |
|---|---|---|---|
R_mat | array_like | ohm | Loop resistance matrix. |
L_mat | array_like | H | Passive-to-active mutual inductance. |
M_mat | array_like | H | Passive-to-passive mutual inductance. |
coil_plasma_currents | array_like | A | Driving current history, one row per time and one column per source. |
time | array_like | s | Time base of that history. |
dt_sub | float, optional | s | Substep of the integration. |
method | str, optional | - | Decomposition passed to the propagator. |
| Returns | |||
| — | np.ndarray | A | Eddy current in each passive loop over time. |
Convention
Driven by the rate of change of the driving current, not by its value, so a flat coil programme drives nothing however large. The integration is substepped and advanced by a single reused propagator, which is what makes it cheap over a long shot.
Defaults · Applicability · Limitations · Provenance
Defaults
The substep is a hard-coded value. It is meant to be finer than the input grid, and the shipped value is coarser than the 40 microsecond diagnostics grid, making this a mild rate reduction rather than the refinement intended; tracked in #425.
Applicability
Machine-independent.
Limitations
The driving derivative is taken from the supplied history, so a coarsely sampled programme understates a fast ramp. Assumes the circuit is constant in time, so no geometry or resistance change during the shot is represented.
Provenance
- The legacy
vfit_eddyworkflow, whose matrix setup this retains structural similarity to. - Issue #425, tracking the substep default.
wall_propagator
Machine-independentConvention-sensitive
source
wall_propagator(R_mat, M_mat, dt_sub, *, method='auto')
The one-substep propagator of the passive circuit.
| Name | Type | Unit | Description |
|---|---|---|---|
R_mat | array_like | ohm | Loop resistance matrix, diagonal and positive. |
M_mat | array_like | H | Passive-to-passive mutual inductance matrix. |
dt_sub | float | s | Length of the substep. |
method | str, optional | - | Which decomposition to use: automatic, general, or symmetric. |
| Returns | |||
| — | np.ndarray | - | The propagator advancing the loop currents by one substep. |
Convention
The matrix exponential of the negative circuit operator times the substep.
solve_eddy_currents consumes nothing from the decomposition except
this, so it is the whole seam for a faster one.
The symmetric path uses the symmetric-definite pencil: with resistance diagonal and positive and inductance symmetric, a change of variable makes the operator symmetric, so the symmetric eigensolver applies and the eigenvector inverse is a transpose. On the real 950-loop machine that is about eleven times faster than the general solver and agrees to about one part in 1e14 (#308). It is valid only when the inductance is symmetric, which the loader guarantees for the packaged asset (#347) but nothing guarantees for a caller-built matrix, so the automatic mode checks and otherwise leaves the general path unchanged.
Raises
ValueErrorThe method is not one of the three accepted names.
Defaults · Applicability · Limitations · Provenance
Defaults
Automatic selection is a numerical convenience: it takes the fast path when the check passes and is otherwise identical to the general one.
Applicability
Machine-independent.
Limitations
Assumes the circuit is constant over the substep, which is what makes a single propagator reusable across every step.
Provenance
- Issue #308 for the measured speedup and agreement; issue #347 for the loader guarantee that makes the symmetric path safe on the packaged asset.