/ proof-of-concept / bead-percussion
Sign in
proof-of-concept / bead-percussion
bead-percussion / src / sim / types.ts
80 lines · 3.2 KBCodeBlameHistory
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;
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;
27 // Dashpots on relative velocity: F_i = c (v_j - v_i)
28 di: Int32Array;
29 dj: Int32Array;
30 dc: Float64Array;
31 friction: Float64Array; // n, F_i = -c0_i v_i (N s/m)
33 relax: boolean; // move the beads to static equilibrium (springs + load) before simulating
35 listenBeads: Int32Array;
36 listenDir: [number, number, number]; // unit vector
37 duration: number; // s
38 sampleRate: number; // Hz, audio output
39 dt: number; // s; 0 = automatic
40 safety: number; // fraction of the stability limit used when dt is automatic
41 method: Method;
42 frameRate: number; // Hz, snapshots for animation and mode energies
43 modes: boolean; // compute linear transverse modes and track their energies
46export interface SimProgress {
47 t: number;
48 duration: number;
51export interface Modes {
52 freqs: Float64Array; // Hz, ascending
54 // freedom in dof, column-major (dof.length x nModes)
57 kind: "transverse" | "full"; // z motion of a flat net only, or all motion
60export interface SimResult {
61 audio: Float32Array; // listener displacement at sampleRate (m)
62 sampleRate: number;
63 dt: number;
64 substeps: number; // solver steps per audio sample
65 omegaMax: number; // rad/s, highest linearized frequency
66 frameTimes: Float64Array; // times of the energy records (s)
67 energy: Float64Array; // mechanical energy above the rest state at each frame (J)
68 animTimes: Float64Array; // times of the stored displacement snapshots (s)
69 animFrames: Float32Array[]; // displacement (3n) at each snapshot (m)
70 dissipated: Float64Array; // cumulative energy removed by damping (J)
71 // mode energies (nModes per frame, frame-major), present when modes were computed
72 modeEnergy: Float32Array | null;
73 residualForce: number; // max |F| on free beads at rest (N)
74 maxTension: number; // max spring force at rest (N)
75 energyDrift: number; // max relative change in E + dissipated after the last excitation
76 freqErrors: { hz: number; cents: number }[]; // integrator frequency error at a few frequencies
77 elapsedMs: number;
78 aborted: string | null; // reason if the run stopped early
79 warnings: string[];
↑↓ move↵openescclose