/ proof-of-concept / cymmodes
Sign in
proof-of-concept / cymmodes
cymmodes / src / model / simulator.ts
62 lines · 3.2 KBBlameHistoryRaw
1// The interface shared by the CPU and the GPU time loops, extended (relative to cymsimweb) with
2// modal drive and projection: a backend can start from a prescribed state, apply a distributed
3// harmonic force, and return snapshots of the state projected onto a set of transverse modes.
4export interface ChunkResult {
5 firstSample: number; // audio index of pressureFront[0]
6 pressureFront: Float32Array; // baffled Rayleigh pressure [Pa]
7 pressureBack: Float32Array; // diffracted back term [Pa]; unbaffled = front - back
8 frames: Float32Array[]; // displacement w at every node, captured every `movieEvery` audio samples
9 frameSamples: number[]; // audio sample index of each frame
10 proj: Float32Array[]; // modal snapshots (2 Nm each: q_m then qdot_m), every `projEvery` audio samples
11 projSamples: number[]; // audio sample index of each modal snapshot
12 trace: Float32Array; // one mode's coordinate q_m at every audio sample (empty when off)
13 traceBase: number; // audio sample index of trace[0]
16export interface HitState { peakForce: number; contactTime: number; velocity: number; height: number }
18export interface Diagnostics {
19 time: number; kinetic: number; membrane: number; bending: number; exciters: number; maxWoverH: number; hits: HitState[];
22/** A distributed transverse drive f_w(n, t) = fNode[n] * env(t) * sin(omega t), env a linear ramp
23 * over rampSteps sub-steps, cut off at stopStep. fNode is in Newtons per node. */
24export interface DriveParams {
25 fNode: Float64Array; // (N,) nodal force amplitudes on w
26 omega: number; // [rad/s]
27 rampSteps: number; // sub-steps of the linear onset ramp (>= 1)
28 stopStep: number; // first sub-step at which the drive is off
31/** Projection of the running state onto Nm transverse modes: q_m = sum_n phiM[m N + n] w_n and
32 * the same sum over the velocities. phiM is the mass-weighted mode matrix (mode-major), so with
33 * mass-normalised shapes the q_m are the modal coordinates. */
34export interface ProjectionSpec {
35 phiM: Float32Array; // (Nm, N) mode-major, phi_m(n) * Mw(n)
36 nModes: number;
37 every: number; // audio samples between snapshots
40export interface BackendOptions {
41 movieEvery?: number; // > 0 captures w every that many audio samples
42 drive?: DriveParams;
43 projection?: ProjectionSpec;
44 /** Mode whose coordinate is captured at the full audio rate (needs `projection`), so its true
45 * oscillation frequency, unlike the energy envelopes, can be read off an STFT. */
46 traceMode?: number;
49export interface SimulatorBackend {
50 readonly kind: "cpu" | "gpu";
51 readonly samplesDone: number;
52 /** Largest chunk (audio samples) runChunk accepts. */
53 readonly maxChunk: number;
54 /** Set the state before the run: q and v are (5 N) node-major (u, v, w, thx, thy). */
55 setState(q: Float64Array, v: Float64Array): void;
56 /** Advance by nSamples audio samples and return the pressure samples completed meanwhile. */
57 runChunk(nSamples: number): Promise<ChunkResult>;
58 diagnostics(): Promise<Diagnostics>;
59 /** Transverse displacement w at every node, for the plate view. */
60 displacement(): Promise<Float32Array>;
61 dispose(): void;
↑↓ move↵openescclose