088be4cAn interactive tutorial on the Dirichlet problem, accuracy against costJeremy Magland 1// Figures for the two-dimensional labs: the computed field, and the pointwise
2// error beside it on a logarithmic colour scale, which is the only way to see
3// both the interior and the corners of an error that spans decades.
4import Field from '../../plot/Field.tsx'
5import type { Num } from '../../engine/types.ts'
6import { fmtErr } from '../onedim/panels.tsx'
8export interface Single2DOut {
9 names: string[]
10 ms: number
11 maxerr: Num
12 unknowns: number
13 x: number[]
14 y: number[]
15 U: Num[][]
16 Err: Num[][]
17}
19/** A signed field gets the diverging ramp; a one-signed field the sequential
20 * one, so that the whole colour range is used either way. */
21function signOf(z: Num[][]): 'div' | 'seq' {
22 let lo = Infinity
23 let hi = -Infinity
24 for (const row of z) {
25 for (const v of row) {
26 if (v == null || !isFinite(v)) continue
27 if (v < lo) lo = v
28 if (v > hi) hi = v
29 }
30 }
31 return lo < 0 && hi > 0 ? 'div' : 'seq'
32}
34/** Decades to span in an error picture: what the data actually covers. */
35function decadesOf(z: Num[][]): number {
36 let lo = Infinity
37 let hi = 0
38 for (const row of z) {
39 for (const v of row) {
40 if (v == null || !isFinite(v) || v <= 0) continue
41 if (v < lo) lo = v
42 if (v > hi) hi = v
43 }
44 }
45 if (!isFinite(lo) || hi <= 0) return 6
46 return Math.min(14, Math.max(3, Math.ceil(Math.log10(hi / lo))))
47}
49export function Fields2D({
50 data,
51 xDomain = [0, 1],
52 yDomain = [0, 1],
53 curves,
54}: {
55 data: Single2DOut
56 xDomain?: [number, number]
57 yDomain?: [number, number]
58 curves?: { x: number[]; y: number[]; color?: string }[]
59}) {
60 const emax = data.maxerr == null || !isFinite(data.maxerr) ? 1 : Math.log10(data.maxerr)
61 return (
62 <div className="figure-row">
63 <Field
64 z={data.U}
65 xDomain={xDomain}
66 yDomain={yDomain}
67 kind={signOf(data.U)}
68 title="computed solution"
69 curves={curves}
70 />
71 <Field
72 z={data.Err}
73 xDomain={xDomain}
74 yDomain={yDomain}
75 kind="log"
76 zmax={Math.ceil(emax)}
77 decades={decadesOf(data.Err)}
78 title={`|error|, largest ${fmtErr(data.maxerr)}`}
79 curves={curves}
80 />
81 </div>
82 )
83}