GRIN
Closed this issue · 1 comments
dccote commented
Adding GRIN is not easy: they need to be split in smaller GRINs for display purposes. Here is some code that works, but is not that good looking:
from raytracing import *
class GRIN(MatrixGroup):
r"""Gradient index (GRIN) lens of length L, with a quadratic index of refraction.
The index is given by n^2 = n0^2 * ( 1 - r^2 alpha^2) ≈ n0 * ( 1 - 1/2 * r^2 alpha^2)
At Thorlabs, the alpha parameter is equal to √A.
An example is here: https://www.thorlabs.com/newgrouppage9.cfm?objectgroup_ID=11167
A ray propagating in a GRIN will oscillate up and down. The number of complete oscillations
is called the pitch. You can initialize with either the alpha parameter (which is a physical parameter)
or the pitch (which is a usage parameter).
Parameters
----------
d : float
the length of the GRIN
n0 : float
The base refraction index of the GRIN. This value cannot be negative. (default=1)
alpha : float
The quadratic parameter for the index (default= None)
pitch : float
The pitch parameter of the the GRIN (number of oscillations alpha*L = 2*pi*pitch) (default=None)
diameter: float
Diameter of GRIN (default = infinity)
label : string
The label of the free space
"""
def __init__(self, L, N=100, n0=1, alpha=None, pitch=None, diameter=float('+Inf'), label=''):
if alpha is None and pitch is None:
raise ValueError("You must set either alpha or the pitch (but not both)")
if alpha is None:
alpha = 2*pi*pitch/L
elif pitch is None:
pitch = alpha*L/2/pi
self.n0 = n0
self.alpha = alpha
self.pitch = pitch
self.dz = L/N # 20 pts per cycle
if self.pitch > 1:
self.dz /= self.pitch
elements = []
for i in range(N):
dzMatrix = Matrix(A=cos(alpha*self.dz),
B=1/alpha*sin(alpha*self.dz),
C=-alpha*sin(alpha*self.dz),
D=cos(alpha*self.dz),
physicalLength=self.dz,
frontVertex=0,
backVertex=self.dz,
frontIndex=n0,
backIndex=n0,
apertureDiameter=diameter,
label=label)
elements.append(dzMatrix)
super().__init__(elements=elements)
def transferMatrix(self, upTo=float('+Inf'), startingAt=float(0)):
""" Returns a Matrix() corresponding to a partial propagation
if the requested distance is smaller than the length of this element.
You can have a
Parameters
----------
upTo : float
The length of the propagation (default=Inf)
Returns
-------
transferMatrix : object of class Matrix
the corresponding matrix to the propagation
"""
if upTo > self.L:
upTo = self.L
if startingAt > upTo:
raise ValueError("In transferMatrix(), `startingAt` {0} must be smaller than `upTo` {1}".format(startingAt, upTo))
distance = upTo-startingAt
if distance < self.L:
return GRIN(L=distance, n0=self.n0, alpha=self.alpha, diameter=self.apertureDiameter, label=self.label)
else:
return self
if __name__ == "__main__":
path = ImagingPath()
path.append(Space(d=10))
path.append(GRIN(10, n0=1, pitch=1, diameter=8, label=''))
path.display()
github-actions commented
Stale issue message