/ proof-of-concept / cymbalsim
Sign in
proof-of-concept / cymbalsim
cymbalsim / src / presets.ts
293 lines · 12.8 KBCodeBlameHistory
5778036cymbalsim: scripted plate and cymbal designer with a modal linear model and a von Karman GPU modelJeremy Magland 1// Predefined design scripts, selectable from the interface. Each is a
2// MATLAB-syntax script that fills in the `design` struct; see design.ts for
3// the fields. A script is self-contained: the shape functions it uses are
4// ordinary MATLAB functions written at the bottom of the script itself.
6export interface Preset {
7 id: string;
8 label: string;
9 source: string;
12const flatRectangle = `% A flat rectangular sheet of stainless steel, hanging freely (no stand).
13% The script is an ordinary MATLAB program that fills in a struct named
14% design. Lengths are meters; the constants at the top are the only units.
15% A field can be a number or a function handle @(x, y, r, theta) of the
16% point, measured from the center of the bounding box; the handles are
17% applied to whole grid matrices, so use elementwise operators (.*, ./, .^)
18% inside them. Anything else a script needs it defines itself, as MATLAB
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 19% functions at the bottom; the other presets show how. The decay of the
20% sound is not prescribed: it follows from the loss factor of the metal, its
21% thermal constants (thermoelastic damping), the radiation of each mode into
22% the air, and the felt of a stand.
24mm = 1e-3; % m
26design.name = 'Flat steel rectangle';
27design.material.E = 170e9; % Young's modulus [Pa]
28design.material.nu = 0.29; % Poisson ratio
29design.material.rho = 7900; % density [kg/m^3]
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 30design.material.lossFactor = 3e-4; % internal friction of the metal (typical published value)
31design.material.alpha = 17e-6; % thermal expansion [1/K] } for the thermoelastic damping
32design.material.cp = 500; % specific heat [J/(kg K)] }
33design.material.k = 16; % conductivity [W/(m K)] }
5778036cymbalsim: scripted plate and cymbal designer with a modal linear model and a von Karman GPU modelJeremy Magland 34design.bounds.width = 12*inch; % bounding box [m]
35design.bounds.height = 18*inch;
36design.thickness = 0.79*mm;
37design.stand = []; % free plate
38`;
76b7843Slice size follows the bandwidth (about bw/3.5); aluminum square presetJeremy Magland 40const aluminumSquare = `% A flat 12 inch square of 6061-T6 aluminum, 1.02 mm thick, with a center
41% hole on a cymbal stand: felt pads below and above the plate around the
42% rod. Aluminum is a third the density of steel and a third as stiff, so
43% the bending frequencies land near those of a steel plate of the same size
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 44% and thickness. Its high thermal expansion and conductivity give it the
45% strongest thermoelastic damping of the three metals here.
47W = 12*inch; hole = 13*mm;
49design.name = 'Aluminum 6061-T6 square';
50design.material.E = 68.9e9; % Young's modulus [Pa]
51design.material.nu = 0.33; % Poisson ratio
52design.material.rho = 2700; % density [kg/m^3]
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 53design.material.lossFactor = 1e-4; % internal friction of the metal (typical published value)
54design.material.alpha = 23.6e-6; % thermal expansion [1/K] } for the thermoelastic damping
55design.material.cp = 896; % specific heat [J/(kg K)] }
56design.material.k = 167; % conductivity [W/(m K)] }
58design.bounds.height = W;
59design.inside = @(x, y, r, theta) r >= hole/2;
60design.thickness = 1.02*mm;
61design.stand.pad.innerRadius = 7*mm; % the felt sits on the plastic sleeve of the rod
62design.stand.pad.outerRadius = 20*mm;
63design.stand.pad.thickness = 12*mm;
64design.stand.pad.E = 0.5e6; % Pa, felt in compression
65design.stand.pad.lossFactor = 0.3;
66design.stand.topPad = true;
67design.stand.preload = 1*mm; % compression of the top pad by the wing nut
68`;
5778036cymbalsim: scripted plate and cymbal designer with a modal linear model and a von Karman GPU modelJeremy Magland 70const bowedRectangle = `% The same steel sheet with a 3 mm parabolic bow across its width, the
71% kind of bow that rolling and handling leave in real sheet metal. The bow
72% makes the sheet a shallow shell: the linear modes couple bending to
73% stretching, and the full simulation oil-cans and wobbles when struck.
74inch = 0.0254; mm = 1e-3;
75W = 12*inch; H = 18*inch;
77design.name = 'Bowed steel rectangle';
78design.material.E = 170e9;
79design.material.nu = 0.29;
80design.material.rho = 7900;
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 81design.material.lossFactor = 3e-4; % internal friction of the metal (typical published value)
82design.material.alpha = 17e-6; % thermal expansion [1/K] } for the thermoelastic damping
83design.material.cp = 500; % specific heat [J/(kg K)] }
84design.material.k = 16; % conductivity [W/(m K)] }
86design.bounds.height = H;
87design.thickness = 0.79*mm;
88design.profile = @(x, y, r, theta) bow(x, W, 3*mm, 0.3); % stress-free height [m]
89design.stand = [];
91function v = bow(s, span, sag, offset)
92% A parabola of the given sag across a span centered on 0; s runs along the
93% span, and the offset in -1..1 moves the crest toward one end.
94t = 2*s/span;
95v = sag * (1 - t.^2) .* (1 + offset*t);
96end
97`;
99const flatDisc = `% A flat 16 inch bronze disc with a center hole on a cymbal stand. The
100% stand is a rod through the hole with a felt pad below the plate and
101% another above it under the wing nut; each pad is an annulus of felt of
102% the given radii and thickness, and its stiffness per unit area is E over
103% the thickness. The pads hold the disc level and let it bounce and rock.
104inch = 0.0254; mm = 1e-3;
105D = 16*inch; hole = 13*mm;
107design.name = 'Flat bronze disc';
108design.material.E = 110e9; % bronze
109design.material.nu = 0.34;
110design.material.rho = 8800;
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 111design.material.lossFactor = 2e-4; % internal friction of the metal (typical published value)
112design.material.alpha = 18e-6; % thermal expansion [1/K] } for the thermoelastic damping
113design.material.cp = 370; % specific heat [J/(kg K)] }
114design.material.k = 40; % conductivity [W/(m K)] }
116design.bounds.height = D;
117design.inside = @(x, y, r, theta) (r <= D/2) & (r >= hole/2);
118design.thickness = 1.0*mm;
119design.stand.pad.innerRadius = 7*mm; % the felt sits on the plastic sleeve of the rod
120design.stand.pad.outerRadius = 20*mm;
121design.stand.pad.thickness = 12*mm;
122design.stand.pad.E = 0.5e6; % Pa, felt in compression
123design.stand.pad.lossFactor = 0.3;
124design.stand.topPad = true;
125design.stand.preload = 1*mm; % compression of the top pad by the wing nut
126`;
128const crash16 = `% A 16 inch flat crash: bronze, lathed to a taper from 1.2 mm at the
129% center to 0.7 mm at the edge, on a stand. Flat, so the linear modes are
130% pure bending modes; the tapered profile is what makes it a crash rather
131% than a ride.
132inch = 0.0254; mm = 1e-3;
133D = 16*inch; R = D/2; hole = 13*mm;
134tCenter = 1.2*mm; tEdge = 0.7*mm;
136design.name = '16 inch flat crash';
137design.material.E = 110e9;
138design.material.nu = 0.34;
139design.material.rho = 8800;
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 140design.material.lossFactor = 2e-4; % internal friction of the metal (typical published value)
141design.material.alpha = 18e-6; % thermal expansion [1/K] } for the thermoelastic damping
142design.material.cp = 370; % specific heat [J/(kg K)] }
143design.material.k = 40; % conductivity [W/(m K)] }
145design.bounds.height = D;
146design.inside = @(x, y, r, theta) (r <= R) & (r >= hole/2);
147design.thickness = @(x, y, r, theta) tCenter + (tEdge - tCenter) * ramp(40*mm, R, r);
148design.stand.pad.innerRadius = 7*mm;
149design.stand.pad.outerRadius = 20*mm;
150design.stand.pad.thickness = 12*mm;
151design.stand.pad.E = 0.5e6;
152design.stand.pad.lossFactor = 0.3;
153design.stand.topPad = true;
154design.stand.preload = 1*mm;
156function v = ramp(a, b, x)
157% 0 at x = a, 1 at x = b, clamped to that range outside.
158v = min(max((x - a) ./ (b - a), 0), 1);
159end
160`;
162const ride20 = `% A 20 inch flat ride: thicker bronze, 2.2 mm at the center to 1.4 mm at
163% the edge, on a stand with a loose wing nut (a small preload). The
164% thickness raises every frequency in proportion, and the ride has a
165% clearer ping and a longer decay than the crash.
166inch = 0.0254; mm = 1e-3;
167D = 20*inch; R = D/2; hole = 13*mm;
169design.name = '20 inch flat ride';
170design.material.E = 110e9;
171design.material.nu = 0.34;
172design.material.rho = 8800;
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 173design.material.lossFactor = 2e-4; % internal friction of the metal (typical published value)
174design.material.alpha = 18e-6; % thermal expansion [1/K] } for the thermoelastic damping
175design.material.cp = 370; % specific heat [J/(kg K)] }
176design.material.k = 40; % conductivity [W/(m K)] }
178design.bounds.height = D;
179design.inside = @(x, y, r, theta) (r <= R) & (r >= hole/2);
180design.thickness = @(x, y, r, theta) 2.2*mm + (1.4*mm - 2.2*mm) * ramp(50*mm, R, r);
181design.stand.pad.innerRadius = 7*mm;
182design.stand.pad.outerRadius = 22*mm;
183design.stand.pad.thickness = 12*mm;
184design.stand.pad.E = 0.5e6;
185design.stand.pad.lossFactor = 0.3;
186design.stand.topPad = true;
187design.stand.preload = 0.3*mm;
189function v = ramp(a, b, x)
190v = min(max((x - a) ./ (b - a), 0), 1);
191end
192`;
194const crashBell16 = `% A 16 inch crash with a shallow bow and a cosine bell, on a stand. The
195% profile makes the cymbal a shallow shell: the linear model couples the
196% bending to the stretching (a larger eigenproblem, so the modes take
197% longer), and the full simulation shows the asymmetric nonlinearity of a
198% curved plate. The slopes are kept small; the interface reports the
199% largest one.
200inch = 0.0254; mm = 1e-3;
201D = 16*inch; R = D/2; hole = 13*mm;
202bellR = 55*mm; bellH = 8*mm; bowH = 10*mm;
203tCenter = 1.2*mm; tEdge = 0.7*mm;
205design.name = '16 inch crash with bell';
206design.material.E = 110e9;
207design.material.nu = 0.34;
208design.material.rho = 8800;
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 209design.material.lossFactor = 2e-4; % internal friction of the metal (typical published value)
210design.material.alpha = 18e-6; % thermal expansion [1/K] } for the thermoelastic damping
211design.material.cp = 370; % specific heat [J/(kg K)] }
212design.material.k = 40; % conductivity [W/(m K)] }
214design.bounds.height = D;
215design.inside = @(x, y, r, theta) (r <= R) & (r >= hole/2);
216design.thickness = @(x, y, r, theta) tCenter + (tEdge - tCenter) * ramp(bellR, R, r);
217design.profile = @(x, y, r, theta) bowH * (1 - (r/R).^2) + dome(r, bellR, bellH);
218design.stand.pad.innerRadius = 7*mm;
219design.stand.pad.outerRadius = 20*mm;
220design.stand.pad.thickness = 12*mm;
221design.stand.pad.E = 0.5e6;
222design.stand.pad.lossFactor = 0.3;
223design.stand.topPad = true;
224design.stand.preload = 1*mm;
226function v = ramp(a, b, x)
227v = min(max((x - a) ./ (b - a), 0), 1);
228end
230function v = dome(d, radius, height)
231% A cosine dome of the given height and base radius, with zero slope both at
232% its rim and at its apex; d is the distance from its center.
233v = 0.5 * height * (1 + cos(pi * d / radius)) .* (d < radius);
234end
235`;
237const ellipse = `% A free elliptical steel plate. The outline is any test on the point;
238% an ellipse inscribed in the bounding box here. The degenerate mode pairs
239% of a disc split on an ellipse, which the mode browser shows.
240inch = 0.0254; mm = 1e-3;
241A = 14*inch; B = 10*inch;
243design.name = 'Steel ellipse';
244design.material.E = 170e9;
245design.material.nu = 0.29;
246design.material.rho = 7900;
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 247design.material.lossFactor = 3e-4; % internal friction of the metal (typical published value)
248design.material.alpha = 17e-6; % thermal expansion [1/K] } for the thermoelastic damping
249design.material.cp = 500; % specific heat [J/(kg K)] }
250design.material.k = 16; % conductivity [W/(m K)] }
252design.bounds.height = B;
253design.inside = @(x, y, r, theta) (x/(A/2)).^2 + (y/(B/2)).^2 <= 1;
254design.thickness = 1.0*mm;
255design.stand = [];
256`;
258const thunderSheet = `% A thunder sheet: a large thin steel sheet hung from one corner. Its modes
259% are dense and low, and the full simulation turns a hard hit into a roar.
260% Long at the default spacing; a coarser grid keeps it interactive.
261inch = 0.0254; mm = 1e-3;
263design.name = 'Thunder sheet';
264design.material.E = 200e9;
265design.material.nu = 0.3;
266design.material.rho = 7850;
2a1a6daDerive the losses from physical constants instead of a prescribed decay curveJeremy Magland 267design.material.lossFactor = 3e-4; % internal friction of the metal (typical published value)
268design.material.alpha = 12e-6; % thermal expansion [1/K] } for the thermoelastic damping
269design.material.cp = 460; % specific heat [J/(kg K)] }
270design.material.k = 50; % conductivity [W/(m K)] }
272design.bounds.height = 36*inch;
273design.thickness = 0.5*mm;
274design.stand = [];
275`;
277export const PRESETS: Preset[] = [
278 { id: "flat-rectangle", label: "Flat steel rectangle", source: flatRectangle },
76b7843Slice size follows the bandwidth (about bw/3.5); aluminum square presetJeremy Magland 279 { id: "aluminum-square", label: "Aluminum 6061-T6 square on a stand", source: aluminumSquare },
5778036cymbalsim: scripted plate and cymbal designer with a modal linear model and a von Karman GPU modelJeremy Magland 280 { id: "bowed-rectangle", label: "Bowed steel rectangle", source: bowedRectangle },
281 { id: "flat-disc", label: "Flat bronze disc on a stand", source: flatDisc },
282 { id: "crash-16", label: "16 inch flat crash", source: crash16 },
283 { id: "ride-20", label: "20 inch flat ride", source: ride20 },
284 { id: "crash-bell-16", label: "16 inch crash with bell", source: crashBell16 },
285 { id: "ellipse", label: "Steel ellipse", source: ellipse },
286 { id: "thunder-sheet", label: "Thunder sheet", source: thunderSheet },
287];
289export const DEFAULT_PRESET = "crash-16";
291export function presetById(id: string): Preset | undefined {
292 return PRESETS.find((p) => p.id === id);
↑↓ move↵openescclose