/ proof-of-concept / bead-percussion
Sign in
proof-of-concept / bead-percussion
bead-percussion / src / sim / twin.ts
48 lines · 1.5 KBCodeBlameHistory
95f2216Minimal chaos example and perturbed-twin chaos test with separation plot and growth-rate fitJeremy Magland 1// Perturbed twin: rerun with every hit scaled by (1 + eps) and measure, at
2// each frame, the largest difference in any bead coordinate, relative to the
ac09b0fDefault damping: every mode falls 60 dB in 2.5 s; examples at 2.5 s; twin separation relative to recent displacement; stronger chaos strikeJeremy Magland 3// largest displacement of the original run over the preceding 50 ms (so that
4// the measure stays meaningful while the motion decays).
6import { simulate } from "./solver";
7import type { BeadSystem } from "./types";
9export function runTwin(
10 sys: BeadSystem,
11 saved: Float64Array[], // positions of the original run at each frame
12 dt: number,
13 eps: number,
14 onProgress?: (t: number) => void
15): { audio: Float32Array; sep: Float64Array } {
17 let d = 0;
18 for (let q = 0; q < x.length; q++) d = Math.max(d, Math.abs(x[q] - sys.pos0[q]));
19 return d;
20 });
21 const win = Math.max(1, Math.round(0.05 * sys.frameRate));
22 const scale = disp.map((_, f) => Math.max(...disp.slice(Math.max(0, f - win), f + 1)));
95f2216Minimal chaos example and perturbed-twin chaos test with separation plot and growth-rate fitJeremy Magland 23 const sep = new Float64Array(saved.length);
24 const f = 1 + eps;
25 const r = simulate(
26 {
27 ...sys,
28 dt,
29 hits: sys.hits.map(h => ({
30 ...h,
31 velocity: [h.velocity[0] * f, h.velocity[1] * f, h.velocity[2] * f],
32 force: [h.force[0] * f, h.force[1] * f, h.force[2] * f],
33 })),
34 },
35 {
36 maxAnimBytes: 0,
37 onProgress,
38 onFrame: (fr, _t, x) => {
39 const y = saved[fr];
40 if (!y) return;
41 let d = 0;
42 for (let q = 0; q < x.length; q++) d = Math.max(d, Math.abs(x[q] - y[q]));
45 }
46 );
47 return { audio: r.audio, sep };
↑↓ move↵openescclose