/ proof-of-concept / cymsimweb
Sign in
proof-of-concept / cymsimweb
cymsimweb / tests / shell.test.ts
49 lines · 2.5 KBCodeBlameHistory
2import assert from "node:assert/strict";
3import { CymbalProfile } from "../src/model/geometry.ts";
4import { diskMesh } from "../src/model/mesh.ts";
5import { buildShell } from "../src/model/shell.ts";
6import { shellChecks } from "../src/model/forces.ts";
7import { buildPatch, freeContactTime, maxCompression } from "../src/model/exciter.ts";
8import { fixture, maxAbs, maxAbsDiff } from "./helpers.ts";
10const cfg = fixture.config;
11const profile = new CymbalProfile(cfg.profile, cfg.imperfections);
12const mesh = diskMesh(cfg.profile.radius, cfg.mesh.element_size, cfg.mesh.smoothing);
13const shell = buildShell(mesh, profile, cfg.material, cfg.numerics);
15test("dent-free shell matches the Python assembly", () => {
16 const f = fixture.shell;
17 const rel = (a: number, b: number) => Math.abs(a - b) / Math.abs(b);
18 assert.ok(rel(shell.mass, f.mass) < 1e-10);
19 assert.ok(rel(shell.omegaMax, f.omega_max) < 1e-8, `omega ${shell.omegaMax} vs ${f.omega_max}`);
20 assert.equal(shell.limitingElement, f.limiting_element);
21 assert.ok(rel(shell.maxSlope, f.max_slope) < 1e-10);
22 assert.ok(rel(Math.min(...shell.hE), f.h_e_min) < 1e-10 && rel(Math.max(...shell.hE), f.h_e_max) < 1e-10);
23 assert.ok(rel(Math.max(...shell.z0Node), f.z0_max) < 1e-10);
24 assert.ok(maxAbsDiff(shell.z0Node.subarray(0, 5), f.z0_node_first5) < 1e-14);
25 assert.ok(maxAbsDiff(shell.Ke.subarray(0, 81), f.Ke0) < 1e-8 * maxAbs(f.Ke0));
26 assert.ok(rel(shell.De[0], f.D0) < 1e-12 && maxAbsDiff(shell.Cm.subarray(0, 3), f.Cm0) < 1e-6);
27 assert.ok(maxAbsDiff(shell.M.subarray(0, 15), f.M_first3.flat()) < 1e-12);
28 const N = mesh.n;
29 assert.ok(maxAbsDiff(shell.Rm.subarray(4 * 5 * N, 4 * 5 * N + 15), f.Rm4_first3.flat()) < 1e-8);
30 assert.deepEqual(shell.zeroModes, [6, 6]);
31});
33test("element and rigid-mode checks", () => {
34 const c = shellChecks(shell);
35 assert.ok(c.rigidTiltResidual < 1e-12);
36 assert.ok(c.constantCurvatureError < 1e-8);
37 assert.ok(c.rigidModeRatio < 1e-8, `rigid ratio ${c.rigidModeRatio}`);
38});
40test("contact patch matches Python", () => {
41 const p = buildPatch(cfg.hits[0], mesh, profile);
42 const f = fixture.patch;
43 assert.deepEqual(Array.from(p.nodes), f.nodes.flat());
44 assert.ok(maxAbsDiff(p.weights, f.weights.flat()) < 1e-10);
45 assert.ok(maxAbsDiff(p.offsets, f.offsets) < 1e-12);
46 assert.ok(Math.abs(p.kTotal / f.k_total - 1) < 1e-12);
47 assert.ok(Math.abs(maxCompression(p) / f.max_compression - 1) < 1e-10);
48 assert.ok(Math.abs(freeContactTime(p) / f.free_contact_time - 1) < 1e-6);
49});
↑↓ move↵openescclose