// Twin separation summary. Usage: tsx tests/twin.ts script.m duration [eps] import { readFileSync, readdirSync } from "fs"; import { runScript } from "../src/sim/runScript"; import { simulate } from "../src/sim/solver"; import { runTwin } from "../src/sim/twin"; import { growthRate } from "../src/sim/analysis"; const helpers = readdirSync("matlab/helpers").map(name => ({ name, source: readFileSync("matlab/helpers/" + name, "utf8") })); const { sys } = runScript(readFileSync(process.argv[2], "utf8"), helpers, () => {}); sys.duration = Number(process.argv[3]); const eps = Number(process.argv[4] ?? 1e-9); const saved: Float64Array[] = []; const a = simulate(sys, { onFrame: (_f, _t, x) => saved.push(x.slice()) }); const { sep } = runTwin(sys, saved, a.dt, eps); const out: string[] = []; const step = Math.max(1, Math.floor(sep.length / 14)); for (let i = 0; i < sep.length; i += step) out.push(`${a.frameTimes[i].toFixed(2)}:${Math.log10(sep[i] + 1e-30).toFixed(1)}`); const g = growthRate(a.frameTimes, sep, eps); console.log(`rate ${g?.toFixed(0) ?? "-"} drift ${a.energyDrift.toExponential(1)} | log10 sep: ${out.join(" ")}`);