Validation#

ElectroSim ships with an interactive validation harness that compares the numerical integrator against the analytical solution for a particle in a uniform electric field. Use it to confirm that physics changes or performance optimisations have not introduced regressions.

Uniform Field Scenario#

The built-in scenario accelerates a single charged particle with a constant field vector configured via UNIFORM_FIELD_VECTOR_NC in electrosim/config.py. When active, the simulation:

  • Clears the scene and spawns one particle at world centre with DEFAULT_CHARGE_C, DEFAULT_MASS_KG, and DEFAULT_RADIUS_M.

  • Enables the uniform field contribution for both forces and field visualisation via UNIFORM_FIELD_ACTIVE = True and UNIFORM_FIELD_VISUAL_OVERRIDE = True.

  • Tracks the analytical trajectory \(x(t) = x_0 + v_0 t + \tfrac{1}{2} a t^2\) where \(a = (q/m)E\) for comparison against the numerically integrated state.

  • Samples the theoretical path at the display cadence (1/FPS_TARGET) so it can be drawn as a yellow guideline (COLOR_THEORY_TRAJECTORY).

The default duration is VALIDATION_DURATION_S = 10.0. After reaching the end time, the simulation auto-pauses and prints a summary of the final position and velocity error to stdout for easy logging.

How to Run It#

  1. Launch the desktop build: python main.py.

  2. Press U (see docs/user_guide/controls.md). The current scene is replaced with the uniform-field setup and validation begins immediately.

  3. Observe the overlay and trajectory while the timer counts up to VALIDATION_DURATION_S.

  4. Inspect the console output when the run completes. The final state is kept on screen so you can inspect the particle visually.

To exit validation mode, either press R to reset to the default scene, C to clear all particles, or simply close the window. Calling Simulation.stop_validation() from code also restores configuration defaults (UNIFORM_FIELD_ACTIVE = False, UNIFORM_FIELD_VISUAL_OVERRIDE = False).

Reading the Overlay#

While validation is active, the overlay (rendered by electrosim.rendering.overlay) displays an additional section:

  • E: The configured uniform field vector in N/C.

  • a: Acceleration derived from \((q/m)E\) using the active particle mass and charge.

  • t and dt: Current validation time and integrator step.

  • |pos_err| and |vel_err|: Euclidean error between analytical and simulated position/velocity with periodic wrapping applied.

  • Final theoretical vs simulated position/velocity once VALIDATION_DURATION_S has elapsed.

The yellow line rendered in main.py uses validation_theory_traj to plot the analytical solution. This makes divergence visually obvious even before the numeric error grows large.

Customising the Scenario#

All relevant knobs live in electrosim/config.py:

  • UNIFORM_FIELD_VECTOR_NC: Change the acceleration direction/magnitude.

  • DEFAULT_CHARGE_C, DEFAULT_MASS_KG: Alter particle properties to stress different regimes.

  • VALIDATION_DURATION_S: Adjust the run length. Longer runs reveal accumulated integration error but increase execution time.

  • FPS_TARGET and SUBSTEPS_BASE_PER_FRAME: Increase to reduce local truncation error at the cost of runtime.

Because the harness operates on the full simulation stack, you can experiment with alternative integrators or force kernels simply by modifying the regular code paths. The validation overlay will pick up the results automatically via the Simulation.validation_* fields.

Automating from Code#

If you need to trigger validation from tests or scripts, import the simulation engine and call electrosim.simulation.engine.Simulation.start_uniform_field_validation(). During the run, increment frames as usual with Simulation.step_frame(). After completion, inspect validation_current_errors or the stored final vectors (validation_final_theory_pos_m, validation_final_sim_pos_m, etc.) for assertions. Remember to call Simulation.stop_validation() to reset the global config flags when you are done.