1import type { MethodDefinition } from "./types";
2import {
3 FREE_EDGE_EQUATIONS,
4 GOVERNING_EQUATIONS,
5 RADIATION_EQUATIONS,
6 STRESS_EQUATIONS,
7} from "./common";
9export const IMPLICIT_METHOD: MethodDefinition = {
10 id: "implicit",
11 name: "Implicit finite differences",
12 shortName: "Implicit FD",
13 summary:
14 "Same stencils as the explicit scheme, stiffness averaged in time; one sparse factorization, no step limit.",
15 solverFunction: "plate_implicit",
16 planFunction: "plate_implicit_plan",
17 supports: {
18 bc: ["simply-supported", "clamped", "free"],
19 excitation: ["impulse", "harmonic"],
20 audio: "clip",
21 },
22 readingOrder: [
23 "plate_implicit.m",
24 "plate_implicit_plan.m",
25 "plate_matrices.m",
26 "plate_rigid_modes.m",
27 "plate_curvature_free.m",
28 "plate_setup.m",
29 "plate_force_time.m",
30 "plate_force_footprint.m",
31 "plate_stress.m",
32 "plate_pad.m",
33 "plate_curvature.m",
34 "plate_listener.m",
35 "plate_spectrum.m",
36 "plate_result_schema.m",
37 ],
38 equations: [
39 ...GOVERNING_EQUATIONS,
40 {
41 tex: String.raw`\frac{w^{n+1} - 2w^n + w^{n-1}}{\Delta t^2} + \sigma_0\frac{w^{n+1} - w^{n-1}}{\Delta t} - \sigma_1 \mathsf L\frac{w^{n+1} - w^{n-1}}{\Delta t} + \kappa^2 \mathsf B\left(\theta w^{n+1} + (1-2\theta) w^n + \theta w^{n-1}\right) = \frac{F^n s}{\mu}`,
42 caption:
43 "Theta scheme: the biharmonic term is averaged over three time levels. L and B are the sparse Laplacian and biharmonic matrices built from the same stencils as the explicit scheme.",
44 },
45 {
46 tex: String.raw`\mathbf A\, w^{n+1} = \mathbf C\, w^n - \mathbf A_{\mathrm{old}}\, w^{n-1} + \frac{\Delta t^2}{\mu} F^n s, \qquad \mathbf A = (1+\sigma_0\Delta t)\mathbf I - \sigma_1\Delta t\,\mathsf L + \theta\kappa^2\Delta t^2\,\mathsf B`,
47 caption:
48 "One linear system per step with a constant symmetric positive definite matrix: factor A once by sparse Cholesky, then two triangular solves per step.",
49 },
50 {
51 tex: String.raw`\theta \ge \tfrac14 \;\Rightarrow\; \text{stable for every } \Delta t, \qquad \frac{T_{\text{num}}}{T} \approx 1 + \frac{(\omega\Delta t)^2}{12} \;\; (\theta = \tfrac14)`,
52 caption:
53 "No stability limit, so the step is chosen for accuracy. The price is period elongation: modes near half the sample rate run slow by tens of percent unless several steps per sample are used.",
54 },
55 ...FREE_EDGE_EQUATIONS,
56 ...STRESS_EQUATIONS,
57 ...RADIATION_EQUATIONS,
58 ],
59 validity: [
60 "Second-order truncation error in dx and dy, identical to the explicit scheme, since the spatial stencils are the same.",
61 "Second order in dt but dispersive: high modes are detuned rather than unstable. Two steps per sample keeps a 10 kHz mode within about 4 percent.",
62 "The probe is snapped to the nearest interior grid node; stress fields are evaluated only at the saved frames.",
63 "Cost per step is a sparse triangular solve pair, about a millisecond for a 61 x 41 grid in the browser, independent of the plate stiffness.",
64 "Audio covers only the simulated window.",
65 "Free edges: the moment and shear conditions are natural conditions of a discrete bending energy, met to first order at the boundary and second order inside; the three rigid-body motions are removed after every step, so the displacement is that of a plate on soft supports, not one drifting in space.",
66 ],
67 durationOf: (spec) => spec.implicit.duration,
68 gridOf: (spec) => [spec.implicit.nx, spec.implicit.ny],
69 settingsKey: "implicit",
70 usPerCellStep: 1.0,
71};