// Set-up summary, energy and hit tables, and a short log. import type { SetupSummary } from "../model/setup.ts"; import type { Diagnostics } from "../model/simulator.ts"; const f = (x: number, d = 3) => (Number.isFinite(x) ? x.toFixed(d) : "-"); const e = (x: number) => (Number.isFinite(x) ? x.toExponential(2) : "-"); export function formatSummary(s: SetupSummary): string { const lines = [ `mesh: ${s.nodes} nodes, ${s.elements} triangles, ${s.dofs} DOFs`, `profile: height ${f(s.height * 1e3, 1)} mm, rim warp p-p ${f(s.rimWarp * 1e3, 2)} mm, ${s.dents} dents, h in [${f(s.hMin * 1e3, 2)}, ${f(s.hMax * 1e3, 2)}] mm, max |grad z0| = ${f(s.maxSlope)}${s.slopeWarning ? " (above the shallow-shell bound)" : ""}, mass ${f(s.mass)} kg`, `omega_max: element bound ${e(s.omegaMax)} rad/s (limiting element at r = ${f(s.limitingR)} m, h = ${f(s.limitingH * 1e3, 2)} mm), global ${e(s.omegaGlobal)} rad/s (${s.omegaGlobalIterations} power iterations${s.omegaGlobalConverged ? "" : ", did not converge"}); ${s.boundUsed} bound used`, `dt = ${e(s.dt)} s, ${s.substeps} sub-steps per sample, ${s.nSteps} steps`, ]; s.hits.forEach((h, k) => lines.push( `hit ${k} at t = ${f(h.time)} s: ${h.kind}, ${h.points}-point patch at r = ${f(h.r)} m, k = ${e(h.kTotal)} N/m^${f(h.alpha, 2)}, m = ${f(h.mass)} kg, v = ${f(h.velocity, 1)} m/s, energy ${f(h.energy, 2)} J, free contact ~ ${f(h.freeContact * 1e3, 2)} ms (direct excitation below ~${f(h.directBelow, 0)} Hz)${h.late ? " (after the end of the run)" : ""}`)); lines.push(`set-up took ${f(s.setupSeconds, 1)} s`); return lines.join("\n"); } export class Readouts { private readonly root: HTMLElement; private readonly energies: HTMLTableElement; private readonly hits: HTMLTableElement; private readonly logEl: HTMLDivElement; private lines: string[] = []; constructor(root: HTMLElement) { this.root = root; this.energies = document.createElement("table"); this.hits = document.createElement("table"); this.logEl = document.createElement("div"); this.logEl.className = "log"; root.append(this.energies, this.hits, this.logEl); this.energies.innerHTML = "