Formulation
The numerical core is C++17 with Eigen, compiled to WebAssembly (and natively, for the tests). Linear triangular elements (P1) generated by Tangle.
Magnetostatics
Planar (x, y). The unknown is the vector potential \(A_z\), with
where \(\nu = 1/\mu\) is the reluctivity and \(\mathbf{B}_r\) the magnet remanence.
Axisymmetric (r, z). The unknown is \(\psi = r\,A_\varphi\), which vanishes on the axis:
with a \(1/r\) weight evaluated at the centroid radius of each element.
Materials. Linear, \(\nu = 1/(\mu_0\mu_r)\), or nonlinear through the B-H curve: \(H(B)\) as a monotone cubic and Newton-Raphson with a line search. Magnets through their remanence, \(\mathbf{H} = \nu(\mathbf{B} - \mathbf{B}_r)\), with the direction set on the region.
Laminated sheets. With stacking factor \(f\), sheet and insulation are in parallel along the depth: \(B(H) = f\,B_{steel}(H) + (1-f)\,\mu_0 H\) (linear: \(\mu_{ef} = f\mu_r + 1 - f\)), with no bulk conductivity. Iron losses use the steel volume and \(B_{steel} = B/f\), i.e. coefficients \(k_h f^{1-\alpha}\) and \(k_e/f\) over the region volume; the classical eddy term in a sheet of thickness \(d\) is \(k_e = \pi^2\sigma d^2/6\).
Sources. \(J = N\,I/S\), with \(N\) turns, current \(I\) (of the region or circuit) and region area \(S\).
Boundary conditions
As in FEMM:
Prescribed A (Dirichlet): \(A = A_0 + A_1 x + A_2 y\).
Neumann (natural): \(\partial A/\partial n = 0\).
Mixed (Robin): \(\nu\,\partial A/\partial n + c_0 A + c_1 = 0\). In axisymmetric problems, with \(\psi = rA\), the boundary term is \(\oint (c_0/r - \nu\, n_r/r^2)\,\psi\, N_i N_j + c_1 N_i\), integrated with 2-point Gauss. Asymptotic open boundary: \(c_0 = 1/(\mu_0 R)\).
Periodic and antiperiodic: elimination of matched nodes (Tangle splits both curves in sync).
Solution
Static: sparse LDLᵀ (
SimplicialLDLT).Circuit and AC: sparse LU (
SparseLU, complex for AC).Nonlinear: Newton-Raphson with a line search.
Transient
Implicit Euler with eddy currents in conducting regions without a source:
Sources are functions of \(t\) evaluated at every step. The external circuit joins the same system (strong, monolithic coupling), solved with Newton at every step.
Harmonic (AC)
With phasors,
Materials with a B-H curve use the effective permeability \(\nu_{ef} = H(\hat{B})/\hat{B}\) with the peak \(|B|\) of each element, iterated with relaxation (as in FEMM). The field is shown over one period, \(A(t) = \mathrm{Re}(\hat{A}\,e^{j\omega t})\).
Eddy-current losses: \(\tfrac{1}{2}\,\sigma\,\omega^2 |\hat{A}|^2\) (\(\psi/r\) in axisymmetric problems).
Iron losses (Steinmetz): \(p = k_h f \hat{B}^{\alpha} + k_e (f \hat{B})^2\).
AC losses in the wires
With \(\delta = \sqrt{2/(\omega\mu_0\sigma)}\) and \(k = (1-j)/\delta\), for a round wire of radius \(a\):
Skin: \(R_{ac}/R_{dc} = \mathrm{Re}\left[\tfrac{ka}{2}\,J_0(ka)/J_1(ka)\right]\) (low frequency \(1 + (a/\delta)^4/48\); high, \(a/(2\delta) + 1/4 + 3\delta/(32a)\)). \(P_{skin} = F\,R_{dc}\,\hat I^2/2\).
Proximity (transverse field of peak \(\hat B\)), per metre of wire: \(P' = \tfrac{\pi\omega^2\sigma}{2}|D|^2\int_0^a |J_1(kr)|^2 r\,dr\), \(D = 2\hat B/(k J_0(ka))\); low frequency \(\pi\sigma\omega^2\hat B^2 a^4/8\). Summed over the coil elements with \(|N|\cdot n_{par}/A\) strands per area.
Rectangular (\(w \times h\)): Dowell in each direction, \(P' = w\,P'_{foil}(h, \hat B_x) + h\,P'_{foil}(w, \hat B_y)\), with \(P'_{foil} = \tfrac{H_0^2}{\sigma\delta}\,\tfrac{\sinh\xi - \sin\xi}{\cosh\xi + \cos\xi}\), \(\xi = t/\delta\); skin from the foil of thickness \(\min(w, h)\) (approximation).
Steady thermal
\(-\nabla\cdot(k\nabla T) = q\) in the solid (P1; \(2\pi r\) weight in axisymmetric problems), with convection \(-k\,\partial T/\partial n = h\,(T - T_{ref})\) on exposed edges, the depth faces in planar problems as a sink \(2h/d\,(T - T_{amb})\), and fixed temperature. \(q\) comes from the magnetic physics: \(J^2/(2\sigma)\) in coils (AC; with the wire, \(\times A_{region}/(|N| A_{turn})\) and the skin factor), proximity, \(\tfrac12\sigma\omega^2|\hat A|^2\) in solid conductors and Steinmetz in iron. Air channels: \(T_{air} = T_{in} + P/(2\rho c_p Q)\). Resistivity: \(\rho(T) = \rho_{20}[1 + \alpha(T - 20)]\), iterating with the AC. Conjugate gradient with Jacobi.
Post-processing
Energy: \(W = \tfrac{1}{2}\int \nu\,|\mathbf{B} - \mathbf{B}_r|^2\, dV\).
Flux linkage: \(\lambda = \sum (N/S)\int A\, d\Omega \times\) depth (planar) or \(\sum (N/S)\int 2\pi\psi\, d\Omega\) (axisymmetric); \(L = \lambda/I\); \(R_{DC} = \sum N^2 \ell/(\sigma S)\), or \(\sum |N|\,\ell/(\sigma A_{turn})\) with the wire set.
Flux through a curve: \(\Phi = -\Delta A \times\) depth (planar) or \(2\pi\,\Delta\psi\) (axisymmetric).
Interpolation: gradient recovered at the nodes (per region) and a quadratic interpolant per triangle.
Force and torque
With the Maxwell stress tensor, \(T = (\mathbf{B}\mathbf{B}^\mathsf{T} - \tfrac{1}{2}|\mathbf{B}|^2 I)/\mu_0\):
Surface (weighted, like the FEMM block integral): \(\mathbf{F} = -\int T\cdot\nabla g\, dV\), with \(g = 1\) at the body nodes and \(0\) elsewhere; only the air elements around the body contribute.
Line (closed contour in air): \(\mathbf{F} = \oint T\cdot\mathbf{n}\, dl \times\) depth, with B smoothed at the nodes.
Torque is about the origin.