/ proof-of-concept / plate-dynamics-lab
Sign in
proof-of-concept / plate-dynamics-lab
plate-dynamics-lab / packages / core / src / spec / presets.ts
386 lines · 14.5 KBBlameHistoryRaw
1import type { Damping, Material, PlateGeometry, ProblemSpec, ThreadMaterial } from "./types";
3/**
4 * Material presets. Values are room-temperature handbook figures for the named
5 * alloy (ASM Handbook, MatWeb, Copper Development Association) and are typical
6 * rather than certified: real stock varies by a few percent in E and rho.
7 * The damping values are illustrative starting points in the two-parameter
8 * loss model, not measurements; damping in a real plate depends heavily on the
9 * mounting, which is part of what this lab is about.
10 */
11export interface MaterialPreset {
12 id: string;
13 material: Material;
14 damping: Damping;
15 /** Where the numbers come from and what they do not capture */
16 source: string;
19export const MATERIAL_PRESETS: MaterialPreset[] = [
20 {
21 id: "a36-steel",
22 material: { name: "A36 structural steel", E: 200e9, nu: 0.26, rho: 7850 },
23 damping: { sigma0: 1.0, sigma1: 0.005 },
24 source: "ASTM A36 hot-rolled plate; E and nu typical of low-carbon steel.",
25 },
26 {
27 id: "304-stainless",
28 material: { name: "304 stainless steel", E: 193e9, nu: 0.29, rho: 8000 },
29 damping: { sigma0: 1.0, sigma1: 0.005 },
30 source: "Annealed 304 sheet, typical values.",
31 },
32 {
33 id: "6061-t6",
34 material: { name: "6061-T6 aluminium", E: 68.9e9, nu: 0.33, rho: 2700 },
35 damping: { sigma0: 1.2, sigma1: 0.006 },
36 source: "6061-T6 sheet and plate, typical values.",
37 },
38 {
39 id: "c260-brass",
40 material: { name: "C260 cartridge brass", E: 110e9, nu: 0.375, rho: 8530 },
41 damping: { sigma0: 1.0, sigma1: 0.006 },
42 source: "70/30 brass, half-hard sheet, typical values.",
43 },
44 {
45 id: "ti-6al-4v",
46 material: { name: "Ti-6Al-4V titanium", E: 113.8e9, nu: 0.342, rho: 4430 },
47 damping: { sigma0: 0.8, sigma1: 0.004 },
48 source: "Annealed Grade 5 titanium sheet, typical values.",
49 },
50 {
51 id: "b20-bronze",
52 material: { name: "B20 bell bronze (CuSn20)", E: 105e9, nu: 0.34, rho: 8800 },
53 damping: { sigma0: 0.4, sigma1: 0.002 },
54 source:
55 "Bell and cymbal bronze with about 20% tin; E ranges 100 to 110 GPa depending on the casting and working. Low damping is what makes it ring.",
56 },
57 {
58 id: "b8-bronze",
59 material: { name: "B8 bronze (CuSn8)", E: 110e9, nu: 0.34, rho: 8800 },
60 damping: { sigma0: 0.5, sigma1: 0.0025 },
61 source: "8% tin bronze used for cymbals and as phosphor bronze sheet; typical values.",
62 },
63 {
64 id: "1095-spring-steel",
65 material: { name: "1095 spring steel (bar stock)", E: 205e9, nu: 0.29, rho: 7850 },
66 damping: { sigma0: 0.5, sigma1: 0.003 },
67 source:
68 "High-carbon steel used for glockenspiel and chime bars; E and rho typical of carbon steel.",
69 },
70];
72export interface PlatePreset {
73 id: string;
74 name: string;
75 plate: PlateGeometry;
76 /** Notes on what this stands in for */
77 note: string;
80const inch = 0.0254;
82export const PLATE_PRESETS: PlatePreset[] = [
83 {
84 id: "sheet-300x200x2",
85 name: "300 x 200 x 2 mm sheet",
86 plate: { shape: "rectangle", Lx: 0.3, Ly: 0.2, h: 0.002 },
87 note: "A common cut-to-size sheet; the default problem.",
88 },
89 {
90 id: "sheet-12x12x1-8in",
91 name: "12 x 12 x 1/8 in plate",
92 plate: { shape: "rectangle", Lx: 12 * inch, Ly: 12 * inch, h: inch / 8 },
93 note: "Square stock in imperial sizes.",
94 },
95 {
96 id: "sheet-500x300x1",
97 name: "500 x 300 x 1 mm sheet",
98 plate: { shape: "rectangle", Lx: 0.5, Ly: 0.3, h: 0.001 },
99 note: "Thin and large: many modes below 20 kHz, expensive for finite differences, and the one where the self-weight tension shifts the lowest modes most.",
100 },
101 {
102 id: "disk-300x2",
103 name: "Disk, 300 mm diameter x 2 mm",
104 plate: { shape: "ellipse", Lx: 0.3, Ly: 0.3, h: 0.002 },
105 note: "A round blank; hung from a hole near the rim it is a small gong.",
106 },
107 {
108 id: "disk-250x1",
109 name: "Disk, 250 mm diameter x 1 mm",
110 plate: { shape: "ellipse", Lx: 0.25, Ly: 0.25, h: 0.001 },
111 note: "Thin enough to hold between two fingers and strike.",
112 },
113 {
114 id: "ellipse-300x200x2",
115 name: "Elliptical plate, 300 x 200 x 2 mm",
116 plate: { shape: "ellipse", Lx: 0.3, Ly: 0.2, h: 0.002 },
117 note: "The default sheet cut to an ellipse: same box, same strike, less plate.",
118 },
119 {
120 id: "cymbal-flat-400x1p2",
121 name: "Flat cymbal stand-in, 400 mm diameter x 1.2 mm",
122 plate: { shape: "ellipse", Lx: 0.4, Ly: 0.4, h: 0.0012 },
123 note: "A cymbal is a disk, free at the rim and held at the centre between felts. What this flat disk leaves out is the curvature (a real cymbal is a shallow cone with a raised bell), the taper in thickness and the hole.",
124 },
125 {
126 id: "glockenspiel-bar",
127 name: "Glockenspiel bar, 200 x 32 x 6 mm",
128 plate: { shape: "rectangle", Lx: 0.2, Ly: 0.032, h: 0.006 },
129 note: "Real bars rest on two pads under the nodes of the first mode, which is the pads mount here. Thickness is a fifth of the width, at the edge of thin-plate validity.",
130 },
131 {
132 id: "ruler-300x50x3",
133 name: "Steel strip, 300 x 50 x 3 mm",
134 plate: { shape: "rectangle", Lx: 0.3, Ly: 0.05, h: 0.003 },
135 note: "A ruler-sized strip; clamp one end in a vise and it is the classic cantilever.",
136 },
137];
139export interface ThreadPreset {
140 id: string;
141 thread: ThreadMaterial;
142 note: string;
145/**
146 * Threads. The shear modulus is what sets the torsional stiffness G J / L,
147 * which for any of these is so small that a plate on one thread spins with a
148 * period of minutes; it is here so that the spin has a frequency at all.
149 */
150export const THREAD_PRESETS: ThreadPreset[] = [
151 {
152 id: "nylon-0p5",
153 thread: { name: "nylon monofilament, 0.5 mm", diameter: 0.5e-3, G: 1.0e9 },
154 note: "Fishing line or sewing nylon; G about 1 GPa.",
155 },
156 {
157 id: "cotton-1",
158 thread: { name: "cotton string, 1 mm", diameter: 1e-3, G: 0.3e9 },
159 note: "A twisted string; its effective shear modulus is low and uncertain.",
160 },
161 {
162 id: "steel-wire-0p3",
163 thread: { name: "steel wire, 0.3 mm", diameter: 0.3e-3, G: 80e9 },
164 note: "Music wire; still a weak torsion spring at this diameter.",
165 },
166];
168export interface PadPreset {
169 id: string;
170 name: string;
171 /** Stiffness [N/m^3] and damping [N s/m^3] per unit area */
172 k: number;
173 c: number;
174 note: string;
177/**
178 * Support materials as a stiffness and damping per unit area, E / t for a
179 * layer of modulus E and thickness t with a loss factor of a few tenths at
180 * some hundred hertz. Every one of these is an order-of-magnitude figure.
181 */
182export const PAD_PRESETS: PadPreset[] = [
183 {
184 id: "foam-20",
185 name: "soft foam, 20 mm",
186 k: 2.5e6,
187 c: 1.2e3,
188 note: "Polyurethane packing foam, E about 50 kPa.",
189 },
190 {
191 id: "felt-5",
192 name: "felt, 5 mm",
193 k: 2e8,
194 c: 6e4,
195 note: "Dense wool felt, E about 1 MPa: the washers of a cymbal stand, the pads of a glockenspiel.",
196 },
197 {
198 id: "rubber-5",
199 name: "rubber, 5 mm",
200 k: 6e8,
201 c: 1e5,
202 note: "A rubber sheet, E about 3 MPa.",
203 },
204 {
205 id: "cork-5",
206 name: "cork, 5 mm",
207 k: 4e9,
208 c: 3e5,
209 note: "Cork, E about 20 MPa.",
210 },
211 {
212 id: "hard-edge",
213 name: "hard edge (wood or metal)",
214 k: 1e10,
215 c: 1e5,
216 note: "A knife edge or a bare bench: the stiffness is a penalty, not a measurement, and it shortens the time step a little.",
217 },
218];
220export interface ScenarioPreset {
221 id: string;
222 name: string;
223 /** What is on the bench and what to look for */
224 note: string;
225 spec: ProblemSpec;
228const mat = (id: string) => MATERIAL_PRESETS.find((m) => m.id === id)!;
229const plate = (id: string) => ({ ...PLATE_PRESETS.find((p) => p.id === id)!.plate });
230const thread = (id: string) => ({ ...THREAD_PRESETS.find((t) => t.id === id)!.thread });
231const pad = (id: string) => PAD_PRESETS.find((p) => p.id === id)!;
232const felt = pad("felt-5");
233const foam = pad("foam-20");
235const AIR = { c: 343, rho_air: 1.2 };
237/**
238 * Whole problems: plate, material, mount, orientation, excitation, probe and
239 * listener set together. Each is something you could build and strike; the
240 * note says what the run should show.
241 */
242export const SCENARIO_PRESETS: ScenarioPreset[] = [
243 {
244 id: "sheet-on-thread",
245 name: "Steel sheet on a thread",
246 note: "A 300 x 200 mm sheet hung from a hole near the top edge and struck off-centre. It swings on the thread at about 0.8 Hz, rocks about the hole at about 3 Hz, spins slowly about the thread, and rings; the unbaffled listener loses the low end.",
247 spec: {
248 plate: plate("sheet-300x200x2"),
249 material: { ...mat("a36-steel").material },
250 gravity: { g: 9.81 },
251 mount: { type: "thread", x: 0.15, y: 0.19, length: 0.3, thread: thread("nylon-0p5") },
252 damping: { ...mat("a36-steel").damping },
253 excitation: { type: "impulse", x: 0.1, y: 0.08, force: 50, duration: 1e-3, radius: 0.012 },
254 probe: { x: 0.2, y: 0.12 },
255 listener: { x: 0.15, y: 0.1, z: 1.0, ...AIR, model: "unbaffled" },
256 output: { fs: 44100, nframes: 90 },
257 fd: { nx: 41, ny: 27, cfl: 0.9, duration: 3.0 },
258 },
259 },
260 {
261 id: "gong-on-cords",
262 name: "Gong on two cords",
263 note: "A bronze disk hung from two holes near the rim, struck at the centre. Two cords stop the spin and the yaw; the swing and sway remain, and the low damping of bell bronze lets it ring for the whole run.",
264 spec: {
265 plate: plate("disk-300x2"),
266 material: { ...mat("b20-bronze").material },
267 gravity: { g: 9.81 },
268 mount: { type: "threads", x1: 0.091, y1: 0.277, x2: 0.209, y2: 0.277, length: 0.4 },
269 damping: { ...mat("b20-bronze").damping },
270 excitation: { type: "impulse", x: 0.15, y: 0.15, force: 100, duration: 2e-3, radius: 0.02 },
271 probe: { x: 0.15, y: 0.08 },
272 listener: { x: 0.15, y: 0.15, z: 1.0, ...AIR, model: "unbaffled" },
273 output: { fs: 44100, nframes: 90 },
274 fd: { nx: 41, ny: 41, cfl: 0.9, duration: 3.0 },
275 },
276 },
277 {
278 id: "glockenspiel-bar",
279 name: "Glockenspiel bar on nodal pads",
280 note: "A spring-steel bar on two felt strips placed under the nodes of its first free-free mode, 22.4 percent in from each end, struck in the middle. The pads barely disturb that mode; the bar bounces on them a little after the strike.",
281 spec: {
282 plate: plate("glockenspiel-bar"),
283 material: { ...mat("1095-spring-steel").material },
284 gravity: { g: 9.81 },
285 mount: {
286 type: "pads",
287 pads: [
288 { x: 0.0448, y: 0.016, rx: 0.004, ry: 0.02 },
289 { x: 0.1552, y: 0.016, rx: 0.004, ry: 0.02 },
290 ],
291 k: felt.k,
292 c: felt.c,
293 },
294 damping: { ...mat("1095-spring-steel").damping },
295 excitation: { type: "impulse", x: 0.1, y: 0.016, force: 20, duration: 0.3e-3, radius: 0.006 },
296 probe: { x: 0.05, y: 0.016 },
297 listener: { x: 0.1, y: 0.016, z: 0.5, ...AIR, model: "baffled" },
298 output: { fs: 44100, nframes: 90 },
299 fd: { nx: 61, ny: 11, cfl: 0.9, duration: 0.5 },
300 },
301 },
302 {
303 id: "sheet-on-foam",
304 name: "Sheet on four foam blocks",
305 note: "The steel sheet lying on foam pads under its corners, struck hard in the middle. The strike lifts it off the pads for a moment; watch the pad forces go to zero and the plate land again.",
306 spec: {
307 plate: plate("sheet-300x200x2"),
308 material: { ...mat("a36-steel").material },
309 gravity: { g: 9.81 },
310 mount: {
311 type: "pads",
312 pads: [
313 { x: 0.03, y: 0.03, rx: 0.02, ry: 0.02 },
314 { x: 0.27, y: 0.03, rx: 0.02, ry: 0.02 },
315 { x: 0.03, y: 0.17, rx: 0.02, ry: 0.02 },
316 { x: 0.27, y: 0.17, rx: 0.02, ry: 0.02 },
317 ],
318 k: foam.k,
319 c: foam.c,
320 },
321 damping: { ...mat("a36-steel").damping },
322 excitation: { type: "impulse", x: 0.15, y: 0.1, force: 300, duration: 1e-3, radius: 0.012 },
323 probe: { x: 0.2, y: 0.12 },
324 listener: { x: 0.15, y: 0.1, z: 1.0, ...AIR, model: "baffled" },
325 output: { fs: 44100, nframes: 90 },
326 fd: { nx: 41, ny: 27, cfl: 0.9, duration: 2.0 },
327 },
328 },
329 {
330 id: "cymbal-on-stand",
331 name: "Cymbal on a stand",
332 note: "A flat bronze disk between the felts of a stand, struck near the edge. The felts hold the centre with a preload; a hard enough strike separates one of them for an instant. What is missing is the cymbal's bow and bell.",
333 spec: {
334 plate: plate("cymbal-flat-400x1p2"),
335 material: { ...mat("b20-bronze").material },
336 gravity: { g: 9.81 },
337 mount: { type: "cymbal", r_rod: 0.006, r_felt: 0.02, k: felt.k, c: felt.c, preload: 0.5e-3 },
338 damping: { ...mat("b20-bronze").damping },
339 excitation: { type: "impulse", x: 0.36, y: 0.2, force: 30, duration: 1e-3, radius: 0.015 },
340 probe: { x: 0.2, y: 0.33 },
341 listener: { x: 0.2, y: 0.2, z: 1.0, ...AIR, model: "unbaffled" },
342 output: { fs: 44100, nframes: 90 },
343 fd: { nx: 41, ny: 41, cfl: 0.9, duration: 2.0 },
344 },
345 },
346 {
347 id: "cantilever-in-vise",
348 name: "Cantilever in a vise",
349 note: "A steel strip gripped at one end in a vise, held horizontal, its free end pulled down 10 mm and let go. It sags under its own weight first (the static field), then rings at its cantilever frequency; tilt the vise to hang it or stand it up.",
350 spec: {
351 plate: plate("ruler-300x50x3"),
352 material: { ...mat("a36-steel").material },
353 gravity: { g: 9.81 },
354 mount: { type: "vise", edge: "x0", depth: 0.015, tilt: 90 },
355 damping: { ...mat("a36-steel").damping },
356 excitation: { type: "release", x: 0.29, y: 0.025, displacement: 0.01, radius: 0.008 },
357 probe: { x: 0.25, y: 0.025 },
358 listener: { x: 0.15, y: 0.025, z: 0.5, ...AIR, model: "baffled" },
359 output: { fs: 44100, nframes: 90 },
360 fd: { nx: 61, ny: 11, cfl: 0.9, duration: 2.0 },
361 },
362 },
363 {
364 id: "disk-in-hand",
365 name: "Disk pinched in the hand",
366 note: "A thin stainless disk held between finger and thumb near its rim, hanging, and struck. The fingers are a soft, lossy spring: the disk swings from them and its vibration dies faster than on a thread.",
367 spec: {
368 plate: plate("disk-250x1"),
369 material: { ...mat("304-stainless").material },
370 gravity: { g: 9.81 },
371 mount: { type: "pinched", x: 0.125, y: 0.235, radius: 0.008, k: 2000, c: 20, tilt: 0 },
372 damping: { ...mat("304-stainless").damping },
373 excitation: { type: "impulse", x: 0.125, y: 0.1, force: 30, duration: 1e-3, radius: 0.012 },
374 probe: { x: 0.18, y: 0.125 },
375 listener: { x: 0.125, y: 0.125, z: 1.0, ...AIR, model: "unbaffled" },
376 output: { fs: 44100, nframes: 90 },
377 fd: { nx: 41, ny: 41, cfl: 0.9, duration: 2.0 },
378 },
379 },
380];
382export function scenarioPreset(id: string): ScenarioPreset {
383 const s = SCENARIO_PRESETS.find((x) => x.id === id);
384 if (!s) throw new Error(`unknown scenario ${id}`);
385 return s;
↑↓ move↵openescclose