def test_reflect(): rng = np.random.default_rng(57721) 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]) 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.full_like(x, 1) rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.reflect(sum, rv.copy()) rvr2 = sum.reflect(rv.copy()) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = sum.normal(rvr.x, rvr.y) # Test law of reflection a0 = np.einsum("ad,ad->a", normal, rv.v)[~rvr.failed] a1 = np.einsum("ad,ad->a", normal, -rvr.v)[~rvr.failed] np.testing.assert_allclose(a0, a1, rtol=0, atol=1e-12) # 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_reflect(): rng = np.random.default_rng(57721) 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) 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.full_like(x, 1) rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.reflect(quad, rv.copy()) rvr2 = quad.reflect(rv.copy()) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = quad.normal(rvr.x, rvr.y) # Test law of reflection a0 = np.einsum("ad,ad->a", normal, rv.v)[~rvr.failed] a1 = np.einsum("ad,ad->a", normal, -rvr.v)[~rvr.failed] np.testing.assert_allclose(a0, a1, rtol=0, atol=1e-12) # 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_reflect(): rng = np.random.default_rng(57721) size = 10_000 for i in range(100): R = 1. / rng.normal(0.0, 0.3) # negative allowed para = batoid.Paraboloid(R) 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.full_like(x, 1) rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.reflect(para, rv.copy()) rvr2 = para.reflect(rv.copy()) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = para.normal(rvr.x, rvr.y) # Test law of reflection a0 = np.einsum("ad,ad->a", normal, rv.v)[~rvr.failed] a1 = np.einsum("ad,ad->a", normal, -rvr.v)[~rvr.failed] np.testing.assert_allclose(a0, a1, rtol=0, atol=1e-12) # 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_reflect(): rng = np.random.default_rng(5772) size = 10_000 tanx = rng.uniform(-0.1, 0.1) tany = rng.uniform(-0.1, 0.1) plane = batoid.Tilted(tanx, tany) 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.ones_like(x) rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.reflect(plane, rv.copy()) rvr2 = plane.reflect(rv.copy()) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = plane.normal(rvr.x, rvr.y) # Test law of reflection a0 = np.einsum("ad,ad->a", normal, rv.v)[~rvr.failed] a1 = np.einsum("ad,ad->a", normal, -rvr.v)[~rvr.failed] np.testing.assert_allclose(a0, a1, rtol=0, atol=1e-12) # 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_reflect(): rng = np.random.default_rng(57721) 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) 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.full_like(x, 1) rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.reflect(bc, rv.copy()) rvr2 = bc.reflect(rv.copy()) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = bc.normal(rvr.x, rvr.y) # Test law of reflection a0 = np.einsum("ad,ad->a", normal, rv.v)[~rvr.failed] a1 = np.einsum("ad,ad->a", normal, -rvr.v)[~rvr.failed] np.testing.assert_allclose( a0, a1, rtol=0, atol=1e-12 ) # 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_reflect(): rng = np.random.default_rng(577215) size = 10_000 for i in range(10): jmax = rng.integers(4, 36+1) 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 x = rng.uniform(-lim, lim, size=size) y = rng.uniform(-lim, lim, size=size) z = np.full_like(x, -1.0) vx = rng.uniform(-1e-5, 1e-5, size=size) vy = rng.uniform(-1e-5, 1e-5, size=size) vz = np.full_like(x, 1) rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.reflect(zernike, rv.copy()) rvr2 = zernike.reflect(rv.copy()) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = zernike.normal(rvr.x, rvr.y) # Test law of reflection a0 = np.einsum("ad,ad->a", normal, rv.v)[~rvr.failed] a1 = np.einsum("ad,ad->a", normal, -rvr.v)[~rvr.failed] np.testing.assert_allclose( a0, a1, rtol=0, atol=1e-12 ) # 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_reflect(): rng = np.random.default_rng(57721) 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)) 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.full_like(x, 1) rv = batoid.RayVector(x, y, z, vx, vy, vz) rvr = batoid.reflect(asphere, rv.copy()) rvr2 = asphere.reflect(rv.copy()) rays_allclose(rvr, rvr2) # print(f"{np.sum(rvr.failed)/len(rvr)*100:.2f}% failed") normal = asphere.normal(rvr.x, rvr.y) # Test law of reflection a0 = np.einsum("ad,ad->a", normal, rv.v)[~rvr.failed] a1 = np.einsum("ad,ad->a", normal, -rvr.v)[~rvr.failed] np.testing.assert_allclose(a0, a1, rtol=0, atol=1e-12) # 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)