Permanent Magnet Node#

Module: mime.nodes.actuation.permanent_magnet Stability: experimental Algorithm ID: MIME-NODE-101 Version: 1.0.0 Verification Mode: Mode 2 (Independent)

Summary#

Computes the magnetic field $\mathbf{B}$ and its spatial gradient $\nabla\mathbf{B}$ produced by a finite permanent magnet at an arbitrary target point in world coordinates. Three field models are available (point_dipole, current_loop, coulombian_poles) plus an unconditional uniform Earth-field background. The gradient $\nabla\mathbf{B}$ is computed by jax.jacrev of the same function used for $\mathbf{B}$ — a single code path guarantees the analytical gradient is consistent with the analytical field for every model.

Governing Equations#

Let the magnet sit at world position $\mathbf{p}_m$ with orientation quaternion $\mathbf{q}_m$ and body-frame magnetisation axis $\hat{\mathbf{a}}_b$. The world-frame moment is

$$ \mathbf{m}_{\text{world}} = R(\mathbf{q}_m),(|\mathbf{m}| , \hat{\mathbf{a}}_b) $$

with $|\mathbf{m}|$ the configured dipole_moment_a_m2.

For a target point $\mathbf{x}_T$, define $\mathbf{r} = \mathbf{x}_T - \mathbf{p}_m$, $r = |\mathbf{r}|$, $\hat{\mathbf{r}} = \mathbf{r}/r$.

Point dipole (point_dipole):

$$ \mathbf{B}_{\text{dipole}}(\mathbf{r}) = \frac{\mu_0}{4\pi} \cdot \frac{3(\mathbf{m}\cdot\hat{\mathbf{r}})\hat{\mathbf{r}} - \mathbf{m}}{r^3}. $$

Current loop, on-axis ($\rho = 0$, $z$ measured along $\hat{\mathbf{m}}$):

$$ B_z^{\text{loop}}(z) = \frac{\mu_0 I R^2}{2 (R^2 + z^2)^{3/2}}, \qquad I_{\text{eff}} = \frac{|\mathbf{m}|}{\pi R^2}. $$

Off-axis: dipole field with a near-field correction $(1 - (R/r)^2)$ clipped to $[0, 1]$.

Coulombian poles (uniformly magnetised cylinder), on-axis:

$$ B_z^{\text{coul}}(z) = \frac{\mu_0 M}{2} \left[ \frac{z + L/2}{\sqrt{R^2 + (z + L/2)^2}}#

\frac{z - L/2}{\sqrt{R^2 + (z - L/2)^2}} \right], \qquad M = \frac{|\mathbf{m}|}{\pi R^2 L}. $$

Off-axis: dipole field (closed form involves elliptic integrals; not yet implemented).

Total field with amplitude scale and Earth background:

$$ \mathbf{B}_{\text{total}}(\mathbf{x}T) = \alpha,\mathbf{B}{\text{model}}(\mathbf{x}_T)

  • \mathbf{B}_{\text{earth}}. $$

Spatial gradient (single code path):

$$ \bigl[\nabla \mathbf{B}\bigr]_{ij} = \frac{\partial B_i}{\partial x_j}#

\bigl[\mathrm{jacrev}(\mathbf{B}_{\text{total}}, \mathbf{x}T)\bigr]{ij}. $$

Discretization#

Analytical for all three field models on the magnet axis. AGM-based complete elliptic integrals $K(m)$, $E(m)$ are provided as a JAX- traceable library (12 iterations $\Rightarrow \approx 7$–$9$ digit agreement with scipy.special.ellipk/ellipe); they are not used in the v1 off-axis path but are available for future upgrades. Off-axis current_loop and coulombian_poles fall back to dipole + finite-size correction.

The gradient $\nabla\mathbf{B}$ is reverse-mode automatic differentiation of the same function returning $\mathbf{B}$ — machine precision, no hand-coded gradient drift.

Implementation Mapping#

Equation Term

Implementation

Notes

$\mathbf{m}_{\text{world}} = R(\mathbf{q}m),\mathbf{m}{\text{body}}$

mime.nodes.actuation.permanent_magnet.PermanentMagnetNode._m_world

quat_to_rotation_matrix(q) @ m_body

$\mathbf{B}_{\text{dipole}} = (\mu_0/4\pi)[3(\mathbf{m}\cdot\hat{\mathbf{r}})\hat{\mathbf{r}} - \mathbf{m}]/r^3$

mime.nodes.actuation.permanent_magnet._b_point_dipole

Closed form

$B_z^{\text{loop}} = \mu_0 I R^2 / (2(R^2+z^2)^{3/2})$ on axis; dipole $\times(1-(R/r)^2)$ off axis

mime.nodes.actuation.permanent_magnet._b_current_loop

jnp.where(on_axis, ...)

$B_z^{\text{coul}}$ closed form on axis; dipole off axis

mime.nodes.actuation.permanent_magnet._b_coulombian_poles

Two opposite-sign discs

$\mathbf{B}{\text{total}} = \alpha,\mathbf{B}{\text{model}} + \mathbf{B}_{\text{earth}}$

mime.nodes.actuation.permanent_magnet._b_total_world

Dispatch via _FIELD_MODELS

$\nabla\mathbf{B}$

mime.nodes.actuation.permanent_magnet.PermanentMagnetNode.update

jax.jacrev(_field_fn)(target) — single code path for all three models

AGM $K(m)$, $E(m)$ library

mime.nodes.actuation.permanent_magnet._ellipk_agm / _ellipe_agm

JAX-traceable, 12 iterations

Assumptions and Simplifications#

  1. Rigid permanent moment — no demagnetisation, no temperature drift.

  2. Magnet pose supplied externally — no internal dynamics for the magnet.

  3. Earth field is uniform and static over the workspace.

  4. current_loop and coulombian_poles use closed form on-axis; off-axis falls back to dipole $\times$ near-field correction. Full elliptic-integral off-axis form is not implemented in v1.

  5. No eddy currents or shielding from biological tissue.

Validated Physical Regimes#

Parameter

Verified Range

Notes

$

r

/R_{\text{magnet}}$

$

\mathbf{m}

$

amplitude_scale

0–1

Linear scaling of magnet contribution

Known Limitations and Failure Modes#

  1. point_dipole only valid at $z \gtrsim 5,R_{\text{magnet}}$ — $\approx 4%$ error at $z = 3,R_{\text{magnet}}$ (e.g. 3 mm from a 1 mm magnet) and $< 1%$ at $z = 10,R_{\text{magnet}}$. See docs/deliverables/dejongh_benchmark_summary.md lines 393–413 for the calibrating numbers.

  2. Off-axis current_loop and coulombian_poles fall back to dipole + $(1 - (R/r)^2)$ correction — for high-fidelity off-axis fields use a magnetostatic FEM solver.

  3. Coulombian model assumes a uniformly magnetised cylinder; non-uniform magnetisation is not represented.

  4. No saturation, hysteresis, or B-H curve — the moment is constant and rigid.

Stability Conditions#

Unconditionally stable — analytical evaluation, no time integration.

State Variables#

Field

Shape

Units

Description

field_vector

(3,)

T

Last-computed B at the target

field_gradient

(3,3)

T/m

Last-computed $\partial B_i / \partial x_j$ at the target

Parameters#

Parameter

Type

Default

Units

Description

dipole_moment_a_m2

float

required

A·m²

Magnitude of the magnetic moment

magnetization_axis_in_body

tuple

(0,0,1)

Moment axis in magnet body frame (will be normalised)

magnet_geometry

str

“cylinder”

Free-form geometry tag (documentation only)

magnet_radius_m

float

required

m

Cylinder radius

magnet_length_m

float

required

m

Cylinder length

field_model

str

“point_dipole”

One of point_dipole, current_loop, coulombian_poles

earth_field_world_t

tuple

(2e-5, 0, -4.5e-5)

T

Static Earth-field background (mid-latitude rough)

Boundary Inputs#

Field

Shape

Default

Coupling Type

Description

magnet_pose_world

(7,)

identity at origin

replacive

Magnet pose [x,y,z, qw,qx,qy,qz]

target_position_world

(3,)

zeros

replacive

Point at which to evaluate $\mathbf{B}$, $\nabla\mathbf{B}$

amplitude_scale

()

1.0

replacive

Commandable multiplier on magnet contribution

Boundary Fluxes (outputs)#

Field

Shape

Units

Description

field_vector

(3,)

T

$\mathbf{B}$ at target (for downstream PermanentMagnetResponse)

field_gradient

(3,3)

T/m

$\nabla\mathbf{B}$ at target

MIME-Specific Sections#

Anatomical Operating Context#

Compartment

Flow Regime

Re Range

pH Range

Temp Range

Viscosity Range

CSF

stagnant or pulsatile

n/a (external)

n/a

n/a

n/a

Blood

poiseuille / pulsatile

n/a (external)

n/a

n/a

n/a

The magnet is an external apparatus — it does not sit in the fluid. The field it produces does, however, drive the magnetised UMR inside CSF or blood; the operating regime is therefore inherited from the downstream PermanentMagnetResponseNode and RigidBodyNode.

Mode 2 Independent Verification#

Three benchmarks accompany this node (full reports under docs/validation/benchmark_reports/):

  • MIME-VER-110 (mime_ver_110_dipole_field.md) — far-field point-dipole formula vs analytical; on-axis current_loop and coulombian_poles against their own closed-form expressions.

  • MIME-VER-111 (mime_ver_111_dipole_gradient.md) — jax.jacrev of the dipole field against the analytical $\nabla\mathbf{B}$ formula; verifies the single-code-path gradient claim.

  • MIME-VER-112 (mime_ver_112_earth_field_superposition.md) — Earth-field superposition is exact; flipping the Earth field flips the residual by exactly $2,\mathbf{B}_{\text{earth}}$.

In addition, the test suite contains JAX-traceability tests (jit, grad, vmap) and a GraphManager integration test that runs the node for one step inside a graph.

References#

  • [@Jackson1998] Jackson, J.D. (1998). Classical Electrodynamics, Sec. 5.6 — magnetic dipole field.

  • [@Abbott2009] Abbott, J.J. et al. (2009). How Should Microrobots Swim? — magnetic actuation of microrobots.

  • [@deJongh2024] de Jongh, S. et al. (2024). Confined-swimming benchmark; calibrating numbers for the near-field validity envelope.

  • [@Furlani2001] Furlani, E.P. (2001). Permanent Magnet and Electromechanical Devices — closed-form Coulombian-pole and current-loop expressions for cylindrical bar magnets, used by the current_loop and coulombian_poles field models.

Verification Evidence#

  • MIME-VER-110: Dipole field vs analytical

  • MIME-VER-111: Dipole gradient (jax.jacrev) vs analytical

  • MIME-VER-112: Earth-field superposition exactness

  • Test file: tests/verification/test_permanent_magnet.py

Changelog#

Version

Date

Change

1.0.0

2026-04-30

Initial implementation — three field models + AGM elliptic library + jacrev gradient