/ tutorials / laplace-dirichlet
Sign in
tutorials / laplace-dirichlet
laplace-dirichlet / src / chapters / ch02 / chapter.ts
96 lines · 3.0 KBCodeBlameHistory
088be4cAn interactive tutorial on the Dirichlet problem, accuracy against costJeremy Magland 1import { createElement } from 'react'
2import type { Chapter } from '../../ui/types.ts'
3import driver from '../onedim/driver.m?raw'
4import fd2 from '../ch01/fd2.m?raw'
5import richardson from './richardson.m?raw'
6import text from './text.md?raw'
7import { Convergence, fmtErr, type SweepOut } from '../onedim/panels.tsx'
8import { KIND_CONTROL, NS_1D } from '../shared.ts'
10export const ch02: Chapter = {
11 id: 'limits',
12 nav: 'Second order to its limit',
13 part: 'One dimension',
14 title: 'Second order, to its limit',
15 blurb: 'Conditioning, the roundoff floor at about eight digits, and Richardson extrapolation.',
16 text,
17 labs: [
18 {
19 id: 'floor',
20 title: 'Refining until it stops helping',
21 caption:
22 'Nine resolutions from 16 to 262144 intervals. The last few take a second or two each; the whole sweep runs on request.',
23 driver,
24 script: fd2,
25 manual: true,
26 controls: [
27 KIND_CONTROL,
28 {
29 kind: 'slider',
30 key: 'nmax',
31 label: 'finest N',
32 values: [16384, 65536, 262144, 1048576],
33 min: 0,
34 max: 3,
35 format: (v) => String(v),
36 },
37 ],
38 defaults: { kind: 'smooth', mode: 'sweep', ns: [], nmax: 262144, nmaxs: [1e9], timed: 1 },
39 derive: (p) => ({
40 ...p,
41 ns: [16, 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576].filter((n) => n <= Number(p.nmax)),
42 }),
43 render: (d: SweepOut) =>
44 createElement(Convergence, {
45 data: d,
46 style: {
47 slots: ['fd2'],
48 refs: [
49 { p: -2, label: 'slope −2: discretisation' },
50 { p: 2, label: 'slope +2: roundoff × κ(A)', at: [1e3, 2e-13] },
51 ],
52 },
53 height: 340,
54 }),
55 summary: (d: SweepOut) => {
56 const es = d.E[0]
57 let bi = 0
58 es.forEach((v, i) => {
59 if (v != null && (es[bi] == null || v < (es[bi] as number))) bi = i
60 })
61 return [
62 { label: 'best error', value: fmtErr(es[bi]) },
63 { label: 'at N', value: String(d.ns[bi]) },
64 ]
65 },
66 },
67 {
68 id: 'richardson',
69 title: 'Two second-order solves, one fourth-order answer',
70 caption: 'Change the manufactured solution to lowreg and watch the gain evaporate.',
71 driver,
72 script: richardson,
73 editorOpen: true,
74 controls: [KIND_CONTROL],
75 defaults: { kind: 'smooth', mode: 'sweep', ns: NS_1D, nmaxs: [1e9, 1e9], timed: 0 },
76 render: (d: SweepOut) =>
77 createElement(Convergence, {
78 data: d,
79 style: {
80 slots: ['fd2', 'fd4'],
81 refs: [
82 { p: -2, label: 'slope −2' },
83 { p: -4, label: 'slope −4' },
84 ],
85 },
86 }),
87 summary: (d: SweepOut) => {
88 const q = d.orders[1]?.[d.orders[1].length - 1]
89 return [
90 { label: 'extrapolated error', value: fmtErr(d.E[1]?.[d.E[1].length - 1]) },
91 { label: 'observed order', value: q == null ? '--' : q.toFixed(2) },
92 ]
93 },
94 },
95 ],
↑↓ move↵openescclose