Add files
Added scripts for visualizing paths of rays reflected from a spherical mirror
This commit is contained in:
56
spherical_collimated.py
Normal file
56
spherical_collimated.py
Normal file
@@ -0,0 +1,56 @@
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
|
||||
radius = 100 # curvature radius of the mirror in mm
|
||||
angle_deg = 0 # angle of incidence of the incident beam in degrees
|
||||
rays = 21 # number of rays
|
||||
|
||||
focal_length = radius / 2 # focal length of the mirror
|
||||
a = 1.1 * focal_length # mirror field
|
||||
inc_ang = -angle_deg * np.pi / 180 if angle_deg > 0.000001 else 0.000001 * np.pi / 180 # incident ray angle in radians
|
||||
var = np.arange(-a, a, 0.1)
|
||||
|
||||
# mirror equation
|
||||
def surface(y):
|
||||
return np.sqrt(radius ** 2 - y ** 2) - radius
|
||||
|
||||
# reflection angle
|
||||
def refl_ang(y, inc_ang):
|
||||
return inc_ang - 2 * np.arcsin((-y / np.tan(inc_ang) - surface(y)) / radius * np.sin(inc_ang))
|
||||
|
||||
# incident ray vector (y_start, y_end)
|
||||
# x_vec is vector (x_start, x_end)
|
||||
def inc_vec(y, inc_ang, x_vec):
|
||||
return np.tan(-inc_ang) * (x_vec - surface(y)) + y
|
||||
|
||||
# reflected ray vector (y_start, y_end)
|
||||
# x_vec is vector (x_start, x_end)
|
||||
def refl_vec(y, inc_ang, x_vec):
|
||||
r = refl_ang(y, inc_ang)
|
||||
return np.tan(r) * (x_vec - surface(y) + y / np.tan(r))
|
||||
|
||||
|
||||
plt.figure(figsize=(13, 8))
|
||||
plt.plot(surface(var), var) # mirror surface visualization
|
||||
plt.plot([-2 * radius, 0], [0, 0]) # axis of the mirror
|
||||
plt.plot([-focal_length], [0], 'o') # focal point
|
||||
|
||||
for y in np.linspace(-focal_length, focal_length, rays):
|
||||
x_vec = np.array([-radius, surface(y)])
|
||||
|
||||
plt.plot(x_vec, inc_vec(y, inc_ang, x_vec), 'k', lw=1)
|
||||
|
||||
r = refl_ang(y, inc_ang)
|
||||
if (r < np.pi / 2 and r > -np.pi / 2):
|
||||
plt.plot(x_vec, refl_vec(y, inc_ang, x_vec), 'r', lw=1)
|
||||
else:
|
||||
x_vec_out = np.array([surface(y), 0])
|
||||
plt.plot(x_vec_out, refl_vec(y, inc_ang, x_vec_out), 'r', lw=1)
|
||||
|
||||
plt.title("Radius = {:.1f} mm. Focal length = {:.1f} mm. Incident angle = {:.1f} deg. Number of rays = {}".format(radius, focal_length, angle_deg, rays))
|
||||
plt.xlabel("z, mm")
|
||||
plt.ylabel("r, mm")
|
||||
plt.ylim(-a, a)
|
||||
plt.xlim(-radius, 0)
|
||||
plt.grid()
|
||||
plt.show()
|
||||
77
spherical_point_source.py
Normal file
77
spherical_point_source.py
Normal file
@@ -0,0 +1,77 @@
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from numpy.lib.function_base import angle
|
||||
|
||||
radius = 100 # curvature radius of the mirror in mm (must be positive)
|
||||
angle_d = 30 # maximum angle of incidence of the incident beam in degrees
|
||||
num_rays = 21 # number of rays
|
||||
source_pos = 80 # source position in mm (must be positive)
|
||||
|
||||
focal_length = radius / 2 # focal length of the mirror
|
||||
y = np.linspace(-radius, radius, 1000)
|
||||
|
||||
# mirror equation z = sqrt(R^2 - y^2) - R
|
||||
def surface(y):
|
||||
return np.sqrt(radius ** 2 - y ** 2) - radius
|
||||
|
||||
# angle between the incident ray and the line connecting the point of incidence
|
||||
# of the ray on the mirror and the center of curvature of the mirror
|
||||
def epsilon(inc_angle):
|
||||
q = radius - source_pos
|
||||
return np.arcsin(q / radius * np.sin(inc_angle))
|
||||
|
||||
# angle of reflected ray
|
||||
def ref_angle(inc_angle):
|
||||
return inc_angle - 2 * epsilon(inc_angle)
|
||||
|
||||
# the z-coordinate of the intersection of the reflected ray with the axis
|
||||
def ref_z(inc_angle):
|
||||
q = radius * np.sin(-epsilon(inc_angle)) / np.sin(ref_angle(inc_angle))
|
||||
return radius - q
|
||||
|
||||
# the y-coordinate of the intersection of the incident ray with the mirror
|
||||
def height(inc_angle):
|
||||
phi = ref_angle(inc_angle) + epsilon(inc_angle)
|
||||
return radius * np.sin(phi)
|
||||
|
||||
# line equation for extension of the reflected ray
|
||||
def line(inc_angle, z, z0):
|
||||
return np.tan(inc_angle) * (z - z0)
|
||||
|
||||
|
||||
plt.figure(figsize=(13, 8))
|
||||
plt.plot(surface(y), y) # mirror surface visualization
|
||||
plt.plot([-2 * radius, 0], [0, 0]) # axis of the mirror
|
||||
plt.plot([-focal_length], [0], 'o') # focal point
|
||||
|
||||
for ang in np.linspace(-angle_d, angle_d, num_rays):
|
||||
inc_angle = ang * np.pi / 180
|
||||
h = height(inc_angle)
|
||||
|
||||
z_inc = np.array([-source_pos, surface(h)])
|
||||
y_inc = np.array([0, h])
|
||||
plt.plot(z_inc, y_inc, 'k', lw=1) # draw incident beam
|
||||
|
||||
z_0 = ref_z(inc_angle)
|
||||
if np.isnan(z_0):
|
||||
z_0 = -2 * radius
|
||||
|
||||
if source_pos >= focal_length:
|
||||
z_0 = -z_0 if z_0 > 0 else z_0
|
||||
else:
|
||||
z_0 = z_0 if z_0 > 0 else -z_0
|
||||
|
||||
z_ref = np.array([surface(h), -2 * radius])
|
||||
y_ref = np.array([h, line(ref_angle(inc_angle), -2 * radius, z_0)])
|
||||
if abs(source_pos) < abs(2 * focal_length) and abs(source_pos) > abs(focal_length) and abs(z_0) > abs(2 * radius):
|
||||
z_ref = np.array([surface(h), z_0])
|
||||
y_ref = np.array([h, 0])
|
||||
plt.plot(z_ref, y_ref, 'r', lw=1)
|
||||
|
||||
plt.title("Radius = {:.1f} mm. Focal length = {:.1f} mm. Source position = {:.1f} mm.\nMaximum incident angle = {:.1f} deg. Number of rays = {}".format(radius, focal_length, -source_pos, angle_d, num_rays))
|
||||
plt.xlabel("z, mm")
|
||||
plt.ylabel("r, mm")
|
||||
plt.ylim(-radius, radius)
|
||||
plt.xlim(-2 * radius, 0)
|
||||
plt.grid()
|
||||
plt.show()
|
||||
Reference in New Issue
Block a user