1import copy
3import numpy as np
5from cymsim.mesh import disk_mesh
6from cymsim.radiation import element_sources
7from cymsim.simulate import Simulator
10def test_slope_corrected_sources_are_exact_for_quadratics():
11 m = disk_mesh(0.2, 0.02)
12 x, y = m.xy[:, 0], m.xy[:, 1]
13 a = 1.0 + 2 * x - 3 * y + 5 * x * x - 4 * x * y + 7 * y * y
14 gx, gy = 2 + 10 * x - 4 * y, -3 - 4 * x + 14 * y
15 xc = m.centroid[:, None, :] - m.xy[m.tri]
16 # exact element means of the quadratic: value at the centroid plus the second-moment term
17 p = m.xy[m.tri] - m.centroid[:, None, :]
18 xx, xy_, yy = [(p[:, :, i] * p[:, :, j]).sum(1) / 12 for i, j in ((0, 0), (0, 1), (1, 1))]
19 cx, cy = m.centroid[:, 0], m.centroid[:, 1]
20 exact = 1 + 2 * cx - 3 * cy + 5 * (cx * cx + xx) - 4 * (cx * cy + xy_) + 7 * (cy * cy + yy)
21 corrected = np.asarray(element_sources(a, gx, gy, m.tri, xc))
22 plain = np.asarray(element_sources(a, None, None, m.tri, xc))
23 assert np.abs(corrected - exact).max() < 1e-12
24 assert np.abs(plain - exact).max() > 1e-5 # the plain mean is not exact
27def test_slope_quadrature_run(coarse_config):
28 cfg = copy.deepcopy(coarse_config)
29 cfg.listener.quadrature = "slope"
30 res = Simulator(cfg).run()
31 ref = Simulator(coarse_config).run()
32 p, q = res.pressure_rayleigh, ref.pressure_rayleigh
33 assert np.isfinite(p).all()
34 # same motion, slightly different sum: the two signals agree at low frequency and differ a little
35 rel = np.sqrt(np.mean((p - q) ** 2) / np.mean(q ** 2))
36 assert 1e-6 < rel < 0.5