Commit 8e45aecc authored by Daniel Toyra's avatar Daniel Toyra
Browse files

Added modematching functions for 1 and 2 lenses. Not very generalised at the moment.

parent 116aa3e9
import pylab as pl
import scipy.optimize as opt
from pykat import finesse
from pykat.detectors import *
from pykat.components import *
from pykat.commands import *
from pykat.structs import *
from numpy import *
# from modematch import modematch
import pykat.utilities.optics.ABCD as abcd
import time
def mmf(f, d, q1, q2, c, d2_min):
'''
Function used to optimize lenses for modematching
f - array of slice objects. It gives the allowed focal lengths.
d - array of slice objects. Gives the allowed range of distances.
D - total distance between the two beam waists
q1 - beam parameter at first waist
q2 - beam parameter at second waist
'''
# Optimizes the distances d for each focal lenght in f1 and f2.
res = opt.brute(mmd, d, args=(f, q1, q2, c, d2_min), \
full_output=True, finish=opt.fmin, disp=True)
# Returns the error of the optimised distances.
return res[1]
def mmd(d, f, q1, q2, c, d2_min):
'''
Function used ot optimize distances between waists and lenses,
given focal lengths f1 and f2. The parameters are the same as
defined above for mmf.
'''
D = d[1]
d = d[0]
# Checking if the distances are valid
if D>d2_min+2*c and d > c and d < D-c-d2_min:
# ABCD-matrices
M1 = abcd.space(1,d)
M2 = abcd.lens(f)
M3 = abcd.space(1,D-d)
# Total ABCD-matrix
M = M3*M2*M1
A = M[0,0]
B = M[0,1]
C = M[1,0]
D = M[1,1]
# Obtained beam parameter at the second waist position
q = (A*q1 + B)/(C*q1 + D)
# Returns the difference between the obtained
# parameter and the target.
return abs(q-q2)
# If the distances are invalid, return inf
else:
return inf
def mmf2(f, d, D, q1, q2, c1, c2, c3):
'''
Function used to optimize two lenses in serial for modematching
f - array of arrays of slice objects giving the allowed focal lengths.
d - array of slice objects. Gives the allowed range of distances.
D - total distance between the two beam waists
q1 - beam parameter at first waist
q2 - beam parameter at second waist
'''
# Focal lengths
f1 = f[0]
f2 = f[1]
# Optimizes the distances d for each focal lenght in f1 and f2.
res = opt.brute(mmd2, d, args=(f1, f2, D, q1, q2, c1, c2, c3), \
full_output=True, finish=opt.fmin)
# Returns the error of the optimised distances.
return res[1]
def mmd2(d, f1, f2, L, q1, q2, c1, c2, c3):
'''
Function used ot optimize distances between waists and lenses,
given focal lengths f1 and f2. The parameters are the same as
defined above for mmf2.
'''
# Distance waist1 --> lens1
d1 = d[0]
# Distance lens1 --> lens2
d2 = d[1]
# Checking if the distances are valid
if d1 > c1 and d1 < L-c2-c3 and d2 > c2 and \
d2 < L-c3-d1:
# ABCD-matrices
M1 = abcd.space(1,d1)
M2 = abcd.lens(f1)
M3 = abcd.space(1,d2)
M4 = abcd.lens(f2)
M5 = abcd.space(1,L-d1-d2)
# Total ABCD-matrix
M = M5*M4*M3*M2*M1
A = M[0,0]
B = M[0,1]
C = M[1,0]
D = M[1,1]
# Obtained beam parameter at the second waist position
q = (A*q1 + B)/(C*q1 + D)
# Returns the difference between the obtained
# parameter and the target.
return abs(q-q2)
# If the distances are invalid, return inf
else:
return inf
def moma2(d, f1, f2, D, q1, q2):
'''
Unused function that was used to solve a system of two equations
to modematch. The parameters are the same as defined above for
mmf and mmd.
'''
d1 = d[0]
d2 = d[1]
M1 = abcd.space(1,d1)
M2 = abcd.lens(f1)
M3 = abcd.space(1,d2)
M4 = abcd.lens(f2)
M5 = abcd.space(1,D-d1-d2)
M = M5*M4*M3*M2*M1
A = M[0,0]
B = M[0,1]
C = M[1,0]
D = M[1,1]
# q = (A*q1 + B)/(C*q1 + D)
f = q2 - (A*q1 + B)/(C*q1 + D)
return [f.real, f.imag]
def modematch(q1, q2, f, D, d1, d2_min=.0, c=.01):
'''
Simple and not efficient modematching using 1 lens. Quickly translated from the
two lens case just to test for the filter cavity simulations. Should be fixed
to a more general, efficient, and useful function at some point.
q1 d1 f d2 q2
| <--> | <--> |
| <------ D -----> |
Input: q1, q2, f, D, d1, d2_min
q1, q2 - Complex beam parameters to be mode matched.
f - Slice-object of available lense. E.g., if the
available lenses are of focal length 1, 1.5
and 2 meters, then f = slice(1, 2, 0.5).
D - Slice-oject with total distances between q1 and
q2 that are be searched with brute force. The
best match of these distances will be optimised
further. E.g., D = slice(D_min, D_max, D_step).
d1 - Slice-object with distanes between q1 and the
lens. E.g., d1 = slice(d1_min, d1_max, d1_step),
where d1_max < D_max-d2_min-2*c
d2_min - Minimum distance between the lens and q2
c - Minimum distance between the lens and any other
optic. Here, we are assuming that there are
optics constraining all the distances, thus c is
the absolute shortest distance d1 and d2 can take
even if themselves have 0 as minimum distance.
Returns: f, d1, d2, D, res
f - The focal length of the "best" match found.
d1 - The d1 of the "best" match found.
d2 - The d2 of the "best" match found.
D - The D of the "best" match found.
res - abs(q1-q2) of this match.
By Daniel Toyra (dtoyra@star.sr.bham.ac.uk)
'''
d = [d1, D]
f = [f]
# Finding optimal lens
fsol = opt.brute(mmf, f, args=(d, q1, q2, c, d2_min),
full_output=True, finish=None)
print(fsol)
f = fsol[0]
# Finding optimal lens positions given f1, f2
dsol = opt.brute(mmd, d, args=(f, q1, q2, c, d2_min), \
full_output=True, finish=opt.fmin)
d1 = dsol[0][0]
D = dsol[0][1]
d2 = D-d1
res = dsol[1]
return f, d1, d2, D, res
def modematch2(q1, q2, D, c1, c2, c3):
'''
Modematching with 2 lenses. The allowed focal lengths are
specified inside this function. Later, it would probably
be better to pass the available lenses as an argument.
D is total distance between q1 and q2. c1, c2, and c3 are the
minimum distances between q1 and lens1, lens1 and lens2, and
lens2 and q2, respectively. c2 also moonlights as the minimum
distance between any pair of optics. q1 and q2 are the complex
beam parameters to be matched.
q1 d1 f1 d2 f2 q2
| <--> | <--> | |
| <---------- D ---------> |
By Daniel Toyra (dtoyra@star.sr.bham.ac.uk)
'''
print ' Modematching...'
# Controller
# -----------------------------------------------------
# Allowed lenses
f1_range = slice(-1.0, -0.05, 0.05)
f2_range = slice(0.05, 1.0, 0.05)
# Number of distance points between each pair of optic
N = 15
# -----------------------------------------------------
f = (f1_range, f2_range)
start1 = c1
stop1 = D-c2-c3
step1 = (stop1-start1)/N
start2 = c2
stop2 = D-c1-c3
step2 = (stop2-start2)/N
d1_range = slice(start1, stop1, step1)
d2_range = slice(start2, stop2, step2)
d = (d1_range, d2_range)
# Finding optimal pair of lenses
fsol = opt.brute(mmf2, f, args=(d, D, q1, q2, c1, c2, c3), \
full_output=True, finish=None)
f1 = fsol[0][0]
f2 = fsol[0][1]
# Finding optimal lens positions given f1, f2
dsol = opt.brute(mmd2, d, args=(f1, f2, D, q1, q2, c1, c2, c3), \
full_output=True, finish=opt.fmin)
d1 = dsol[0][0]
d2 = dsol[0][1]
d3 = D-d1-d2
res = dsol[1]
# Checking if the solution satisfies the constraints.
# (it should always be okay, so remove this later if
# no invalid solutions are found in a while)
if d1 > c1 and d1 < D-c2-c3 and d2 > c2 and \
d2 < D-d1-c3 and d3 > c3:
isMM = True
print ' Match found!'
print ' res = ' + str(res)
print ' d1 = ' + str(d1) + ' m'
print ' d2 = ' + str(d2) + ' m'
print ' d3 = ' + str(d3) + ' m'
print ' f1 = ' + str(f1) + ' m'
print ' f2 = ' + str(f2) + ' m'
print ' D_tot = ' + str(d1+d2+d3) + ' m'
else:
isMM = False
print ' No match found. Unphysical solution...'
print d1
print d2
print d3
print res
return f1, f2, d1, d2, d3, res, isMM
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment