Commit 82b2d8f0 authored by Daniel Brown's avatar Daniel Brown

Merge branch 'master' of git.ligo.org:finesse/pykat

parents ac4b7da6 c300c6c3
......@@ -45,6 +45,7 @@ import pykat.style as style
from pykat.optics.gaussian_beams import BeamParam
from pykat.plotting import init_pykat_plotting
from pykat.style import use as set_plot_style
from .SIfloat import SIfloat
......
......@@ -26,6 +26,11 @@ import pkg_resources
from scipy.constants import c as clight
from scipy.optimize import fmin
from pykat.optics.hellovinet import hellovinet
from pykat.tools.lensmaker import lensmaker
from pykat.tools.compound_lens import combine
class ADV_IFO(IFO):
"""
This contains advanced Virgo specific methods for computing interferometer
......@@ -47,8 +52,6 @@ class ADV_IFO(IFO):
self._f4 = np.nan
self._f36M = np.nan
@property
def DARMoffset(self):
......@@ -363,7 +366,7 @@ class ADV_IFO(IFO):
self.kat.nodes.replaceNode(self.kat.sPRCin, 'nHAM2out', 'nLaserOut')
def remove_FI_OMC(self, removeFI=True, removeOMC=True):
def remove_OMC(self):
"""
Method for removing the OMC and the FI blocks in kat-objects having these
included. The FI block contains an ideal Faraday isolator as well as the
......@@ -379,19 +382,17 @@ class ADV_IFO(IFO):
removeOMC : Boolean
If True, the OMC is removed. Must be True if removeFI = True.
"""
self.kat.removeBlock('OMCpath')
self.kat.removeBlock('OMC')
self.kat.cavOMC1.remove()
self.kat.cavOMC2.remove()
if removeFI and not removeOMC:
raise pkex.BasePyKatException("Must remove OMC if removing FI")
if removeFI:
self.kat.nodes.replaceNode(self.kat.sSRM_FI, 'nFI2a', 'nAS')
self.kat.removeBlock('FI')
self.kat.removeBlock('OMC')
self.kat.cavOMC.remove()
elif removeOMC:
self.kat.nodes.replaceNode(self.kat.sOM3_OMC, 'nOMC_ICa', 'nAS')
self.kat.removeBlock('OMC')
self.kat.cavOMC.remove()
self.kat.nodes.replaceNode(self.kat.sOut,
self.kat.sOut.nodes[0],
self.kat.components[self.mirrors['SRMAR']].nodes[1].name)
def adjust_PRC_length(self, verbose=False):
"""
Adjust PRC length so that it fulfils the requirement
......@@ -893,7 +894,7 @@ def make_kat(name="design_PR", katfile=None, verbose = False, debug=False, keepC
"""
# Pre-defined file-names
names = ['design_PR', 'design_PR_OMC']
names = ['design_PR', 'design_PR_OMC', "avirgo_PR_OMC", 'avirgo_PR_OMC_22012018']
# Mirror names. Mapping to IFO-specific names to faciliate creating new IFO-specific files.
# Change the values in the dictionary to the IFO-specific mirror names. Do not change the
......@@ -908,6 +909,8 @@ def make_kat(name="design_PR", katfile=None, verbose = False, debug=False, keepC
'SR2': None, 'SR3': None,
'BS': 'BS', 'BSARX': 'BSAR1', 'BSARY': 'BSAR2'}
#signalNames = {'AS_DC': 'B1_DC', 'POP_f1': 'B2_f1', 'POP_f2': 'B2_f2', 'POP_f3': 'B2_f3', 'POP_f4':
# 'B2_f4', 'REFL_f1': 'B4_f1', 'REFL_f2': 'B4_f2'}
......@@ -1179,9 +1182,42 @@ def make_kat(name="design_PR", katfile=None, verbose = False, debug=False, keepC
kat.IFO.ASC_P_DOFs = kat.IFO.ASC_P_DOFs + (kat.IFO.PR3_P,)
kat.IFO.mirrors = mirrors
# Mirror properties for computing thermal effects
MPs = {}
# Common properties. Check if this is true.
common_properties = {}
common_properties['K'] = 1.380 # Thermal conductivity. Check value!
common_properties['T0'] = 295.0 # Temperature. Check value!
common_properties['emiss'] = 0.89 # Emissivity. Check value!
common_properties['alpha'] = 0.54e-6 # Thermal expansion coeff. Check value!
common_properties['sigma'] = 0.164 # Poisson ratio. Check value!
common_properties['dndT'] = 8.7e-6 # dn/dT. Check value!
# Setting common propertis
for k,v in mirrors.items():
if not ('AR' in k or v is None):
# print(k)
MPs[v] = copy.deepcopy(common_properties)
# Setting mirror specific properties
# HR coating absorptions. Values from Valeria Sequino.
MPs[mirrors['EX']]['aCoat'] = 0.24e-6
MPs[mirrors['EY']]['aCoat'] = 0.24e-6
MPs[mirrors['IX']]['aCoat'] = 0.19e-6
MPs[mirrors['IY']]['aCoat'] = 0.28e-6
# Substrate absorption [1/m]. Using upper limits from [TDR, table 2.6].
MPs[mirrors['EX']]['aSub'] = 3.0e-5
MPs[mirrors['EY']]['aSub'] = 3.0e-5
MPs[mirrors['IX']]['aSub'] = 3.0e-5
MPs[mirrors['IY']]['aSub'] = 3.0e-5
kat.IFO.mirror_properties = MPs
kat.IFO.update()
kat.IFO.lockNames = None
return kat
......@@ -1456,3 +1492,129 @@ def generate_locks(kat, gainsAdjustment = [0.1, 0.9, 0.9, 0.001, 0.02],
data['SRCL'] = {"accuracy": accuracies[4], "gain": gains[4]}
return data
def thermal_effect(kat, mirror_list, nScale=False):
out = compute_thermal_effect(kat, mirror_list, nScale=nScale)
kat1 = kat.deepcopy()
mirrors = kat1.IFO.mirrors
# Setting values to kat-object
for k,v in out.items():
# Setting new RoC
kat1.components[k].Rc = v[1][0]
# Setting new lens
if k == mirrors['IX']:
kat1.CPN_TL.f = float(v[5][0])
elif k == mirrors['IY']:
kat1.CPW_TL.f = float(v[5][0])
return kat1
def compute_thermal_effect(kat, mirror_list, nScale=False):
#################################
# Get powers and spot sizes
#################################
kat1 = kat.deepcopy()
mirrors = kat1.IFO.mirrors
code = ""
Ms = {}
for m in mirror_list:
# Getting HR-surface
hr = kat1.components[m]
# Getting AR-surface
arname = m+'AR'
if m == mirrors['BS']:
arname += '1'
ar = kat1.components[arname]
# Getting substrate
subname = 's'+m+'sub'
if m == mirrors['BS']:
subname += '1'
sub = kat1.components[subname]
# Storing compound mirrors in dictionary
Ms[m] = {'HR': hr, 'SUB': sub, 'AR': ar}
# Node definitions are different depending on mirrors
if m == mirrors['IY'] or m == mirrors['IX'] or m == mirrors['PRM']:
# Going into HR-side
code += "pd P_{}_HR {}*\n".format(m, hr.nodes[1].name)
# Substrate, from AR to HR (or going into AR)
code += "pd P_{}_sub1 {}\n".format(m, ar.nodes[1].name)
# Substrate, from HR to AR (or coming out of AR)
code += "pd P_{}_sub2 {}*\n".format(m, ar.nodes[1].name)
# Spot size
code += "bp w_{}_x x w {}\n".format(m, hr.nodes[1].name)
code += "bp w_{}_y y w {}\n".format(m, hr.nodes[1].name)
elif m == mirrors['EX'] or m == mirrors['EY'] or m == mirrors['BS'] or m == mirrors['SRM']:
# Going into HR-side
code += "pd P_{}_HR {}*\n".format(m, hr.nodes[0].name)
# Substrate, from AR to HR (or going into AR)
code += "pd P_{}_sub1 {}\n".format(m, ar.nodes[0].name)
# Substrate, from HR to AR (or coming out of AR)
code += "pd P_{}_sub2 {}*\n".format(m, ar.nodes[0].name)
# Spot size
code += "bp w_{}_x x w {}\n".format(m, hr.nodes[0].name)
code += "bp w_{}_y y w {}\n".format(m, hr.nodes[0].name)
code += 'noxaxis\n'
code += 'yaxis abs'
kat1.parse(code)
out = kat1.run()
#################################
# Compute thermal effects
#################################
res = {}
for k,v in Ms.items():
# Dictionary for mirror properties
mp = copy.deepcopy(kat1.IFO.mirror_properties[k])
mp['HR_RoC'] = v['HR'].Rc.value
mp['AR_RoC'] = v['AR'].Rc.value
# Switching signs of RoC for mirrors depending on tracing direction
if k == mirrors['IY'] or k == mirrors['IX'] or k == mirrors['PRM']:
mp['HR_RoC'] = -mp['HR_RoC']
mp['AR_RoC'] = -mp['AR_RoC']
mp['thickness'] = v['SUB'].L.value
mp['n'] = v['SUB'].n.value
mp['w'] = np.sqrt(out['w_{}_x'.format(k)])*np.sqrt(out['w_{}_y'.format(k)])
mp['nScale'] = nScale
P_coat = out['P_'+k+'_HR']
P_sub_in = out['P_'+k+'_sub1']
P_sub_out = out['P_'+k+'_sub2']
res[k] = hellovinet(P_coat, P_sub_in, P_sub_out, mirror_properties = mp)
# Switching signs of RoC for mirrors depending on tracing direction
if k == mirrors['IY'] or k == mirrors['IX'] or k == mirrors['PRM']:
res[k][1][0] = -res[k][1][0]
res[k][1][1] = -res[k][1][1]
# Computing effective thermal lens for input mirrors
if k == mirrors['IX'] or k == mirrors['IY']:
# Computing thickness of effective thermal lens
d = res[k][3][1][np.abs(res[k][0]).argmin()]
# Computing focal length
f = lensmaker(-res[k][1][1], mp['HR_RoC'], d, mp['n'])
res[k] += (f,)
# Combining CP and input mirror thermal lenses into 1
if k == mirrors['IX']:
f_old = kat1.CPN_TL.f.value
d = kat1.sCPN_NI.L.value
else:
f_old = kat1.CPW_TL.f.value
d = kat1.sCPW_WI.L.value
f_new = combine(f_old, f, d=d)
res[k] += (f_new,)
return res
......@@ -2,17 +2,21 @@
patch.facecolor: r
# FONT
font.size : 9
font.size : 11
# TEXT
text.usetex : False
# AXES
axes.grid : True
axes.formatter.useoffset : False
axes.formatter.useoffset : True
axes.formatter.use_locale : False
axes.prop_cycle: cycler('color', ['0000FF', 'FF0000', '000000', '00FF00', 'FF00FF'])
#TICKS
xtick.labelsize : 9
ytick.labelsize : 9
# GRIDS
grid.color : 999999
grid.linestyle : :
......@@ -20,7 +24,7 @@ grid.linewidth : 0.25
# FIGURES
figure.titlesize : 12
figure.figsize : 6.69291, 4.13645
figure.figsize : 6, 3.708
figure.dpi : 96
# IMAGES
......@@ -30,7 +34,6 @@ image.origin : lower
# SAVING FIGURES
savefig.dpi : 300
savefig.bbox : tight
savefig.transparent : True
pdf.compression : 9
pdf.fonttype : 42
figure.figsize : 7.33915, 4.53585
# FONT
font.family : serif
font.serif : ["Latin Modern"]
font.size : 9
# FIGURE
figure.figsize : 6.69291, 4.13645
# TEXT
text.usetex : True
Markdown is supported
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