import type { Chapter } from '../../ui/types.ts' import type { Params } from '../../engine/types.ts' import driver from '../membrane/driver.m?raw' import script from './drum.m?raw' import text from './text.md?raw' import { OrdersPanels, SCHEME, STRIKE_CONTROL, StrikePanels, strikeParams, strikeSummary, type OrdersOut, type StrikeOut, } from '../membrane/panels.tsx' import { fmtCents } from '../common/panels.tsx' /** each scheme at a Courant number just inside its own stability limit */ const LAM: Record = { fd2: 0.7, fd4: 0.6, fd44: 0.7 } export const ch05: Chapter = { id: 'order', nav: 'Fewer points per wavelength', part: 'Drums', title: 'Fewer points per wavelength', blurb: 'Fourth-order stencils in space, in time, and in both, measured by pitch error against cost, and why raising the order in space alone buys little.', text, labs: [ { id: 'orders', title: 'Three schemes, three test modes', caption: 'Each scheme runs at a Courant number just inside its own stability limit. This lab takes several seconds, so it waits for the run button.', driver, script, controls: [], defaults: {}, derive: () => ({ mode: 'orders', Ns: [16, 24, 32, 48, 64, 96], schemes: ['fd2', 'fd4', 'fd44'], lams: [LAM.fd2, LAM.fd4, LAM.fd44], modes: [4, 3, 9, 2, 14, 1], }), manual: true, editorOpen: true, render: (d: OrdersOut) => , summary: (d: OrdersOut) => d.schemes.map((s, k) => ({ label: `${s}, N = ${d.Ns[d.Ns.length - 1]}`, value: fmtCents(d.worst[k][d.Ns.length - 1]), })), }, { id: 'listen', title: 'The drum again, by each scheme', caption: 'Chapter 4’s drum on the same grid with each scheme. On a coarse grid the fourth-order scheme is much closer to the exact sound.', driver, script, controls: [ { kind: 'select', key: 'scheme', label: 'scheme', options: Object.entries(SCHEME).map(([k, v]) => ({ value: k, label: v.label })), }, { kind: 'slider', key: 'N', label: 'grid intervals N', min: 0, max: 0, values: [24, 32, 48] }, STRIKE_CONTROL, ], defaults: { scheme: 'fd44', N: 32, at: 'off' }, derive: (p: Params) => strikeParams({ ...p, lam: LAM[String(p.scheme)] }, String(p.scheme)), render: (d: StrikeOut, p: Params) => , summary: strikeSummary, }, ], }