import { createElement, Fragment } from 'react' import type { Chapter } from '../../ui/types.ts' import driver from '../twodim/driver.m?raw' import script from './fastpoisson.m?raw' import text from './text.md?raw' import { Convergence, WorkPrecision, fmtErr, type SweepOut } from '../onedim/panels.tsx' import { EXACT2D_CONTROL } from '../shared.ts' import type { MethodKey } from '../../plot/palette.ts' const SLOTS: MethodKey[] = ['fd2', 'fast'] export const ch06: Chapter = { id: 'fast-poisson', nav: 'The fast Poisson solver', part: 'Two dimensions', title: 'The fast Poisson solver', blurb: 'The same discretisation, diagonalised by the sine transform: a million unknowns in half a second.', text, labs: [ { id: 'compare', title: 'Elimination against the sine transform', caption: 'Both curves are the same discretisation, so where they overlap they lie exactly on top of each other; the sine transform is drawn dashed so that the dense solve shows through. The dense solve stops at N = 32 because that is where it stops being possible.', driver, script, manual: true, editorOpen: true, controls: [ EXACT2D_CONTROL, { kind: 'slider', key: 'nmax', label: 'finest N for the fast solver', values: [128, 256, 512, 1024, 2048], min: 0, max: 4, format: (v) => String(v), }, ], defaults: { kind: 'expsin', par: 1, mode: 'sweep', ns: [], nmax: 512, nmaxs: [32, 512], timed: 1, }, derive: (p) => ({ ...p, ns: [8, 16, 32, 64, 128, 256, 512, 1024, 2048].filter((n) => n <= Number(p.nmax)), nmaxs: [32, Number(p.nmax)], }), render: (d: SweepOut) => createElement( Fragment, null, createElement(Convergence, { key: 'c', data: d, style: { slots: SLOTS, dashes: [undefined, '7 5'], refs: [{ p: -2, label: 'slope −2' }] }, }), createElement(WorkPrecision, { key: 'w', data: d, style: { slots: SLOTS, dashes: [undefined, '7 5'] } }), ), summary: (d: SweepOut) => { const last = d.E[1].length - 1 return [ { label: 'finest error', value: fmtErr(d.E[1][last]) }, { label: 'in', value: `${(d.T[1][last] ?? 0).toFixed(0)} ms` }, ] }, }, ], }