import { createElement, Fragment } from 'react' import type { Chapter } from '../../ui/types.ts' import driver from '../twodim/driver.m?raw' import script from './highorder2d.m?raw' import text from './text.md?raw' import { Fields2D, type Single2DOut } from '../twodim/panels.tsx' 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', 'fd4', 'spectral'] export const ch07: Chapter = { id: 'high-order-2d', nav: 'Sixth order for the same price', part: 'Two dimensions', title: 'Sixth order for the same price', blurb: 'The compact nine-point stencil, Chebyshev collocation on the square, and a million-fold difference in unknowns.', text, labs: [ { id: 'fields', title: 'The same grid, three stencils', caption: 'Watch the error scale on the right, not the picture on the left: at N = 32 they differ by ten orders of magnitude.', driver, script, controls: [ EXACT2D_CONTROL, { kind: 'select', key: 'mid', label: 'method', options: [ { value: 1, label: '5-point' }, { value: 2, label: '9-point compact' }, { value: 3, label: 'Chebyshev' }, ], }, { kind: 'slider', key: 'N', label: 'N', values: [8, 16, 24, 32, 48, 64], min: 8, max: 64 }, { kind: 'slider', key: 'par', label: 'shape parameter', min: 1, max: 8, step: 1, format: (v) => String(v) }, ], defaults: { kind: 'expsin', par: 1, mode: 'single', mid: 2, N: 32, maxpix: 97 }, render: (d: Single2DOut) => createElement(Fields2D, { data: d }), summary: (d: Single2DOut) => [ { label: 'unknowns', value: String(d.unknowns) }, { label: 'max error', value: fmtErr(d.maxerr) }, ], }, { id: 'sweep', title: 'Order six against order two', caption: 'Chebyshev is capped at N = 64, which is already 3969 unknowns and machine precision.', driver, script, manual: true, editorOpen: true, controls: [EXACT2D_CONTROL, { kind: 'slider', key: 'par', label: 'shape parameter', min: 1, max: 8, step: 1, format: (v) => String(v) }], defaults: { kind: 'expsin', par: 1, mode: 'sweep', ns: [8, 16, 32, 64, 128, 256, 512], nmaxs: [512, 512, 64], timed: 1, }, render: (d: SweepOut) => createElement( Fragment, null, createElement(Convergence, { key: 'c', data: d, style: { slots: SLOTS, refs: [ { p: -2, label: 'slope −2' }, { p: -6, label: 'slope −6' }, ], }, height: 340, }), createElement(WorkPrecision, { key: 'w', data: d, style: { slots: SLOTS }, height: 340 }), ), summary: (d: SweepOut) => [ { label: 'best 5-point', value: fmtErr(Math.min(...(d.E[0].filter((v) => v != null) as number[]))) }, { label: 'best 9-point', value: fmtErr(Math.min(...(d.E[1].filter((v) => v != null) as number[]))) }, { label: 'best Chebyshev', value: fmtErr(Math.min(...(d.E[2].filter((v) => v != null) as number[]))) }, ], }, ], }