2546961Plate mechanics lab: Kirchhoff-Love plates solved by numbl in the browserJeremy Magland 1import type { MethodDefinition } from "./methods/types";
3/**
4 * Wall-time estimate for grid-based methods. This is a calibration, not
5 * physics: the plan (cell count, steps) comes from the method's plan function
6 * running in numbl; only the seconds-per-cell-step constant lives here, seeded
81f3b30Elliptical plates, a WebGPU time loop for the explicit method, and WAV exportJeremy Magland 7 * from the method definition and refined by each finished run. The GPU path of
8 * a method is calibrated separately: its cost is nearly independent of the
9 * cell count at the grids used here, so its per-cell-step rate is a stand-in
10 * that the measurements correct for the grid in use.
2546961Plate mechanics lab: Kirchhoff-Love plates solved by numbl in the browserJeremy Magland 11 */
12export class CostModel {
13 private us = new Map<string, number>();
14 private readonly overheadMs = 150;
81f3b30Elliptical plates, a WebGPU time loop for the explicit method, and WAV exportJeremy Magland 16 private key(method: MethodDefinition, gpu: boolean): string {
17 return gpu ? `${method.id}:gpu` : method.id;
81f3b30Elliptical plates, a WebGPU time loop for the explicit method, and WAV exportJeremy Magland 20 private rate(method: MethodDefinition, gpu: boolean): number {
21 return (
22 this.us.get(this.key(method, gpu)) ??
23 (gpu ? (method.gpu?.usPerCellStep ?? method.usPerCellStep) : method.usPerCellStep)
24 );
25 }
27 estimateMs(method: MethodDefinition, cellSteps: number, gpu = false): number {
28 return (cellSteps * this.rate(method, gpu)) / 1000 + this.overheadMs;
31 /** Blend a measurement in, weighting recent runs more. */
81f3b30Elliptical plates, a WebGPU time loop for the explicit method, and WAV exportJeremy Magland 32 observe(method: MethodDefinition, cellSteps: number, wallMs: number, gpu = false): void {
2546961Plate mechanics lab: Kirchhoff-Love plates solved by numbl in the browserJeremy Magland 33 if (cellSteps <= 0 || wallMs <= 0) return;
34 const measured = ((wallMs - this.overheadMs) * 1000) / cellSteps;
35 if (!Number.isFinite(measured) || measured <= 0) return;
81f3b30Elliptical plates, a WebGPU time loop for the explicit method, and WAV exportJeremy Magland 36 this.us.set(this.key(method, gpu), 0.5 * this.rate(method, gpu) + 0.5 * measured);
38}