<jupyter_start><jupyter_text>Lecture-02 Snell's Law* author : <NAME>* Data : 2019/12/03<jupyter_code>%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np<jupyter_output><empty_output><jupyter_text>Snell's LawSnell's Law is an equation describing the relation between the angle of the incident ray and the angle of the refracted ray. $n_i$ and $n_t$ is the refractive index of the incident material and the transmissive material, respectively. Besides, $\theta_i$ is the incident angle and $\theta_t$ is the transmissive angle as in **Fig. 1**.$$Fig. 1. (a) n_tn_i $$ Snell's Law:$$n_isin\theta_i = n_tsin\theta_t$$From Snell's Law, it is obvious that if $n_tn_i$, $\theta_t$ would be smaller than $\theta_i$ as in **Fig. 1(b)**.<jupyter_code>def SnellLaw(theta_i, ni, nt=1.0):
    # theta_i : incident angle
    # ni : the refractive index of the incident material
    # nt : the refractive index of the transmissive material
    theta_i = np.array( theta_i, dtype=np.complex_ )
    
    # theta_t : refractive angle
    theta_t = np.arcsin( (ni/nt) * np.sin(theta_i) )
    return theta_t
theta_i = np.linspace(0, np.pi/2, 10000)
theta_t = SnellLaw( theta_i, ni = 1.5, nt = 1.0)

## plot data
fig, axes = plt.subplots(1,1)
axes.plot( theta_i*180/np.pi, theta_t*180/np.pi, 'r-', linewidth=2.0)
axes.set_xlabel(r'$\theta_i$ (deg.)', fontsize=20)
axes.set_ylabel(r'$\theta_t$ (deg.)', fontsize=20)
plt.xlim( 0, 90);
plt.ylim( 0, 90);
theta_i = np.linspace(0, np.pi/2, 1000)
theta_t = SnellLaw( theta_i, ni = 1.0, nt = 1.5)

## plot data
fig, axes = plt.subplots(1,1)
axes.plot( theta_i*180/np.pi, theta_t*180/np.pi, 'r-', linewidth=2.0)
axes.set_xlabel(r'$\theta_i$ (deg.)', fontsize=20)
axes.set_ylabel(r'$\theta_t$ (deg.)', fontsize=20)
plt.xlim( 0, 90);
plt.ylim( 0, 90);<jupyter_output>C:\Users\User\Anaconda3\lib\site-packages\numpy\core\numeric.py:492: ComplexWarning: Casting complex values to real discards the imaginary part
  return array(a, dtype, copy=False, order=order)<jupyter_text>* From Snell's Law, critical angle, $\theta_c$, can be defined as $$\theta_c=sin^{-1}(\frac{n_t}{n_i})$$<jupyter_code>def CriticalAngle( ni, nt):
    return np.arcsin( nt/ni ) if nt<=ni else np.pi/2 
print( 'From ni=1.0 into nt=1.5, critical angle is {0:>.2f} degree'.format( CriticalAngle( 1.0, 1.5) * 180/np.pi ) )
print( 'From ni=1.5 into nt=1.0, critical angle is {0:>.2f} degree'.format( CriticalAngle( 1.5, 1.0) * 180/np.pi ) )
ni = 1.5;
nt_list = np.linspace(1.0, 2.5, 150)

## find critical angles
CA_List = np.zeros( nt_list.size, dtype=np.float64 )
for ii in range( len( nt_list ) ):
     CA_List[ii] = CriticalAngle( ni, nt_list[ii] )
        
## plot data
fig, axes = plt.subplots(1,1)
axes.plot(nt_list, CA_List*180/np.pi, 'r-', linewidth=2.0)
axes.set_xlabel(r'$n_t$', fontsize=20)
axes.set_ylabel(r'$\theta_c$ (deg.)', fontsize=20)
plt.xlim( np.min(nt_list), np.max(nt_list));
plt.ylim( 0, 90);<jupyter_output><empty_output><jupyter_text>But how does  Snell's Law come from?In the physics of senior high school, the teacher would tell us that the light is in wave nature. Here, we'll going to use wave property to prove the Snell's Law.As in **Fig.2.**, the wave front should be normal to the propagation direction and besides, the propagation vector is parallel to the wave vector $\textbf{k}=(k_x,k_y,k_z)$ and the relation between $k_x,k_y,k_z$, refractive index (n), and the angular frequency, $\omega$, is $$(nk_0)^2 = k^2 = k_x^2 + k_y^2 + k_z^2$$$$k_o = \omega/c = 2\pi/\lambda$$where c is the speed of light in vacuum and $k_o$ is the wave number in vacuum.Besides, as shown in **Fig. 2.**, according to the boundary condition, the wavelength along the surface should be continuous in both the incident material and the transmissive material. (i.e. $\lambda_{x,i}=\lambda_{x,t}$ and $\lambda_{y,i}=\lambda_{y,t}$ ). Besides, as discussed in **Lecture 1**, the components of the wave vector can be quitely write down by the wavelength along the arbitraty direction (i.e. $k_x = 2\pi/\lambda_x$). So the tangential wave number should also be continuous on the boundary. Then, $$k_{x,i}=k_{x,t}$$$$k_{y,i}=k_{y,t}$$As a result, the z component of the wave vector in material 1 and material 2 can be calculated as the following blocks.$$Fig. 2. $$<jupyter_code>def cal_kz(k, kx, ky):
    # n : refractive index
    # ko : wave number in vacuum
    # kx : wave number along x-axis
    # ky : wave number along y-axis
    kz = np.sqrt( k**2 - kx**2 - ky**2, dtype=np.complex_ )
    # process floating
    mask = np.abs( np.real(kz) )<1e-15  
    kz[mask] = 1j * np.imag( kz[mask] )
    mask = (np.real(kz)==0) & (np.imag( kz )<0)
    kz[mask] = -kz[mask]
    return kz
wavelength = 550 # incident wavelength (nm)
ko = 2 * np.pi/wavelength # wave number in vacuum
ni = 1.5 # refractive index of incident material
nt = 1.0 # refractive index of transmissive material<jupyter_output><empty_output><jupyter_text>$$k_x = ksin\theta cos\phi$$$$k_y = ksin\theta sin\phi$$$$k_z = kcos\theta$$<jupyter_code>k_i = ni * ko
theta_i = np.linspace(0, np.pi/2, 1000, dtype=np.complex_)
phi_i = np.zeros( theta_i.size, dtype=np.complex_)
kx_i = k_i * np.sin(theta_i) * np.cos(phi_i)
ky_i = k_i * np.sin(theta_i) * np.sin(phi_i)
kz_i = cal_kz(k_i, kx_i, ky_i)

## plot data
fig, axes = plt.subplots(1,1)
axes.plot(theta_i*180/np.pi, kx_i, 'r-', linewidth=2.0)
axes.plot(theta_i*180/np.pi, kz_i, 'k-', linewidth=2.0)
axes.set_xlabel(r'$\theta_i$ (deg.)', fontsize=20)
axes.legend([r'$k_{x,i}$', r'$k_{z,i}$'], fontsize=20)
plt.xlim( 0, 90);
k_t = nt * ko
kx_t, ky_t = kx_i, ky_i # continuity in tangential components of the wave vector
kz_t = cal_kz(k_t, kx_t, ky_t)

## plot data
fig, axes = plt.subplots(1,1)
axes.plot(theta_i*180/np.pi, kx_i, 'r-', linewidth=2.0)
axes.plot(theta_i*180/np.pi, kz_i, 'k-', linewidth=2.0)
axes.plot(theta_i*180/np.pi, kz_t, 'b-', linewidth=2.0)

axes.set_xlabel(r'$\theta_i$ (deg.)', fontsize=20)
axes.legend([r'$k_{x,i}$', r'$k_{z,i}$', r'$k_{z,t}$'], fontsize=10)
plt.xlim( 0, 90);<jupyter_output>C:\Users\User\Anaconda3\lib\site-packages\numpy\core\numeric.py:492: ComplexWarning: Casting complex values to real discards the imaginary part
  return array(a, dtype, copy=False, order=order)<jupyter_text>Up to now, we have calculated the wave vector of the refracted light, hence the refracted angle can be calculated as:$$\theta = cos^{-1}(\frac{k_z}{k})$$<jupyter_code>def cal_theta_from_vector(vx, vy, vz):
    v_len = np.sqrt( vx**2 + vy**2 + vz**2)
    theta = np.arccos( vz/v_len )
    return theta
theta_t = cal_theta_from_vector(kx_t, ky_t, kz_t)
theta_t_SL = SnellLaw(theta_i, ni, nt)

## plot data
fig, axes = plt.subplots(1,1)
axes.plot( theta_i*180/np.pi, theta_t_SL*180/np.pi, 'k-', linewidth=2.0)
axes.plot( theta_i*180/np.pi, theta_t*180/np.pi, 'r-', linewidth=2.0)
axes.set_xlabel(r'$\theta_i$ (deg.)', fontsize=20)
axes.set_ylabel(r'$\theta_t$ (deg.)', fontsize=20)
axes.legend(["calculate from Snell's Law", "calculate from wave front"], fontsize=15)
plt.xlim( 0, 90);
plt.ylim( 0, 90);<jupyter_output>C:\Users\User\Anaconda3\lib\site-packages\numpy\core\numeric.py:492: ComplexWarning: Casting complex values to real discards the imaginary part
  return array(a, dtype, copy=False, order=order)
{'fraction_non_alphanumeric': 0.16228130596500895, 'fraction_numerical': 0.0351288056206089, 'mean_word_length': 4.6498054474708175, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '498078', 'license': 'MIT', 'n_tokens_mistral': 3168, 'n_tokens_neox': 2890, 'n_words': 771, 'path': "Lecture-02 Snell's Law.ipynb", 'repo_name': 'd04943016/PlanarOpticsLecture', 'size': '7264'}