1import { describe, expect, it } from "vitest";
2import { buildCompareBundle, parseCompareResult } from "../src/index";
3import { relL2, runner, solve, testSpec } from "./helpers";
5describe("modal versus finite differences on the same problem", () => {
6 it("agree on displacement to about a percent and on stress to a few percent", async () => {
7 const spec = testSpec();
8 // Match the modal run to the FD window and grid so frames line up
9 spec.output.duration = spec.fd.duration;
10 spec.output.grid = [spec.fd.nx, spec.fd.ny];
11 const modal = await solve(spec, "modal");
12 const fd = await solve(spec, "fd");
13 const cmpRun = await runner.run({
14 bundle: buildCompareBundle(),
15 inputs: { A: modal.run.ok ? modal.run.value : 0, B: fd.run.ok ? fd.run.value : 0 },
16 });
17 expect(cmpRun.ok).toBe(true);
18 if (!cmpRun.ok) return;
19 const cmp = parseCompareResult(cmpRun.value);
20 expect(cmp.w_rel_l2).toBeLessThan(0.03);
21 expect(cmp.vm_rel_l2).toBeLessThan(0.1);
22 // stress error exceeds displacement error, as a second derivative should
23 expect(cmp.vm_rel_l2).toBeGreaterThan(cmp.w_rel_l2);
24 expect(Math.abs(cmp.w_peak_a - cmp.w_peak_b) / cmp.w_peak_a).toBeLessThan(0.03);
25 // frames compared on the shared grid
26 expect(cmp.frames_rel_l2.length).toBe(modal.result.frames.t.length);
27 expect(cmp.frames_diff).not.toBeNull();
28 // the JS-side norm of the aligned series agrees with the .m norm
29 expect(relL2(cmp.w_a, cmp.w_b)).toBeCloseTo(cmp.w_rel_l2, 6);
30 });
31});