Next-Stage Plan Implementation Status¶
This document tracks progress against the "Next-Stage Development Plan — Time Series, Forces, and Advanced Probes" roadmap.
Stage progress — From Magnetostatics to Basic Motor Simulation¶
- Stage 0.1 (SIMD-ready linops): Extracted the core linear algebra kernels
(
applyA, dot products, axpy/scal, residual norms) intomotorsim::linopswith optional vectorisation hints guarded by the newMOTORSIM_ENABLE_SIMD_HINTSCMake switch (-DMOTORSIM_SIMD_HINTS). Solver code now routes through these utilities, paving the way for SIMD or threaded back-ends without changing behaviour. - Stage 0.2 (Live progress polish): Expanded the runtime controls with
--progress-every,--snapshot-every, and the new--progress-historyoutput. The CLI now records residual samples to CSV (timeline runs append_frame_###), enabling CI to archive a long CG history directly frommotor_sim. - Stage 1 (Three-phase synchronous baseline): Restored
python/gen_three_phase_stator.pyto emit the original stator-only rotating field demo. The generator continues to supply CI and hi-res profiles, anddocs/three_phase_stator.mdfocuses on the bore-angle regression (python/check_three_phase_field.py), ParaView.pvdseries, and animation workflow without introducing rotor geometry. Maxwell-stress and back-EMF probes remain available for stator studies, with regression coverage intests/back_emf_probe_test.cpp. - Stage 2.1 (RL circuit co-simulation): Scenario JSON now accepts
lumped-element circuits with per-phase resistors, inductors, voltage sources,
and coil links. Timeline frames drive the network via
"voltage_sources", the solver integrates branch currents with RK4 (while feeding back-dλ/dtfrom coil flux), and the newpython/gen_three_phase_pm_motor.pyemits the default three-phase star connection for the permanent-magnet motor demo.tests/circuit_rk_test.cppexercises the RK integrator against the analytic RL step response, anddocs/three_phase_pm_motor.mddocuments the voltage-driven workflow. Thecurrent_regionsource now records slot turns and copper fill fraction so the rasteriser deposits ampere-turns instead of raw current; coil links validate the turn count so the circuit and field models stay in sync, and the newtests/current_region_turns_test.cppregression integrates the deposited density to keep the ampere-turn budget within 5% of the analytic target. Each scenario can now request acircuit_traceoutput; the runtime records per-coil current, ampere-turn, and back-EMF histories so downstream tooling (notablypython/generate_rotor_animation.py) can colour stator slots by the solved waveforms. CI archives these CSVs for the PM, induction, and DC motor demos and renders rotor-only GIF/PNG snapshots alongside the field-map animations. Follow-up work introduced commutator metadata oncoil_linkentries so coil orientation can depend on rotor angle.CircuitSimulatornow reads per-link segment tables, queries the currentdc_rotorangle from the mechanical or timeline state, and applies the requested sign flip before depositing currents or integrating flux. The DC motor generator (python/gen_dc_motor.py) uses this plumbing to emit a brushed armature demo alongside a four-framecommutator_testfixture.tests/dc_commutator_test.cppconfirms the orientation switching logic, whiletests/dc_motor_spinup_test.cppexercises the full EM/circuit/mechanical loop with balanced stator and rotor ampere-turn budgets. Documentation lives indocs/dc_commutated_motor.md, and CI now runs the generator, solver, and mechanical validator to archive the new artefacts. - Stage 2.2 (Mechanical coupling): Introduced a light-weight rotor
dynamics module that integrates speed and position via RK4 using the torque
reported by Maxwell-stress probes. Scenarios can now declare inertial,
damping, and load torque terms under
"mechanical"; the PM motor generator provides a default configuration with a constant load, and the runtime keeps timeline frames sequential to ensure warm-started field solves feed the coupled ODE. The integrator automatically stands down when timeline frames provide explicit rotor angles so deterministic synchronous demos (e.g. the PM motor walkthrough) keep their scripted pose, while scenarios without those overrides step the coupled mechanics.tests/mechanical_spinup_test.cppverifies the integrator against a constant-torque spin-up. Follow-up fixes ensure timeline exporters respect basenames that already end in_frame, restoring the expectedthree_phase_frame_000.vtiartefact that CI archives for the stator rotating-field demo, and the newtests/pm_motor_spinup_test.cppregression drives the full EM/circuit/mechanical loop to assert the rotor angle and speed rise over a short spin-up timeline while the CLI exposes amechanical_traceoutput so CI and users can verify the rotor state history viapython/check_pm_spinup.py. The PM motor guide now summarises the CI fixture parameters and documents lighter generator overrides for local smoke tests so developers can iterate without modifying the stored regression JSON. The generator now carves the magnet out of the rotor iron, assigns it μᵣ≈1.05, and trims the magnet strength (1×10⁵ A/m) alongside the phase drive (35 A peak warm-start currents, 20 V peak). The rotor bore field therefore stays on the same tens-of-millitesla scale as the stator-only demo instead of spiking into the 50–200 T range that occurred when the magnet inherited the 800× permeability of the surrounding steel. Timeline solves now aggregate torque probe samples into the requested base path (time_s,frame_index,Fx,Fy,Tz[,CoEnergy]) so the PM, DC, and induction spin-up demos expose ready-to-plot torque histories without scraping individual_frame_###files. Follow-on cleanup reduced the CI tessellation counts (18 stator vertices, 12 for the bore, 10 for the rotor loop) so the committed spin-up fixture stays close to 1.3k lines, and thepython/check_pm_spinup.pyhelper now evaluates absolute angle/speed gains to accommodate rotors that accelerate in either direction. The brushed DC spin-up fixture now caps the CI profile at two electrical cycles (24 frames) so the archived mechanical trace remains monotonic for the commutator regression, while the hires preset retains the longer six-cycle sweep for offline studies. - Stage 3 (Frequency-domain induction path): Extended the material schema
with per-material conductivities (
sigma) and taught the rasteriser and grid container to tracksigma, complex impressed currents, and an imaginary vector potential. A new harmonic solver assembles the coupled real/imaginary system and applies CG to the normal equations so frequency-domain eddy currents can be simulated without leaving the matrix-free framework. Utility routines compute complex \(\mathbf{B}\) and \(\mathbf{H}\) fields, and the regressiontests/skin_depth_test.cppvalidates skin-depth decay against the analytic \(e^{-x/\delta}\) profile for a half-space conductor, enforcing a ≤15% slope error on the bundled scenario. - Stage 4 (Transient magnetodynamics foundations): Introduced a
Crank–Nicolson-style transient wrapper that augments the existing matrix-free
operator with \(\sigma/\Delta t\) mass terms and reuses the CG machinery (and
preconditioners) to march conductive regions forward in time. Timeline frames
now opt into transient solves via the
"transient"block, and the main loop detects when scripted rotor angles are absent so the coupled circuit/mechanical subsystems advance in lock-step with the EM step. The regressiontests/diffusion_test.cppdrives the newinputs/tests/diffusion_test.jsonscenario to check magnetic diffusion into a conducting slab against the analytic erfc profile, enforcing a ≤20% envelope error while archiving the recovered surface field amplitude. Stage 4.2 now ships an induction spin-up path:python/gen_three_phase_induction_motor.pyemits a conductive-bar rotor demo,tests/induction_spinup_test.cppverifies the coupled transient/mechanical loop accelerates the rotor while staying below synchronous speed, and CI captures the accompanying VTK/mechanical artefacts. - Stage 5 (Solver UX/perf prep): Added a
--pc {none|jacobi|ssor}CLI flag and matching scenario schema to control CG preconditioners. Jacobi and a matrix-free SSOR sweep are exposed as first-class options, documented in the solver guide alongside usage tips. The default remains unpreconditioned, but CI, the local workflow helper, and the docs now spell out when Jacobi or SSOR provide faster convergence on conductive or highly anisotropic cases.
Completed Milestones¶
- VTK export and verification: Implemented via
motorsim::write_vti_field_mapwith regression coverage intests/output_quantity_test.cppand exercised in CI through the rotor ripple timeline artefacts. Exports now bundle combinedB/Hvector arrays plus geometry outline polydata companions to streamline ParaView workflows. Thepython/verify_vtk.pyutility (documented indocs/vtk_output.md) runs during CI to sanity-check the generated.vtifiles. - Time-series infrastructure: Scenario timelines, per-frame solving, and parallel execution are available (see
docs/time_series.md). Rotors now group geometry, magnets, and sources under named pivots so timeline frames can rotate complete assemblies via the newrotor_anglesoverrides. The CI workflow drivesinputs/tests/rotor_ripple_test.jsonwith--parallel-framesto emit multi-frame datasets and CSV/VTI artefacts. - Maxwell stress probes: Force/torque evaluation and documentation reside in
docs/torque_forces.md, with validation fixtures intests/torque_validation_test.cppand rotor ripple torque ripple checks. - Back-EMF probes: Flux integration across timeline frames emits per-interval voltages (
docs/back_emf.md) and is now represented in the artefact bundle viaoutputs/rotor_ripple_emf.csv. - Visualization upgrades:
python/visualize_scenario_field.pyexposes log-scale colormaps, boundary overlays, streamline controls, analytic overlays, and vector scaling modes (documented indocs/visualization.md). CI renders both static validation scenes and the new rotor ripple frames. - Rotor animation toolkit:
python/rotor_animation.py+python/generate_rotor_animation.pynow turn scenario geometry, mechanical traces, and circuit currents into coloured slot animations. The PM, induction, and DC demos requestcircuit_traceoutputs so the helper can tint slots by ampere-turns; CI runs capture both GIF and PNG artefacts, andtests/rotor_animation_smoke.pycovers the CLI in both explicit-trace and timeline-fallback modes.
CI artefact coverage¶
- Field plots:
ci_artifacts/rotor_ripple_frame0.pngandci_artifacts/rotor_ripple_frame2.pngillustrate timeline evolution alongside the existing two-wire/interface/iron-ring renders. - Accuracy reports:
ci_artifacts/test_accuracy_report.txtaggregates analytic/regression solver comparisons, now including force, torque, and back-EMF validation summaries captured from the dedicated regression binaries; additional torque/back-EMF CSVs are copied directly fromoutputs/. - Sample VTK:
outputs/rotor_ripple_field_frame_000.vti(and subsequent frames) are exported on every CI run and verified withpython/verify_vtk.py. Companion outline polydata and_labels.csvmapping files are uploaded for ParaView inspection. - Rotor timeline bundles now rotate a multi-segment rotor and high-µ stator, emit outline polydata that ParaView can load without crashing, and log symmetry metrics (
opposition60_120,repeat0_180) plus relative probe/back-EMF errors in the regression summary to track solver accuracy over time.
High-compute follow-up runs¶
The CI fixtures intentionally stay coarse (≤65×65 grids with short timelines).
When more compute is available, regenerate the following scenarios with their
hires profiles to produce denser artefacts, longer spin-ups, or complete
electrical cycles:
python/gen_three_phase_stator.py --profile hires --out inputs/three_phase_stator_hires.jsonfollowed by./build/motor_sim --scenario inputs/three_phase_stator_hires.json --solve --vtk-series outputs/three_phase_hires.pvdto render the 401×401 bore field sweep.python/gen_three_phase_pm_motor.py --profile hires --mode spinup --out inputs/pm_motor_spinup_hires.jsonthen./build/motor_sim --scenario inputs/pm_motor_spinup_hires.json --solve --vtk-series outputs/pm_motor_hires.pvdfor a multi-cycle permanent-magnet spin-up with higher polygon resolution.python/gen_three_phase_induction_motor.py --profile hires --mode spinup --out inputs/induction_motor_hires.jsonand./build/motor_sim --scenario inputs/induction_motor_hires.json --solve --vtk-series outputs/induction_motor_hires.pvdto capture the transient slip behaviour over several mechanical revolutions.python/gen_dc_motor.py --profile hires --mode spinup --out inputs/dc_motor_spinup_hires.jsonwith./build/motor_sim --scenario inputs/dc_motor_spinup_hires.json --solve --vtk-series outputs/dc_motor_hires.pvdto inspect the commutated armature waveforms and torque under finer discretisation.- After each hires solve, re-run
python/generate_rotor_animation.pywith the emitted mechanical and circuit traces to capture high-resolution GIF/PNG animations (matching the CI commands but pointing at the hires scenario and output directories). The rotor animation helper consumes both timeline data and recorded currents, so the hires artefacts retain the correct slot colour modulation. - For all of the above, re-run
python/check_pm_spinup.pywith the emitted--mechanicaltraces and loosened thresholds to validate the long-horizon acceleration, and archive the residual CSVs (--progress-history 1) alongside the high-resolution VTK artefacts.
Remaining work¶
- Additional UX polish (e.g., non-uniform grid bands and parallel CG kernels) can build on the new preconditioner hooks once the transient pipeline settles. Longer transient runs that co-simulate the RL network, slip-tuned voltage sources, and coarse-to-fine prolongation for induction demos remain on the wishlist alongside the optional mechanical enhancements from Stage 5.