fc06d37Bead-and-spring percussion simulator: numbl-scripted setup, Verlet/Yoshida solver with exact damping, linear modes, browser appJeremy Magland 1// The bead system as the solver sees it. Indices are 0-based here; the
2// script uses 1-based indices and parse.ts converts them.
4export type Method = "verlet" | "yoshida4";
6export interface Hit {
7 t: number; // start time (s)
8 beads: Int32Array;
9 // Impulse: velocity added to each bead at time t (m/s). Used when duration == 0.
10 velocity: [number, number, number];
11 // Force pulse: raised-cosine force on each bead, peak `force` (N), lasting `duration` (s).
12 force: [number, number, number];
13 duration: number;
14}
16export interface BeadSystem {
17 n: number;
18 pos0: Float64Array; // 3n, interleaved x,y,z (m)
19 mass: Float64Array; // n (kg)
20 pinned: Uint8Array; // n, 1 = held fixed
21 // Springs: f = k e + k3 e^3, e = L - L0
22 si: Int32Array;
23 sj: Int32Array;
24 sk: Float64Array;
25 sL0: Float64Array;
26 sk3: Float64Array;
74b1dcdFree edges: bending triplets (sys.bends) with damping, lattice triplets from bp_hexdisk/bp_chain, bp_decay for bending, bp_anchor soft supports, zero-mode warning; plate and bar examplesJeremy Magland 27 // Bending triplets (j the middle bead): energy kb/2 |x_i - 2 x_j + x_k|^2,
28 // with damping force -cb (v_i - 2 v_j + v_k) (1, -2, 1) on (i, j, k)
29 bi: Int32Array;
30 bj: Int32Array;
31 bk: Int32Array;
32 bkb: Float64Array;
33 bcb: Float64Array;
fc06d37Bead-and-spring percussion simulator: numbl-scripted setup, Verlet/Yoshida solver with exact damping, linear modes, browser appJeremy Magland 34 // Dashpots on relative velocity: F_i = c (v_j - v_i)
35 di: Int32Array;
36 dj: Int32Array;
37 dc: Float64Array;
38 friction: Float64Array; // n, F_i = -c0_i v_i (N s/m)
39 hits: Hit[];
40 listenBeads: Int32Array;
41 listenDir: [number, number, number]; // unit vector
42 duration: number; // s
43 sampleRate: number; // Hz, audio output
44 dt: number; // s; 0 = automatic
45 safety: number; // fraction of the stability limit used when dt is automatic
46 method: Method;
47 frameRate: number; // Hz, snapshots for animation and mode energies
48 modes: boolean; // compute linear transverse modes and track their energies
49}
51export interface SimProgress {
52 t: number;
53 duration: number;
54}
56export interface Modes {
57 freqs: Float64Array; // Hz, ascending
185968eRevert "Dome example: chaos that keeps its pitch..."Jeremy Magland 58 // psi: orthonormal eigenvectors of M^{-1/2} K M^{-1/2} over free beads,
59 // column-major (nFree x nModes)
fc06d37Bead-and-spring percussion simulator: numbl-scripted setup, Verlet/Yoshida solver with exact damping, linear modes, browser appJeremy Magland 60 psi: Float64Array;
185968eRevert "Dome example: chaos that keeps its pitch..."Jeremy Magland 61 free: Int32Array; // bead index of each row of psi
fc06d37Bead-and-spring percussion simulator: numbl-scripted setup, Verlet/Yoshida solver with exact damping, linear modes, browser appJeremy Magland 62}
64export interface SimResult {
65 audio: Float32Array; // listener displacement at sampleRate (m)
66 sampleRate: number;
67 dt: number;
68 substeps: number; // solver steps per audio sample
69 omegaMax: number; // rad/s, highest linearized frequency
70 frameTimes: Float64Array; // times of the energy records (s)
71 energy: Float64Array; // mechanical energy above the rest state at each frame (J)
72 animTimes: Float64Array; // times of the stored displacement snapshots (s)
73 animFrames: Float32Array[]; // displacement (3n) at each snapshot (m)
74 dissipated: Float64Array; // cumulative energy removed by damping (J)
75 // mode energies (nModes per frame, frame-major), present when modes were computed
76 modeEnergy: Float32Array | null;
77 residualForce: number; // max |F| on free beads at rest (N)
78 maxTension: number; // max spring force at rest (N)
79 energyDrift: number; // max relative change in E + dissipated after the last excitation
80 freqErrors: { hz: number; cents: number }[]; // integrator frequency error at a few frequencies
81 elapsedMs: number;
82 aborted: string | null; // reason if the run stopped early
83 warnings: string[];
84}