Process reference: ntv_coil_response
Generated from the docstrings of vaft.process.ntv_coil_response:
11 public functions. Each entry is what
vaft.process.describe("ntv_coil_response.<name>") prints.
All process categories
Overview
A non-axisymmetric coil set with K independently driven groups is described
by one complex phasor per group, c_k = A_k exp(+i phi_k). On a fixed
plasma and kinetic background, the signed toroidal torque PENTRC computes from
the GPEC displacement that excitation drives may – or may not – be a
Hermitian quadratic form of the phasors (issue #1887):
T(c) = c^H Q c, Q = Q^H.
This module holds the algebra for testing that hypothesis and, only where it
holds, for using it. It runs no solver: each torque it takes is a number some
GPEC -> PENTRC evaluation produced (vaft.code.gpec.torque_profile), and
each phasor is the excitation that evaluation was run with.
quadratic_probe_design ──▶ K^2 probes (e_i, e_i+e_j, e_i+i e_j)
hermitian_torque_matrix ─▶ Q from the probes' torques
quadratic_invariance_checks ─▶ T(a c) = a^2 T(c), T(-c) = T(c), T(e^{i chi} c) = T(c)
qualify_torque_matrix ───▶ held-out error -> "qualified" / "rejected" / "insufficient"
fit_inhomogeneous_torque ─▶ T0 + 2 Re(b^H c) + c^H Q c, to see whether T0 and b vanish
two_group_phase_extrema, budgeted_torque_extrema, fixed_amplitude_phase_extrema
A rejected hypothesis is a result, not a failure of this module: the direct
scan it was tested on is then the operating-space study, and no optimizer here
should be fed that Q.
| Symbol | Meaning | Unit |
|---|---|---|
| K | number of independently driven coil groups | - |
| c | complex excitation phasor per group, c_k = A_k exp(+i phi_k) | phasor |
| A_k | declared amplitude normalization of group k (not a sector-peak | |
| phi_k | phase of group k | rad |
| T | signed scalar torque of one evaluation (e.g. the enclosed edge | |
| Q | Hermitian torque matrix, T = c^H Q c | N m / phasor^2 |
| D | Hermitian positive-definite excitation metric of a budget c^H D c [-] |
Phasor sign. c_k = A_k exp(+i phi_k) and T = c^H Q c. The
cross-term recovery below depends on it: with the opposite phasor sign the
imaginary part of every Q_ij changes sign.
Signed torque. T keeps PENTRC’s sign; nothing here takes |T|. A
failed or uncomputed evaluation is NaN, never zero.
Common phase. For a single toroidal mode, T(e^{i chi} c) = T(c), so a
K-group phase optimum has K - 1 free phases; group 0’s phase is held
at zero.
Functions
budgeted_torque_extrema | Largest and smallest signed torque over free complex excitations with c^H D c = budget.
Convention |
coil_phasors | Complex excitation phasors A_k exp(+i phi_k) of the coil groups.
Convention |
fit_inhomogeneous_torque | Least-squares T = T0 + 2 Re(b^H c) + c^H Q c, to test whether T0 and b vanish.
Convention |
fixed_amplitude_phase_extrema | Phases of the largest and smallest signed torque with every group amplitude fixed. Convention |
hermitian_torque_matrix | The Hermitian Q of T = c^H Q c from the probe torques.
Convention |
ntv_operating_space | Direct NTV torques (and a qualified model) as a #1178 coil operating-space result. Convention |
quadratic_invariance_checks | Tests of a pure quadratic response that need no Q: scaling, sign, common phase.
Convention |
quadratic_probe_design | The K^2 unit excitations that determine a Hermitian Q.
Convention |
quadratic_torque | Signed torque c^H Q c of one excitation or a stack of them.
Convention |
qualify_torque_matrix | Qualify or reject a Q against direct evaluations it was not built from.
Convention |
two_group_phase_extrema | Relative phases of the largest and smallest signed torque of two groups. Convention |
No function matches.
budgeted_torque_extrema
Machine-independentConvention-sensitive
source
budgeted_torque_extrema(Q, D, budget)
Show source vaft/process/ntv_coil_response.py, lines 647–716
def budgeted_torque_extrema(Q: np.ndarray, D: np.ndarray, budget: float) -> dict[str, object]:
"""Largest and smallest signed torque over free complex excitations with ``c^H D c = budget``.
Parameters
----------
Q : numpy.ndarray
Hermitian torque matrix of a qualified model, possibly indefinite [N m / phasor^2].
D : numpy.ndarray
Hermitian positive-definite excitation metric [-].
budget : float
The excitation budget ``P_0 > 0`` [phasor^2].
Returns
-------
extrema : dict
``T_max``/``T_min`` [N m], ``c_max``/``c_min`` meeting the budget
[phasor], and the generalized ``eigenvalues`` ascending [N m / phasor^2].
Raises
------
ValueError
``D`` is not positive definite, shapes disagree, or the budget is not
positive.
Processing steps
----------------
1. Solve ``Q v = lambda D v`` (generalized Hermitian eigenproblem).
2. Scale the extreme eigenvectors to ``v^H D v = P_0``; ``T = lambda P_0``.
Convention
----------
Signed: with an indefinite ``Q`` the minimum is a negative torque, not a
small magnitude. The returned phasors are defined up to a common phase.
Applicability
-------------
Machine-independent.
Limitations
-----------
A mathematical optimum of the phasor space: actual sector or circuit
current limits, winding signs and fixed group amplitudes are not imposed
and must be checked separately.
Provenance
----------
.. [1887] Issue #1887, Sec. 8 (free complex excitation with a budget).
"""
from scipy.linalg import eigh
q = _hermitian(Q)
d = _hermitian(D)
if d.shape != q.shape:
raise ValueError("Q and D differ in shape")
if not budget > 0:
raise ValueError("the budget must be positive")
if np.linalg.eigvalsh(d).min() <= 0:
raise ValueError("D must be positive definite")
values, vectors = eigh(q, d)
def scaled(v):
return v * np.sqrt(budget / float(np.real(v.conj() @ d @ v)))
return {
"T_max": float(values[-1] * budget),
"T_min": float(values[0] * budget),
"c_max": scaled(vectors[:, -1]),
"c_min": scaled(vectors[:, 0]),
"eigenvalues": values,
}Largest and smallest signed torque over free complex excitations with c^H D c = budget.
| Name | Type | Unit | Description |
|---|---|---|---|
Q | numpy.ndarray | N m / phasor^2 | Hermitian torque matrix of a qualified model, possibly indefinite. |
D | numpy.ndarray | - | Hermitian positive-definite excitation metric. |
budget | float | phasor^2 | The excitation budget |
| Returns | |||
extrema | dict | N m / phasor^2 |
|
Convention
Signed: with an indefinite Q the minimum is a negative torque, not a
small magnitude. The returned phasors are defined up to a common phase.
Raises
ValueErrorDis not positive definite, shapes disagree, or the budget is not positive.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Solve
Q v = lambda D v(generalized Hermitian eigenproblem). - Scale the extreme eigenvectors to
v^H D v = P_0;T = lambda P_0.
Applicability
Machine-independent.
Limitations
A mathematical optimum of the phasor space: actual sector or circuit current limits, winding signs and fixed group amplitudes are not imposed and must be checked separately.
Provenance
- Issue #1887, Sec. 8 (free complex excitation with a budget).
coil_phasors
Machine-independentConvention-sensitive
source
coil_phasors(amplitudes, phases)
Show source vaft/process/ntv_coil_response.py, lines 116–156
def coil_phasors(amplitudes: Sequence[float], phases: Sequence[float]) -> np.ndarray:
"""Complex excitation phasors ``A_k exp(+i phi_k)`` of the coil groups.
Parameters
----------
amplitudes : sequence of float
Declared amplitude normalization of each group, not negative [phasor].
phases : sequence of float
Phase of each group [rad].
Returns
-------
c : numpy.ndarray
Complex phasor per group [phasor].
Raises
------
ValueError
The two sequences differ in length or an amplitude is negative or not
finite.
Convention
----------
``c_k = A_k exp(+i phi_k)``; the sign of the exponent is the one
:func:`hermitian_torque_matrix` recovers cross terms in.
Applicability
-------------
Machine-independent.
Provenance
----------
.. [1887] Issue #1887, phasor convention.
"""
a = np.asarray(amplitudes, dtype=float).ravel()
phi = np.asarray(phases, dtype=float).ravel()
if a.shape != phi.shape:
raise ValueError(f"{a.size} amplitudes for {phi.size} phases")
if not np.all(np.isfinite(a)) or np.any(a < 0):
raise ValueError("amplitudes must be finite and not negative")
return a * np.exp(1j * phi)Complex excitation phasors A_k exp(+i phi_k) of the coil groups.
| Name | Type | Unit | Description |
|---|---|---|---|
amplitudes | sequence of float | phasor | Declared amplitude normalization of each group, not negative. |
phases | sequence of float | rad | Phase of each group. |
| Returns | |||
c | numpy.ndarray | phasor | Complex phasor per group. |
Convention
c_k = A_k exp(+i phi_k); the sign of the exponent is the one
hermitian_torque_matrix recovers cross terms in.
Raises
ValueErrorThe two sequences differ in length or an amplitude is negative or not finite.
Applicability · Provenance
Applicability
Machine-independent.
Provenance
- Issue #1887, phasor convention.
fit_inhomogeneous_torque
Machine-independentConvention-sensitive
source
fit_inhomogeneous_torque(phasors, torques)
Least-squares T = T0 + 2 Re(b^H c) + c^H Q c, to test whether T0 and b vanish.
| Name | Type | Unit | Description |
|---|---|---|---|
phasors | numpy.ndarray | phasor |
|
torques | sequence of float | N m | Their signed torques. |
| Returns | |||
fit | dict | - |
|
Convention
2 Re(b^H c) = 2 (Re b . Re c + Im b . Im c) and
c^H Q c = sum_i Q_ii |c_i|^2 + 2 sum_{i<j} Re(conj(c_i) Q_ij c_j).
Raises
ValueErrorFewer finite samples than the1 + 2K + K^2real unknowns, shapes disagree, or the samples do not determine every unknown (rank deficient) – e.g. a scan at fixed amplitudes|c_k|, whereT0and theQ_iiare collinear.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Real unknowns:
T0,Re b,Im b,Q_iiand, fori < j,Re Q_ijandIm Q_ij. - Each sample contributes one real equation; solve by least squares.
- Refuse a rank-deficient design rather than split collinear terms.
Applicability
Machine-independent.
Limitations
A nonzero T0 or b means a background (an error field, another
coil) is present; the pure form c^H Q c then does not apply as is.
Provenance
- Issue #1887, Sec. 5 (the inhomogeneous form tested first).
fixed_amplitude_phase_extrema
Machine-independentConvention-sensitive
source
fixed_amplitude_phase_extrema(Q, amplitudes, *, grid_points, refine)
Phases of the largest and smallest signed torque with every group amplitude fixed.
| Name | Type | Unit | Description |
|---|---|---|---|
Q | numpy.ndarray | N m / phasor^2 |
|
amplitudes | sequence of float | phasor | Fixed amplitude of each group, not negative. |
grid_points | int | - | Phase samples per free phase of the deterministic grid, at least 4. |
refine | int | - | How many of the best grid points per extremum to polish with a local optimizer; 0 keeps the grid answer. |
| Returns | |||
extrema | dict | - |
|
Convention
c_k = A_k exp(+i phi_k); extrema of the signed torque.
Raises
ValueErrorShapes disagree, an amplitude is negative,grid_points < 4, or the grid would exceed two million points.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Hold group 0’s phase at 0 (common phase is irrelevant for one
n). - Evaluate
c^H Q con agrid_points^(K-1)phase grid. - Polish the
refinebest points of each extremum with L-BFGS-B on the free phases and keep the best.
Applicability
Machine-independent.
Limitations
Nonconvex for K >= 3: the grid plus local polish is a deterministic
reference, not a proof of the global optimum at coarse grids. The grid
grows as grid_points^(K-1).
Provenance
- Issue #1887, Sec. 8 (multi-group fixed-amplitude optimization).
hermitian_torque_matrix
Machine-independentConvention-sensitive
source
hermitian_torque_matrix(torques, groups)
Show source vaft/process/ntv_coil_response.py, lines 207–270
def hermitian_torque_matrix(torques: Mapping[str, float], groups: int) -> np.ndarray:
"""The Hermitian ``Q`` of ``T = c^H Q c`` from the probe torques.
Parameters
----------
torques : mapping of str to float
Signed torque of each probe of :func:`quadratic_probe_design`, keyed
by its label [N m].
groups : int
Number of coil groups ``K`` [-].
Returns
-------
Q : numpy.ndarray
``K x K`` Hermitian matrix [N m / phasor^2].
Raises
------
KeyError
A probe label is missing.
ValueError
A probe torque is not finite (a failed evaluation cannot identify ``Q``).
Processing steps
----------------
1. ``Q_ii = T(e_i)``.
2. ``Re Q_ij = [T(e_i + e_j) - T(e_i) - T(e_j)] / 2``.
3. ``Im Q_ij = [T(e_i) + T(e_j) - T(e_i + i e_j)] / 2``.
4. ``Q_ji = conj(Q_ij)``.
Convention
----------
With ``c = e_i + i e_j``, ``c^H Q c = Q_ii + Q_jj - 2 Im Q_ij``, which is
step 3; it holds for the ``exp(+i phi)`` phasor of :func:`coil_phasors`.
Applicability
-------------
Machine-independent.
Limitations
-----------
A ``Q`` that reproduces its own probes exactly is not thereby validated:
the probes determine it. Only :func:`qualify_torque_matrix` on held-out
evaluations can qualify it.
Provenance
----------
.. [1887] Issue #1887, Sec. 6.
"""
k = int(groups)
labels = [label for label, _ in quadratic_probe_design(k)]
values = {label: float(torques[label]) for label in labels}
bad = sorted(label for label, value in values.items() if not np.isfinite(value))
if bad:
raise ValueError(f"probe torques are not finite: {bad}")
q = np.zeros((k, k), dtype=complex)
for i in range(k):
q[i, i] = values[f"e{i}"]
for i, j in combinations(range(k), 2):
real = 0.5 * (values[f"e{i}+e{j}"] - values[f"e{i}"] - values[f"e{j}"])
imag = 0.5 * (values[f"e{i}"] + values[f"e{j}"] - values[f"e{i}+ie{j}"])
q[i, j] = real + 1j * imag
q[j, i] = real - 1j * imag
return qThe Hermitian Q of T = c^H Q c from the probe torques.
| Name | Type | Unit | Description |
|---|---|---|---|
torques | mapping of str to float | N m | Signed torque of each probe of |
groups | int | - | Number of coil groups |
| Returns | |||
Q | numpy.ndarray | N m / phasor^2 |
|
Convention
With c = e_i + i e_j, c^H Q c = Q_ii + Q_jj - 2 Im Q_ij, which is
step 3; it holds for the exp(+i phi) phasor of coil_phasors.
Raises
KeyErrorA probe label is missing.ValueErrorA probe torque is not finite (a failed evaluation cannot identifyQ).
Processing steps · Applicability · Limitations · Provenance
Processing steps
Q_ii = T(e_i).Re Q_ij = [T(e_i + e_j) - T(e_i) - T(e_j)] / 2.Im Q_ij = [T(e_i) + T(e_j) - T(e_i + i e_j)] / 2.Q_ji = conj(Q_ij).
Applicability
Machine-independent.
Limitations
A Q that reproduces its own probes exactly is not thereby validated:
the probes determine it. Only qualify_torque_matrix on held-out
evaluations can qualify it.
Provenance
- Issue #1887, Sec. 6.
ntv_operating_space
Machine-independentConvention-sensitive
source
ntv_operating_space(groups, n, phasors, torques, *, sample_ids, roles, amplitude_unit, frame, provenance, qualification=None)
Direct NTV torques (and a qualified model) as a #1178 coil operating-space result.
| Name | Type | Unit | Description |
|---|---|---|---|
groups | sequence of str | - | Coil-group names in phasor order. |
n | int | - | Toroidal mode number. |
phasors | numpy.ndarray | phasor |
|
torques | sequence of float | N m | Direct signed torque per sample; NaN for a failed evaluation. |
sample_ids | sequence of str | - | Stable id per sample. |
roles | sequence of str | - | Role per sample, from |
amplitude_unit | float | A per turn | Cosine amplitude of one phasor unit. |
frame | str | - | The toroidal frame the sector angles were taken in. |
provenance | mapping | - | What produced the direct torques: method, scalar radius, kinetic identity, solver tolerances. |
qualification | TorqueMatrixQualification, optional | - | A |
| Returns | |||
result | vaft.process.coil_operating_space.CoilOperatingSpace | - |
|
Convention
The excitation convention is
vaft.process.coil_operating_space.COIL_EXCITATION_CONVENTION
(c = A exp(+i delta)); measured and modelled torques never share a
metric.
Raises
ValueErrorLengths disagree,amplitude_unitis not positive, the qualification given is notqualified, or itsQis for another number of groups.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Amplitudes
|c| * amplitude_unitand phasesarg c mod 2 pi. - One
ntv_torquerow per sample:validwith its value, orfailedwith NaN. - With a qualified model, one
ntv_torque_modelrow per sample,c^H Q c; its provenance records the qualification.
Applicability
Machine-independent.
Limitations
A model row is a prediction valid only within the qualified domain the
qualification’s provenance describes. Nothing checks that Q was built
from the same PENTRC method and tolerances as torques; the caller’s
provenance is recorded as that claim.
Provenance
- Issue #1887, NTV torque on the #1178 operating space.
- Issue #1886, the result schema.
quadratic_invariance_checks
Machine-independentConvention-sensitive
source
quadratic_invariance_checks(base_torque, *, scaled=(), reversed_torque=None, rotated=(), atol, rtol)
Show source vaft/process/ntv_coil_response.py, lines 309–388
def quadratic_invariance_checks(
base_torque: float,
*,
scaled: Sequence[tuple[float, float]] = (),
reversed_torque: float | None = None,
rotated: Sequence[tuple[float, float]] = (),
atol: float,
rtol: float,
) -> tuple[QuadraticTorqueCheck, ...]:
"""Tests of a pure quadratic response that need no ``Q``: scaling, sign, common phase.
Parameters
----------
base_torque : float
Signed torque of the reference excitation ``c`` [N m].
scaled : sequence of (float, float)
``(a, T(a c))`` for positive real factors ``a`` [-, N m].
reversed_torque : float, optional
``T(-c)`` [N m].
rotated : sequence of (float, float)
``(chi, T(exp(i chi) c))`` for common phase rotations [rad, N m].
atol : float
Absolute tolerance, the scale below which a torque is near zero [N m].
rtol : float
Relative tolerance away from zero [-].
Returns
-------
checks : tuple of QuadraticTorqueCheck
``amplitude_scaling`` (expects ``a^2 T(c)``), ``sign_reversal``
(expects ``T(c)``) and ``common_phase`` (expects ``T(c)``), each only
when its samples were given [-].
Raises
------
ValueError
A tolerance is negative, a factor ``a`` is not positive, or a torque
is not finite.
Processing steps
----------------
1. Expected torque per sample from the homogeneous-quadratic hypothesis.
2. A sample passes when ``|T - T_expected| <= atol + rtol |T_expected|``.
3. One check per kind, passed only if every sample of that kind passes.
Convention
----------
The common-phase test assumes a single toroidal mode ``n``; a mixed-``n``
excitation is not phase-invariant and should not be given here.
Applicability
-------------
Machine-independent.
Limitations
-----------
A failed check rejects the *pure* quadratic form; a constant or linear
term (a background field) is examined by :func:`fit_inhomogeneous_torque`.
The tolerances are the caller's: no universal NTV tolerance exists.
Provenance
----------
.. [1887] Issue #1887, Sec. 5.
"""
_tolerances(atol, rtol)
base = _finite(base_torque, "base_torque")
checks: list[QuadraticTorqueCheck] = []
if scaled:
factors = np.array([float(a) for a, _ in scaled])
if np.any(factors <= 0):
raise ValueError("scaling factors must be positive")
values = np.array([_finite(t, "scaled torque") for _, t in scaled])
checks.append(_check("amplitude_scaling", values, factors**2 * base, atol, rtol))
if reversed_torque is not None:
checks.append(_check("sign_reversal", np.array([_finite(reversed_torque, "reversed_torque")]),
np.array([base]), atol, rtol))
if rotated:
values = np.array([_finite(t, "rotated torque") for _, t in rotated])
checks.append(_check("common_phase", values, np.full(values.shape, base), atol, rtol))
return tuple(checks)Tests of a pure quadratic response that need no Q: scaling, sign, common phase.
| Name | Type | Unit | Description |
|---|---|---|---|
base_torque | float | N m | Signed torque of the reference excitation |
scaled | sequence of (float, float) | -, N m |
|
reversed_torque | float, optional | N m |
|
rotated | sequence of (float, float) | rad, N m |
|
atol | float | N m | Absolute tolerance, the scale below which a torque is near zero. |
rtol | float | - | Relative tolerance away from zero. |
| Returns | |||
checks | tuple of QuadraticTorqueCheck | - |
|
Convention
The common-phase test assumes a single toroidal mode n; a mixed-n
excitation is not phase-invariant and should not be given here.
Raises
ValueErrorA tolerance is negative, a factorais not positive, or a torque is not finite.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Expected torque per sample from the homogeneous-quadratic hypothesis.
- A sample passes when
|T - T_expected| <= atol + rtol |T_expected|. - One check per kind, passed only if every sample of that kind passes.
Applicability
Machine-independent.
Limitations
A failed check rejects the pure quadratic form; a constant or linear
term (a background field) is examined by fit_inhomogeneous_torque.
The tolerances are the caller’s: no universal NTV tolerance exists.
Provenance
- Issue #1887, Sec. 5.
quadratic_probe_design
Machine-independentConvention-sensitive
source
quadratic_probe_design(groups)
Show source vaft/process/ntv_coil_response.py, lines 159–204
def quadratic_probe_design(groups: int) -> tuple[tuple[str, np.ndarray], ...]:
"""The ``K^2`` unit excitations that determine a Hermitian ``Q``.
Parameters
----------
groups : int
Number of independently driven coil groups ``K``, at least 1 [-].
Returns
-------
probes : tuple of (str, numpy.ndarray)
``("e0", e_0)``, ..., then for every ``i < j`` ``("e{i}+e{j}", e_i + e_j)``
and ``("e{i}+ie{j}", e_i + i e_j)``: ``K + 2 C(K, 2) = K^2`` phasors [phasor].
Raises
------
ValueError
``groups`` is below 1.
Convention
----------
The mixed probes put ``+i`` on the higher-index group, matching the
``exp(+i phi)`` phasor of :func:`coil_phasors`.
Applicability
-------------
Machine-independent.
Limitations
-----------
``K^2`` evaluations identify ``Q`` only; validating it needs further
held-out evaluations (:func:`qualify_torque_matrix`).
Provenance
----------
.. [1887] Issue #1887, Sec. 6 (probe identities and their count).
"""
k = int(groups)
if k < 1:
raise ValueError("at least one coil group is needed")
unit = np.eye(k, dtype=complex)
probes = [(f"e{i}", unit[i]) for i in range(k)]
for i, j in combinations(range(k), 2):
probes.append((f"e{i}+e{j}", unit[i] + unit[j]))
probes.append((f"e{i}+ie{j}", unit[i] + 1j * unit[j]))
return tuple(probes)The K^2 unit excitations that determine a Hermitian Q.
| Name | Type | Unit | Description |
|---|---|---|---|
groups | int | - | Number of independently driven coil groups |
| Returns | |||
probes | tuple of (str, numpy.ndarray) | phasor |
|
Convention
The mixed probes put +i on the higher-index group, matching the
exp(+i phi) phasor of coil_phasors.
Raises
ValueErrorgroupsis below 1.
Applicability · Limitations · Provenance
Applicability
Machine-independent.
Limitations
K^2 evaluations identify Q only; validating it needs further
held-out evaluations (qualify_torque_matrix).
Provenance
- Issue #1887, Sec. 6 (probe identities and their count).
quadratic_torque
Machine-independentConvention-sensitive
source
quadratic_torque(Q, phasors)
Show source vaft/process/ntv_coil_response.py, lines 273–306
def quadratic_torque(Q: np.ndarray, phasors: np.ndarray) -> np.ndarray:
"""Signed torque ``c^H Q c`` of one excitation or a stack of them.
Parameters
----------
Q : numpy.ndarray
``K x K`` Hermitian torque matrix [N m / phasor^2].
phasors : numpy.ndarray
One phasor vector of length ``K``, or an ``(N, K)`` stack [phasor].
Returns
-------
torque : numpy.ndarray
Real signed torque, scalar or length ``N`` [N m].
Raises
------
ValueError
``Q`` is not square and Hermitian, or the phasors do not match it.
Convention
----------
``T = c^H Q c`` with ``c_k = A_k exp(+i phi_k)``; the imaginary part,
zero for a Hermitian ``Q``, is dropped after the check.
Applicability
-------------
Machine-independent.
"""
q = _hermitian(Q)
c = np.asarray(phasors, dtype=complex)
if c.shape[-1] != q.shape[0]:
raise ValueError(f"phasors of length {c.shape[-1]} for a {q.shape[0]}-group Q")
return np.real(np.einsum("...i,ij,...j->...", c.conj(), q, c))Signed torque c^H Q c of one excitation or a stack of them.
| Name | Type | Unit | Description |
|---|---|---|---|
Q | numpy.ndarray | N m / phasor^2 |
|
phasors | numpy.ndarray | phasor | One phasor vector of length |
| Returns | |||
torque | numpy.ndarray | N m | Real signed torque, scalar or length |
Convention
T = c^H Q c with c_k = A_k exp(+i phi_k); the imaginary part,
zero for a Hermitian Q, is dropped after the check.
Raises
ValueErrorQis not square and Hermitian, or the phasors do not match it.
Applicability
Applicability
Machine-independent.
qualify_torque_matrix
Machine-independentConvention-sensitive
source
qualify_torque_matrix(Q, held_out_phasors, held_out_torques, *, atol, rtol, invariance_checks=())
Qualify or reject a Q against direct evaluations it was not built from.
| Name | Type | Unit | Description |
|---|---|---|---|
Q | numpy.ndarray | N m / phasor^2 | Hermitian torque matrix, e.g. from |
held_out_phasors | numpy.ndarray | phasor |
|
held_out_torques | sequence of float | N m | Their direct signed torques; NaN marks a failed evaluation. |
atol | float | N m | Absolute tolerance, the near-zero torque scale. |
rtol | float | - | Relative tolerance away from zero. |
invariance_checks | sequence of QuadraticTorqueCheck, optional | - | From |
| Returns | |||
qualification | TorqueMatrixQualification | - |
|
Convention
The comparison is on the signed torque; a model that matches |T| but
not its sign fails.
Raises
ValueErrorShapes disagree,Qis not Hermitian, or a tolerance is negative.
Processing steps · Applicability · Limitations · Provenance
Processing steps
- Set aside held-out samples whose direct torque is NaN, and count them.
- Compare
c^H Q cwith the direct torque per sample, passing when|dT| <= atol + rtol |T_direct|. - Combine with the invariance checks into one status.
Applicability
Machine-independent.
Limitations
Qualification holds for the background, n, PENTRC method, grid and
amplitude range the evaluations covered, and nowhere else.
Provenance
- Issue #1887, Sec. 6 (held-out validation).
two_group_phase_extrema
Machine-independentConvention-sensitive
source
two_group_phase_extrema(Q, amplitudes)
Show source vaft/process/ntv_coil_response.py, lines 580–644
def two_group_phase_extrema(Q: np.ndarray, amplitudes: Sequence[float]) -> dict[str, object]:
"""Relative phases of the largest and smallest signed torque of two groups.
Parameters
----------
Q : numpy.ndarray
``2 x 2`` Hermitian torque matrix of a qualified model [N m / phasor^2].
amplitudes : sequence of float
Fixed amplitudes ``(A_1, A_2)``, not negative [phasor].
Returns
-------
extrema : dict
``delta_phi_max`` and ``delta_phi_min`` in ``[0, 2 pi)`` [rad], or
``None`` when the torque does not depend on the phase; ``T_max`` and
``T_min`` [N m]; ``phase_independent`` [-].
Raises
------
ValueError
``Q`` is not ``2 x 2`` Hermitian or an amplitude is negative.
Processing steps
----------------
1. ``T(dphi) = Q_11 A_1^2 + Q_22 A_2^2 + 2 A_1 A_2 |Q_12| cos(dphi + arg Q_12)``.
2. Maximum at ``dphi = -arg Q_12``, minimum at ``pi - arg Q_12``.
3. With ``Q_12 = 0`` or a zero amplitude no phase is preferred.
Convention
----------
``c = (A_1, A_2 exp(+i dphi))``; the extrema are of the *signed* torque,
not of ``|T|`` or of a braking criterion.
Applicability
-------------
Machine-independent.
Limitations
-----------
Valid only where :func:`qualify_torque_matrix` qualified ``Q``.
Provenance
----------
.. [1887] Issue #1887, Sec. 8.
"""
q = _hermitian(Q)
if q.shape != (2, 2):
raise ValueError("two_group_phase_extrema needs a 2 x 2 Q")
a1, a2 = (float(a) for a in amplitudes)
if a1 < 0 or a2 < 0:
raise ValueError("amplitudes must not be negative")
base = float(np.real(q[0, 0])) * a1**2 + float(np.real(q[1, 1])) * a2**2
swing = 2 * a1 * a2 * abs(q[0, 1])
scale = max(abs(base), abs(q[0, 0]) * a1**2, abs(q[1, 1]) * a2**2, np.finfo(float).tiny)
if swing <= 64 * np.finfo(float).eps * scale: # below the roundoff of the diagonal terms
return {"delta_phi_max": None, "delta_phi_min": None, "T_max": base, "T_min": base,
"phase_independent": True}
arg = float(np.angle(q[0, 1]))
return {
"delta_phi_max": float(np.mod(-arg, 2 * np.pi)),
"delta_phi_min": float(np.mod(np.pi - arg, 2 * np.pi)),
"T_max": base + swing,
"T_min": base - swing,
"phase_independent": False,
}Relative phases of the largest and smallest signed torque of two groups.
| Name | Type | Unit | Description |
|---|---|---|---|
Q | numpy.ndarray | N m / phasor^2 |
|
amplitudes | sequence of float | phasor | Fixed amplitudes |
| Returns | |||
extrema | dict | - |
|
Convention
c = (A_1, A_2 exp(+i dphi)); the extrema are of the signed torque,
not of |T| or of a braking criterion.
Raises
ValueErrorQis not2 x 2Hermitian or an amplitude is negative.
Processing steps · Applicability · Limitations · Provenance
Processing steps
T(dphi) = Q_11 A_1^2 + Q_22 A_2^2 + 2 A_1 A_2 |Q_12| cos(dphi + arg Q_12).- Maximum at
dphi = -arg Q_12, minimum atpi - arg Q_12. - With
Q_12 = 0or a zero amplitude no phase is preferred.
Applicability
Machine-independent.
Limitations
Valid only where qualify_torque_matrix qualified Q.
Provenance
- Issue #1887, Sec. 8.