/ proof-of-concept / bead-percussion
Sign in
proof-of-concept / bead-percussion
bead-percussion / src / sim / runScript.ts
49 lines · 1.8 KBCodeBlameHistory
fc06d37Bead-and-spring percussion simulator: numbl-scripted setup, Verlet/Yoshida solver with exact damping, linear modes, browser appJeremy Magland 1// Run a numbl script with the bp_* helpers on its path, and turn its `sys`
2// struct into a BeadSystem. Shared by the browser worker and the tests.
4import { executeCode, RTV } from "numbl";
5import { parseSystem } from "./parse";
8import type { BeadSystem } from "./types";
10export interface HelperFile {
11 name: string;
12 source: string;
15export function runScript(
16 source: string,
17 helpers: HelperFile[],
18 onOutput: (text: string) => void
19): { sys: BeadSystem; warnings: string[] } {
20 const result = executeCode(source, { onOutput, displayResults: true }, helpers, "script.m");
21 return parseSystem(result.variableValues.sys);
25// under the load). Returns notes for the run report.
26export function prepareSystem(sys: BeadSystem): string[] {
27 const notes: string[] = [];
28 if (sys.relax) {
29 const r = relax(sys);
30 let sag = 0;
31 for (let q = 0; q < r.pos.length; q++) sag = Math.max(sag, Math.abs(r.pos[q] - sys.pos0[q]));
32 sys.pos0 = r.pos;
33 notes.push(
34 `Relaxed to equilibrium in ${r.iterations} iterations (largest net force ${r.residual.toExponential(1)} N; beads moved up to ${(sag * 1000).toPrecision(3)} mm).`
35 );
36 }
37 return notes;
41export const numblEig: SymEig = (A, n) => {
42 const r = executeCode("[V, D] = eig(A); d = diag(D);", {
43 initialVariableValues: { A: RTV.tensor(A, [n, n]) },
44 });
45 const V = r.variableValues.V as unknown as { data: Float64Array };
46 const d = r.variableValues.d as unknown as { data: Float64Array } | number;
47 const values = typeof d === "number" ? Float64Array.of(d) : d.data;
48 return { values, vectors: V.data ?? Float64Array.of(1) };
49};
↑↓ move↵openescclose