2004981Plate dynamics lab 2: a hammer on a hung plate by Rayleigh-Ritz and by Mindlin-Reissner finite elementsJeremy Magland 1import type { Hammer, Material, PlateGeometry, ProblemSpec } from "./types";
3/**
4 * Material presets. E, nu and rho are room-temperature handbook figures for
5 * the named alloy (ASM Handbook, MatWeb) and typical rather than certified.
6 * The quality factor Q is the internal, structural loss alone; it is an
7 * order-of-magnitude figure, and the air loading and the thread's dashpot are
8 * added to it per mode (plate_damping.m). The default 6061-T6 values are
9 * those of the simulators this lab follows.
10 */
11export interface MaterialPreset {
12 id: string;
13 material: Material;
14 source: string;
15}
17export const MATERIAL_PRESETS: MaterialPreset[] = [
18 {
19 id: "6061-t6",
20 material: { name: "6061-T6 aluminium", E: 68.9e9, nu: 0.33, rho: 2700, Q: 1400 },
21 source: "6061-T6 sheet, typical values; Q = 1400 is the reference simulators' figure.",
22 },
23 {
24 id: "a36-steel",
25 material: { name: "A36 structural steel", E: 200e9, nu: 0.26, rho: 7850, Q: 2500 },
26 source: "Hot-rolled low-carbon steel; steel rings longer than aluminium.",
27 },
28 {
29 id: "304-stainless",
30 material: { name: "304 stainless steel", E: 193e9, nu: 0.29, rho: 8000, Q: 2000 },
31 source: "Annealed 304 sheet, typical values.",
32 },
33 {
34 id: "c260-brass",
35 material: { name: "C260 cartridge brass", E: 110e9, nu: 0.375, rho: 8530, Q: 1500 },
36 source: "70/30 brass, half-hard sheet, typical values.",
37 },
38 {
39 id: "b20-bronze",
40 material: { name: "B20 bell bronze (CuSn20)", E: 105e9, nu: 0.34, rho: 8800, Q: 4000 },
41 source: "Bell and cymbal bronze; its low internal loss is what makes it ring.",
42 },
43 {
44 id: "ti-6al-4v",
45 material: { name: "Ti-6Al-4V titanium", E: 113.8e9, nu: 0.342, rho: 4430, Q: 3000 },
46 source: "Annealed Grade 5 titanium sheet, typical values.",
47 },
48];
50export interface PlatePreset {
51 id: string;
52 name: string;
53 plate: PlateGeometry;
54 note: string;
55}
57export const PLATE_PRESETS: PlatePreset[] = [
58 {
59 id: "coupon-30x30x1",
60 name: "30 x 30 x 1 mm coupon",
61 plate: { width: 0.03, height: 0.03, thickness: 0.001 },
62 note: "The reference plate: a square coupon whose lowest partial is near 3.6 kHz and whose highest kept mode is ultrasonic.",
63 },
64 {
65 id: "coupon-40x30x1",
66 name: "40 x 30 x 1 mm coupon",
67 plate: { width: 0.04, height: 0.03, thickness: 0.001 },
68 note: "Not square: the degenerate pairs of the square split into distinct partials.",
69 },
70 {
71 id: "coupon-30x30x0p5",
72 name: "30 x 30 x 0.5 mm shim",
73 plate: { width: 0.03, height: 0.03, thickness: 0.0005 },
74 note: "Half the thickness: every partial at half the frequency, and twice as many below the cutoff.",
75 },
76 {
77 id: "plate-60x60x1",
78 name: "60 x 60 x 1 mm plate",
79 plate: { width: 0.06, height: 0.06, thickness: 0.001 },
80 note: "Four times the area: partials a quarter as high, four times as many modes, and a longer eigensolve.",
81 },
82 {
83 id: "plate-50x30x2",
84 name: "50 x 30 x 2 mm bar",
85 plate: { width: 0.05, height: 0.03, thickness: 0.002 },
86 note: "Thicker and oblong; the thin-plate assumption of the Rayleigh-Ritz method is at its edge here.",
87 },
88];
90export interface HammerPreset {
91 id: string;
92 name: string;
93 hammer: Hammer;
94 note: string;
95}
97export const HAMMER_PRESETS: HammerPreset[] = [
98 {
99 id: "steel-10g",
100 name: "10 g steel hammer, 2 mm tip",
101 hammer: { mass: 0.01, tip_radius: 0.002, speed: 0.45, E: 200e9, nu: 0.29, restitution: 0.62 },
102 note: "The reference strike: a small steel hammer at 0.45 m/s.",
103 },
104 {
105 id: "steel-5g-sharp",
106 name: "5 g steel hammer, 1 mm tip",
107 hammer: { mass: 0.005, tip_radius: 0.001, speed: 0.6, E: 200e9, nu: 0.29, restitution: 0.62 },
108 note: "Lighter and sharper: a shorter contact excites the high partials more.",
109 },
110 {
111 id: "brass-20g",
112 name: "20 g brass hammer, 4 mm tip",
113 hammer: { mass: 0.02, tip_radius: 0.004, speed: 0.3, E: 110e9, nu: 0.35, restitution: 0.55 },
114 note: "Heavier, softer and rounder: a longer contact that favours the lowest partials.",
115 },
116];
118export interface ScenarioPreset {
119 id: string;
120 name: string;
121 note: string;
122 spec: ProblemSpec;
123}
125const mat = (id: string) => ({ ...MATERIAL_PRESETS.find((m) => m.id === id)!.material });
126const plate = (id: string) => ({ ...PLATE_PRESETS.find((p) => p.id === id)!.plate });
127const hammer = (id: string) => ({ ...HAMMER_PRESETS.find((h) => h.id === id)!.hammer });
129const COMMON = {
130 hole: { diameter: 0.8e-3, edge_offset: 1.5e-3 },
131 thread: { length: 0.2, dashpot: 7.5e-4 },
132 probe: { x: 0.008, y: -0.006 },
133 mic: { distance: 0.35, air_density: 1.204, sound_speed: 343 },
134 render: {
135 fs: 96000,
136 duration: 4,
137 modes: 72,
138 normalize_dbfs: -1,
139 nframes: 120,
140 frame_span: 0.002,
141 },
142 rr: { basis_order: 12, quadrature_order: 30, grid: 49 },
143 fem: { mesh_x: 48, mesh_y: 48 },
144};
146/**
147 * Whole problems. The first is the reference centre hit of the simulators
148 * this lab follows; the others move the strike, change the hammer or the
149 * plate. Each note says what to look for.
150 */
151export const SCENARIO_PRESETS: ScenarioPreset[] = [
152 {
153 id: "center-hit",
154 name: "Centre hit (the reference)",
155 note: "The 30 mm 6061-T6 coupon struck at its centre. The centre lies on both symmetry axes, so most asymmetric modes are silent; the strong partials are near 6.7, 17.2 and 33.5 kHz (Rayleigh-Ritz) and a percent or two away from those in the finite-element model.",
156 spec: {
157 plate: plate("coupon-30x30x1"),
158 material: mat("6061-t6"),
159 hammer: hammer("steel-10g"),
160 strike: { x: 0, y: 0 },
161 ...COMMON,
162 },
163 },
164 {
165 id: "off-center-hit",
166 name: "Off-centre hit, (6, -4) mm",
167 note: "The same coupon struck 6 mm right of and 4 mm below the centre. The modes the centre hit could not reach now sound, including the lowest at 3.6 kHz; the finite-element contact is shorter and lighter than at the centre because the plate under the hammer is more compliant there.",
168 spec: {
169 plate: plate("coupon-30x30x1"),
170 material: mat("6061-t6"),
171 hammer: hammer("steel-10g"),
172 strike: { x: 0.006, y: -0.004 },
173 ...COMMON,
174 },
175 },
176 {
177 id: "sharp-tap",
178 name: "Sharp tap near a corner",
179 note: "A light, sharp hammer near the lower-right corner: a short contact that excites the high partials, on the part of the plate that moves most.",
180 spec: {
181 plate: plate("coupon-30x30x1"),
182 material: mat("6061-t6"),
183 hammer: hammer("steel-5g-sharp"),
184 strike: { x: 0.011, y: -0.011 },
185 ...COMMON,
186 },
187 },
188 {
189 id: "brass-plate",
190 name: "Brass coupon, oblong",
191 note: "A 40 x 30 mm brass coupon struck off-centre with the heavier brass hammer. Denser and softer than aluminium, brass rings lower; the oblong outline splits the square's degenerate pairs into distinct partials.",
192 spec: {
193 plate: plate("coupon-40x30x1"),
194 material: mat("c260-brass"),
195 hammer: hammer("brass-20g"),
196 strike: { x: 0.008, y: -0.005 },
197 ...COMMON,
198 },
199 },
200 {
201 id: "thin-shim",
202 name: "Thin shim",
203 note: "A 0.5 mm shim of the same outline: every partial at half the frequency, twice as many below the cutoff, and a contact the plate yields to much more, so the two contact models differ most here.",
204 spec: {
205 plate: plate("coupon-30x30x0p5"),
206 material: mat("6061-t6"),
207 hammer: hammer("steel-10g"),
208 strike: { x: 0.005, y: -0.003 },
209 ...COMMON,
210 },
211 },
212 {
213 id: "bronze-bell-plate",
214 name: "Bell-bronze plate, 60 mm",
215 note: "A 60 mm bronze square: four times the area, partials a quarter as high, many more modes below the cutoff, and bronze's low loss keeps it ringing for the whole four seconds. The eigensolve takes longer.",
216 spec: {
217 plate: plate("plate-60x60x1"),
218 material: mat("b20-bronze"),
219 hammer: hammer("steel-10g"),
220 strike: { x: 0.012, y: -0.008 },
221 ...COMMON,
222 probe: { x: 0.016, y: -0.012 },
223 },
224 },
225];
227export function scenarioPreset(id: string): ScenarioPreset {
228 const s = SCENARIO_PRESETS.find((x) => x.id === id);
229 if (!s) throw new Error(`unknown scenario ${id}`);
230 return s;
231}