concept-collection / turing-surface-cache
turing-surface-cache / src / mgpu / registry.ts
121 lines · 4.3 KBBlameHistoryRaw
1/**
2 * The available models: their MATLAB source, and the metadata the host owns.
3 *
4 * A model's *algorithm* lives in its .m file. Everything around it lives here:
5 * the parameter names the .m may take as arguments, their defaults and slider
6 * ranges, which grid fields to render, and the dealiasing degree. The .m
7 * declares nothing about these — it just names the parameters it wants, and
8 * `CompiledModel` matches each against this table.
9 *
10 * Trimmed from turing-surface: the three flux-form models ship (Schnakenberg,
11 * Brusselator, Allen-Cahn); the 12-transform Algorithm-4 reference does not,
12 * since it solves the same equations as Schnakenberg and would only duplicate
13 * cache entries under different hashes. The discrete parameter choices the
14 * app actually offers live in src/cache/options.ts; the min/max/step here are
15 * only the numeric bounds.
16 *
17 * Naming convention, documented in each .m:
18 * `u`, `v`, ... grid fields the model computes and the app renders
19 * `U`, `V`, ... the corresponding spectral state (uppercase)
20 */
21import schnakenbergSource from '../../models/schnakenberg.m?raw';
22import brusselatorSource from '../../models/brusselator.m?raw';
23import allencahnSource from '../../models/allencahn.m?raw';
25export type Params = Record<string, number>;
27/** A tunable scalar the .m may take as an argument. */
28export interface ParamSpec {
29 key: string;
30 label: string;
31 value: number;
32 min: number;
33 max: number;
34 step: number;
35 /**
36 * This parameter is a random seed: its value picks a draw and means nothing
37 * on its own, so the UI offers a button that jumps to another one rather
38 * than a box to type a number into. `min`/`max` still bound what the button
39 * picks.
40 */
41 reseed?: boolean;
44export interface MModel {
45 key: string;
46 label: string;
47 blurb: string;
48 /** Grid fields to render, one panel each. */
49 species: string[];
50 /** Spectral state names the .m advances. */
51 state: string[];
52 params: ParamSpec[];
53 /** Polynomial degree of the reaction in the fields, for grid dealiasing. */
54 pdeg: number;
55 /** Amplitude of the seeded perturbation handed to `init`. */
56 seedAmp: number;
57 /** MATLAB source — the algorithm itself. */
58 source: string;
61/** Spectral state names follow the grid-field names, uppercased. */
62const stateFor = (species: string[]): string[] => species.map((s) => s.toUpperCase());
64const schnakenberg: MModel = {
65 key: 'schnakenberg',
66 label: 'Schnakenberg',
67 blurb: 'Turing spots.',
68 species: ['u', 'v'],
69 state: stateFor(['u', 'v']),
70 params: [
71 { key: 'a', label: 'a', value: 0.1, min: 0.01, max: 0.5, step: 0.01 },
72 { key: 'b', label: 'b', value: 0.9, min: 0.1, max: 2, step: 0.05 },
73 { key: 'D1', label: 'D₁', value: 4e-4, min: 1e-5, max: 5e-3, step: 1e-5 },
74 { key: 'D2', label: 'D₂', value: 8e-3, min: 1e-4, max: 5e-2, step: 1e-4 },
75 { key: 'dt', label: 'dt', value: 0.05, min: 0.005, max: 0.5, step: 0.005 },
76 ],
77 pdeg: 3,
78 seedAmp: 1e-2,
79 source: schnakenbergSource,
80};
82const brusselator: MModel = {
83 key: 'brusselator',
84 label: 'Brusselator',
85 blurb: 'Turing stripes and spots.',
86 species: ['u', 'v'],
87 state: stateFor(['u', 'v']),
88 params: [
89 { key: 'A', label: 'A', value: 3, min: 0.5, max: 6, step: 0.1 },
90 { key: 'B', label: 'B', value: 9, min: 1, max: 15, step: 0.25 },
91 { key: 'D1', label: 'D₁', value: 3.33e-3, min: 1e-4, max: 2e-2, step: 1e-4 },
92 { key: 'D2', label: 'D₂', value: 1.67e-2, min: 1e-3, max: 1e-1, step: 1e-3 },
93 { key: 'dt', label: 'dt', value: 0.02, min: 0.002, max: 0.1, step: 0.002 },
94 ],
95 pdeg: 3,
96 seedAmp: 1e-2,
97 source: brusselatorSource,
98};
100const allencahn: MModel = {
101 key: 'allencahn',
102 label: 'Allen–Cahn',
103 blurb: 'One species: interfaces form, then coarsen.',
104 species: ['u'],
105 state: stateFor(['u']),
106 params: [
107 { key: 'eps2', label: 'ε²', value: 1e-3, min: 1e-4, max: 1e-2, step: 1e-4 },
108 { key: 'dt', label: 'dt', value: 0.02, min: 0.002, max: 0.2, step: 0.002 },
109 ],
110 pdeg: 3,
111 seedAmp: 1e-2,
112 source: allencahnSource,
113};
115export const mModels: MModel[] = [schnakenberg, brusselator, allencahn];
117export const mModelByKey = (key: string): MModel | undefined =>
118 mModels.find((m) => m.key === key);
120export const defaultParams = (m: MModel): Params =>
121 Object.fromEntries(m.params.map((p) => [p.key, p.value]));