def test_force_normal(self): # The ray is normally incident on the sphere c = np.array([5.0,0,0]) R = 1 o = np.array([[0.0,0,0]]) l = np.array([[1.0,0,0]]) # This is the relative refractive index of the sphere nr = 1.5 # And this is the polarization of the ray in Jones notation p = np.array([[1.0,0,0]]) opt = osys.OpticalSystem(c, R, nr) opt._c = np.array([c]) opt._l = l opt._o = o forces = opt._ray_force(p) # There should be a force towards +x. Moreover, it should more than 0.04 (reflectivity) self.assertGreater(forces[0,0], 0.04) # And the forces in the other directions should be zero self.assertTrue(np.allclose(forces[0,1:], 0))
def test_force_sign(self): # The ray is a bit displaced to the top c = np.array([5.0,0,0]) R = 1 o = np.array([[0,0,0.1]]) l = np.array([[1.0,0,0]]) # This is the relative refractive index of the sphere nr = 1.5 # And this is the polarization of the ray in Jones notation p = np.array([[1.0,0,0]]) opt = osys.OpticalSystem(c, R, nr) opt._c = np.array([c]) opt._l = l opt._o = o forces = opt._ray_force(p) # Since the ray will be refracted towards -z, the force should be towards +z self.assertGreater(forces[0,2], 0) # And there should be a force towards +x self.assertGreater(forces[0,0], 0)
def test_snell_homogeneous(self): # If the relative index is 1, then there should be no change of propagation at all opt = osys.OpticalSystem(np.array([4.0,0,0]), 1, 1) th = np.array([0, np.pi/3, np.pi/4, np.pi/5]) self.assertTrue(np.allclose(opt._snell(th), th))
def test_snell_tangent(self): # At tangent incidence, the refr. angle should be critical: nr = 1.5 opt = osys.OpticalSystem(np.array([4.0,0,0]), 1, nr) r = opt._snell(np.array([np.pi/2])) self.assertAlmostEqual(np.sin(r)[0], 1/nr)
def test_intersect_normal_angle_director(self): opt = osys.OpticalSystem(np.array([3.0,0,0]), 1, 1.5) opt._o = np.array([[3.0,0,0]]) opt._l = np.array([[1.0,1,1]]) angle = opt._intersection_angle() self.assertAlmostEqual(angle[0], 0)
def test_intersect_45(self): # Here, the ray should intersect the sphere at 45 degrees opt = osys.OpticalSystem(np.array([4.0,0,0]), 1, 1.5) opt._o = np.array([[0,0,-3.0]]) opt._l = np.array([[1,0,1.0]]) angle = opt._intersection_angle() self.assertAlmostEqual(angle[0], np.pi/4)
def test_intersect_tangent(self): # What happens if the ray is exactly tangent to the sphere? opt = osys.OpticalSystem(np.array([3.0,0,0]), 1, 1.5) opt._o = np.array([[4.0,0,10]]) opt._l = np.array([[0,0,-1.0]]) angle = opt._intersection_angle() self.assertAlmostEqual(angle[0], np.pi/2)
def test_intersect_normal_at_zero(self): # What happens if the position of the intersection is (0,0,0)? opt = osys.OpticalSystem(np.array([1.0,0,0]), 1, 1.5) opt._o = np.array([[1.0,0,0]]) opt._l = np.array([[-1.0,1,1]]) angle = opt._intersection_angle() self.assertAlmostEqual(angle[0], 0)
def test_intersect_normal_angle_director_external(self): # And now let the line hit the sphere normally, but at an angle to an axis opt = osys.OpticalSystem(np.array([5.0,0,0]), 1, 1.5) opt._o = np.array([[0,0,5.0]]) opt._l = np.array([[1.0,0,-1]]) angle = opt._intersection_angle() self.assertAlmostEqual(angle[0], 0, places=5)
def test_intersect_normal_inv_director(self): opt = osys.OpticalSystem(np.array([3.0,0,0]), 1, 1.5) opt._o = np.array([[3.0,0,0]]) opt._l = np.array([[1.0,0,0]]) opt._l = -6 * opt._l ## Inverting the line director shouldn't have any effect: angle = opt._intersection_angle() self.assertAlmostEqual(angle[0], 0)
def test_fresnel_brewster(self): # The reflectivity of a p-polarized ray should be nearly 0 at Brewster's angle nr = 1.5 # Length of test sample testlen = 20 th = np.arctan(nr) * np.ones(testlen) r = np.zeros(testlen) Pp = np.ones(testlen) opt = osys.OpticalSystem(np.array([4.0,0,0]), 1, nr) r = opt._snell(th) T, R = opt._fresnel(th, r, Pp) self.assertTrue(np.allclose(R, 0))
def test_fresnel_tangent(self): # The reflectivity should be 1 at tangent incidence, regardless of polarization nr = 1.5 # Length of test sample testlen = 20 th = np.pi/2 * np.ones(testlen) r = np.zeros(testlen) Pp = np.linspace(0, 1, testlen) opt = osys.OpticalSystem(np.array([4.0,0,0]), 1, nr) r = opt._snell(th) T, R = opt._fresnel(th, r, Pp) self.assertTrue(np.allclose(T+R, 1)) self.assertTrue(np.allclose(R, 1))
def test_fresnel_normal(self): # Test Fresnel at normal incidence. It should not depend on the polarization, and the energy must be conserved between the transmittance and reflectance # Note that Fresnel only really depends on the relative index. # Also note that the polarization is specified as the normalized power of p-polarization (Pp). Then, the power of the s-polarization is simply (1-Pp). nr = 1.5 # Length of test sample testlen = 20 th = np.zeros(testlen) r = np.zeros(testlen) Pp = np.linspace(0, 1, testlen) opt = osys.OpticalSystem(np.array([4.0,0,0]), 1, nr) T, R = opt._fresnel(th, r, Pp) self.assertTrue(np.allclose(T+R, 1)) self.assertTrue(np.allclose(R, ((1 - nr)/(1 + nr))**2))
def test_force_ashkin(self): # Test the maximum gradient forces published in Ashkin, 1992 # The origin of the ray will be on the sphere for simpler calculations: c = np.array([1.0,0,0]) R = 1 o = np.array([[0.0,0,0]]) opt = osys.OpticalSystem(np.array([4.0,0,0]), 1, 1.5) opt._c = np.array([c]) # And this is the polarization of the ray in Jones notation (circular) p = np.array([[1.0,1j,0]]) data = np.array([ [1.1, np.sqrt(0.429**2 + 0.262**2), 79*np.pi/180], [1.2, np.sqrt(0.506**2 + 0.341**2), 72*np.pi/180], [1.4, np.sqrt(0.566**2 + 0.448**2), 64*np.pi/180], [1.6, np.sqrt(0.570**2 + 0.535**2), 60*np.pi/180], [1.8, np.sqrt(0.547**2 + 0.625**2), 59*np.pi/180], [2.0, np.sqrt(0.510**2 + 0.698**2), 59*np.pi/180], [2.5, np.sqrt(0.405**2 + 0.837**2), 64*np.pi/180] ]) def check(row): th = row[2] Q = row[1] nr = row[0] opt.set_particle_index(nr) opt._l = np.array([[np.cos(th), 0, np.sin(th)]]) forces = opt._ray_force(p) return np.abs(npl.norm(forces[0,:]) - Q) res = np.apply_along_axis(check, axis=1, arr=data) #print(res) self.assertLess(np.max(res), 0.021)
def test_snell_normal(self): # At normal incidence, the angle stays zero: opt = osys.OpticalSystem(np.array([4.0,0,0]), 1, 1.5) r = opt._snell(np.array([0])) self.assertAlmostEqual(r[0], 0)
def test_intersect_invalid_radius(self): ## The system should not accept zero or negative sphere radiuses for R in [-1, 0]: with self.assertRaises(ValueError): opt = osys.OpticalSystem(np.array([4.0,0,0]), R, 1.5)