1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
|
#!/usr/bin/env ruby
# Frequency response of a Fabry-Perot Michelson interferometer
#
require("gsl")
CLIGHT = GSL::CONST::MKSA::SPEED_OF_LIGHT
class Michelson
def initialize(len, wavelength)
@len = len.to_f
@laserfreq = 2.0*Math::PI*CLIGHT/wavelength.to_f
end
def response(f)
if f.class != GSL::Vector; f = GSL::Vector[f]; end
r = GSL::Vector::Complex[f.size]
f.each_index do |i|
freq = f[i]
omega = 2.0*Math::PI*freq
a = @len*omega/CLIGHT
# r[i] = 2.0*@laserfreq/omega*Math::sin(a)*GSL::Complex[0, -a].exp
r[i] = 2.0*@laserfreq/omega*Math::sin(a)*GSL::Complex::exp(0, -a)
end
r
end
attr_reader :len, :laserfreq
end
class FabryPerot
# rF: Reflectance of the front mirror
# rE: Reflectance of the end mirror
# tF: Transmittance of the front mirror
def initialize(len, wavelength, rF, rE)
@len = len.to_f
@laserfreq = 2.0*Math::PI*CLIGHT/wavelength.to_f
@tF = Math::sqrt(1.0 - rF*rF)
@rF = rF
@rE = rE
end
def response(f)
if f.class != GSL::Vector; f = GSL::Vector[f]; end
r = GSL::Vector::Complex[f.size]
f.each_index do |i|
freq = f[i]
omega = 2.0*Math::PI*freq
a = 2.0*@len*omega/CLIGHT
r[i] = @tF*@tF*@rE/(1.0 - @rF*@rE)/(1.0 - @rF*@rE*GSL::Complex::exp(0, -a))
end
r
end
attr_reader :len, :laserfreq, :tF, :rF, :rE
end
class FPMI
def initialize(len, wavelength, rF, rE)
@mi = Michelson.new(len, wavelength)
@fp = FabryPerot.new(len, wavelength, rF, rE)
end
def response(f)
@mi.response(f)*@fp.response(f)
end
attr_reader :mi, :fp
end
# Fabry-Perot Michelson IFO of the same length
fpmi = FPMI.new(3000, 1e-6, 0.85, 1.0)
f = GSL::Vector.linspace(10, 100000, 1000)
rmi = fpmi.mi.response(f).amp/1e11
rfpmi = fpmi.response(f).amp/1e11
GSL::graph(f, rmi, rfpmi, "-C -g 3 -l x -l y -y 1e-3 1e2 -L 'Red: MI 3km, Green: FPMI 3km'")
|