Add compute_energy_flux() using the Hardy formula:
J_b = 1/2 * F_bond_on_i * (v_i + v_j)
New 4th subplot shows J vs bond position (x coordinate of bond midpoint).
J > 0: energy flows rightward; J = 0: standing wave; J < 0: leftward.
Ideal standing wave would show J ≈ 0 everywhere.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Plot 1: x/y/z displacements overlaid on one axes
- Plot 2: per-atom KE/PE/total energy overlaid on one axes
- Plot 3: system energy vs time (unchanged)
All three stacked vertically. Shared y-axis scale within each panel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New 4x2 layout: left col = x/y/z displacement waves, right col = per-atom KE/PE/total energy + system energy vs time.
PE split 50/50 for normal bonds; 100% to non-driven atom when bonded to driver; driven atom PE = E_SHO - KE.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add show=False parameter to plot_wave(); when called from dynamics.py,
pass show=False and set matplotlib Agg backend to avoid NonGuiException.
Also print full traceback on failure for easier debugging.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>