1/**
2 * The available geometries: their MATLAB source, and the metadata the host owns.
3 *
4 * The same split as the model registry — the .m is the shape, everything around
5 * it (parameter names, defaults, slider ranges) lives here, and the .m declares
6 * which of them it wants by naming them as arguments.
7 *
8 * `sphere` is first and is not merely one entry among several: it is the case
9 * the whole project is checked against, where the surface is exactly the unit
10 * sphere and every result must match turing-sphere.
11 */
12import sphereSource from '../../geometries/sphere.m?raw';
13import ellipsoidSource from '../../geometries/ellipsoid.m?raw';
14import peanutSource from '../../geometries/peanut.m?raw';
15import bumpySource from '../../geometries/bumpy.m?raw';
16import blobSource from '../../geometries/blob.m?raw';
17import type { ParamSpec, Params } from '../mgpu/registry.ts';
19export interface MGeometry {
20 key: string;
21 label: string;
22 blurb: string;
23 params: ParamSpec[];
24 /** MATLAB source — the shape itself. */
25 source: string;
26}
28const sphere: MGeometry = {
29 key: 'sphere',
30 label: 'Sphere',
31 blurb: 'The unit sphere — the reference case.',
32 params: [],
33 source: sphereSource,
34};
36const ellipsoid: MGeometry = {
37 key: 'ellipsoid',
38 label: 'Ellipsoid',
39 blurb: 'The sphere with each axis scaled independently.',
40 params: [
41 { key: 'ax', label: 'a', value: 1.5, min: 0.2, max: 3, step: 0.05 },
42 { key: 'ay', label: 'b', value: 1, min: 0.2, max: 3, step: 0.05 },
43 { key: 'az', label: 'c', value: 0.6, min: 0.2, max: 3, step: 0.05 },
44 ],
45 source: ellipsoidSource,
46};
48const peanut: MGeometry = {
49 key: 'peanut',
50 label: 'Peanut',
51 blurb: 'A dumbbell pinched at the equator.',
52 params: [
53 { key: 'waist', label: 'waist', value: 0.6, min: 0, max: 0.9, step: 0.05 },
54 { key: 'stretch', label: 'stretch', value: 0.6, min: 0, max: 2, step: 0.05 },
55 ],
56 source: peanutSource,
57};
59const bumpy: MGeometry = {
60 key: 'bumpy',
61 label: 'Bumpy',
62 blurb: 'Equatorial lobes plus a pear-shaped offset.',
63 params: [
64 { key: 'amp', label: 'amp', value: 0.3, min: 0, max: 0.6, step: 0.02 },
65 { key: 'nlobe', label: 'lobes', value: 5, min: 1, max: 12, step: 1 },
66 { key: 'pear', label: 'pear', value: 0.15, min: -0.4, max: 0.4, step: 0.05 },
67 ],
68 source: bumpySource,
69};
71const blob: MGeometry = {
72 key: 'blob',
73 label: 'Blob',
74 blurb: 'The sphere warped by a smooth random function — a fresh shape per seed.',
75 params: [
76 { key: 'amp', label: 'amp', value: 0.5, min: 0, max: 0.8, step: 0.05 },
77 { key: 'scale', label: 'λ', value: 1, min: 0.5, max: 3, step: 0.1 },
78 { key: 'seed', label: 'seed', value: 1, min: 0, max: 9999, step: 1, reseed: true },
79 ],
80 source: blobSource,
81};
83export const mGeometries: MGeometry[] = [sphere, ellipsoid, peanut, bumpy, blob];
85export const mGeometryByKey = (key: string): MGeometry | undefined =>
86 mGeometries.find((g) => g.key === key);
88export const defaultGeometryParams = (g: MGeometry): Params =>
89 Object.fromEntries(g.params.map((p) => [p.key, p.value]));
91/** The geometry every result is checked against, and what a caller who names
92 * none gets: the case where the solver is exact. */
93export const SPHERE_KEY = 'sphere';
95/** What the app and the benchmark start on. Not the sphere: this project
96 * exists for the other shapes, and opening on the reference case would hide
97 * the one thing it adds. */
98export const DEFAULT_GEOMETRY_KEY = 'ellipsoid';