PCB traces become line-current segments whose free-space field is summed by Biot-Savart in a compute shader. The magnetic rotor and back plate then respond through a reduced scalar potential: H = Hs − ∇φ, with ∇·(μ∇φ) = ∇·(μHs), solved by conjugate gradients on a 3D grid. Torque comes from the Maxwell stress tensor on a box around the rotor.
The PCB is non-magnetic and carries the currents, so its field is exact free-space Biot-Savart. Traces are modelled as concentric trapezoidal loops per layer, a close stand-in for spiral coils. Per-phase fields are computed once per geometry and cached, so changing current angle or rotor position only re-runs the potential solve. Changing rotor position re-rasterizes the materials, while the traces stay put.
The reduced scalar potential is accurate for moderate permeability, which suits iron-filled filament. At steel-like μᵣ in the hundreds or thousands, H inside the material becomes a small difference of two large numbers, and f32 loses it. The sphere test at μᵣ = 2000 shows this directly. The standard fix is the two-potential method, which uses the total potential inside iron.
Project files are plain JSON with units in every field name. They hold the design parameters, view settings and a summary of the last solve, but not the field itself; opening one re-solves, which reproduces the result. The model export is a zip with an OBJ of every part, printable STLs, and an SVG of the copper pattern.
The 3D view draws the machine from its analytic geometry (smooth arcs, trace ribbons), not the solver grid. The field is uploaded as a filtered 3D texture and ray-marched on the GPU; field lines are streamlines of B traced through that same field. The outer box is held at φ = 0, with a margin around the machine. Torque is integrated on two box surfaces whose bottom faces sit at different heights in the air gap. Close agreement between the two estimates is a useful check on grid resolution.