/ proof-of-concept / cymbalsim
Sign in
proof-of-concept / cymbalsim
Slice size follows the bandwidth (about bw/3.5); aluminum square preset
Jeremy Magland <jeremy.magland@gmail.com> committed commit 76b78438fb7a parent 9cfbfd1 Browse files
3 changed files+40−3
src/modal/modes.tsmodified+12−2View file
@@ -54,7 +54,7 @@ export interface ModeSet {
5454 }
5555
5656 export interface ModeOptions {
57- /** Target number of modes per slice; 80 by default. */
57+ /** Target number of modes per slice; by default defaultSliceSize(bw), which balances the factorizations against the Lanczos work. */
5858 sliceSize?: number;
5959 /** Progress callback with the number of finished and total slices. */
6060 onProgress?: (done: number, total: number) => void;
@@ -62,6 +62,16 @@ export interface ModeOptions {
6262 minFreq?: number;
6363 }
6464
65+/**
66+ * The slice size that balances the cost of a slice's factorization, about
67+ * n bw^2, against the Lanczos work per mode, whose reorthogonalization grows
68+ * with the square of the slice: the optimum is near bw / 3.5, so that a
69+ * finer grid, whose band is wider, uses fewer and larger slices.
70+ */
71+export function defaultSliceSize(bw: number): number {
72+ return Math.max(20, Math.round(bw / 3.5));
73+}
74+
6575 interface Slice {
6676 lo: number;
6777 hi: number;
@@ -75,7 +85,7 @@ interface Slice {
7585 */
7686 export async function computeModes(sys: LinearSystem, fMax: number, runner: JobRunner, opts: ModeOptions = {}): Promise<ModeSet> {
7787 const t0 = performance.now();
78- const sliceSize = opts.sliceSize ?? 80;
88+ const sliceSize = opts.sliceSize ?? defaultSliceSize(sys.bw);
7989 const minFreq = opts.minFreq ?? 1;
8090 const w2 = (f: number) => (2 * Math.PI * f) ** 2;
8191 const lamMin = -w2(1); // slightly below zero so that the rigid modes are counted in the first slice
src/modal/pool.tsmodified+1−1View file
@@ -113,7 +113,7 @@ export class WorkerPool {
113113 /** The modes of the system, computed by the workers. */
114114 async modes(sys: LinearSystem, fMax: number, onProgress?: (done: number, total: number) => void): Promise<ModeSet> {
115115 await this.setSystem(sys);
116- return computeModes(sys, fMax, this.runner(), { sliceSize: sys.fields === 1 ? 30 : 100, onProgress });
116+ return computeModes(sys, fMax, this.runner(), { onProgress });
117117 }
118118
119119 /** Splits the modes of the model between the workers. */
src/presets.tsmodified+27−0View file
@@ -31,6 +31,32 @@ design.stand = []; % free plate
3131 design.loss.T60 = @(f) 3 ./ (1 + f/1500); % decay time [s] as a function of frequency [Hz]
3232 `;
3333
34+const aluminumSquare = `% A flat 12 inch square of 6061-T6 aluminum, 1.02 mm thick, with a center
35+% hole on a cymbal stand: felt pads below and above the plate around the
36+% rod. Aluminum is a third the density of steel and a third as stiff, so
37+% the bending frequencies land near those of a steel plate of the same size
38+% and thickness; the material damping is low, hence the long decay.
39+inch = 0.0254; mm = 1e-3;
40+W = 12*inch; hole = 13*mm;
41+
42+design.name = 'Aluminum 6061-T6 square';
43+design.material.E = 68.9e9; % Young's modulus [Pa]
44+design.material.nu = 0.33; % Poisson ratio
45+design.material.rho = 2700; % density [kg/m^3]
46+design.bounds.width = W;
47+design.bounds.height = W;
48+design.inside = @(x, y, r, theta) r >= hole/2;
49+design.thickness = 1.02*mm;
50+design.stand.pad.innerRadius = 7*mm; % the felt sits on the plastic sleeve of the rod
51+design.stand.pad.outerRadius = 20*mm;
52+design.stand.pad.thickness = 12*mm;
53+design.stand.pad.E = 0.5e6; % Pa, felt in compression
54+design.stand.pad.lossFactor = 0.3;
55+design.stand.topPad = true;
56+design.stand.preload = 1*mm; % compression of the top pad by the wing nut
57+design.loss.T60 = @(f) 4 ./ (1 + f/2000);
58+`;
59+
3460 const bowedRectangle = `% The same steel sheet with a 3 mm parabolic bow across its width, the
3561 % kind of bow that rolling and handling leave in real sheet metal. The bow
3662 % makes the sheet a shallow shell: the linear modes couple bending to
@@ -219,6 +245,7 @@ design.loss.T60 = @(f) 2.5 ./ (1 + f/1000);
219245
220246 export const PRESETS: Preset[] = [
221247 { id: "flat-rectangle", label: "Flat steel rectangle", source: flatRectangle },
248+ { id: "aluminum-square", label: "Aluminum 6061-T6 square on a stand", source: aluminumSquare },
222249 { id: "bowed-rectangle", label: "Bowed steel rectangle", source: bowedRectangle },
223250 { id: "flat-disc", label: "Flat bronze disc on a stand", source: flatDisc },
224251 { id: "crash-16", label: "16 inch flat crash", source: crash16 },
↑↓ move↵openescclose