/ proof-of-concept / cymsim
Sign in
proof-of-concept / cymsim
cymsim / tools / make_web_fixture.py
71 lines · 2.9 KBCodeBlameHistory
e30c940save .cymsim fileJeremy Magland 1"""Refresh the run-dependent parts of cymsimweb's Python reference fixture.
3Usage: python tools/make_web_fixture.py ../cymsimweb/tests/fixtures/python_reference.json
5The fixture's configuration (a coarse, dent-free profile) is kept; the ``config``, ``timestep``,
6``run`` and ``run_linear`` entries are rewritten from a fresh run of this package, including the
7recorded normal acceleration of a few nodes and a sample of the decimation taps, which the web
8tests compare against their own implementation. The mesh, shell, DKT and patch entries do not
9depend on the time loop and are left as they are.
10"""
11from __future__ import annotations
13import dataclasses
14import json
15import sys
17import numpy as np
19from cymsim.config import SimulationConfig
20from cymsim.simulate import Simulator
22ACC_NODES = [0, 50, 120]
25def run_entry(cfg: SimulationConfig) -> dict:
26 sim = Simulator(cfg)
27 res = sim.run()
28 a = res.acceleration.as_float()
29 return {
30 "hits": [dataclasses.asdict(h) for h in res.hits],
31 "energy_log": [[e.time, e.kinetic, e.membrane, e.bending, e.exciters, e.max_w_over_h] for e in res.energy_log],
32 "pressure_rayleigh": res.pressure_rayleigh.tolist(),
33 "pressure_unbaffled": res.pressure_unbaffled.tolist(),
34 "fs": res.fs,
35 "acceleration_nodes": ACC_NODES,
36 "acceleration": [a[:, i].astype(float).tolist() for i in ACC_NODES],
37 "n_steps": sim.n_steps,
38 }, sim
41def main(path: str) -> None:
42 with open(path) as f:
43 fx = json.load(f)
44 cfg = SimulationConfig.from_dict(fx["config"])
45 cfg.output.record_acceleration = True
46 cfg.output.displacement_rate = 0.0
47 sim0 = Simulator(cfg)
48 # whole blocks must end on an audio sample so that the web loop can stop at the same time
49 m = sim0.substeps
50 if cfg.numerics.steps_per_block % m:
51 cfg.numerics.steps_per_block = m * max(1, cfg.numerics.steps_per_block // m)
52 fx["config"] = cfg.to_dict()
53 run, sim = run_entry(cfg)
54 lin_cfg = SimulationConfig.from_dict(cfg.to_dict())
55 lin_cfg.numerics.nonlinear = False
56 run_linear, _ = run_entry(lin_cfg)
42c1bf8Time step from the global stability bound (power iteration), with numerics.stability_bound to keep the element boundJeremy Magland 57 fx["timestep"] = {"dt": sim.dt, "substeps": sim.substeps, "omega_global": sim.shell.omega_global,
58 "omega_global_iterations": sim.shell.omega_global_iterations}
e30c940save .cymsim fileJeremy Magland 59 fx["run"], fx["run_linear"] = run, run_linear
60 taps = sim.taps
61 fx["decimation"] = {"span": taps.shape[0], "substeps": taps.shape[1],
62 "taps_sample": [[int(w), int(k), float(taps[w, k])] for w, k in
63 [(0, 0), (15, 0), (15, m - 1), (16, 0), (31, m - 1), (7, m // 2)]],
64 "normal_first3": sim.shell.normal_node[:3].tolist()}
65 with open(path, "w") as f:
66 json.dump(fx, f)
67 print(f"wrote {path}: {len(run['pressure_unbaffled'])} samples, {sim.n_steps} steps, m = {m}")
70if __name__ == "__main__":
71 main(sys.argv[1])
↑↓ move↵openescclose