def test_refract(): rng = np.random.default_rng(577215) size = 10_000 for _ in range(100): s1 = batoid.Sphere(1. / rng.normal(0., 0.2)) s2 = batoid.Paraboloid(rng.uniform(1, 3)) sum = batoid.Sum([s1, s2]) m0 = batoid.ConstMedium(rng.normal(1.2, 0.01)) m1 = batoid.ConstMedium(rng.normal(1.3, 0.01)) x = rng.uniform(-1, 1, size=size) y = rng.uniform(-1, 1, size=size) z = np.full_like(x, -10.0) vx = rng.uniform(-1e-5, 1e-5, size=size) vy = rng.uniform(-1e-5, 1e-5, size=size) vz = np.sqrt(1 - vx * vx - vy * vy) / m0.n rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.refract(sum, rv.copy(), m0, m1) rvr2 = sum.refract(rv.copy(), m0, m1) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = sum.normal(rvr.x, rvr.y) # Test Snell's law s0 = np.sum(np.cross(normal, rv.v * m0.n)[~rvr.failed], axis=-1) s1 = np.sum(np.cross(normal, rvr.v * m1.n)[~rvr.failed], axis=-1) np.testing.assert_allclose(m0.n * s0, m1.n * s1, rtol=0, atol=1e-9) # Test that rv.v, rvr.v and normal are all in the same plane np.testing.assert_allclose(np.einsum("ad,ad->a", np.cross(normal, rv.v), rv.v)[~rvr.failed], 0.0, rtol=0, atol=1e-12)
def test_refract(): rng = np.random.default_rng(577215) size = 10_000 for i in range(100): R = 1. / rng.normal(0.0, 0.3) conic = rng.uniform(-2.0, 1.0) quad = batoid.Quadric(R, conic) m0 = batoid.ConstMedium(rng.normal(1.2, 0.01)) m1 = batoid.ConstMedium(rng.normal(1.3, 0.01)) lim = min(0.7 * abs(R) / np.sqrt(1 + conic) if conic > -1 else 10, 10) x = rng.uniform(-lim, lim, size=size) y = rng.uniform(-lim, lim, size=size) z = np.full_like(x, -100.0) vx = rng.uniform(-1e-5, 1e-5, size=size) vy = rng.uniform(-1e-5, 1e-5, size=size) vz = np.sqrt(1 - vx * vx - vy * vy) / m0.n rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.refract(quad, rv.copy(), m0, m1) rvr2 = quad.refract(rv.copy(), m0, m1) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = quad.normal(rvr.x, rvr.y) # Test Snell's law s0 = np.sum(np.cross(normal, rv.v * m0.n)[~rvr.failed], axis=-1) s1 = np.sum(np.cross(normal, rvr.v * m1.n)[~rvr.failed], axis=-1) np.testing.assert_allclose(m0.n * s0, m1.n * s1, rtol=0, atol=1e-9) # Test that rv.v, rvr.v and normal are all in the same plane np.testing.assert_allclose(np.einsum("ad,ad->a", np.cross(normal, rv.v), rv.v)[~rvr.failed], 0.0, rtol=0, atol=1e-12)
def test_refract(): rng = np.random.default_rng(57721) size = 10_000 tanx = rng.uniform(-0.1, 0.1) tany = rng.uniform(-0.1, 0.1) plane = batoid.Tilted(tanx, tany) m0 = batoid.ConstMedium(rng.normal(1.2, 0.01)) m1 = batoid.ConstMedium(rng.normal(1.3, 0.01)) x = rng.normal(0.0, 1.0, size=size) y = rng.normal(0.0, 1.0, size=size) z = np.full_like(x, -100.0) vx = rng.uniform(-1e-5, 1e-5, size=size) vy = rng.uniform(-1e-5, 1e-5, size=size) vz = np.sqrt(1 - vx * vx - vy * vy) / m0.n rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.refract(plane, rv.copy(), m0, m1) rvr2 = plane.refract(rv.copy(), m0, m1) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = plane.normal(rvr.x, rvr.y) # Test Snell's law s0 = np.sum(np.cross(normal, rv.v * m0.n)[~rvr.failed], axis=-1) s1 = np.sum(np.cross(normal, rvr.v * m1.n)[~rvr.failed], axis=-1) np.testing.assert_allclose(m0.n * s0, m1.n * s1, rtol=0, atol=1e-9) # Test that rv.v, rvr.v and normal are all in the same plane np.testing.assert_allclose(np.einsum("ad,ad->a", np.cross(normal, rv.v), rv.v)[~rvr.failed], 0.0, rtol=0, atol=1e-12)
def test_refract(): rng = np.random.default_rng(577215) size = 10_000 for _ in range(10): def f(x, y): a = rng.uniform(size=5) return ( a[0]*x**2*y - a[1]*y**2*x + a[2]*3*x - a[3] + a[4]*np.sin(y)*np.cos(x)**2 ) xs = np.linspace(0, 1, 1000) ys = np.linspace(0, 1, 1000) zs = f(*np.meshgrid(xs, ys)) bc = batoid.Bicubic(xs, ys, zs) m0 = batoid.ConstMedium(rng.normal(1.2, 0.01)) m1 = batoid.ConstMedium(rng.normal(1.3, 0.01)) x = rng.uniform(0.1, 0.9, size=size) y = rng.uniform(0.1, 0.9, size=size) z = np.full_like(x, -10.0) vx = rng.uniform(-1e-5, 1e-5, size=size) vy = rng.uniform(-1e-5, 1e-5, size=size) vz = np.sqrt(1-vx*vx-vy*vy)/m0.n rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.refract(bc, rv.copy(), m0, m1) rvr2 = bc.refract(rv.copy(), m0, m1) np.testing.assert_array_equal(rvr.failed, rvr2.failed) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = bc.normal(rvr.x, rvr.y) # Test Snell's law s0 = np.sum(np.cross(normal, rv.v*m0.n)[~rvr.failed], axis=-1) s1 = np.sum(np.cross(normal, rvr.v*m1.n)[~rvr.failed], axis=-1) np.testing.assert_allclose( m0.n*s0, m1.n*s1, rtol=0, atol=1e-9 ) # Test that rv.v, rvr.v and normal are all in the same plane np.testing.assert_allclose( np.einsum( "ad,ad->a", np.cross(normal, rv.v), rv.v )[~rvr.failed], 0.0, rtol=0, atol=1e-12 )
def test_refract(): rng = np.random.default_rng(5772156) size = 10_000 for i in range(10): jmax = rng.integers(4, 100) coef = rng.normal(size=jmax+1)*1e-3 R_outer = rng.uniform(0.5, 5.0) R_inner = rng.uniform(0.0, 0.65*R_outer) zernike = batoid.Zernike(coef, R_outer=R_outer, R_inner=R_inner) lim = 0.7*R_outer m0 = batoid.ConstMedium(rng.normal(1.2, 0.01)) m1 = batoid.ConstMedium(rng.normal(1.3, 0.01)) x = rng.uniform(-lim, lim, size=size) y = rng.uniform(-lim, lim, size=size) z = np.full_like(x, -10.0) vx = rng.uniform(-1e-5, 1e-5, size=size) vy = rng.uniform(-1e-5, 1e-5, size=size) vz = np.sqrt(1-vx*vx-vy*vy)/m0.n rv = batoid.RayVector(x, y, z, vx, vy, vz, t=0) rvr = batoid.refract(zernike, rv.copy(), m0, m1) rvr2 = zernike.refract(rv.copy(), m0, m1) rays_allclose(rvr, rvr2, atol=1e-13) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = zernike.normal(rvr.x, rvr.y) # Test Snell's law s0 = np.sum(np.cross(normal, rv.v*m0.n)[~rvr.failed], axis=-1) s1 = np.sum(np.cross(normal, rvr.v*m1.n)[~rvr.failed], axis=-1) np.testing.assert_allclose( m0.n*s0, m1.n*s1, rtol=0, atol=1e-9 ) # Test that rv.v, rvr.v and normal are all in the same plane np.testing.assert_allclose( np.einsum( "ad,ad->a", np.cross(normal, rv.v), rv.v )[~rvr.failed], 0.0, rtol=0, atol=1e-12 )
def test_refract(): rng = np.random.default_rng(577215) size = 10_000 for i in range(100): zmax = np.inf while zmax > 3.0: R = 0.0 while abs(R) < 15.0: # Don't allow too small radius of curvature R = 1. / rng.normal(0.0, 0.3) # negative allowed conic = rng.uniform(-2.0, 1.0) ncoef = rng.choice(5) coefs = [rng.normal(0, 1e-8) for i in range(ncoef)] asphere = batoid.Asphere(R, conic, coefs) lim = min(0.7 * abs(R) / np.sqrt(1 + conic) if conic > -1 else 5, 5) zmax = abs(asphere.sag(lim, lim)) m0 = batoid.ConstMedium(rng.normal(1.2, 0.01)) m1 = batoid.ConstMedium(rng.normal(1.3, 0.01)) x = rng.uniform(-lim, lim, size=size) y = rng.uniform(-lim, lim, size=size) z = np.full_like(x, -10.0) vx = rng.uniform(-1e-5, 1e-5, size=size) vy = rng.uniform(-1e-5, 1e-5, size=size) vz = np.sqrt(1 - vx * vx - vy * vy) / m0.n rv = batoid.RayVector(x, y, z, vx, vy, vz, t=0) rvr = batoid.refract(asphere, rv.copy(), m0, m1) rvr2 = asphere.refract(rv.copy(), m0, m1) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = asphere.normal(rvr.x, rvr.y) # Test Snell's law s0 = np.sum(np.cross(normal, rv.v * m0.n)[~rvr.failed], axis=-1) s1 = np.sum(np.cross(normal, rvr.v * m1.n)[~rvr.failed], axis=-1) np.testing.assert_allclose(m0.n * s0, m1.n * s1, rtol=0, atol=1e-9) # Test that rv.v, rvr.v and normal are all in the same plane np.testing.assert_allclose(np.einsum("ad,ad->a", np.cross(normal, rv.v), rv.v)[~rvr.failed], 0.0, rtol=0, atol=1e-12)