initial copy of files from /psi.ch/project/SLS2/BD/OnlineModel/ after talking to Masamitsu
This commit is contained in:
@@ -0,0 +1,532 @@
|
||||
"""
|
||||
import of M.Aiba's OnlineModel to tracy-null via the general tracy-null dictionary statement parser
|
||||
|
||||
draft version from July 21 by Bernard Riemann.
|
||||
This version is only kept as a 'snapshot', as Masamitsu will modify and adapt it as the model develops.
|
||||
|
||||
the main function to be used is: onlinemodel_to_statements
|
||||
|
||||
Further Notes:
|
||||
|
||||
the onlinemodel reader, onlinemodel_to_statements, returns only a list of dictionaries.
|
||||
The dictionaries are understood by the general tracy-null input parser
|
||||
(the conversion into the c tracy lattice happens in the function trap/readers.py : push_family,
|
||||
note that push_family should not be changed too much, as a reinstall/update of tracy in the environment is required for changes to take effect)
|
||||
|
||||
if it is problematic to load OMFacility on Merlin or you want to sahre the results with someone who dont uses the OMFacility, you can export the statement list of dictionaries into .json format (see data/sls2/b068/import.ipynb for examples). Another person can then load the dictionaries again from json and import
|
||||
|
||||
"""
|
||||
from OMFacility import *
|
||||
|
||||
#exec(open('/afs/psi.ch/project/SLS2/BD/OnlineModel/OMFacility.py').read())
|
||||
|
||||
from trap.trapc import LatticeType # from c module, see trap/src/main.cpp or tracy/src/*.{cc,h}
|
||||
from trap.readers import check_stadict, replace_subsequence # see trap/readers.py
|
||||
from numpy import deg2rad
|
||||
from warnings import warn
|
||||
from copy import copy, deepcopy
|
||||
|
||||
def ocell_to_dict(ocell, include_markers=False) -> list:
|
||||
"""
|
||||
for a given cell in the OMFacility.Facility, return a list of statements.
|
||||
if ocell.APERTURE is defined, aperture information is included (aper.. keys)
|
||||
|
||||
Typically, there is only one entry in the list.
|
||||
But sometimes, elements are ignored (no entries) or have more than one statement (like step-wise bends, MBSC)
|
||||
|
||||
returned dicts are input for the tracy-null python parser
|
||||
"""
|
||||
|
||||
otype = ocell.SN
|
||||
|
||||
|
||||
# note: not using round(ocell.L, 6) gives only ~2micron total length diff to elegant
|
||||
# Sign of 'roll' to be checked, i.e., consistency among elegant, MADX and tracy...
|
||||
if otype=='MMAP':
|
||||
outdict = {'name': ocell.NAME,
|
||||
'dx': ocell.MAX, 'dy': ocell.MAY, 'roll': ocell.MAR}
|
||||
elif otype=='DRIF':
|
||||
outdict = {'name': ocell.NAME, 'length': ocell.L,
|
||||
'dx': 0, 'dy': 0, 'roll': 0}
|
||||
elif otype in ('RCAV','R3HC'):
|
||||
outdict = {'name': ocell.NAME, 'length': ocell.L,
|
||||
'dx': 0, 'dy': 0, 'roll': 0}
|
||||
else:
|
||||
outdict = {'name': ocell.NAME, 'length': ocell.L,
|
||||
'dx': ocell.MAX, 'dy': ocell.MAY, 'roll': ocell.MAR}
|
||||
|
||||
# note: RFE and RGE are only used internally for parsing the OM file. they are not themselves propagated through tracy, although their effects in multipole strengths are considered
|
||||
try:
|
||||
outdict['RFE'] = ocell.RFE
|
||||
except AttributeError:
|
||||
pass
|
||||
try:
|
||||
outdict['RGE'] = ocell.RGE
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if ocell.APERTURE is not None:
|
||||
try:
|
||||
aperxa, aperya, shp = ocell.APERTURE
|
||||
# for the moment, shp='E' elliptical is treated like rectangular 'R'
|
||||
outdict.update({'aperxa': aperxa, 'aperya': aperya})
|
||||
except ValueError:
|
||||
# 4 entries instead of 3
|
||||
aperx, apery, shp, shpa = ocell.APERTURE
|
||||
if shpa=='+x':
|
||||
outdict['aperxp'] = aperx
|
||||
elif shpa=='-x':
|
||||
outdict['aperxn'] = aperx
|
||||
elif shpa=='+y':
|
||||
# if aperyp is defined here, it will be understood by the tracy parser
|
||||
raise NotImplementedError
|
||||
elif shpa=='-y':
|
||||
# if aperyn is defined here, it will be understood by the tracy parser
|
||||
raise NotImplementedError
|
||||
else:
|
||||
raise SyntaxError('aperture specification not understood')
|
||||
|
||||
|
||||
if otype=='DRIF':
|
||||
outdict['etype'] = 'drift'
|
||||
elif otype in ('RCAV','R3HC'):
|
||||
outdict['etype'] = 'drift'
|
||||
|
||||
|
||||
elif otype=='MMAP':
|
||||
# Only MQCO implemented for the moment. 19.07.2022
|
||||
# Update to include more
|
||||
|
||||
Qrange=None
|
||||
SQrange=None
|
||||
Srange=None
|
||||
Orange=None
|
||||
dk=0
|
||||
dks=0
|
||||
if ocell.OVERLAP:
|
||||
for oe in ocell.OVERLAP:
|
||||
if oe[0]=='MQCO':
|
||||
Qrange=range(oe[1],oe[1]+oe[2])
|
||||
dk=oe[3]
|
||||
if oe[0]=='MQSK':
|
||||
SQrange=range(oe[1],oe[1]+oe[2])
|
||||
dks=oe[3]
|
||||
if oe[0]=='MSXT':
|
||||
Srange=range(oe[1],oe[1]+oe[2])
|
||||
dk2=oe[3]
|
||||
if oe[0]=='MOCT':
|
||||
Orange=range(oe[1],oe[1]+oe[2])
|
||||
dk3=oe[3]/(oe[2]*0.001)
|
||||
|
||||
|
||||
if ocell.RGE or dk or dks:
|
||||
fin=open(ocell.FILENAME,'r')
|
||||
fout=open(ocell.FILENAME+'.'+ocell.NAME,'w')
|
||||
|
||||
|
||||
il=0
|
||||
for line in fin:
|
||||
sline=line.split()
|
||||
if len(sline)>10:
|
||||
k1p=float(sline[10]) # k1 value without field error
|
||||
k1n=k1p*(1+ocell.RGE)
|
||||
|
||||
k03p=float(sline[6])
|
||||
k03n=k03p*(1+ocell.RGE) # Sextupole and quadrupole gradient error will be the same... let's accept it
|
||||
k21p=float(sline[16])
|
||||
k21n=k21p*(1+ocell.RGE)
|
||||
|
||||
k13p=float(sline[12])
|
||||
k13n=k13p*(1+ocell.RGE) # The same for octupole
|
||||
k31p=float(sline[22])
|
||||
k31n=k31p*(1+ocell.RGE)
|
||||
|
||||
|
||||
|
||||
if Qrange:
|
||||
if il in Qrange:
|
||||
k1n=k1n+dk
|
||||
sline[10]=str(k1n)
|
||||
if SQrange:
|
||||
if il in SQrange:
|
||||
# Factor of 1/2, not clear why needed...
|
||||
sline[15]=str(dks/2)
|
||||
if Srange:
|
||||
if il in Srange:
|
||||
k21n=k21n+dk2
|
||||
k03n=k03n-dk2/3.0
|
||||
sline[6]=str(k03n)
|
||||
sline[16]=str(k21n)
|
||||
if Orange:
|
||||
if il in Orange:
|
||||
k13n=k13n-dk3
|
||||
k31n=k31n+dk3
|
||||
sline[12]=str(k13n)
|
||||
sline[22]=str(k31n)
|
||||
|
||||
|
||||
wline='len'
|
||||
for si in range(1,len(sline)):
|
||||
wline=wline+' '+sline[si]
|
||||
wline=wline+'\n'
|
||||
il=il+1
|
||||
else:
|
||||
wline=line
|
||||
fout.write(wline)
|
||||
|
||||
fin.close()
|
||||
fout.close()
|
||||
|
||||
tfile=ocell.FILENAME+'.'+ocell.NAME
|
||||
else:
|
||||
tfile=ocell.FILENAME
|
||||
|
||||
|
||||
outdict['etype']='magtubefile'
|
||||
outdict['filename']= tfile
|
||||
#fgt=open(ocell.FILENAME,'r')
|
||||
#for line in fgt:
|
||||
# if 'driftlen' in line:
|
||||
# sline=line.split()
|
||||
#fgt.close()
|
||||
|
||||
# The following is experimental. 10.11.2021
|
||||
# enclose in kick
|
||||
kick_name = outdict['name']+'_E'
|
||||
kick_elem = {'name': kick_name, 'etype': 'corrector', 'k0l': -deg2rad(ocell.ANGLE)*ocell.RFE/2}
|
||||
|
||||
# trick: when only a name(string) like kick_name is passed as a list element,
|
||||
# it is agreed for onlinemodel_to_statements function,
|
||||
# that it will just append the name to the sequence, not defining a new element
|
||||
return [kick_elem, check_stadict(outdict), kick_name]
|
||||
|
||||
|
||||
elif otype=='UIND':
|
||||
print (ocell.NAME,ocell.L)
|
||||
#outdict['etype'] = 'drift'
|
||||
outdict.update({'etype': 'bend', 'angle': 0, 'k1': 0, 'e1': 0, 'e2': 0})
|
||||
|
||||
|
||||
elif otype in ('MBEN', 'MBCF'):
|
||||
k1 = ocell.K1*(1+ocell.RGE) if otype=='MBCF' else 0
|
||||
outdict.update({'etype': 'bend', 'angle': deg2rad(ocell.ANGLE), 'k1': k1,
|
||||
'e1': deg2rad(ocell.E1), 'e2': deg2rad(ocell.E2)})
|
||||
|
||||
# enclose in kick
|
||||
kick_name = outdict['name']+'_E'
|
||||
kick_elem = {'name': kick_name, 'etype': 'corrector', 'k0l': -outdict['angle']*ocell.RFE/2}
|
||||
|
||||
# trick: when only a name(string) like kick_name is passed as a list element,
|
||||
# it is agreed for onlinemodel_to_statements function,
|
||||
# that it will just append the name to the sequence, not defining a new element
|
||||
return [kick_elem, check_stadict(outdict), kick_name]
|
||||
|
||||
elif otype=='MBSC':
|
||||
# interpretation: multiple bends
|
||||
outdict['etype'] = 'bend'
|
||||
name = outdict.pop('name')
|
||||
|
||||
kick_name = name+'_E'
|
||||
kick_elem = {'name': kick_name, 'etype': 'corrector', 'k0l': -deg2rad(ocell.TANGLE)*ocell.RFE/2}
|
||||
|
||||
# start sequence of elements with kick
|
||||
li=[kick_elem]
|
||||
|
||||
# interior
|
||||
lengths = outdict.pop('length') # it was a list of lengths
|
||||
dxs = outdict.pop('dx')
|
||||
dys = outdict.pop('dy')
|
||||
for n, (length, angle, e1deg, e2deg, dx, dy) in enumerate(zip(lengths, ocell.ANGLE, ocell.E1, ocell.E2, dxs, dys)):
|
||||
outdict.update({'name': f'{name}_{n}', 'length': length, 'angle': deg2rad(angle),
|
||||
'e1': deg2rad(e1deg), 'e2': deg2rad(e2deg), 'dx': dx, 'dy': dy})
|
||||
li.append(copy(check_stadict(outdict)))
|
||||
|
||||
# only kick_name string to end the list, see MBEN/MBCF entry
|
||||
li.append(kick_name)
|
||||
return li
|
||||
|
||||
elif otype=='MQUA':
|
||||
outdict.update({'etype': 'quadrupole', 'k1': ocell.K1*(1+ocell.RFE)})
|
||||
|
||||
elif otype=='MQCO':
|
||||
outdict.update({'etype': 'quadrupole', 'k1': ocell.K1*(1+ocell.RFE)})
|
||||
|
||||
elif otype=='MSXT':
|
||||
outdict.update({'etype': 'sextupole', 'k2': ocell.K2*(1+ocell.RFE)})
|
||||
|
||||
elif otype=='MOCT':
|
||||
outdict.update({'etype': 'sextupole', 'k3l': ocell.K3L*(1+ocell.RFE)})
|
||||
|
||||
|
||||
elif otype in ('MCOX', 'MCOY'):
|
||||
outdict['etype'] = 'corrector'
|
||||
vertical = otype.endswith('Y')
|
||||
length = outdict['length']
|
||||
kick = ocell.VKICK if vertical else -ocell.HKICK
|
||||
if length==0:
|
||||
outdict['j0l' if vertical else 'k0l'] = kick
|
||||
else:
|
||||
outdict['j0' if vertical else 'k0'] = kick / length
|
||||
|
||||
|
||||
elif otype in ('MKIK', 'MSEP'):
|
||||
# interpretation: kicker set to zero
|
||||
#outdict['etype'] = 'corrector'
|
||||
#outdict['etype'] = 'drift'
|
||||
#outdict['etype'] = 'corrector'
|
||||
outdict.update({'etype': 'bend', 'angle': 0, 'k1': 0, 'e1': 0, 'e2': 0})
|
||||
|
||||
elif otype=='DBPM':
|
||||
outdict['etype'] = 'monitor'
|
||||
|
||||
elif otype=='VCOL':
|
||||
outdict['etype'] = 'drift'
|
||||
|
||||
elif otype=='NONE':
|
||||
if outdict['length']==0.0:
|
||||
return []
|
||||
# interpretation: just treat it as a drift with length ocell.L (already in outdict)
|
||||
outdict['etype'] = 'drift'
|
||||
|
||||
elif otype in ('GMRK', 'GSRC'):
|
||||
if include_markers:
|
||||
return [{'name': outdict['name'], 'etype': 'marker'}] #every other thing (apertures etc.) ignored
|
||||
else:
|
||||
return []
|
||||
|
||||
elif otype in ('EMALIGN', 'EWATCH'):
|
||||
return [] #ignored
|
||||
|
||||
else:
|
||||
#outdict.update({'etype': 'NOT IMPL'})
|
||||
raise NotImplementedError(f'{otype = }, {ocell = }')
|
||||
|
||||
return [check_stadict(outdict)] # when you arriive here, list has only one entry
|
||||
|
||||
|
||||
# for aperture settings, see OMFacility.Facility.setAperture()
|
||||
|
||||
def onlinemodel_to_statements(omf, cavity: int, undulator_spaces: bool):
|
||||
"""
|
||||
convert an instance omf of OMFacility.Facility into a list of statement-dictionaries, that can be read as input to the tracy-null parser
|
||||
uses aperture information if it was set in onlinemodel by .setApertures
|
||||
|
||||
cavity: toggles inclusion of predefined cavity into sequence
|
||||
undulator_spaces: toggles inclusion of predefined cavity into sequence
|
||||
"""
|
||||
statements = list() # a list of statement dictionaries
|
||||
sequence = list() # names of elements
|
||||
|
||||
statements.append( {'name': 'energy', 'variable': '2.7'} ) # in every other place in this example, it can be a number instead of string..
|
||||
|
||||
usedDriftNames = dict() # to look up if a drift name has already been used
|
||||
for ocell in omf.Ring:
|
||||
if isinstance(ocell, str):
|
||||
pass
|
||||
else:
|
||||
# basic statement parsing (no overlays and special drift treatments, but already step-wise bends):
|
||||
new_statements = ocell_to_dict(ocell)
|
||||
|
||||
for stadict in new_statements:
|
||||
if isinstance(stadict, str): #if list item is a string, just append it to sequence
|
||||
sequence.append(stadict)
|
||||
continue # skip the rest, to next iteration
|
||||
|
||||
name = stadict['name']
|
||||
|
||||
if stadict['etype']=='drift':
|
||||
if name in usedDriftNames:
|
||||
usedDriftNames[name] += 1
|
||||
name = f'{name}_{usedDriftNames[name]}'
|
||||
stadict['name'] = name
|
||||
else:
|
||||
usedDriftNames[name] = 0
|
||||
|
||||
# impose overlaps. Note: applied for any name that occurs in OverlapC, not just MQCO
|
||||
if name in omf.OverlapC:
|
||||
for ov_ocell in omf.OverlapC[name]:
|
||||
# set additional skew quad (j1) or octupole (k3) strength of existing multipole
|
||||
if ov_ocell.SN=='MQSK':
|
||||
# assumption: skew quadrupole strength oe.k1*(..) is INTEGRATED strength j1*l like in OMElegant.py,
|
||||
# is this a typo and should read .K1L similar to octupole?
|
||||
#stadict['j1'] = ov_ocell.K1 * (1+stadict['RFE']) / stadict['length']
|
||||
stadict['j1'] = ov_ocell.K1 * (1+ov_ocell.RFE) / stadict['length']
|
||||
|
||||
elif ov_ocell.SN=='MOCT':
|
||||
stadict['k3'] = ov_ocell.K3L* (1+ov_ocell.RFE) / stadict['length']
|
||||
|
||||
|
||||
# remove temporary entries
|
||||
stadict.pop('RFE', 0.0)
|
||||
stadict.pop('RGE', 0.0)
|
||||
sequence.append(stadict['name'])
|
||||
|
||||
statements.append(stadict)
|
||||
|
||||
# now come some modifiers
|
||||
if cavity>=0:
|
||||
# the online model so far has no cavity, so it is appended manually here
|
||||
#stadict = {'name': 'cav', 'etype': 'cavity',
|
||||
# 'freq': 480*2.99792458e8/288.0, 'volt': 1.44e6, 'phase': deg2rad(151.8), 'h': 480}
|
||||
# No phase entry/ Bernard's mail on 1.08.2021
|
||||
stadict = {'name': 'cav', 'etype': 'cavity',
|
||||
'freq': 480*2.99792458e8/288.0, 'volt': 1.44e6, 'h': 480}
|
||||
|
||||
statements.append(stadict)
|
||||
sequence.insert(cavity, 'cav') # insert at beginning of list
|
||||
|
||||
if undulator_spaces: # use this before exporting to Simona for specific undulator locations
|
||||
# BR: this is just an example for a single blank unulator space, i don't know the actual lengths
|
||||
# note that the length of the replaced elements should match those of the new one
|
||||
stadict = {'name': 'fancy_costly_undulator', 'etype': 'multipole', 'length': 1.23}
|
||||
statements.append(stadict)
|
||||
# this will throw a warning, as there is no element 'abcd' present in the sequence:
|
||||
n = replace_subsequence(sequence, ('ARS08-DRIF-1970', 'abcd'), ('fancy_costly_undulator',))
|
||||
print(f'{n} replacements for ' + stadict['name'])
|
||||
|
||||
# here i added keys for k1 (quadruople), j1 (skew quadrupole) and k3 (octupole)
|
||||
stadict = {'name': 'cheap_undulator', 'etype': 'multipole', 'length': 4.56,
|
||||
'k1': 0.2, 'j1': 89.7, 'k3': 42.0}
|
||||
statements.append(stadict)
|
||||
# this will show 1 replacement
|
||||
n = replace_subsequence(sequence, ('ARS01-MKIK-0140', 'ARS01-DRIF-0140_1'), ('cheap_undulator',))
|
||||
print(f'{n} replacements for ' + stadict['name'])
|
||||
|
||||
# sequence is just packed as a statement an appended
|
||||
statements.append( {'name': 'ring', 'sequence': sequence} )
|
||||
return statements
|
||||
|
||||
|
||||
def get_onlinemodel(masterfile: str, PF: dict, Aperture: bool):
|
||||
# its just the things you normally do with onlinemodel
|
||||
# this needs to be executed in your onlinemodel folder.
|
||||
# (idea for future: make OMFacility a module that can be installed in environment)
|
||||
|
||||
omf=Facility(masterfile)
|
||||
|
||||
|
||||
#if omf.Version!=PF['Pversion'].upper():
|
||||
# print (omf.Version)
|
||||
# print (Pversion.upper())
|
||||
# raise Exception('Version of Master layout and Pattern file does not match.')
|
||||
|
||||
omf.TracyFM=True
|
||||
omf.Layout('full',-1) # StrPat is for the ring with no cycle. CYCLE marker appears with a switch of -1 (or any negtive int)
|
||||
StrPat={}
|
||||
Tdone=[]
|
||||
for k in PF['Pattern'].keys():
|
||||
StrPat[k]=[]
|
||||
for e in PF['Pattern'][k]:
|
||||
print (e)
|
||||
StrPat[k].append(PF['Strength'][e])
|
||||
if e not in Tdone:
|
||||
Tdone.append(e)
|
||||
|
||||
for k in PF['Strength'].keys():
|
||||
if k not in Tdone:
|
||||
StrPat[k]=PF['Strength'][k]
|
||||
|
||||
del(StrPat['MKIK'])
|
||||
|
||||
omf.setStrength(StrPat)
|
||||
|
||||
if Aperture:
|
||||
print('using aperture')
|
||||
omf.setAperture(Aperture)
|
||||
return omf
|
||||
|
||||
|
||||
|
||||
def replace_elems(omf, sub_sequence: list, replace_with: list):
|
||||
# replace routine as in trap.readers but specifically for 'statements' that is generated through this OM2TN module
|
||||
# defs is the definition of elements that are in replace_with
|
||||
|
||||
|
||||
compatible=0
|
||||
for i in range(0,len(omf.Ring)):
|
||||
if type(omf.Ring[i])==str:
|
||||
# Assumed that the first element of sub_sequence is not CYCLE
|
||||
pass
|
||||
elif omf.Ring[i].NAME==sub_sequence[0]:
|
||||
s_idx=i
|
||||
for j in range(1,len(sub_sequence)):
|
||||
if omf.Ring[i+j].NAME==sub_sequence[j]:
|
||||
compatible=1
|
||||
else:
|
||||
compatible=0
|
||||
break
|
||||
|
||||
if not compatible:
|
||||
raise Exception('Sub-sequence does not match to OMF layout')
|
||||
|
||||
omf.Ring=omf.Ring[0:s_idx]+replace_with+omf.Ring[s_idx+len(sub_sequence):]
|
||||
|
||||
|
||||
return omf
|
||||
|
||||
|
||||
def FieldMapLengthCorrection(omf):
|
||||
# The length of the field map is shorter by a half step size in tracy-null.
|
||||
# If self.get_onlinemodel is used (or Facility instance is geneerated with omf.TracyFM=True)
|
||||
# this missing length is adjusted by Facility.individuateS2.
|
||||
# If not, this routine needs to be called.
|
||||
|
||||
if not omf.Ring:
|
||||
return None
|
||||
|
||||
imap=[]
|
||||
for i in range(0,len(omf.Ring)):
|
||||
c=omf.Ring[i]
|
||||
|
||||
if type(c)==str:
|
||||
pass
|
||||
else:
|
||||
if c.SN=='MMAP':
|
||||
if c.RL:
|
||||
imap.append(i)
|
||||
|
||||
while imap:
|
||||
c=omf.Ring[imap[-1]]
|
||||
|
||||
|
||||
pr1={}
|
||||
pr1['L']=abs(c.RL)
|
||||
pr1['RL']=0
|
||||
pr1['SN']='DRIF'
|
||||
pr1['NAME']=c.NAME.replace('MMAP','DRIF')
|
||||
pr1['INDEX']=c.INDEX
|
||||
pr1['TYPE']='DRIFT'
|
||||
pr1['DNAME']='DR'+c.TYPE # Name that appears in OPA file
|
||||
|
||||
pr1['S']=c.S-abs(c.RL) # Is that correct? not c.S? The same is in OMFacility...
|
||||
pr1['MS']=c.S-abs(c.RL)/2
|
||||
|
||||
pr1['SANGLE']=c.SANGLE
|
||||
pr1['MANGLE']=c.SANGLE
|
||||
pr1['SECTOR']=c.SECTOR
|
||||
pr1['GIRDER']=c.GIRDER
|
||||
pr1['RESERVE']=1
|
||||
|
||||
|
||||
pr2=deepcopy(pr1)
|
||||
|
||||
pr2['S']=c.S+c.TL # Is that correct? -c.RL might be missing? The same is in OMFacility...
|
||||
pr2['MS']=pr2['S']+c.RL/2
|
||||
pr2['RESERVE']=1
|
||||
|
||||
|
||||
if 'ANGLE' in c.__dict__.keys():
|
||||
pr2['SANGLE']=c.SANGLE+c.ANGLE
|
||||
else:
|
||||
pr2['SANGLE']=c.SANGLE
|
||||
|
||||
if c.RL<0:
|
||||
drif=Drift(pr1)
|
||||
omf.Ring.insert(imap[-1],drif)
|
||||
else:
|
||||
drif=Drift(pr2)
|
||||
omf.Ring.insert(imap[-1]+1,drif)
|
||||
|
||||
imap.pop(-1)
|
||||
|
||||
return omf
|
||||
@@ -0,0 +1,452 @@
|
||||
import os
|
||||
from math import *
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
|
||||
Energy = 2.7e9
|
||||
HarmNumber = 480
|
||||
RFVoltage = 1.44e6
|
||||
RFVoltage_3HC = 0.375e6
|
||||
DriftPass = "'DriftPass'"
|
||||
BendPass = "'BndMPoleSymplectic4Pass'"
|
||||
QuadPass = "'StrMPoleSymplectic4Pass'"
|
||||
SextPass = "'StrMPoleSymplectic4Pass'"
|
||||
# OctPass = "'StrMPoleSymplectic4Pass'"
|
||||
OctPass = "'ThinMPolePass'"
|
||||
MultipolePass = "'ThinMPolePass'"
|
||||
RcavPass = "'RFCavityPass'"
|
||||
R3HCPass = "'DriftPass'"
|
||||
|
||||
class AcceleratorToolbox():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def openFile(self,name='SLS2.m'):
|
||||
self.fout=open(name,'w')
|
||||
|
||||
def closeFile(self):
|
||||
self.fout.close()
|
||||
|
||||
def write(self,line):
|
||||
line=line+'\n'
|
||||
self.fout.write(line)
|
||||
|
||||
def appendMisalignments(self,transErrors,name,dx,dy,tilt):
|
||||
transErrors['name'].append(name)
|
||||
transErrors['dx'].append(str(dx))
|
||||
transErrors['dy'].append(str(dy))
|
||||
transErrors['tilt'].append(str(tilt))
|
||||
|
||||
|
||||
def defineSequence(self,S2,Radiation=0,Aperture=0,RF=0):
|
||||
# Input is an instance of OMFacility.Facility
|
||||
if Aperture:
|
||||
cnow=Aperture['Nominal']
|
||||
RingA=[cnow]
|
||||
for c in S2.Ring:
|
||||
if type(c)==str:
|
||||
pass
|
||||
elif c.SN[0]=='E':
|
||||
RingA.append(c)
|
||||
elif cnow!=c.APERTURE:
|
||||
cnow=c.APERTURE
|
||||
RingA.append(cnow)
|
||||
RingA.append(c)
|
||||
else:
|
||||
RingA.append(c)
|
||||
else:
|
||||
RingA=S2.Ring
|
||||
|
||||
d2r=pi/180.0
|
||||
|
||||
|
||||
|
||||
Drift={}
|
||||
seq=[]
|
||||
transErrors = {'name': [], 'dx': [], 'dy': [], 'tilt': []}
|
||||
|
||||
cir=0
|
||||
Iap=1
|
||||
|
||||
|
||||
self.write("function RING = SLS2")
|
||||
self.write("RING = {...")
|
||||
for index,c in enumerate(RingA):
|
||||
|
||||
if type(c)==str:
|
||||
pass
|
||||
elif type(c)==list:
|
||||
Name='APERTURE'+str(Iap)
|
||||
seq.append(Name)
|
||||
Iap=Iap+1
|
||||
if c[0]==None:
|
||||
xm=0.05
|
||||
else:
|
||||
xm=c[0]
|
||||
if c[1]==None:
|
||||
ym=0.05
|
||||
else:
|
||||
ym=c[1]
|
||||
if c[2]=='E' or c[2]=='e':
|
||||
ell='1'
|
||||
else:
|
||||
ell='0'
|
||||
if len(c)==4:
|
||||
wline=Name.replace('-','_')+' : MAXAMP, X_MAX= '+str(xm) \
|
||||
+', Y_MAX= '+str(ym)+', ELLIPTICAL= '+str(ell)+', OPEN_SIDE= '+str(c[3])
|
||||
else:
|
||||
wline=Name.replace('-','_')+' : MAXAMP, X_MAX= '+str(xm) \
|
||||
+', Y_MAX= '+str(ym)+', ELLIPTICAL= '+str(ell)
|
||||
self.write(wline)
|
||||
elif c.SN=='EMALIGN':
|
||||
wline=c.NAME+"atmarker('malign');"
|
||||
self.write(wline)
|
||||
seq.append(c.NAME)
|
||||
elif c.SN=='EWATCH':
|
||||
wline="atmarker('WATCH');"
|
||||
self.write(wline)
|
||||
seq.append(c.NAME)
|
||||
elif c.SN=='DSCR' or c.SN=='GMRK' or c.SN=='GSRC' or c.SN=='DICT':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
|
||||
wline="atmarker('"+elemName+"','Type','"+typeName+"','SN','"+c.SN+"');..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
elif c.SN=='DRIF':
|
||||
if c.NAME in Drift.keys():
|
||||
Name=c.NAME+'_'+str(Drift[c.NAME])
|
||||
Drift[c.NAME]=Drift[c.NAME]+1
|
||||
else:
|
||||
Name=c.NAME
|
||||
Drift[c.NAME]=1
|
||||
elemName = Name.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atdrift('"+elemName+"',"+str(round(c.L,6))+",'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
cir=cir+c.L
|
||||
elif c.SN=='RCAV':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atrfcavity('"+elemName+"',"+str(round(c.L,6))+","+str(RFVoltage)+",500e6,480,"+str(Energy)+",'TimeLag',0,'Type','"+typeName+"','SN','"+c.SN+"'"+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
cir=cir+c.L
|
||||
|
||||
elif c.SN=='R3HC':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atdrift('"+elemName+"',"+str(round(c.L,6))+",'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MBEN' or c.SN=='MBCF':
|
||||
if c.SN=='MBCF':
|
||||
k1=c.K1*(1+c.RGE)
|
||||
else:
|
||||
k1=0
|
||||
|
||||
if c.TYPE=='SVBI':
|
||||
print(c.K1)
|
||||
print(c.NAME)
|
||||
print(index)
|
||||
|
||||
if c.TYPE=='DCSYIN1' or c.TYPE=='DCSYIN2':
|
||||
c.NAME = c.NAME.replace('MBEN','MSEP')
|
||||
|
||||
elemName_E = c.NAME.replace('-','_')+"_E"
|
||||
typeName = c.TYPE.replace('-','_')+"_E"
|
||||
|
||||
wline = "atcorrector('"+elemName_E+"',0,["+str(d2r*c.ANGLE*c.RFE/2)+" 0],'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName_E)
|
||||
|
||||
|
||||
|
||||
if c.NAME in S2.OverlapC:
|
||||
elemName = c.NAME.replace('-','_')+"_1" #name of the element
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atsbend('"+elemName+"',"+str(round(c.L/2,6))+','+str(d2r*c.ANGLE/2)+","+str(k1)+", 'EntranceAngle',"+str(d2r*c.E1)+", 'ExitAngle',0,'PolynomB',[0 "+str(k1)+" 0 0], 'MaxOrder',4,'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
self.appendMisalignments(transErrors,elemName,c.MAX,c.MAY,-c.MAR)
|
||||
seq.append(elemName)
|
||||
|
||||
oe = S2.OverlapC[c.NAME][0]
|
||||
elemNameOE = oe.NAME.replace('-','_')
|
||||
typeNameOE = oe.TYPE.replace('-','_')
|
||||
wline="atmarker('"+elemNameOE+"','Type','"+typeNameOE+"','SN','"+oe.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemNameOE)
|
||||
|
||||
|
||||
elemName = c.NAME.replace('-','_')+"_2" #name of the element
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atsbend('"+elemName+"',"+str(round(c.L/2,6))+','+str(d2r*c.ANGLE/2)+","+str(k1)+", 'EntranceAngle',0, 'ExitAngle',"+str(d2r*c.E2)+",'PolynomB',[0 "+str(k1)+" 0 0], 'MaxOrder',4,'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
self.appendMisalignments(transErrors,elemName,c.MAX,c.MAY,-c.MAR)
|
||||
seq.append(elemName)
|
||||
|
||||
|
||||
|
||||
else:
|
||||
elemName = c.NAME.replace('-','_') #name of the element
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atsbend('"+elemName+"',"+str(c.L)+','+str(d2r*c.ANGLE)+","+str(k1)+",'EntranceAngle',"+str(d2r*c.E1)+", 'ExitAngle',"+str(d2r*c.E2)+",'PolynomB',[0 "+str(k1)+" 0 0], 'MaxOrder',4,'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
self.appendMisalignments(transErrors,elemName,c.MAX,c.MAY,-c.MAR)
|
||||
seq.append(elemName)
|
||||
|
||||
|
||||
"""
|
||||
# Minus sign for c.MAR is to be consistent with
|
||||
elemName = c.NAME.replace('-','_') #name of the element
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline=elemName+" = atsbend('"+elemName+"','Length',"+str(round(c.L,6))+',... \n' \
|
||||
+" 'BendingAngle'," +str(d2r*c.ANGLE)+", 'EntranceAngle',"+str(d2r*c.E1)+", 'ExitAngle',"+str(d2r*c.E2)+',... \n' \
|
||||
+" 'PolynomB',[0,"+str(k1)+",0,0], 'MaxOrder',4,'PassMethod',"+BendPass+",'Type','"+typeName+"','SN','"+c.SN+"');"
|
||||
self.write(wline)
|
||||
self.appendMisalignments(transErrors,elemName,c.MAX,c.MAY,-c.MAR)
|
||||
seq.append(elemName)
|
||||
"""
|
||||
|
||||
|
||||
seq.append(elemName_E)
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MBSC':
|
||||
if hasattr(c,'k1'):
|
||||
k1 = c.k1;
|
||||
else:
|
||||
k1 = 0
|
||||
elemName_E = c.NAME.replace('-','_')+"_E"
|
||||
typeName = c.TYPE.replace('-','_')+"_E"
|
||||
wline = "atcorrector('"+elemName_E+"',0,["+str(d2r*c.TANGLE*c.RFE/2)+" 0],'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_')+'_E')
|
||||
|
||||
for i in range(0,floor(len(c.L)/2)):
|
||||
elemName = c.NAME.replace('-','_')+'_'+str(i) #name of the element
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atsbend('"+elemName+"',"+str(c.L[i])+"," +str(d2r*c.ANGLE[i])+","+str(k1)+",'EntranceAngle',"+str(d2r*c.E1[i])+", 'ExitAngle',"+str(d2r*c.E2[i])+",'PolynomB',[0 "+str(k1)+" 0 0], 'MaxOrder',4,'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
self.appendMisalignments(transErrors,elemName,c.MAX[i],c.MAY[i],-c.MAR)
|
||||
seq.append(elemName)
|
||||
|
||||
|
||||
oe = S2.OverlapC[c.NAME][0]
|
||||
elemNameOE = oe.NAME.replace('-','_')
|
||||
typeNameOE = oe.TYPE.replace('-','_')
|
||||
wline="atmarker('"+elemNameOE+"','Type','"+typeNameOE+"','SN','"+oe.SN+"'"+",'Energy',"+str(Energy)+");"
|
||||
self.write(wline)
|
||||
seq.append(elemNameOE)
|
||||
|
||||
for i in range(floor(len(c.L)/2),len(c.L)):
|
||||
elemName = c.NAME.replace('-','_')+'_'+str(i) #name of the element
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atsbend('"+elemName+"',"+str(c.L[i])+','+str(d2r*c.ANGLE[i])+","+str(k1)+",'EntranceAngle',"+str(d2r*c.E1[i])+", 'ExitAngle',"+str(d2r*c.E2[i])+",'PolynomB',[0 "+str(k1)+" 0 0], 'MaxOrder',4,'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
self.appendMisalignments(transErrors,elemName,c.MAX[i],c.MAY[i],-c.MAR)
|
||||
seq.append(elemName)
|
||||
|
||||
seq.append(elemName_E)
|
||||
cir=cir+c.TL
|
||||
elif c.SN=='UIND':
|
||||
|
||||
elemName = c.NAME.replace('-','_').replace('DRIF','UIND')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
|
||||
if c.NAME in S2.OverlapC:
|
||||
wline1="atdrift('"+elemName+"',"+str(round(c.L/2,6))+",'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline1)
|
||||
seq.append(elemName)
|
||||
oe = S2.OverlapC[c.NAME][0]
|
||||
elemNameOE = oe.NAME.replace('-','_')
|
||||
typeNameOE = oe.TYPE.replace('-','_')
|
||||
wline="atmarker('"+elemNameOE+"','Type','"+typeNameOE+"','SN','"+oe.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
wline="atdrift('"+elemName+"',"+str(round(c.L/2,6))+",'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemNameOE)
|
||||
seq.append(elemName)
|
||||
else:
|
||||
wline="atdrift('"+elemName+"',"+str(round(c.L,6))+",'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MQUA':
|
||||
k1 = c.K1*(1+c.RFE)
|
||||
elemName = c.NAME.replace('-','_') #name of the element
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atquadrupole('"+elemName+"',"+str(round(c.L,6))+","+str(k1)+",'MaxOrder',4,'PolynomB',[0 "+str(k1)+" 0 0],'Type','"+typeName+"','SN','"+c.SN+"','BDN','"+c.BDN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
self.appendMisalignments(transErrors,elemName,c.MAX,c.MAY,-c.MAR)
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MQCO':
|
||||
k1 = c.K1*(1+c.RFE)
|
||||
elemName = c.NAME.replace('-','_')+'_1'
|
||||
typeName = c.TYPE.replace('-','_')+'_1'
|
||||
wline="atquadrupole('"+elemName+"',"+str(round(c.L/2,6))+","+str(k1)+",'MaxOrder',4,'PolynomB',[0 "+str(k1)+" 0 0],'Type','"+typeName+"','SN','"+c.SN+"','BDN','"+c.BDN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
self.appendMisalignments(transErrors,elemName,str(c.MAX),str(c.MAY),str(-c.MAR))
|
||||
|
||||
for oe in S2.OverlapC[c.NAME]:
|
||||
elemName = oe.NAME.replace('-','_')
|
||||
typeName = oe.TYPE.replace('-','_')
|
||||
|
||||
if oe.SN=='MQSK':
|
||||
tl=-0.78539816339744828-c.MAR
|
||||
# Need to check the sign of tilt
|
||||
wline = "atmultipole('"+elemName+"',0,[0 0 0 0 0],[0 "+str(oe.K1*(1+oe.RFE))+" 0 0],'PassMethod',"+MultipolePass+",'Type','"+typeName+"','SN','"+oe.SN+"','BDN','"+oe.BDN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
elif oe.SN=='MOCT':
|
||||
wline = "atmultipole('"+elemName+"',0,[0 0 0 0 0],[0 0 0 "+str(oe.K3L*(1+oe.RFE))+"],'PassMethod',"+MultipolePass+",'MaxOrder',5,'Type','"+typeName+"','SN','"+oe.SN+"','BDN','"+oe.BDN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
self.appendMisalignments(transErrors,elemName,str(c.MAX),str(c.MAY),str(-c.MAR))
|
||||
|
||||
elemName = c.NAME.replace('-','_')+'_2'
|
||||
typeName = c.TYPE.replace('-','_')+'_2'
|
||||
wline="atquadrupole('"+elemName+"',"+str(round(c.L/2,6))+","+str(k1)+",'MaxOrder',4,'PolynomB',[0 "+str(k1)+" 0 0],'Type','"+typeName+"','SN','"+c.SN+"','BDN','"+c.BDN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
self.appendMisalignments(transErrors,elemName,str(c.MAX),str(c.MAY),str(-c.MAR))
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MSXT':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline="atsextupole('"+elemName+"',"+str(round(c.L,6))+","+str(c.K2*(1+c.RFE))+",'MaxOrder',4,'PolynomB',[0 0 "+str(c.K2*(1+c.RFE))+" 0],'Type','"+typeName+"','SN','"+c.SN+"','BDN','"+c.BDN+"'"+",'PSFamily','"+c.FAMILY+"','Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
self.appendMisalignments(transErrors,elemName,str(c.MAX),str(c.MAY),str(-c.MAR))
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MCOX':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline = "atcorrector('"+elemName+"',"+str(round(c.L,6))+",["+str(c.HKICK)+" 0],'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MCOY':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline = "atcorrector('"+elemName+"',"+str(round(c.L,6))+",[0 "+str(c.VKICK)+"],'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MKIK' or c.SN=='MSEP':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline = "atcorrector('"+elemName+"',"+str(round(c.L,6))+",[0 0],'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
cir=cir+c.L
|
||||
elif c.SN=='DBPM':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline = "atdrift('"+elemName+"',"+str(round(c.L,6))+",'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='VCOL':
|
||||
elemName = c.NAME.replace('-','_')
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
wline = "atdrift('"+elemName+"',"+str(round(c.L,6))+",'EApertures',[1 1],'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
cir=cir+c.L
|
||||
elif c.SN=='NONE':
|
||||
if c.NAME == 'ARS03-NONE-0380':
|
||||
print(c.NAME)
|
||||
print(c.TYPE)
|
||||
print(c.L)
|
||||
print(c.SN)
|
||||
|
||||
if c.L:
|
||||
if c.NAME in Drift.keys():
|
||||
Name=c.NAME+'_'+str(Drift[c.NAME])
|
||||
typeName = c.TYPE.replace('-','_')+'_'+str(Drift[c.NAME])
|
||||
Drift[c.NAME]=Drift[c.NAME]+1
|
||||
else:
|
||||
Name=c.NAME
|
||||
Drift[c.NAME]=1
|
||||
typeName = c.TYPE.replace('-','_')
|
||||
|
||||
elemName = Name.replace('-','_')
|
||||
wline="atdrift('"+elemName+"',"+str(round(c.L,6))+",'Type','"+typeName+"','SN','"+c.SN+"'"+",'Energy',"+str(Energy)+");..."
|
||||
self.write(wline)
|
||||
seq.append(elemName)
|
||||
cir=cir+c.L
|
||||
else:
|
||||
print ('Element unknown:',c.NAME,c.SN,c.L)
|
||||
|
||||
|
||||
# wline='MAL: malign, on_pass=0, force_modify_matrix=0\n'
|
||||
# self.write(wline)
|
||||
# wline='W1: WATCH,MODE=parameter,FILENAME=monitor.w1\n'
|
||||
# self.write(wline)
|
||||
# wline='W2: WATCH,MODE=coordinate,FILENAME=monitor.w2, interval=1\n'
|
||||
# self.write(wline)
|
||||
|
||||
# wline='RF1 : RFCA, L=0.0, FREQ=500e6, VOLT=1.44e6, PHASE=151, T_REFERENCE=0.0\n'
|
||||
# self.write(wline)
|
||||
# wline='RF3 : RFCA, L=0.0, FREQ=1500e6, VOLT=0.375e6, PHASE=0.0, T_REFERENCE=0.0\n'
|
||||
# self.write(wline)
|
||||
|
||||
# wline = "RF1 = atrfcavity('RF1','Length',0,'Frequency',500e6,'Voltage',"+str(RFVoltage)+",'TimeLag',0.251492);"
|
||||
# self.write(wline)
|
||||
# seq.append('RF1')
|
||||
# wline = "RF3 = atrfcavity('RF3','Length',0,'Frequency',1500e6,'Voltage',"+str(RFVoltage_3HC)+",'TimeLag',0.0);"
|
||||
# self.write(wline)
|
||||
# seq.append('RF3')
|
||||
|
||||
# wline = '\n %%%% Setting shifts %%%% \n'
|
||||
#for i in range(0,len(transErrors['name'])):
|
||||
#wline=wline+transErrors['name'][i]+'=atshiftelem('+transErrors['name'][i]+","+transErrors['dx'][i]+","+transErrors['dy'][i]+");\n"
|
||||
#wline = '\n %%%% Setting tilts %%%% \n'
|
||||
#for i in range(0,len(transErrors['name'])):
|
||||
# wline=wline+transErrors['name'][i]+'=attiltelem('+transErrors['name'][i]+","+transErrors['tilt'][i]+");\n"
|
||||
#self.write(wline)
|
||||
|
||||
#wline = 'RING = {...\n '
|
||||
#for i in range(0,len(seq)):
|
||||
#wline=wline+seq[i]+", "
|
||||
#if i%5==0 and i!=len(seq)-1:
|
||||
#wline=wline+'... \n '
|
||||
|
||||
#wline=wline[0:len(wline)-1]+"}';\n"
|
||||
wline = '};\n'
|
||||
#wline=wline+'RING = atsetenergy(RING,'+str(Energy)+');\n'
|
||||
wline=wline+'RING = atsetRFCavity(RING,'+str(RFVoltage)+",1,"+str(HarmNumber)+",0);\n"
|
||||
wline=wline+'RING = atSetRingProperties(RING);'
|
||||
self.write(wline)
|
||||
|
||||
print ('cccccccccccc',cir)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class EMALIGN:
|
||||
def __init__(self, prop):
|
||||
self.SN='EMALIGN'
|
||||
self.NAME=prop['Name']
|
||||
|
||||
class EWATCH:
|
||||
def __init__(self, prop):
|
||||
self.SN='EWATCH'
|
||||
self.NAME=prop['Name']
|
||||
self.MODE=prop['Mode']
|
||||
self.FILENAME=prop['Filename']
|
||||
self.INTERVAL=prop['Interval']
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
from math import *
|
||||
from random import gauss, seed, random
|
||||
|
||||
from os import system
|
||||
|
||||
class BeamDynamics:
|
||||
|
||||
def __init__(self):
|
||||
# SLS2 SR parameters (can be changed for the booster or other ring)
|
||||
self.Circumference=288.0
|
||||
self.BeamEnergy=2.7e9
|
||||
self.Vrf=1.44e6
|
||||
self.Vrf=1.75e6
|
||||
|
||||
self.frf=500e6
|
||||
self.U0=688e3
|
||||
self.alpha=1.05e-4
|
||||
|
||||
self.EnergySpread=1.16e-3
|
||||
|
||||
self.c=2.99792458e8
|
||||
|
||||
|
||||
def BoosterParameter(self):
|
||||
self.Circumference=270.0
|
||||
self.BeamEnergy=2.7e9
|
||||
self.Vrf=0.5e6
|
||||
self.frf=500e6
|
||||
self.U0=373e3
|
||||
self.alpha=5e-3
|
||||
|
||||
self.EnergySpread=0.844e-3
|
||||
|
||||
def SLSparameter(self):
|
||||
|
||||
self.Circumference=288.0
|
||||
self.BeamEnergy=2.4e9
|
||||
self.Vrf=2.4e6
|
||||
self.frf=500e6
|
||||
self.U0=549e3
|
||||
self.alpha=6e-4
|
||||
|
||||
self.EnergySpread=0.88e-3
|
||||
|
||||
|
||||
|
||||
def SynchronousPhase(self, Degree=False):
|
||||
|
||||
|
||||
ph=asin(self.U0/self.Vrf)
|
||||
|
||||
if Degree:
|
||||
ph=ph*180/pi
|
||||
|
||||
return ph
|
||||
|
||||
def SynchrotronTune(self):
|
||||
|
||||
|
||||
phis=self.SynchronousPhase()
|
||||
|
||||
T0=self.Circumference/self.c
|
||||
frev=1/T0
|
||||
|
||||
h=self.frf/frev
|
||||
|
||||
q2=h*self.alpha*self.Vrf*cos(phis)/2/pi/self.BeamEnergy
|
||||
q=sqrt(q2)
|
||||
|
||||
return q
|
||||
|
||||
def BucketHeight(self):
|
||||
|
||||
phis=self.SynchronousPhase()
|
||||
|
||||
T0=self.Circumference/self.c
|
||||
frev=1/T0
|
||||
|
||||
h=self.frf/frev
|
||||
|
||||
F2=cos(phis)-(pi-2*phis)/2*sin(phis)
|
||||
b2=2*self.Vrf/pi/self.BeamEnergy/h/self.alpha*abs(F2)
|
||||
|
||||
b=sqrt(b2)
|
||||
|
||||
return b
|
||||
|
||||
|
||||
def BunchLength(self,mm=True):
|
||||
|
||||
|
||||
q=self.SynchrotronTune()
|
||||
T0=self.Circumference/self.c
|
||||
|
||||
w=2*pi*q/T0
|
||||
|
||||
if mm:
|
||||
bl=self.alpha*self.c*self.EnergySpread/w
|
||||
else:
|
||||
bl=self.alpha*self.c*self.EnergySpread/w/self.c
|
||||
|
||||
|
||||
|
||||
return bl
|
||||
|
||||
def generateBunch(self,InDic,File=None,Format='plain'):
|
||||
|
||||
|
||||
# InDic keys are
|
||||
# bx
|
||||
# by
|
||||
# ax
|
||||
# ay
|
||||
# ex: h emittance (m)
|
||||
# ey
|
||||
# l: bunch length (mm)
|
||||
# d: energy spread(fractional)
|
||||
# N: number of particle
|
||||
|
||||
|
||||
bx=InDic['bx']
|
||||
by=InDic['by']
|
||||
ax=InDic['ax']
|
||||
ay=InDic['ay']
|
||||
|
||||
ex=InDic['ex']
|
||||
ey=InDic['ey']
|
||||
d=InDic['d']
|
||||
|
||||
|
||||
s=InDic['l']
|
||||
|
||||
Mx11=sqrt(bx)
|
||||
Mx12=0.0
|
||||
Mx21=-ax/sqrt(bx)
|
||||
Mx22=1.0/sqrt(bx)
|
||||
|
||||
My11=sqrt(by)
|
||||
My12=0.0
|
||||
My21=-ay/sqrt(by)
|
||||
My22=1.0/sqrt(by)
|
||||
|
||||
|
||||
if File:
|
||||
fout=open(File,'w')
|
||||
else:
|
||||
B=[]
|
||||
|
||||
for i in range(0,InDic['N']):
|
||||
ph=2*pi*random()
|
||||
amp=2*ex*log(1.0/(1.0-random()))
|
||||
xt=sqrt(amp)*cos(ph)
|
||||
xpt=sqrt(amp)*sin(ph)
|
||||
|
||||
x=Mx11*xt+Mx12*xpt
|
||||
xp=Mx21*xt+Mx22*xpt
|
||||
|
||||
ph=2*pi*random()
|
||||
amp=2*ey*log(1.0/(1.0-random()))
|
||||
yt=sqrt(amp)*cos(ph)
|
||||
ypt=sqrt(amp)*sin(ph)
|
||||
|
||||
y=My11*yt+My12*ypt
|
||||
yp=My21*yt+My22*ypt
|
||||
|
||||
|
||||
ph=2*pi*random()
|
||||
amp=2*log(1.0/(1.0-random()))
|
||||
ss=sqrt(s*1e-12*amp)*cos(ph)
|
||||
p=sqrt(d*amp)*sin(ph)
|
||||
|
||||
if File:
|
||||
wline=str(x)+' '+str(xp)+' '+str(y)+' '+str(yp)+' '+str(ss)+' '+str(p)+'\n'
|
||||
fout.write(wline)
|
||||
else:
|
||||
B.append([x,xp,y,yp,ss,p])
|
||||
|
||||
if File:
|
||||
fout.close()
|
||||
else:
|
||||
return B
|
||||
|
||||
return
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
import os
|
||||
|
||||
from math import *
|
||||
|
||||
|
||||
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
|
||||
|
||||
class Elegant():
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def openFile(self,name='SLS2.lat'):
|
||||
self.fout=open(name,'w')
|
||||
|
||||
def closeFile(self):
|
||||
self.fout.close()
|
||||
|
||||
def write(self,line):
|
||||
line=line+'\n'
|
||||
self.fout.write(line)
|
||||
|
||||
|
||||
def defineSequence(self,S2,Radiation=0,Aperture=0,RF=0):
|
||||
# Input is an instance of OMFacility.Facility
|
||||
if Aperture:
|
||||
cnow=Aperture['Nominal']
|
||||
RingA=[cnow]
|
||||
for c in S2.Ring:
|
||||
if type(c)==str:
|
||||
pass
|
||||
elif c.SN[0]=='E':
|
||||
RingA.append(c)
|
||||
elif cnow!=c.APERTURE:
|
||||
cnow=c.APERTURE
|
||||
RingA.append(cnow)
|
||||
RingA.append(c)
|
||||
else:
|
||||
RingA.append(c)
|
||||
else:
|
||||
RingA=S2.Ring
|
||||
|
||||
d2r=pi/180.0
|
||||
|
||||
Drift={}
|
||||
seq=[]
|
||||
cir=0
|
||||
Iap=1
|
||||
for c in RingA:
|
||||
if type(c)==str:
|
||||
pass
|
||||
elif type(c)==list:
|
||||
Name='APERTURE'+str(Iap)
|
||||
seq.append(Name)
|
||||
Iap=Iap+1
|
||||
if c[0]==None:
|
||||
xm=0.05
|
||||
else:
|
||||
xm=c[0]
|
||||
if c[1]==None:
|
||||
ym=0.05
|
||||
else:
|
||||
ym=c[1]
|
||||
if c[2]=='E' or c[2]=='e':
|
||||
ell='1'
|
||||
else:
|
||||
ell='0'
|
||||
if len(c)==4:
|
||||
wline=Name.replace('-','_')+' : MAXAMP, X_MAX= '+str(xm) \
|
||||
+', Y_MAX= '+str(ym)+', ELLIPTICAL= '+str(ell)+', OPEN_SIDE= '+str(c[3])
|
||||
else:
|
||||
wline=Name.replace('-','_')+' : MAXAMP, X_MAX= '+str(xm) \
|
||||
+', Y_MAX= '+str(ym)+', ELLIPTICAL= '+str(ell)
|
||||
self.write(wline)
|
||||
elif c.SN=='EMALIGN':
|
||||
wline=c.NAME+': malign, on_pass=0, force_modify_matrix=0'
|
||||
self.write(wline)
|
||||
seq.append(c.NAME)
|
||||
elif c.SN=='EWATCH':
|
||||
wline=c.NAME+': WATCH,MODE='+c.MODE+',FILENAME='+c.FILENAME
|
||||
self.write(wline)
|
||||
seq.append(c.NAME)
|
||||
elif c.SN=='DRIF':
|
||||
if c.NAME in Drift.keys():
|
||||
Name=c.NAME+'_'+str(Drift[c.NAME])
|
||||
Drift[c.NAME]=Drift[c.NAME]+1
|
||||
else:
|
||||
Name=c.NAME
|
||||
Drift[c.NAME]=1
|
||||
wline=Name.replace('-','_')+' : EDRIFT, L= '+str(round(c.L,6))
|
||||
self.write(wline)
|
||||
seq.append(Name.replace('-','_'))
|
||||
cir=cir+c.L
|
||||
elif c.SN[0]=='R':
|
||||
wline=c.NAME.replace('-','_')+' : EDRIFT, L= '+str(round(c.L,6))
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MBEN' or c.SN=='MBCF':
|
||||
if c.SN=='MBCF':
|
||||
k1=c.K1*(1+c.RGE)
|
||||
else:
|
||||
k1=0
|
||||
|
||||
wline=c.NAME.replace('-','_')+'_E : EHKICK, L=0, Kick='+str(d2r*c.ANGLE*c.RFE/2)
|
||||
self.write(wline)
|
||||
|
||||
# Minus sign for c.MAR is to be consistent with MADX definition
|
||||
wline=c.NAME.replace('-','_')+' : CSBEND, L= '+str(c.L)+', &\n' \
|
||||
+' ANGLE=' +str(d2r*c.ANGLE)+', E1 ='+str(d2r*c.E1)+', E2 ='+str(d2r*c.E2)+', &\n' \
|
||||
+' K1 ='+str(k1)+', N_KICKS=10, INTEGRATION_ORDER=4, &\n' \
|
||||
+' USE_RAD_DIST='+str(Radiation)+', ADD_OPENING_ANGLE='+str(Radiation)
|
||||
#+' DX='+str(c.MAX)+', DY='+str(c.MAY)+', ETILT='+str(-c.MAR)+', &\n' \
|
||||
self.write(wline)
|
||||
|
||||
seq.append(c.NAME.replace('-','_')+'_E')
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
seq.append(c.NAME.replace('-','_')+'_E')
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MBSC':
|
||||
wline=c.NAME.replace('-','_')+'_E : EHKICK, L=0, Kick='+str(d2r*c.TANGLE*c.RFE/2)
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_')+'_E')
|
||||
for i in range(0,len(c.L)):
|
||||
wline=c.NAME.replace('-','_')+'_'+str(i)+' : CSBEND, L= '+str(c.L[i])+', &\n' \
|
||||
+' ANGLE=' +str(d2r*c.ANGLE[i])+', E1 ='+str(d2r*c.E1[i])+', E2 ='+str(d2r*c.E2[i])+', &\n' \
|
||||
+' K1 =0, N_KICKS=2, INTEGRATION_ORDER=4, &\n' \
|
||||
+' USE_RAD_DIST='+str(Radiation)+', ADD_OPENING_ANGLE='+str(Radiation)
|
||||
|
||||
#+' DX='+str(c.MAX[i])+', DY='+str(c.MAY[i])+', ETILT='+str(-c.MAR)+', &\n' \
|
||||
|
||||
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_')+'_'+str(i))
|
||||
seq.append(c.NAME.replace('-','_')+'_E')
|
||||
cir=cir+c.TL
|
||||
elif c.SN=='UIND':
|
||||
wline=c.NAME.replace('-','_').replace('DRIF','UIND')+' : EDRIFT, L= '+str(round(c.L,6))
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_').replace('DRIF','UIND'))
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MQUA':
|
||||
|
||||
wline=c.NAME.replace('-','_')+' : KQUAD, L= '+str(round(c.L,6))+',N_KICKS=10 , K1= '+str(c.K1*(1+c.RFE))+'\n' \
|
||||
# +' DX='+str(c.MAX)+', DY='+str(c.MAY)+', TILT='+str(-c.MAR)
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MQCO':
|
||||
|
||||
wline=c.NAME.replace('-','_')+'_1'+' : KQUAD, L= '+str(round(c.L/2,6))+',N_KICKS=4 , K1= '+str(c.K1*(1+c.RFE))+'\n'
|
||||
# +' DX='+str(c.MAX)+', DY='+str(c.MAY)+', TILT='+str(-c.MAR)
|
||||
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_')+'_1')
|
||||
for oe in S2.OverlapC[c.NAME]:
|
||||
if oe.SN=='MQSK':
|
||||
tl=-0.78539816339744828-c.MAR
|
||||
# Need to check the sign of tilt
|
||||
wline=oe.NAME.replace('-','_')+' : MULT, ORDER=1, L=0, TILT='+str(tl)+', KNL='+str(oe.K1*(1+c.RFE))+'\n'
|
||||
#+' DX='+str(c.MAX)+', DY='+str(c.MAY)
|
||||
self.write(wline)
|
||||
seq.append(oe.NAME.replace('-','_'))
|
||||
elif oe.SN=='MOCT':
|
||||
wline=oe.NAME.replace('-','_')+' : MULT, ORDER=3, L=0, KNL='+str(oe.K3L*6*(1+c.RFE))+'\n'
|
||||
#+' DX='+str(c.MAX)+', DY='+str(c.MAY)+', TILT='+str(-c.MAR)
|
||||
self.write(wline)
|
||||
seq.append(oe.NAME.replace('-','_'))
|
||||
wline=c.NAME.replace('-','_')+'_2'+' : KQUAD, L= '+str(round(c.L/2,6))+',N_KICKS=4 , K1= '+str(c.K1*(1+c.RFE))+'\n'
|
||||
#+' DX='+str(c.MAX)+', DY='+str(c.MAY)+', TILT='+str(-c.MAR)
|
||||
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_')+'_2')
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MSXT':
|
||||
|
||||
wline=c.NAME.replace('-','_')+' : KSEXT, L= '+str(round(c.L,6))+',N_KICKS=8 , K2= '+str(c.K2*2*(1+c.RFE))+'\n'
|
||||
# +' DX='+str(c.MAX)+', DY='+str(c.MAY)+', TILT='+str(-c.MAR)
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MCOX':
|
||||
|
||||
wline=c.NAME.replace('-','_')+' : EHKICK, L= '+str(round(c.L,6))+', Kick='+str(c.HKICK)
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MCOY':
|
||||
|
||||
wline=c.NAME.replace('-','_')+' : EVKICK, L= '+str(round(c.L,6))+', Kick='+str(c.VKICK)
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='MKIK' or c.SN=='MSEP':
|
||||
|
||||
wline=c.NAME.replace('-','_')+' : EHKICK, L= '+str(round(c.L,6))+', Kick=0'
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
|
||||
cir=cir+c.L
|
||||
elif c.SN=='DBPM':
|
||||
|
||||
wline=c.NAME.replace('-','_')+' : MONI, L= '+str(round(c.L,6))
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
|
||||
cir=cir+c.L
|
||||
|
||||
|
||||
elif c.SN=='VCOL':
|
||||
wline=c.NAME.replace('-','_')+' : EDRIFT, L= '+str(round(c.L,6))
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
cir=cir+c.L
|
||||
|
||||
|
||||
elif c.SN=='MMAP':
|
||||
wline=c.NAME.replace('-','_')+' : BGGEXP'
|
||||
self.write(wline)
|
||||
seq.append(c.NAME.replace('-','_'))
|
||||
|
||||
cir=cir+c.TL
|
||||
|
||||
|
||||
|
||||
|
||||
elif c.SN=='NONE':
|
||||
if c.L:
|
||||
if c.NAME in Drift.keys():
|
||||
Name=c.NAME+'_'+str(Drift[c.NAME])
|
||||
Drift[c.NAME]=Drift[c.NAME]+1
|
||||
else:
|
||||
Name=c.NAME
|
||||
Drift[c.NAME]=1
|
||||
wline=Name.replace('-','_')+' : EDRIFT, L= '+str(round(c.L,6))
|
||||
self.write(wline)
|
||||
seq.append(Name.replace('-','_'))
|
||||
cir=cir+c.L
|
||||
else:
|
||||
print ('xxxxxxxxxxxxxx',c.NAME,c.SN,c.L)
|
||||
|
||||
|
||||
wline='MAL: malign, on_pass=0, force_modify_matrix=0\n'
|
||||
self.write(wline)
|
||||
wline='W1: WATCH,MODE=parameter,FILENAME=monitor.w1\n'
|
||||
self.write(wline)
|
||||
wline='W2: WATCH,MODE=coordinate,FILENAME=monitor.w2, interval=1\n'
|
||||
self.write(wline)
|
||||
|
||||
wline='RF1 : RFCA, L=0.0, FREQ=500e6, VOLT=1.44e6, PHASE=151, T_REFERENCE=0.0\n'
|
||||
self.write(wline)
|
||||
wline='RF3 : RFCA, L=0.0, FREQ=1500e6, VOLT=0.375e6, PHASE=0.0, T_REFERENCE=0.0\n'
|
||||
self.write(wline)
|
||||
|
||||
|
||||
|
||||
if RF:
|
||||
wline='RING : LINE=(MAL,RF1,RF3,W1,W2,'
|
||||
else:
|
||||
wline='RING : LINE=(MAL,W1,W2,'
|
||||
|
||||
for i in range(0,len(seq)):
|
||||
wline=wline+seq[i]+','
|
||||
if i%5==0 and i!=len(seq)-1:
|
||||
wline=wline+' &\n'
|
||||
|
||||
wline=wline[0:len(wline)-1]+')'
|
||||
self.write(wline)
|
||||
|
||||
print ('cccccccccccc',cir)
|
||||
|
||||
class EMALIGN:
|
||||
def __init__(self, prop):
|
||||
self.SN='EMALIGN'
|
||||
self.NAME=prop['Name']
|
||||
|
||||
class EWATCH:
|
||||
def __init__(self, prop):
|
||||
self.SN='EWATCH'
|
||||
self.NAME=prop['Name']
|
||||
self.MODE=prop['Mode']
|
||||
self.FILENAME=prop['Filename']
|
||||
self.INTERVAL=prop['Interval']
|
||||
|
||||
|
||||
|
||||
|
||||
+715
@@ -0,0 +1,715 @@
|
||||
|
||||
|
||||
import PyCafe
|
||||
from OMSLS2Magnet import *
|
||||
|
||||
|
||||
import pickle
|
||||
|
||||
|
||||
from time import sleep
|
||||
|
||||
class EpicsChannel:
|
||||
|
||||
def __init__(self,S2,VA=False,Default=False):
|
||||
|
||||
# "Dictionary" for the epics channels,
|
||||
# the names of which may be changing
|
||||
# S2 is an instance of OMFacility
|
||||
# The names are temporary. Change them only in this script.
|
||||
# The actual epics name shoud not be used
|
||||
# in other script for consistency.
|
||||
|
||||
|
||||
if VA:
|
||||
self.pf=VA+'-'
|
||||
else:
|
||||
self.pf=''
|
||||
|
||||
|
||||
self.cafe=PyCafe.CyCafe()
|
||||
self.cafe.init()
|
||||
self.cyca=PyCafe.CyCa()
|
||||
|
||||
if S2:
|
||||
# Relevant modules
|
||||
self.S2=S2
|
||||
self.SM=SLS2Magnet()
|
||||
|
||||
|
||||
# Some important channels
|
||||
# RF frequency
|
||||
self.frf=self.pf+'AGARF-TIM:BO-FREQ-SET' # This should be used. 'AGARF' is not typo
|
||||
#self.frf=self.pf+'AGERF-MO01:FREQ-SET'
|
||||
|
||||
# from 0.1 Hz to 100000(?) Hz == 10 Hz/s to 10 MHz/s
|
||||
self.frfrate=self.pf+'AGERF-MO01:FREQ-STEP'
|
||||
|
||||
# Trigger
|
||||
|
||||
self.TriggerEnable=self.pf+'AGETI-CVME-MASTER-TMA:SR-Inj-Status-Sel'
|
||||
#self.Trigger=self.pf+'ALIRF-VME-A-GUN:CH1-SWTRIG' # Gun trigger
|
||||
#self.Trigger=self.pf+'ALIRF-VME-A-GUN:CH1-MODE' # Gun trigger
|
||||
self.Trigger=self.pf+'AGETI-CVME-MASTER-TMA:Evt-10-Ena-Sel'
|
||||
|
||||
self.BPMTrigger='AGETI-CVME-MASTER-TMA:Evt-11-Ena-Sel'
|
||||
|
||||
|
||||
# This may be used to keep the booster and the linac running. Masked -> Down ramp, not extracted
|
||||
self.TriggerMask=self.pf+'AGETI-CVME-MASTER-TMA:Evt-BO-Ext-Mask-SP'
|
||||
|
||||
|
||||
self.ch={}
|
||||
self.Handle={}
|
||||
|
||||
#TbT
|
||||
self.TbTopen=False
|
||||
|
||||
# Edit here in case Epics channel is changed...
|
||||
self.Atr_PS={'I':'I-SET',
|
||||
'I-READ':'I-READ',
|
||||
'ON':'ONOFF'}
|
||||
# Kicker power supply
|
||||
self.Atr_KPS={'I':'I-SET',
|
||||
'I-READ':'I-READ',
|
||||
'DELAY':'DELAY',
|
||||
'ON':'ONOFF'}
|
||||
|
||||
|
||||
|
||||
if self.pf:
|
||||
self.Atr_BPM={'X':'X',
|
||||
'Y':'Y',
|
||||
'Q':'Q',
|
||||
'OX':'OFFS-X',
|
||||
'OY':'OFFS-Y',
|
||||
'TBTX':'TBT-X',
|
||||
'TBTY':'TBT-Y',
|
||||
'TBTZ':'TBT-Z',
|
||||
'TBTQ':'TBT-Q',
|
||||
'MODE':'MODE'}
|
||||
else:
|
||||
self.Atr_BPM={'X':'POS-STG2-X',
|
||||
'Y':'POS-STG2-Y',
|
||||
'Q':'POS-STG2-CHARGE',
|
||||
'OX':'OFF-BBA-X',
|
||||
'OY':'OFF-BBA-Y',
|
||||
'OMX':'OFF-PU-X', # Mechanical
|
||||
'OMY':'OFF-PU-Y',
|
||||
'OEX':'OFF-EL-X', # Electronics
|
||||
'OEY':'OFF-EL-Y',
|
||||
'TBTX':'TBT-STG0-X',
|
||||
'TBTY':'TBT-STG0-Y',
|
||||
'TBTQ':'TBT-STG0-Q',
|
||||
'TBTX2':'DAQ-BEAM-STG0-X',
|
||||
'TBTY2':'DAQ-BEAM-STG0-Y',
|
||||
'TBTQ2':'DAQ-BEAM-STG0-CHARGE',
|
||||
'REF-OP-X':'X-B-REF-OP',
|
||||
'REF-OP-Y':'Y-B-REF-OP',
|
||||
'MODE':'MODE'}
|
||||
|
||||
|
||||
self.Atr_ID={'GAP':'GAP-SET',
|
||||
'GAP-READ':'GAP-READ'}
|
||||
|
||||
|
||||
self.Atr_RF={'Phase':'PHASE-SHIFT'}
|
||||
|
||||
|
||||
# Phase of 500 MHz (for all 4 cavities)
|
||||
self.rfphase=self.pf+'ARS05-RSYS-0000:'+self.Atr_RF['Phase']
|
||||
|
||||
if Default and S2:
|
||||
|
||||
def bySN(SN,attribute):
|
||||
elem=S2.listElement_SN(SN)
|
||||
#for s in attribute:
|
||||
# self.ch[SN+'_'+s[0]]=[self.pf+e+':'+s[1] for e in elem]
|
||||
for k in attribute.keys():
|
||||
self.ch[SN+'_'+k]=[self.pf+e+':'+attribute[k] for e in elem]
|
||||
|
||||
def byTYPE(TYPE,attribute,bothIO):
|
||||
elem=S2.listElement_TYPE(TYPE,bothIO)
|
||||
#for s in attribute:
|
||||
# self.ch[TYPE+'_'+s[0]]=[self.pf+e+':'+s[1] for e in elem]
|
||||
for k in attribute.keys():
|
||||
self.ch[TYPE+'_'+k]=[self.pf+e+':'+attribute[k] for e in elem]
|
||||
|
||||
|
||||
#def byTYPE(TYPE,bothIO):
|
||||
|
||||
|
||||
# Atr[i]=['Name easy to remember','Real Epics attribute (it is subject to be changed)']
|
||||
Atr=self.Atr_PS
|
||||
bySN('MQUA', Atr)
|
||||
for t in S2.SN['MQUA']:
|
||||
byTYPE(t, Atr, True)
|
||||
|
||||
#bySN('MSXT', Atr)
|
||||
#for t in S2.SN['MSXT']:
|
||||
# byTYPE(t, Atr, True)
|
||||
|
||||
# Sextupole are in families...
|
||||
SFamily,Dad=S2.getSextFamily()
|
||||
for k in Atr.keys():
|
||||
self.ch['MSXT_'+k]=[self.pf+e+':'+Atr[k] for e in Dad]
|
||||
for t in S2.SN['MSXT']:
|
||||
elem=S2.listElement_TYPE(t,True)
|
||||
for k in Atr.keys():
|
||||
self.ch[t+'_'+k]=[]
|
||||
for e in elem:
|
||||
if e in Dad:
|
||||
self.ch[t+'_'+k].append(self.pf+e+':'+Atr[k])
|
||||
|
||||
|
||||
|
||||
bySN('MOCT', Atr)
|
||||
for t in S2.SN['MOCT']:
|
||||
byTYPE(t, Atr, True)
|
||||
|
||||
bySN('MCOX', Atr)
|
||||
for t in S2.SN['MCOX']:
|
||||
byTYPE(t, Atr, True)
|
||||
|
||||
bySN('MCOY', Atr)
|
||||
for t in S2.SN['MCOY']:
|
||||
byTYPE(t, Atr, True)
|
||||
|
||||
|
||||
bySN('MQCO', Atr)
|
||||
for t in S2.SN['MQCO']:
|
||||
byTYPE(t, Atr, True)
|
||||
|
||||
bySN('MQSK', Atr)
|
||||
for t in S2.SN['MQSK']:
|
||||
byTYPE(t, Atr, True)
|
||||
|
||||
|
||||
Atr=self.Atr_KPS
|
||||
byTYPE('KIN', Atr, False)
|
||||
|
||||
|
||||
Atr=self.Atr_ID
|
||||
bySN('UIND', Atr)
|
||||
|
||||
|
||||
|
||||
Atr=self.Atr_BPM
|
||||
|
||||
|
||||
if VA:
|
||||
Atr['SIMX']='SIM-X'
|
||||
Atr['SIMY']='SIM-Y'
|
||||
|
||||
|
||||
bySN('DBPM', Atr)
|
||||
for t in S2.SN['DBPM']:
|
||||
byTYPE(t, Atr, True)
|
||||
|
||||
|
||||
|
||||
# For convenience.
|
||||
self.ch['BPM_X']=self.ch['DBPM_X']
|
||||
self.ch['BPM_Y']=self.ch['DBPM_Y']
|
||||
self.ch['BPM_OX']=self.ch['DBPM_OX']
|
||||
self.ch['BPM_OY']=self.ch['DBPM_OY']
|
||||
self.ch['BPM_MODE']=self.ch['DBPM_MODE']
|
||||
self.ch['BPM_TBTX']=self.ch['DBPM_TBTX']
|
||||
self.ch['BPM_TBTY']=self.ch['DBPM_TBTY']
|
||||
self.ch['BPM_TBTQ']=self.ch['DBPM_TBTQ']
|
||||
|
||||
if VA:
|
||||
# Beam position from simultion
|
||||
# X=SIM-X + OFFS-X
|
||||
# The operator in the above equation (+ or -) is subject to be confirmed.
|
||||
self.ch['BPM_SIMX']=self.ch['DBPM_SIMX']
|
||||
self.ch['BPM_SIMY']=self.ch['DBPM_SIMY']
|
||||
|
||||
|
||||
# creating handles
|
||||
self.createHandle(self.ch.keys())
|
||||
|
||||
|
||||
|
||||
def get(self, Channel,stat=False,dtype='native'):
|
||||
|
||||
|
||||
if type(Channel)==list:
|
||||
v=[]
|
||||
for n in Channel:
|
||||
vi=self.cafe.get(n,dt=dtype)
|
||||
v.append(vi)
|
||||
return v
|
||||
|
||||
elif Channel in self.Handle.keys():
|
||||
[values, s, slist]=self.cafe.getGroup(self.Handle[Channel],dtype)
|
||||
if stat:
|
||||
return values, s, slist
|
||||
else:
|
||||
return values
|
||||
|
||||
elif ':' in Channel:
|
||||
v=self.cafe.get(Channel,dt=dtype)
|
||||
return v
|
||||
else:
|
||||
print ('Error: Input to EC.get "'+Channel+'" is wrong')
|
||||
return -1
|
||||
|
||||
def getNtimes(self, Channel,N,stat=False,dtype='native',waiting=1):
|
||||
|
||||
|
||||
if type(Channel)==list:
|
||||
v=[[] for _ in range(0,len(Channel))]
|
||||
for nm in range(0,N):
|
||||
for i in range(0,len(Channel)):
|
||||
vi=self.cafe.get(Channel[i],dt=dtype)
|
||||
v[i].append(vi)
|
||||
sleep(waiting)
|
||||
vstd=[]
|
||||
vmean=[]
|
||||
for vi in v:
|
||||
vi=np.array(vi)
|
||||
vstd.append(vi.std())
|
||||
vmean.append(vi.mean())
|
||||
|
||||
|
||||
return v.tolist(),vmean.tolist(),vstd.tolist()
|
||||
|
||||
elif Channel in self.Handle.keys():
|
||||
|
||||
values=[]
|
||||
s=[]
|
||||
slist=[]
|
||||
for i in range(0,n):
|
||||
[valuesi, si, slisti]=self.cafe.getGroup(self.Handle[Channel],dtype)
|
||||
sleep (waiting)
|
||||
values.append(i)
|
||||
s.append(si)
|
||||
slist.append(slisti)
|
||||
|
||||
values=np.array(values)
|
||||
values=values.transpose()
|
||||
s=np.array(s)
|
||||
s=s.transpose()
|
||||
slist=np.array(slist)
|
||||
slist=slist.transpose()
|
||||
vstd=[]
|
||||
vmean=[]
|
||||
for vi in v:
|
||||
vi=np.array(vi)
|
||||
vstd.append(vi.std())
|
||||
vmean.append(vi.mean())
|
||||
|
||||
|
||||
|
||||
if stat:
|
||||
return values.tolist(), vmean.tolist(), vstd.tolist(),s.tolist(), slist.tolist()
|
||||
else:
|
||||
return values.tolist(), vmean.tolist(), vstd.tolist()
|
||||
|
||||
elif ':' in Channel:
|
||||
v=[]
|
||||
for i in range(0,N):
|
||||
vi=self.cafe.get(Channel,dt=dtype)
|
||||
v.append(vi)
|
||||
sleep(waiting)
|
||||
|
||||
v=np.array(v)
|
||||
vmean=v.mean()
|
||||
vstd=v.std()
|
||||
|
||||
return v.tolist(),vmean.tolist(),vstd.tolist()
|
||||
else:
|
||||
print ('Error: Input to EC.get "'+Channel+'" is wrong')
|
||||
return -1
|
||||
|
||||
|
||||
|
||||
|
||||
def put(self, Channel, value):
|
||||
|
||||
|
||||
if type(Channel)==list:
|
||||
|
||||
for i in range(0,len(Channel)):
|
||||
self.cafe.set(Channel[i],value[i],dt=dtype)
|
||||
return v
|
||||
|
||||
elif Channel in self.Handle.keys():
|
||||
if len(value)!=len(self.ch[Channel]):
|
||||
print ('Error: the number of input values does not match to the number of channels of the group, '+Channel)
|
||||
return
|
||||
|
||||
s,slist=self.cafe.setGroup(self.Handle[Channel],value)
|
||||
return s, slist
|
||||
|
||||
elif ':' in Channel:
|
||||
s=self.cafe.set(Channel,value)
|
||||
return s
|
||||
|
||||
|
||||
|
||||
def createHandle(self,key):
|
||||
self.cafe.openGroupPrepare()
|
||||
if type(key)=='str':
|
||||
key=[key]
|
||||
for k in key:
|
||||
if k in self.ch.keys() and k not in self.Handle.keys():
|
||||
if self.pf:
|
||||
for i in range(0,len(self.ch[k])):
|
||||
if self.pf not in self.ch[k][i]:
|
||||
self.ch[k][i]=self.pf+self.ch[k][i]
|
||||
self.Handle[k]=self.cafe.grouping(k, self.ch[k])
|
||||
|
||||
|
||||
if len(key)<30:
|
||||
wait=len(key)*0.5
|
||||
else:
|
||||
wait=20
|
||||
|
||||
self.cafe.openGroupNowAndWait(wait)
|
||||
|
||||
|
||||
|
||||
def getHandle(self,key):
|
||||
if key not in self.Handle.keys():
|
||||
print('OMEpics: No such a handle',key)
|
||||
return None
|
||||
|
||||
return self.Handle[key]
|
||||
|
||||
|
||||
def createGroup(self,key,Channel):
|
||||
|
||||
if self.pf:
|
||||
for i in range(0,len(Channel)):
|
||||
c=Channel[i]
|
||||
if self.pf not in c:
|
||||
Channel[i]=self.pf+c
|
||||
|
||||
|
||||
self.cafe.openGroupPrepare()
|
||||
Handle=self.cafe.grouping(key, Channel)
|
||||
self.cafe.openGroupNowAndWait(1)
|
||||
|
||||
self.Handle[key]=Handle
|
||||
self.ch[key]=Channel
|
||||
return Handle
|
||||
|
||||
|
||||
|
||||
# Interface to the machine
|
||||
|
||||
def updateMachine_TYPE(self,TYPE):
|
||||
|
||||
|
||||
KL=self.S2.getKL_TYPE(TYPE,bothIO=True)
|
||||
|
||||
I=self.SM.KL2I(TYPE,KL)
|
||||
if TYPE in self.S2.SN['MQUA']+self.S2.SN['MSXT']+['KIN']:
|
||||
I=list(np.abs(np.array(I))) # All quad and sext PSs are unipolar
|
||||
self.put(TYPE+'_I',I)
|
||||
|
||||
|
||||
|
||||
def updateModel_TYPE(self,TYPE):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
|
||||
I,s,status=self.get(TYPE+'_I',stat=True)
|
||||
KL=self.SM.I2KL(TYPE,I)
|
||||
|
||||
elem=self.S2.getElement_TYPE(TYPE,bothIO=True)
|
||||
|
||||
for i in range(0,len(elem)):
|
||||
e=elem[i]
|
||||
if e.SN=='MQUA' or e.SN=='MSXT' or e.TYPE=='KIN':
|
||||
if e.POL==-1:
|
||||
KL[i]=-KL[i]
|
||||
#print (e.SN, e.POL, KL[i])
|
||||
|
||||
#if TYPE=='QSOS2A':
|
||||
# print ('debuggingggg',KL)
|
||||
|
||||
self.S2.setKL_TYPE(TYPE,KL,bothIO=True)
|
||||
|
||||
|
||||
|
||||
def updateQuad_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.S2=S2 # synchronization
|
||||
|
||||
for t in self.S2.SN['MQUA']:
|
||||
self.updateMachine_TYPE(t)
|
||||
|
||||
|
||||
|
||||
def updateQuad_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
for t in self.S2.SN['MQUA']:
|
||||
self.updateModel_TYPE(t)
|
||||
|
||||
return self.S2
|
||||
|
||||
|
||||
def updateSext_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.S2=S2 # synchronization
|
||||
|
||||
SFamily,Dad=self.S2.getSextFamily()
|
||||
|
||||
for t in self.S2.SN['MSXT']:
|
||||
#self.updateMachine_TYPE(t)
|
||||
|
||||
elem=self.S2.getElement_TYPE(t,bothIO=True)
|
||||
KL=[]
|
||||
for e in elem:
|
||||
if e.NAME in Dad:
|
||||
KL.append(e.KL())
|
||||
|
||||
I=self.SM.KL2I(t,KL)
|
||||
I=list(np.abs(np.array(I))) # All sext PSs are unipolar
|
||||
self.put(t+'_I',I)
|
||||
|
||||
|
||||
|
||||
|
||||
def updateSext_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
SFamily,Dad=self.S2.getSextFamily()
|
||||
for t in self.S2.SN['MSXT']:
|
||||
#self.updateModel_TYPE(t)
|
||||
|
||||
|
||||
I,s,status=self.get(t+'_I',stat=True)
|
||||
KL=self.SM.I2KL(t,I)
|
||||
#elem=self.S2.getElement_TYPE(TYPE,bothIO=True)
|
||||
|
||||
for n in Dad:
|
||||
e=self.S2.getElement(n)
|
||||
if e.TYPE==t:
|
||||
if e.POL==-1:
|
||||
KL[0]=-KL[0]
|
||||
e.setKL(KL[0])
|
||||
KL.pop(0) # fine to consume
|
||||
|
||||
self.S2.bindSextFamily()
|
||||
|
||||
|
||||
return self.S2
|
||||
|
||||
|
||||
|
||||
|
||||
def updateOct_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.S2=S2 # synchronization
|
||||
|
||||
for t in self.S2.SN['MOCT']:
|
||||
self.updateMachine_TYPE(t)
|
||||
|
||||
|
||||
|
||||
def updateOct_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
for t in self.S2.SN['MOCT']:
|
||||
self.updateModel_TYPE(t)
|
||||
|
||||
return self.S2
|
||||
|
||||
|
||||
def updateCH_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.S2=S2 # synchronization
|
||||
|
||||
for t in self.S2.SN['MCOX']:
|
||||
self.updateMachine_TYPE(t)
|
||||
|
||||
|
||||
def updateCH_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
for t in self.S2.SN['MCOX']:
|
||||
self.updateModel_TYPE(t)
|
||||
|
||||
return self.S2
|
||||
|
||||
|
||||
def updateCV_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.S2=S2 # synchronization
|
||||
|
||||
for t in self.S2.SN['MCOY']:
|
||||
self.updateMachine_TYPE(t)
|
||||
|
||||
|
||||
def updateCV_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
for t in self.S2.SN['MCOY']:
|
||||
self.updateModel_TYPE(t)
|
||||
|
||||
return self.S2
|
||||
|
||||
|
||||
def updateCorr_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.updateCH_Machine(S2)
|
||||
self.updateCV_Machine(S2)
|
||||
|
||||
|
||||
def updateCorr_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
self.updateCH_Model()
|
||||
self.updateCV_Model()
|
||||
|
||||
return self.S2
|
||||
|
||||
def updateQcorr_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.S2=S2 # synchronization
|
||||
|
||||
for t in self.S2.SN['MQCO']:
|
||||
self.updateMachine_TYPE(t)
|
||||
|
||||
|
||||
def updateQcorr_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
for t in self.S2.SN['MQCO']:
|
||||
self.updateModel_TYPE(t)
|
||||
|
||||
return self.S2
|
||||
|
||||
def updateSkewQ_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.S2=S2 # synchronization
|
||||
|
||||
for t in self.S2.SN['MQSK']:
|
||||
self.updateMachine_TYPE(t)
|
||||
|
||||
|
||||
def updateSkewQ_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
|
||||
for t in self.S2.SN['MQSK']:
|
||||
self.updateModel_TYPE(t)
|
||||
|
||||
return self.S2
|
||||
|
||||
|
||||
def updateInjKicker_Machine(self,S2):
|
||||
|
||||
# Model to Machine
|
||||
|
||||
self.S2=S2 # synchronization
|
||||
self.updateMachine_TYPE('KIN')
|
||||
|
||||
|
||||
def updateInjKicker_Model(self):
|
||||
|
||||
# Machine to Model
|
||||
self.updateModel_TYPE('KIN')
|
||||
|
||||
return self.S2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def updateMachine(self,S2):
|
||||
|
||||
# Model to Machine, all electromagnets
|
||||
# Superconducting superbend is not included
|
||||
self.updateQuad_Machine(S2)
|
||||
self.updateSext_Machine(S2)
|
||||
self.updateOct_Machine(S2)
|
||||
self.updateCorr_Machine(S2)
|
||||
self.updateQcorr_Machine(S2)
|
||||
self.updateSkewQ_Machine(S2)
|
||||
self.updateInjKicker_Machine(S2)
|
||||
|
||||
def updateModel(self):
|
||||
|
||||
# Machine to Model, all electromagnets
|
||||
# Superconducting superbend is not included
|
||||
self.updateQuad_Model()
|
||||
self.updateSext_Model()
|
||||
self.updateOct_Model()
|
||||
self.updateCorr_Model()
|
||||
self.updateQcorr_Model()
|
||||
self.updateSkewQ_Model()
|
||||
self.updateInjKicker_Model()
|
||||
|
||||
|
||||
return self.S2
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def getTbT(self,Nturn=4000):
|
||||
# Used in Virtual accelerator but general function
|
||||
# "TbT DAQ server" from Jan may be available in the future
|
||||
|
||||
if Nturn>4000:
|
||||
Nturn=4000
|
||||
|
||||
|
||||
if self.ch.keys():
|
||||
sx,vx,v=self.cafe.getGroup(self.getHandle('BPM_TBTX'))
|
||||
sy,vy,v=self.cafe.getGroup(self.getHandle('BPM_TBTY'))
|
||||
if vx and vy:
|
||||
return sx,sy
|
||||
else:
|
||||
print ('Error: Something wrong with TbT channels')
|
||||
return -1,-1
|
||||
else:
|
||||
print ('Error: Default group must be listed before getting TbT data.')
|
||||
return -1,-1
|
||||
|
||||
|
||||
|
||||
def putTbT(self,X,Y,Q):
|
||||
# Method for Virtual Accelerator
|
||||
|
||||
if self.ch.keys():
|
||||
self.cafe.setGroup(self.getHandle('BPM_TBTX'),X)
|
||||
self.cafe.setGroup(self.getHandle('BPM_TBTY'),Y)
|
||||
self.cafe.setGroup(self.getHandle('BPM_TBTQ'),Q)
|
||||
else:
|
||||
print ('Error: Default group must be listed before putting TbT data.')
|
||||
return -1
|
||||
|
||||
#self.cafe.set(EpicsName,)
|
||||
+3081
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
|
||||
# To be developed?
|
||||
|
||||
class Aperture():
|
||||
def __init__(self,S2):
|
||||
self.S2=S2
|
||||
+808
@@ -0,0 +1,808 @@
|
||||
|
||||
import warnings
|
||||
import math
|
||||
import numpy as np
|
||||
|
||||
|
||||
|
||||
from time import sleep
|
||||
|
||||
class SLS2Magnet:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
|
||||
self.TF={}
|
||||
# [PhysicalLength,MagneticLength,Imax,Ilin,b0,b1,b2,b3,R] # b1/R is the gradient at Imax.
|
||||
# If Ilin = Imax, Ilin is not specified (Completely linear magnet)
|
||||
|
||||
# TF as in the hard edge model (OPA, MADX): Magnetic length needs to be updated.
|
||||
# The reference radius R is to be updated as well.
|
||||
# N.B. The coefficients b0...b3 are the values for the magnetic length self.TF[TYPE][1]
|
||||
|
||||
# Quadrupoles
|
||||
#self.TF['QP'] = [0.1, 0.1, 70.0, 70.0, 0.0, 0.93, 0.0, 0.0, 10e-3] # B' = 93 T/m
|
||||
#self.TF['QPH'] = [0.14, 0.14, 70.0, 70.0, 0.0, 0.98, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QA-SLS'] = [0.2, 0.2, 100.0, 100.0, 0.0, 0.232, 0.0, 0.0, 10e-3] # Imax? Assumed 100 A
|
||||
|
||||
|
||||
# Quadrupoles, RC measurement , Average
|
||||
self.TF['QP']=[0.1, 0.1, 70, 30, 0.0124054210164, 1.17036699272, -0.0365565108681, -0.170883350929, 0.01] # B' = 97.5 T/m
|
||||
self.TF['QPH']=[0.14, 0.14, 70, 30, 0.0102827462421, 1.17181174371, -0.011395413075, -0.159266318031, 0.01] # B' = 101 T/m
|
||||
self.TF['QA-SLS']=[0.2, 0.2, 140, 60, 0.00136432203379, 0.27820143007, 0.0176124050321, -0.0382317191743, 0.01]
|
||||
|
||||
|
||||
# Quad TF for individual magnets, RC measurements. The fitting parameters were optimized for the design KL.
|
||||
|
||||
# QA-SLS. PS is 200A but it is limited by 140 A because the masurement is up to 140 A.
|
||||
self.TF['ARS01-MQUA-0550']=[0.2, 0.2, 140, 100, 0.00488, 0.2713445, -0.0049465, -0.012803, 0.01] # QA-SLS, Iop ~100 A
|
||||
self.TF['ARS01-MQUA-0630']=[0.2, 0.2, 140, 80, 0.002286, 0.2762515, -0.00340875, -0.00876825, 0.01] # QA-SLS, Iop ~90 A
|
||||
self.TF['ARS01-MQUA-0710']=[0.2, 0.2, 140, 60, 0.001557, 0.27769, 0.00252044992238, -0.0149713056857, 0.01] # QA-SLS, Iop ~70 A
|
||||
self.TF['ARS01-MQUA-0790']=[0.2, 0.2, 140, 80, 0.00225, 0.275947, -0.002493, -0.0102735, 0.01] # QA-SLS, Iop ~80 A
|
||||
|
||||
# QPQPH
|
||||
self.TF['ARS01-MQUA-1050']=[0.14, 0.14, 70, 20, 0.0079816469117, 1.18426791131, 0.0607856512304, -0.240357941024, 0.01] # QPHI, Iop ~7.7 A
|
||||
self.TF['ARS01-MQUA-1150']=[0.14, 0.14, 70, 20, 0.00780358419145, 1.18327391369, 0.0592729332282, -0.237078966931, 0.01] # QPHI, Iop ~9.0 A
|
||||
self.TF['ARS01-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0247799757689, 1.13441076405, -0.12621890086, -0.0593464732633, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS01-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00848221658502, 1.18858462161, 0.053299271752, -0.27387803496, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS01-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00889372897434, 1.18708702888, 0.0468748602597, -0.268231245943, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS01-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0260260881338, 1.13154607743, -0.126546336342, -0.0570747831374, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS01-MQUA-5840']=[0.14, 0.14, 70, 40, 0.0211814862285, 1.13867427654, -0.0758619050232, -0.0727559666234, 0.01] # QPHO, Iop ~38.6 A
|
||||
self.TF['ARS01-MQUA-5940']=[0.14, 0.14, 70, 40, 0.021218804957, 1.14130843974, -0.0820442421302, -0.0701489583562, 0.01] # QPHO, Iop ~44.6 A
|
||||
self.TF['ARS02-MQUA-1050']=[0.14, 0.14, 70, 40, 0.0206876279741, 1.14384909713, -0.0868747005732, -0.0670370106246, 0.01] # QPHI, Iop ~44.6 A
|
||||
self.TF['ARS02-MQUA-1150']=[0.14, 0.14, 70, 40, 0.0210358327099, 1.1408488786, -0.0825655559607, -0.0695451730122, 0.01] # QPHI, Iop ~38.6 A
|
||||
self.TF['ARS02-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0281344468765, 1.12829322512, -0.11147754187, -0.068230198569, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS02-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00975104251237, 1.18629392371, 0.0432965311437, -0.261556210155, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS02-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00887526988747, 1.18673090298, 0.0550926317902, -0.272720818131, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS02-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0254463436238, 1.13067866503, -0.124119384679, -0.0587013887557, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS02-MQUA-5840']=[0.14, 0.14, 70, 30, 0.0103821620424, 1.17320069866, -0.00993066582094, -0.161935823288, 0.01] # QPHO, Iop ~33.4 A
|
||||
self.TF['ARS02-MQUA-5940']=[0.14, 0.14, 70, 40, 0.020648451604, 1.1439090513, -0.0823157071707, -0.0702809483788, 0.01] # QPHO, Iop ~36.3 A
|
||||
self.TF['ARS03-MQUA-0790']=[0.1, 0.1, 70, 40, 0.0272066497068, 1.12841779995, -0.115233383507, -0.0645004640065, 0.01] # QPI, Iop ~53.1 A
|
||||
self.TF['ARS03-MQUA-0850']=[0.14, 0.14, 70, 40, 0.0209160870773, 1.14211267618, -0.0820081546424, -0.0706922398986, 0.01] # QPHI, Iop ~36.7 A
|
||||
self.TF['ARS03-MQUA-1050']=[0.14, 0.14, 70, 20, 0.00819675364402, 1.18562474712, 0.0597058598824, -0.23890894014, 0.01] # QPHI, Iop ~22.9 A
|
||||
self.TF['ARS03-MQUA-1150']=[0.14, 0.14, 70, 20, 0.00858152465222, 1.18197092671, 0.0529375528162, -0.231703365243, 0.01] # QPHI, Iop ~17.5 A
|
||||
self.TF['ARS03-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0269406186117, 1.12955549412, -0.118907416087, -0.0619703797266, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS03-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00965256963755, 1.18401903318, 0.0467911845914, -0.264203812484, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS03-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00857027952163, 1.18889972891, 0.0505494793685, -0.271872116878, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS03-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0256548352751, 1.13230392888, -0.129341990792, -0.0544080071894, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS03-MQUA-5840']=[0.14, 0.14, 70, 40, 0.0213806820773, 1.13950226217, -0.0782507183232, -0.0721058497186, 0.01] # QPHO, Iop ~38.6 A
|
||||
self.TF['ARS03-MQUA-5940']=[0.14, 0.14, 70, 40, 0.0206628710298, 1.14212719542, -0.0795591345361, -0.0715860089672, 0.01] # QPHO, Iop ~44.6 A
|
||||
self.TF['ARS04-MQUA-1050']=[0.14, 0.14, 70, 40, 0.0209345318443, 1.14046892518, -0.0786355600943, -0.071896728547, 0.01] # QPHI, Iop ~44.6 A
|
||||
self.TF['ARS04-MQUA-1150']=[0.14, 0.14, 70, 40, 0.0216322849976, 1.13818073211, -0.0798716183076, -0.070319861398, 0.01] # QPHI, Iop ~38.6 A
|
||||
self.TF['ARS04-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0265365959324, 1.13033441086, -0.120305946845, -0.0607396225677, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS04-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00963430309403, 1.18643320353, 0.042977616531, -0.263226334512, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS04-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00861983962921, 1.18624182868, 0.0507152161104, -0.270666875622, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS04-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0251328199829, 1.1332744067, -0.127577980309, -0.056985026738, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS04-MQUA-5840']=[0.14, 0.14, 70, 20, 0.00790583701142, 1.18530354203, 0.0659552290113, -0.245122745463, 0.01] # QPHO, Iop ~16.4 A
|
||||
self.TF['ARS04-MQUA-5940']=[0.14, 0.14, 70, 20, 0.00804610678733, 1.186385026, 0.0606395931537, -0.241377878168, 0.01] # QPHO, Iop ~15.6 A
|
||||
self.TF['ARS05-MQUA-0400']=[0.1, 0.1, 70, 30, 0.0125790177572, 1.17281702, -0.0347460504964, -0.172653881113, 0.01] # QPI, Iop ~28.0 A
|
||||
self.TF['ARS05-MQUA-0440']=[0.14, 0.14, 70, 40, 0.0211634853755, 1.14413196707, -0.0793531303093, -0.0716327579334, 0.01] # QPHI, Iop ~40.4 A
|
||||
self.TF['ARS05-MQUA-0460']=[0.1, 0.1, 70, 30, 0.0126579317795, 1.16922925137, -0.0375603205641, -0.168705762093, 0.01] # QPI, Iop ~27.0 A
|
||||
self.TF['ARS05-MQUA-1050']=[0.14, 0.14, 70, 20, 0.00774486989439, 1.18754949481, 0.0620179277666, -0.24114682342, 0.01] # QPHI, Iop ~23.3 A
|
||||
self.TF['ARS05-MQUA-1150']=[0.14, 0.14, 70, 20, 0.00802871824166, 1.18431759806, 0.0576122341581, -0.236502845788, 0.01] # QPHI, Iop ~22.8 A
|
||||
self.TF['ARS05-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0271287901891, 1.13414292589, -0.121261721603, -0.0604158205581, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS05-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00960159948821, 1.18333529506, 0.0436891146943, -0.261119481475, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS05-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00876466294849, 1.1853873149, 0.0498332611993, -0.269059748251, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS05-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0255139951502, 1.12924950946, -0.124584766918, -0.0573399883576, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS05-MQUA-5840']=[0.14, 0.14, 70, 40, 0.0213666428504, 1.13999184379, -0.0799300156275, -0.0699959750481, 0.01] # QPHO, Iop ~38.6 A
|
||||
self.TF['ARS05-MQUA-5940']=[0.14, 0.14, 70, 40, 0.0218895438638, 1.13758969545, -0.0756379705509, -0.0734605282405, 0.01] # QPHO, Iop ~44.6 A
|
||||
self.TF['ARS06-MQUA-1050']=[0.14, 0.14, 70, 40, 0.0206159749159, 1.14193423012, -0.0806427533998, -0.0711219067748, 0.01] # QPHI, Iop ~44.6 A
|
||||
self.TF['ARS06-MQUA-1150']=[0.14, 0.14, 70, 40, 0.0208669606643, 1.14211127137, -0.0811107642473, -0.0701542973755, 0.01] # QPHI, Iop ~38.6 A
|
||||
self.TF['ARS06-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0268325856985, 1.12641137526, -0.122382240161, -0.0577017897957, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS06-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00930736510072, 1.18441021623, 0.048972494037, -0.266253683669, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS06-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00865003188391, 1.18545647308, 0.0434107952861, -0.265108650677, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS06-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0255249681458, 1.13475658895, -0.131813158637, -0.0535355978289, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS06-MQUA-5840']=[0.14, 0.14, 70, 30, 0.010044621805, 1.17515051983, -0.0128135520533, -0.1590811517, 0.01] # QPHO, Iop ~33.4 A
|
||||
self.TF['ARS06-MQUA-5940']=[0.14, 0.14, 70, 40, 0.0223744436868, 1.13354277752, -0.0722763427687, -0.0745863421613, 0.01] # QPHO, Iop ~36.3 A
|
||||
self.TF['ARS07-MQUA-0790']=[0.1, 0.1, 70, 40, 0.0268261240229, 1.12850775962, -0.118800652519, -0.0628860550894, 0.01] # QPI, Iop ~53.1 A
|
||||
self.TF['ARS07-MQUA-0850']=[0.14, 0.14, 70, 40, 0.0208905323449, 1.13952490478, -0.0799232788124, -0.0703853281269, 0.01] # QPHI, Iop ~36.7 A
|
||||
self.TF['ARS07-MQUA-1050']=[0.14, 0.14, 70, 20, 0.00804233260923, 1.18227651418, 0.0547790934989, -0.233560353823, 0.01] # QPHI, Iop ~22.9 A
|
||||
self.TF['ARS07-MQUA-1150']=[0.14, 0.14, 70, 20, 0.00802871824166, 1.18431759806, 0.0576122341581, -0.236502845788, 0.01] # QPHI, Iop ~17.5 A
|
||||
self.TF['ARS07-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0281031810394, 1.12893170363, -0.117669105678, -0.0625133783651, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS07-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00980882672538, 1.18872328962, 0.0374271684138, -0.256366123299, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS07-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00847524785543, 1.18992810605, 0.0544746450998, -0.275611678451, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS07-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0249982564086, 1.13441872059, -0.1267857731, -0.0578763307642, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS07-MQUA-5840']=[0.14, 0.14, 70, 40, 0.0214016570398, 1.13618633301, -0.0772154462687, -0.0715549107099, 0.01] # QPHO, Iop ~38.6 A
|
||||
self.TF['ARS07-MQUA-5940']=[0.14, 0.14, 70, 40, 0.021270649292, 1.13808807646, -0.0834245165349, -0.0663986333325, 0.01] # QPHO, Iop ~44.6 A
|
||||
self.TF['ARS08-MQUA-1050']=[0.14, 0.14, 70, 40, 0.021866214922, 1.14100488468, -0.0847840451378, -0.0676795914515, 0.01] # QPHI, Iop ~44.6 A
|
||||
self.TF['ARS08-MQUA-1150']=[0.14, 0.14, 70, 40, 0.021583400373, 1.1374895233, -0.0780905864371, -0.0709151165956, 0.01] # QPHI, Iop ~38.6 A
|
||||
self.TF['ARS08-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0262205362497, 1.1325643365, -0.120885991747, -0.0617708042626, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS08-MQUA-1370']=[0.1, 0.1, 70, 20, 0.0100496738163, 1.18381400068, 0.0451620927184, -0.264181428461, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS08-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00847462872389, 1.18869636031, 0.0467484847972, -0.267916853268, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS08-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0253903831111, 1.13613484907, -0.123237046266, -0.060971293687, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS08-MQUA-5840']=[0.14, 0.14, 70, 20, 0.00836745561575, 1.17950303913, 0.0503519252676, -0.227065469804, 0.01] # QPHO, Iop ~22.8 A
|
||||
self.TF['ARS08-MQUA-5940']=[0.14, 0.14, 70, 20, 0.00810429348709, 1.18288656076, 0.0631416700628, -0.242320436554, 0.01] # QPHO, Iop ~23.3 A
|
||||
self.TF['ARS09-MQUA-0530']=[0.1, 0.1, 70, 30, 0.0127891751638, 1.16692866622, -0.0409710312471, -0.164789851012, 0.01] # QPI, Iop ~27.0 A
|
||||
self.TF['ARS09-MQUA-0560']=[0.14, 0.14, 70, 40, 0.0214713744249, 1.14073041109, -0.0856866562901, -0.0665440469885, 0.01] # QPHI, Iop ~40.4 A
|
||||
self.TF['ARS09-MQUA-0600']=[0.1, 0.1, 70, 30, 0.0127619782193, 1.16828383793, -0.0361652515646, -0.170749694948, 0.01] # QPI, Iop ~28.0 A
|
||||
self.TF['ARS09-MQUA-1050']=[0.14, 0.14, 70, 20, 0.00779032031895, 1.18265637839, 0.0594775676297, -0.237358884081, 0.01] # QPHI, Iop ~15.6 A
|
||||
self.TF['ARS09-MQUA-1150']=[0.14, 0.14, 70, 20, 0.0080277997637, 1.18191264557, 0.0597399764031, -0.238021257565, 0.01] # QPHI, Iop ~16.4 A
|
||||
self.TF['ARS09-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0267706894238, 1.13076827934, -0.12013134413, -0.0609304526397, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS09-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00975022252034, 1.1851528742, 0.0462951187818, -0.264920831307, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS09-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00855153353985, 1.18824348557, 0.0472851933418, -0.26792967913, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS09-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0255240672583, 1.13334352816, -0.124209703075, -0.0597870566735, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS09-MQUA-5840']=[0.14, 0.14, 70, 40, 0.0209767380866, 1.1426776217, -0.0830055429835, -0.0700440208241, 0.01] # QPHO, Iop ~38.6 A
|
||||
self.TF['ARS09-MQUA-5940']=[0.14, 0.14, 70, 40, 0.0199847664639, 1.1460043739, -0.08413546869, -0.0695934332314, 0.01] # QPHO, Iop ~44.6 A
|
||||
self.TF['ARS10-MQUA-1050']=[0.14, 0.14, 70, 40, 0.0217641858904, 1.14140891045, -0.0854203959054, -0.0667485107897, 0.01] # QPHI, Iop ~44.6 A
|
||||
self.TF['ARS10-MQUA-1150']=[0.14, 0.14, 70, 40, 0.0207292846941, 1.14423904487, -0.080135185258, -0.0718125452506, 0.01] # QPHI, Iop ~38.6 A
|
||||
self.TF['ARS10-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0258090656403, 1.13553947618, -0.130644282989, -0.0533206254614, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS10-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00947055560653, 1.18815632538, 0.0411679839075, -0.260723655328, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS10-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00911052864507, 1.18393663418, 0.0488972528733, -0.266237706673, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS10-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0260113983687, 1.13095518645, -0.132058997795, -0.0522074038276, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS10-MQUA-5840']=[0.14, 0.14, 70, 30, 0.0106285443939, 1.16665730475, -0.0110844546315, -0.157408907481, 0.01] # QPHO, Iop ~33.6 A
|
||||
self.TF['ARS10-MQUA-5940']=[0.14, 0.14, 70, 40, 0.0218788903308, 1.1376141267, -0.0785207911539, -0.0709542819546, 0.01] # QPHO, Iop ~36.6 A
|
||||
self.TF['ARS11-MQUA-0830']=[0.1, 0.1, 70, 40, 0.0265181957302, 1.13383540023, -0.127380182735, -0.0547182574518, 0.01] # QPI, Iop ~55.1 A
|
||||
self.TF['ARS11-MQUA-0890']=[0.14, 0.14, 70, 40, 0.0205970408064, 1.14515548387, -0.083934978866, -0.0695185459798, 0.01] # QPHI, Iop ~37.6 A
|
||||
self.TF['ARS11-MQUA-1050']=[0.14, 0.14, 70, 20, 0.0079358870871, 1.18061941427, 0.0614609673978, -0.238016106498, 0.01] # QPHI, Iop ~14.5 A
|
||||
self.TF['ARS11-MQUA-1150']=[0.14, 0.14, 70, 20, 0.00800634347948, 1.18471069605, 0.0603066884021, -0.239723573916, 0.01] # QPHI, Iop ~9.4 A
|
||||
self.TF['ARS11-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0273752271128, 1.13241152476, -0.125645642304, -0.0566159720971, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS11-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00965935297016, 1.19194142929, 0.0405792648832, -0.261956785075, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS11-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00849380670863, 1.1894190651, 0.0485528210467, -0.26993497585, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS11-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0256314514959, 1.12963122732, -0.126061205037, -0.0573436886644, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS11-MQUA-5840']=[0.14, 0.14, 70, 40, 0.0213763770321, 1.13734894957, -0.0750542249952, -0.0737853659135, 0.01] # QPHO, Iop ~38.6 A
|
||||
self.TF['ARS11-MQUA-5940']=[0.14, 0.14, 70, 40, 0.0204266463933, 1.14314697383, -0.0813557115322, -0.0701256402485, 0.01] # QPHO, Iop ~44.6 A
|
||||
self.TF['ARS12-MQUA-1050']=[0.14, 0.14, 70, 40, 0.0205229308439, 1.14304301399, -0.08119174372, -0.070698637475, 0.01] # QPHI, Iop ~44.6 A
|
||||
self.TF['ARS12-MQUA-1150']=[0.14, 0.14, 70, 40, 0.0202362585845, 1.1468959314, -0.0868251723613, -0.0671963440997, 0.01] # QPHI, Iop ~38.6 A
|
||||
self.TF['ARS12-MQUA-1260']=[0.1, 0.1, 70, 40, 0.0275665929965, 1.12839886306, -0.117736405417, -0.0623624641848, 0.01] # QPI, Iop ~53.0 A
|
||||
self.TF['ARS12-MQUA-1370']=[0.1, 0.1, 70, 20, 0.00934141409333, 1.18981443873, 0.0480146676568, -0.267751345363, 0.01] # QPI, Iop ~24.3 A
|
||||
self.TF['ARS12-MQUA-5620']=[0.1, 0.1, 70, 20, 0.00843531827322, 1.18999128935, 0.0506938763075, -0.273164664944, 0.01] # QPO, Iop ~24.3 A
|
||||
self.TF['ARS12-MQUA-5730']=[0.1, 0.1, 70, 40, 0.0247221190877, 1.13800703358, -0.132283214609, -0.0554632926452, 0.01] # QPO, Iop ~53.0 A
|
||||
self.TF['ARS12-MQUA-5840']=[0.14, 0.14, 70, 20, 0.00786389740308, 1.18513390968, 0.0617435132693, -0.24107128681, 0.01] # QPHO, Iop ~23.2 A
|
||||
self.TF['ARS12-MQUA-5940']=[0.14, 0.14, 70, 20, 0.00828198631199, 1.1825837794, 0.0563437707965, -0.233951363216, 0.01] # QPHO, Iop ~22.4 A
|
||||
|
||||
|
||||
|
||||
|
||||
# S extupoles
|
||||
# Specification from Andreas' note (or TDR BD chapter) # Keep them for history tacking
|
||||
#self.TF['HS2A'] = [0.09, 0.09, 50.0, 50.0, 0.0, 58.5, 0.0, 0.0, 10e-3] # B''/2 = 5850 T/m**2
|
||||
#self.TF['HS2B'] = [0.09, 0.09, 50.0, 50.0, 0.0, 58.5, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2G'] = [0.08, 0.08, 50.0, 50.0, 0.0, 58.5, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2H'] = [0.08, 0.08, 50.0, 50.0, 0.0, 58.5, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2K'] = [0.08, 0.08, 50.0, 50.0, 0.0, 58.5, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2L'] = [0.08, 0.08, 50.0, 50.0, 0.0, 58.5, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2M'] = [0.08, 0.08, 50.0, 50.0, 0.0, 58.5, 0.0, 0.0, 10e-3]
|
||||
|
||||
#self.TF['SXQ'] = [0.09, 0.09, 70.0, 70.0, 0.0, 58.5, 0.0, 0.0, 10e-3]
|
||||
|
||||
# Simulation by Vjeran. No neighboring magnet. 24.08.2022
|
||||
#self.TF['HS2A'] = [0.09, 0.09, 50.0, 50.0, 0.0, 60.378, 0.0, 0.0, 10e-3] # B''/2 = 5850 T/m**2
|
||||
#self.TF['HS2B'] = [0.09, 0.09, 50.0, 50.0, 0.0, 67.378, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2G'] = [0.08, 0.08, 50.0, 50.0, 0.0, 59.100, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2H'] = [0.08, 0.08, 50.0, 50.0, 0.0, 59.100, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2K'] = [0.08, 0.08, 50.0, 50.0, 0.0, 59.038, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2L'] = [0.08, 0.08, 50.0, 50.0, 0.0, 59.038, 0.0, 0.0, 10e-3]
|
||||
#self.TF['HS2M'] = [0.08, 0.08, 50.0, 50.0, 0.0, 58.650, 0.0, 0.0, 10e-3]
|
||||
|
||||
#self.TF['SXQ'] = [0.09, 0.09, 70.0, 70.0, 0.0, 64.556, 0.0, 0.0, 10e-3]
|
||||
|
||||
# Rotation coil measurement, Average
|
||||
# /afs/psi.ch/project/SLS2/Magnets/MeasurementData/Data2OM_SX.py
|
||||
self.TF['HS2A']=[0.09, 0.09, 50.0, 30.0, 0.268672570371, 68.6573024724, 3.63950855666, -10.8627324327, 0.01]
|
||||
self.TF['HS2B']=[0.09, 0.09, 50.0, 30.0, 0.268672570371, 68.6573024724, 3.63950855666, -10.8627324327, 0.01]
|
||||
self.TF['HS2G']=[0.08, 0.08, 50.0, 30.0, 0.275523116667, 68.5291754064, 3.76726246385, -11.6558744619, 0.01]
|
||||
self.TF['HS2H']=[0.08, 0.08, 50.0, 30.0, 0.275523116667, 68.5291754064, 3.76726246385, -11.6558744619, 0.01]
|
||||
self.TF['HS2K']=[0.08, 0.08, 50.0, 30.0, 0.31366815, 68.4752835626, 3.57602204301, -11.4685644869, 0.01]
|
||||
self.TF['HS2L']=[0.08, 0.08, 50.0, 30.0, 0.31366815, 68.4752835626, 3.57602204301, -11.4685644869, 0.01]
|
||||
self.TF['HS2M']=[0.08, 0.08, 50.0, 30.0, 0.312616666667, 68.4330312501, 4.0780833326, -12.5120999994, 0.01]
|
||||
|
||||
self.TF['SXQ']=[0.09, 0.09, 70.0, 38.0, 0.356884451852, 86.4520837835, -21.2484787107, 0.669766969922, 0.01]
|
||||
|
||||
|
||||
# Including cross-talk and hysteresis. Documentation: "Transfer function based on RC data and Opera.pptx"
|
||||
# Note that the dictionary key is BD name (element.BDN), since the cross talk effect depends on the neiboring magnets
|
||||
self.TF['SXX']=[0.09, 0.09, 50.0, 32.0, 0.268672570371, 68.6573024724, 1.69650336984, -8.91972724591, 0.01] # 32 A with an educated guess
|
||||
self.TF['SXY']=[0.09, 0.09, 50.0, 32.0, 0.268672570371, 68.6573024724, 1.69650336984, -8.91972724591, 0.01]
|
||||
self.TF['SYY']=[0.09, 0.09, 50.0, 32.0, 0.268672570371, 68.6573024724, 1.69650336984, -8.91972724591, 0.01]
|
||||
|
||||
|
||||
self.TF['SDM']=[0.09, 0.09, 70.0, 35.2, 0.715160903971, 86.1953605446, -29.1497302221, 6.90040275271, 0.01]
|
||||
self.TF['SD5']=[0.08, 0.08, 50.0, 32.0, -1.97091476148, 69.1754314874, -4.11968288296, -4.45067935221, 0.01]
|
||||
self.TF['SD4']=[0.08, 0.08, 50.0, 32.0, -1.97091476148, 69.1754314874, -4.11968288296, -4.45067935221, 0.01] # HS2M (SD4I) is approximated with HS2G (SD4O)
|
||||
self.TF['SD3']=[0.08, 0.08, 50.0, 32.0, -1.97091476148, 69.1754314874, -4.11968288296, -4.45067935221, 0.01]
|
||||
self.TF['SD2']=[0.08, 0.08, 50.0, 32.0, -1.97091476148, 69.1754314874, -4.11968288296, -4.45067935221, 0.01]
|
||||
self.TF['SD1']=[0.08, 0.08, 50.0, 32.0, -1.97091476148, 69.1754314874, -4.11968288296, -4.45067935221, 0.01]
|
||||
|
||||
self.TF['SFM']=[0.08, 0.08, 50.0, 32.0, 0.6360058481379699, 68.93581758298821, -9.424073445272223, -0.050151019762392335, 0.01] #
|
||||
self.TF['SF2']=[0.08, 0.08, 50.0, 32.0, 0.251363431128, 68.9500649825, -5.92252125704, -3.02979404361, 0.01]
|
||||
self.TF['SF1']=[0.08, 0.08, 50.0, 32.0, 0.251363431128, 68.9500649825, -5.92252125704, -3.02979404361, 0.01]
|
||||
|
||||
|
||||
# Octupoles
|
||||
# Specification from Andreas' note (or TDR BD chapter)
|
||||
#self.TF['OS2A'] = [0.0, 0.05, 5.0, 5.0, 0.0, 630.0, 0.0, 0.0, 10e-3] # B'''/6 = 63000 T/m**3
|
||||
#self.TF['OS2B'] = [0.0, 0.05, 5.0, 5.0, 0.0, 630.0, 0.0, 0.0, 10e-3]
|
||||
#self.TF['OS2E'] = [0.0, 0.05, 5.0, 5.0, 0.0, 630.0, 0.0, 0.0, 10e-3]
|
||||
#self.TF['OS2F'] = [0.0, 0.05, 5.0, 5.0, 0.0, 630.0, 0.0, 0.0, 10e-3]
|
||||
|
||||
# Simulation by Vjeran. No neighboring magnet. 24.08.2022
|
||||
# Magnetic length is not defined. Keep 5 cm for now. 31.08.2022
|
||||
#self.TF['OS2A'] = [0.0, 0.05, 5.0, 5.0, 0.0, 695.8, 0.0, 0.0, 10e-3] # B'''/6 = 69580 T/m**3
|
||||
#self.TF['OS2B'] = [0.0, 0.05, 5.0, 5.0, 0.0, 695.8, 0.0, 0.0, 10e-3]
|
||||
#self.TF['OS2E'] = [0.0, 0.05, 5.0, 5.0, 0.0, 695.6, 0.0, 0.0, 10e-3]
|
||||
#self.TF['OS2F'] = [0.0, 0.05, 5.0, 5.0, 0.0, 695.6, 0.0, 0.0, 10e-3]
|
||||
|
||||
# RC measurement
|
||||
# /afs/psi.ch/project/SLS2/Magnets/MeasurementData/Data2OM_OC.py
|
||||
# To be verified and on-line
|
||||
self.TF['OS2A']=[0.0, 0.05, 5.0, 0, 0.0, 669.303622067, 86.1565359977, -49.6460189903, 0.01] # B'''/6 = 74934 T/m**3
|
||||
self.TF['OS2B']=[0.0, 0.05, 5.0, 0, 0.0, 668.321158671, 86.5072962136, -49.0092030546, 0.01]
|
||||
self.TF['OS2E']=[0.0, 0.05, 5.0, 0, 0.0, 667.935924897, 88.7205354028, -49.4010112743, 0.01]
|
||||
self.TF['OS2F']=[0.0, 0.05, 5.0, 0, 0.0, 667.618682856, 87.0688628959, -48.4244780922, 0.01]
|
||||
|
||||
|
||||
# Including cross-talk. Hysteresis is excluded since the PS is bipolar. Documentation: "Transfer function based on RC data and Opera.pptx"
|
||||
# Note that the dictionary key is BD name (element.BDN), since the cross talk effect depends on the neiboring magnets
|
||||
# Three cases considered, 1) with no cross talk anticipated, 2) with no direct cross talk anticipated but there is an octupole component nearby, and 3) with cross talk
|
||||
# For OXX, OXY, OYY (Case 1), use the above TFs from RC data, SM.I2KL(element.TYPE, I), provided the cross talk between electromagnets is not signigficant.
|
||||
# For OCY1/OCY2 (Case 2), set option in SM.I2KL(element.TYPE, I, CrossTalk=element.BDN) -> The follwing offset is then included.
|
||||
# For OCX1, OCX2 and OCXM (Case3), use the TFs below. SM.I2KL(element.BDN, I, CrossTalk=element.BDN): Note that both TYPE and CrossTalk = element.BDN
|
||||
self.TF0={}
|
||||
self.TF0['OCY2']=70.070791927 # K3L offset in SDn. Its current dependency is not included here since it is not significant as for OCX
|
||||
self.TF0['OCY1']=70.070791927
|
||||
|
||||
|
||||
self.TF0['OCXM']=56.1877821522+10.7526313278 # C13(ANM) + C10 (Oct off)
|
||||
self.TF0['OCX2']=55.2440968811+10.7526313278 # C11 + C10 (Oct off)
|
||||
self.TF0['OCX1']=28.8497357133+10.7526313278 # C9 + C10 (Oct off)
|
||||
|
||||
|
||||
self.TF['OCXM']=[0.05, 0.05, 5.0, 1.0, 0.0, 727.309735329, -54.0658393851, 35.9640331277, 0.01] # OS2A RC + Opera cross talk + Opera single mag
|
||||
self.TF['OCX2']=[0.05, 0.05, 5.0, 1.0, 0.0, 727.309735329, -54.0658393851, 35.9640331277, 0.01]
|
||||
self.TF['OCX1']=[0.05, 0.05, 5.0, 1.0, 0.0, 727.309735329, -54.0658393851, 35.9640331277, 0.01]
|
||||
|
||||
# Corrector quad, spec requested
|
||||
# Specification from Andreas' note (or TDR BD chapter)
|
||||
#self.TF['QAOS2A'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.056, 0.0, 0.0, 10e-3] # B' = 5.6 T/m
|
||||
#self.TF['QAOS2B'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.056, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QAOS2E'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.056, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QAOS2F'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.056, 0.0, 0.0, 10e-3]
|
||||
|
||||
# Simulation by Vjeran. No neighboring magnet. 24.08.2022
|
||||
#self.TF['QAOS2A'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.06764, 0.0, 0.0, 10e-3] # B' = 6.7 T/m :)
|
||||
#self.TF['QAOS2B'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.06764, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QAOS2E'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.06754, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QAOS2F'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.06754, 0.0, 0.0, 10e-3]
|
||||
|
||||
|
||||
# RC measurement, average
|
||||
self.TF['QAOS2A']=[0.05, 0.05, 5.0, 0, 0.0, 0.063439478074, 0.00894565593072, -0.0047472221448, 0.01] # B' = 6.76 T/m :)
|
||||
self.TF['QAOS2B']=[0.05, 0.05, 5.0, 0, 0.0, 0.0632856330626, 0.00912884806541, -0.00482820798325, 0.01]
|
||||
self.TF['QAOS2E']=[0.05, 0.05, 5.0, 0, 0.0, 0.0628063944775, 0.00978968479097, -0.00512004704693, 0.01]
|
||||
self.TF['QAOS2F']=[0.05, 0.05, 5.0, 0, 0.0, 0.0628383904087, 0.00965142365802, -0.00505041790927, 0.01]
|
||||
|
||||
# Corrector skew, spec requested
|
||||
#self.TF['QSOS2A'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.056, 0.0, 0.0, 10e-3] # B' = 5.6 T/m
|
||||
#self.TF['QSOS2B'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.056, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QSOS2E'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.056, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QSOS2F'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.056, 0.0, 0.0, 10e-3]
|
||||
|
||||
|
||||
# Simulation by Vjeran. No neighboring magnet. 24.08.2022
|
||||
#self.TF['QSOS2A'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.06314, 0.0, 0.0, 10e-3] # B' = 6.3 T/m
|
||||
#self.TF['QSOS2B'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.06314, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QSOS2E'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.06312, 0.0, 0.0, 10e-3]
|
||||
#self.TF['QSOS2F'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.06312, 0.0, 0.0, 10e-3]
|
||||
|
||||
# RC measurement, average
|
||||
self.TF['QSOS2A']=[0.05, 0.05, 5.0, 0, 0.0, 0.0590039543127, 0.00881466567091, -0.00463485306762, 0.01] # B' = 6.32 T/m
|
||||
self.TF['QSOS2B']=[0.05, 0.05, 5.0, 0, 0.0, 0.0588472565198, 0.00900380966447, -0.00471795253389, 0.01]
|
||||
self.TF['QSOS2E']=[0.05, 0.05, 5.0, 0, 0.0, 0.0588507592533, 0.0090524480532, -0.00471766261077, 0.01]
|
||||
self.TF['QSOS2F']=[0.05, 0.05, 5.0, 0, 0.0, 0.0589230620203, 0.00884305456705, -0.00460527483071, 0.01]
|
||||
|
||||
# Corrector. Magnetic/Physical length?
|
||||
#self.TF['CH'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.00072*1.5, 0.0, 0.0, 10e-3] # B = 0.072+0.036 T
|
||||
#self.TF['CHS'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.00072*1.5, 0.0, 0.0, 10e-3] # B = 0.072+0.036 T
|
||||
#self.TF['CV'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.00072, 0.0, 0.0, 10e-3] # B = 0.072 T
|
||||
self.TF['CHY'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.00072*1.5, 0.0, 0.0, 10e-3] # B = 0.072+0.036 T
|
||||
self.TF['CVY'] = [0.0, 0.05, 5.0, 5.0, 0.0, 0.00072, 0.0, 0.0, 10e-3] # B = 0.072 T
|
||||
|
||||
|
||||
# Measurement, average
|
||||
self.TF['CHS']=[0.05, 0.05, 5.0, 0, 0.0, 0.00143101755247, 0.000512080877263, -0.000519022672712, 0.01] # 820 urad!
|
||||
self.TF['CV']=[0.05, 0.05, 5.0, 0, 0.0, 0.00103560521719, 0.000121693453739, -7.77922718062e-05, 0.01] # 600 urad!
|
||||
# Measurement, id3 : Factor 0.92 from LOCO, 2025 02 13
|
||||
self.TF['CH']=[0.05, 0.05, 5.0, 0, 0.0, 0.00157085011963*0.92, 0.000195329502438*0.92, -0.000160199545181*0.92, 0.01]
|
||||
|
||||
# Experimental. Correction from LOCO calibration
|
||||
self.TF['CH1470']=[0.05, 0.05, 5.0, 0, 0.0, 0.00157085011963*0.84, 0.000195329502438*0.84, -0.000160199545181*0.84, 0.01]
|
||||
|
||||
# kicker bump
|
||||
self.TF['KIN'] = [0.6, 0.6, 2500.0, 2500.0, 0.0, 0.0007125, 0.0, 0.0, 10e-3] # 4.75 mrad @ 2500 A @ peak, Mail from Martin on 11.07.2024
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# BTR magnets
|
||||
self.TF['QFA'] =[0.15, 0.173, 150.0, 91.1, 0.0, 0.74521, -0.00813, -0.03542, 22.5e-3] # From MEASUREMENT. Documentation: https://intranet.psi.ch/pub/Swiss_FEL/FinQuadrupoles/QFA.pdf (Link is now invalid...)
|
||||
|
||||
self.TF['CVTO'] = [0.05, 0.05, 5.0, 5.0, 0.0, 0.0036, 0.0, 0.0, 10e-3] # 2 mrad at 5A. The length is arbitrarily set to 0.05 m.
|
||||
self.TF['CVTN'] = [0.171, 0.171, 5.0, 5.0, 0.0, 0.0009984310369419486, 0.0, 0.0, 10e-3] # BL= 0.014 Tm at 4.1 A. If it is at 5A, b1=0.0008187134502923977
|
||||
self.TF['CHTN'] = [0.171, 0.171, 5.0, 5.0, 0.0, 0.0009984310369419486, 0.0, 0.0, 10e-3] # BL= 0.014 Tm at 4.1 A. If it is at 5A, b1=0.0008187134502923977
|
||||
|
||||
self.TF['SYINCH'] = [0.171, 0.171, 5.0, 5.0, 0.0, 0.0019883040935672514, 0.0, 0.0, 10e-3] # BL= 0.034 Tm at 5.0 A. If it is at 5A, b1=0.0008187134502923977
|
||||
|
||||
|
||||
|
||||
|
||||
# brho for 2.7 GeV beam
|
||||
gamma=(2.7e9+511e3)/511e3
|
||||
beta=math.sqrt(1-1/gamma**2)
|
||||
p=511e3*beta*gamma/1e9 # momentum in GeV/c
|
||||
self.brho=p/0.299792 # P[GeV/c]=0.3*Brho[T.m]
|
||||
|
||||
|
||||
|
||||
# Multipole errors based on Vjeran's simulation. Experimental 29.08.2022
|
||||
|
||||
|
||||
self.ME={}
|
||||
# 20 poles is upper limit in tracy-null?
|
||||
#self.ME['OS2A'] = [['k11',-232.9E+15/self.brho]]
|
||||
#self.ME['OS2B'] = [['k11',-232.9E+15/self.brho]]
|
||||
#self.ME['OS2E'] = [['k11',-232.5E+15/self.brho]]
|
||||
#self.ME['OS2F'] = [['k11',-232.5E+15/self.brho]]
|
||||
|
||||
self.ME['QAOS2A'] = [['k5',4.969e6/self.brho/0.05],['k9',-4.993e12/self.brho/0.05]]
|
||||
self.ME['QAOS2B'] = [['k5',4.969e6/self.brho/0.05],['k9',-4.993e12/self.brho/0.05]]
|
||||
self.ME['QAOS2E'] = [['k5',4.966e6/self.brho/0.05],['k9',-4.521e12/self.brho/0.05]]
|
||||
self.ME['QAOS2F'] = [['k5',4.966e6/self.brho/0.05],['k9',-4.521e12/self.brho/0.05]]
|
||||
|
||||
self.ME['QSOS2A'] = [['j5',-4.612e6/self.brho/0.05],['j9',-4.103e12/self.brho/0.05]]
|
||||
self.ME['QSOS2B'] = [['j5',-4.612e6/self.brho/0.05],['j9',-4.103e12/self.brho/0.05]]
|
||||
self.ME['QSOS2E'] = [['j5',-4.617e6/self.brho/0.05],['j9',-4.182e12/self.brho/0.05]]
|
||||
self.ME['QSOS2F'] = [['j5',-4.617e6/self.brho/0.05],['j9',-4.182e12/self.brho/0.05]]
|
||||
|
||||
|
||||
|
||||
# k3 is static
|
||||
self.ME['HS2A'] = [['k8',-1.189e12/self.brho/0.09]]
|
||||
self.ME['HS2B'] = [['k8',-1.189e12/self.brho/0.09]]
|
||||
#self.ME['HS2G'] = [['k8',-1.126e12/self.brho/S2.Type['HS2G']['L']]]
|
||||
#self.ME['HS2H'] = [['k8',-1.126e12/self.brho/S2.Type['HS2H']['L']]]
|
||||
#self.ME['HS2K'] = [['k8',-1.063e12/self.brho/S2.Type['HS2K']['L']]]
|
||||
#self.ME['HS2L'] = [['k8',-1.063e12/self.brho/S2.Type['HS2L']['L']]]
|
||||
#self.ME['HS2M'] = [['k8', -870.5e9/self.brho/S2.Type['HS2M']['L']]]
|
||||
|
||||
|
||||
|
||||
self.ME['HS2G'] = [['k3',540.0],['k8',-1.126e12/self.brho/0.08]]
|
||||
self.ME['HS2H'] = [['k3',315.0],['k8',-1.126e12/self.brho/0.08]]
|
||||
self.ME['HS2K'] = [['k3',315.0],['k8',-1.063e12/self.brho/0.08]]
|
||||
self.ME['HS2L'] = [['k3',315.0],['k8',-1.063e12/self.brho/0.08]]
|
||||
self.ME['HS2M'] = [['k3',315.0],['k8',-870.5e9/self.brho/0.08]]
|
||||
|
||||
|
||||
self.ME['SXQ'] = [['k8',-712.9e9/self.brho/0.09]]
|
||||
|
||||
|
||||
# Permanent magnets, experimental. 30.08.2022
|
||||
self.ME['ANI'] = [['k2',0.3714/0.14],
|
||||
['k3',13.884/0.14],
|
||||
['k4',939.21/0.14],
|
||||
['k5',-44425/0.14]]
|
||||
self.ME['ANO'] = self.ME['ANI']
|
||||
|
||||
self.ME['ANMI'] = [['k2',0.072/0.15],
|
||||
['k3',-28.72/0.15],
|
||||
['k4',5563.4/0.15],
|
||||
['k5',-341404/0.15]]
|
||||
self.ME['ANMO'] = self.ME['ANMI']
|
||||
|
||||
self.ME['BEHI'] = [['k2',-0.3909/0.2287216],
|
||||
['k3',5.5647/0.2287216],
|
||||
['k4',-1273.8/0.2287216],
|
||||
['k5',7580.6/0.2287216]]
|
||||
self.ME['BEHO'] = self.ME['BEHI']
|
||||
|
||||
self.ME['BN'] = [['k2',-0.3010*2/0.405],
|
||||
['k3',3.4507*2/0.405],
|
||||
['k4',-484.29*2/0.405],
|
||||
['k5',-8805.5*2/0.405]]
|
||||
|
||||
self.ME['VBI'] = [['k2',2.3935/0.185],
|
||||
['k3',71.468/0.185],
|
||||
['k4',183.93/0.185],
|
||||
['k5',66049.5/0.185]]
|
||||
self.ME['VBO'] = self.ME['VBI']
|
||||
self.ME['VBXI'] = self.ME['VBI'] # No simulation available at the moment. 30.08.2022
|
||||
self.ME['VBXO'] = self.ME['VBI']
|
||||
|
||||
self.ME['VEI'] = [['k2',-0.13577/0.24],
|
||||
['k3',20.263/0.24],
|
||||
['k4',-2990.5/0.24],
|
||||
['k5',470512.2/0.24]]
|
||||
self.ME['VEO'] = self.ME['VEI']
|
||||
|
||||
|
||||
# Quad and Skew quad axeis shifts with respect to the paired sextupole axis
|
||||
# [qx, qy, sqx, sqy] (mm)
|
||||
self.OctShift={}
|
||||
self.OctShift['ARS01-MOCT-1230']=[0.003, -0.008, 0.02, 0.009]
|
||||
self.OctShift['ARS01-MOCT-1330']=[-0.004, 0.021, -0.002, 0.024]
|
||||
self.OctShift['ARS01-MOCT-1440']=[-0.012, 0.004, -0.007, -0.001]
|
||||
self.OctShift['ARS01-MOCT-1840']=[-0.005, 0.025, 0.007, 0.035]
|
||||
self.OctShift['ARS01-MOCT-1950']=[-0.011, -0.001, -0.005, -0.002]
|
||||
self.OctShift['ARS01-MOCT-2230']=[0.013, 0.037, 0.059, 0.038]
|
||||
self.OctShift['ARS01-MOCT-2360']=[0.004, 0.011, 0.012, 0.018]
|
||||
self.OctShift['ARS01-MOCT-2450']=[0.002, 0.02, 0.009, 0.019]
|
||||
self.OctShift['ARS01-MOCT-2730']=[-0.001, 0.034, 0.015, 0.041]
|
||||
self.OctShift['ARS01-MOCT-2860']=[-0.002, 0.034, 0.005, 0.032]
|
||||
self.OctShift['ARS01-MOCT-2950']=[0.006, 0.017, 0.016, 0.014]
|
||||
self.OctShift['ARS01-MOCT-4040']=[-0.015, -0.005, -0.005, 0.014]
|
||||
self.OctShift['ARS01-MOCT-4130']=[-0.007, 0.043, -0.004, 0.033]
|
||||
self.OctShift['ARS01-MOCT-4260']=[0.009, 0.022, 0.002, 0.026]
|
||||
self.OctShift['ARS01-MOCT-4540']=[0.005, 0.002, 0.027, 0.009]
|
||||
self.OctShift['ARS01-MOCT-4630']=[0.004, -0.003, 0.007, -0.002]
|
||||
self.OctShift['ARS01-MOCT-4760']=[0.008, 0.006, 0.008, 0.0]
|
||||
self.OctShift['ARS01-MOCT-5040']=[0.006, 0.039, 0.014, 0.045]
|
||||
self.OctShift['ARS01-MOCT-5150']=[0.01, 0.015, 0.012, 0.015]
|
||||
self.OctShift['ARS01-MOCT-5550']=[-0.006, 0.011, 0.001, 0.006]
|
||||
self.OctShift['ARS01-MOCT-5660']=[0.012, -0.001, 0.028, -0.015]
|
||||
self.OctShift['ARS01-MOCT-5760']=[0.007, 0.019, 0.014, 0.009]
|
||||
self.OctShift['ARS02-MOCT-1230']=[-0.012, -0.001, 0.011, 0.018]
|
||||
self.OctShift['ARS02-MOCT-1330']=[0.004, 0.023, -0.007, 0.018]
|
||||
self.OctShift['ARS02-MOCT-1440']=[-0.005, 0.018, -0.002, 0.03]
|
||||
self.OctShift['ARS02-MOCT-1840']=[0.006, 0.018, 0.001, 0.046]
|
||||
self.OctShift['ARS02-MOCT-1950']=[-0.005, 0.03, -0.006, 0.033]
|
||||
self.OctShift['ARS02-MOCT-2230']=[-0.012, -0.003, -0.019, -0.006]
|
||||
self.OctShift['ARS02-MOCT-2360']=[-0.002, 0.025, 0.005, 0.026]
|
||||
self.OctShift['ARS02-MOCT-2450']=[0.011, 0.013, -0.001, 0.001]
|
||||
self.OctShift['ARS02-MOCT-2730']=[-0.007, 0.01, -0.016, 0.027]
|
||||
self.OctShift['ARS02-MOCT-2860']=[0.013, -0.004, 0.007, 0.006]
|
||||
self.OctShift['ARS02-MOCT-2950']=[-0.012, 0.022, -0.024, 0.029]
|
||||
self.OctShift['ARS02-MOCT-4040']=[-0.01, 0.001, 0.002, -0.003]
|
||||
self.OctShift['ARS02-MOCT-4130']=[-0.008, 0.014, -0.012, -0.009]
|
||||
self.OctShift['ARS02-MOCT-4260']=[-0.007, 0.015, -0.024, 0.027]
|
||||
self.OctShift['ARS02-MOCT-4540']=[-0.004, 0.003, -0.014, -0.003]
|
||||
self.OctShift['ARS02-MOCT-4630']=[0.007, 0.029, 0.03, 0.03]
|
||||
self.OctShift['ARS02-MOCT-4760']=[-0.006, 0.015, 0.011, 0.0]
|
||||
self.OctShift['ARS02-MOCT-5040']=[-0.001, 0.012, 0.0, 0.015]
|
||||
self.OctShift['ARS02-MOCT-5150']=[-0.002, 0.009, -0.019, 0.004]
|
||||
self.OctShift['ARS02-MOCT-5550']=[0.005, -0.007, -0.01, 0.012]
|
||||
self.OctShift['ARS02-MOCT-5660']=[-0.012, -0.013, -0.017, -0.012]
|
||||
self.OctShift['ARS02-MOCT-5760']=[0.014, 0.001, 0.007, 0.006]
|
||||
self.OctShift['ARS03-MOCT-1230']=[0.013, -0.026, 0.004, -0.027]
|
||||
self.OctShift['ARS03-MOCT-1330']=[-0.004, 0.01, -0.006, 0.019]
|
||||
self.OctShift['ARS03-MOCT-1440']=[-0.012, 0.004, -0.01, 0.019]
|
||||
self.OctShift['ARS03-MOCT-1840']=[-0.002, 0.023, 0.004, 0.03]
|
||||
self.OctShift['ARS03-MOCT-1950']=[-0.002, 0.026, -0.012, 0.018]
|
||||
self.OctShift['ARS03-MOCT-2230']=[-0.001, -0.001, 0.012, -0.0]
|
||||
self.OctShift['ARS03-MOCT-2360']=[0.007, -0.001, -0.003, -0.011]
|
||||
self.OctShift['ARS03-MOCT-2450']=[0.004, 0.016, 0.003, 0.016]
|
||||
self.OctShift['ARS03-MOCT-2730']=[-0.01, 0.009, 0.002, 0.028]
|
||||
self.OctShift['ARS03-MOCT-2860']=[-0.003, -0.009, -0.004, -0.009]
|
||||
self.OctShift['ARS03-MOCT-2950']=[-0.013, 0.014, -0.015, 0.031]
|
||||
self.OctShift['ARS03-MOCT-4040']=[0.007, 0.015, 0.0, 0.028]
|
||||
self.OctShift['ARS03-MOCT-4130']=[0.011, -0.019, 0.013, -0.002]
|
||||
self.OctShift['ARS03-MOCT-4260']=[0.001, 0.041, 0.016, 0.078]
|
||||
self.OctShift['ARS03-MOCT-4540']=[-0.014, 0.04, -0.028, 0.049]
|
||||
self.OctShift['ARS03-MOCT-4630']=[0.009, 0.006, 0.02, 0.011]
|
||||
self.OctShift['ARS03-MOCT-4760']=[0.009, 0.022, -0.002, 0.02]
|
||||
self.OctShift['ARS03-MOCT-5040']=[0.002, -0.013, 0.013, -0.026]
|
||||
self.OctShift['ARS03-MOCT-5150']=[0.001, 0.023, -0.005, 0.018]
|
||||
self.OctShift['ARS03-MOCT-5550']=[0.011, 0.011, 0.008, 0.017]
|
||||
self.OctShift['ARS03-MOCT-5660']=[0.003, 0.038, 0.017, 0.052]
|
||||
self.OctShift['ARS03-MOCT-5760']=[0.002, -0.007, -0.006, -0.015]
|
||||
self.OctShift['ARS04-MOCT-1230']=[0.005, 0.01, 0.012, 0.0]
|
||||
self.OctShift['ARS04-MOCT-1330']=[0.006, -0.007, 0.005, 0.001]
|
||||
self.OctShift['ARS04-MOCT-1440']=[-0.005, -0.019, 0.007, -0.03]
|
||||
self.OctShift['ARS04-MOCT-1840']=[-0.007, 0.003, 0.014, 0.019]
|
||||
self.OctShift['ARS04-MOCT-1950']=[0.011, 0.021, 0.007, 0.027]
|
||||
self.OctShift['ARS04-MOCT-2230']=[-0.004, 0.024, -0.026, 0.037]
|
||||
self.OctShift['ARS04-MOCT-2360']=[-0.011, -0.016, -0.016, -0.026]
|
||||
self.OctShift['ARS04-MOCT-2450']=[-0.006, -0.008, -0.008, 0.0]
|
||||
self.OctShift['ARS04-MOCT-2730']=[0.011, 0.041, 0.012, 0.038]
|
||||
self.OctShift['ARS04-MOCT-2860']=[-0.001, 0.016, 0.005, 0.017]
|
||||
self.OctShift['ARS04-MOCT-2950']=[0.008, 0.02, 0.008, 0.009]
|
||||
self.OctShift['ARS04-MOCT-4040']=[0.015, 0.02, 0.006, 0.021]
|
||||
self.OctShift['ARS04-MOCT-4130']=[-0.013, 0.015, -0.023, 0.008]
|
||||
self.OctShift['ARS04-MOCT-4260']=[0.01, 0.026, 0.011, 0.044]
|
||||
self.OctShift['ARS04-MOCT-4540']=[-0.006, 0.012, 0.012, 0.014]
|
||||
self.OctShift['ARS04-MOCT-4630']=[0.008, 0.014, 0.019, 0.034]
|
||||
self.OctShift['ARS04-MOCT-4760']=[0.002, 0.035, 0.004, 0.038]
|
||||
self.OctShift['ARS04-MOCT-5040']=[0.003, -0.009, 0.017, -0.01]
|
||||
self.OctShift['ARS04-MOCT-5150']=[0.004, 0.014, -0.005, 0.008]
|
||||
self.OctShift['ARS04-MOCT-5550']=[-0.009, 0.029, -0.01, 0.037]
|
||||
self.OctShift['ARS04-MOCT-5660']=[-0.012, 0.029, -0.003, 0.023]
|
||||
self.OctShift['ARS04-MOCT-5760']=[0.006, 0.008, 0.005, 0.011]
|
||||
self.OctShift['ARS05-MOCT-1230']=[-0.013, 0.001, -0.013, -0.006]
|
||||
self.OctShift['ARS05-MOCT-1330']=[-0.002, 0.011, -0.018, 0.001]
|
||||
self.OctShift['ARS05-MOCT-1440']=[-0.01, 0.034, -0.013, 0.048]
|
||||
self.OctShift['ARS05-MOCT-1840']=[0.004, 0.028, -0.002, 0.038]
|
||||
self.OctShift['ARS05-MOCT-1950']=[-0.0, 0.02, 0.015, 0.041]
|
||||
self.OctShift['ARS05-MOCT-2230']=[-0.013, -0.006, -0.014, -0.002]
|
||||
self.OctShift['ARS05-MOCT-2360']=[0.011, 0.021, 0.013, 0.021]
|
||||
self.OctShift['ARS05-MOCT-2450']=[-0.004, 0.037, 0.003, 0.035]
|
||||
self.OctShift['ARS05-MOCT-2730']=[0.003, -0.0, 0.014, 0.013]
|
||||
self.OctShift['ARS05-MOCT-2860']=[0.01, 0.029, 0.014, 0.028]
|
||||
self.OctShift['ARS05-MOCT-2950']=[0.01, 0.024, 0.006, 0.023]
|
||||
self.OctShift['ARS05-MOCT-4040']=[-0.001, -0.019, -0.015, -0.009]
|
||||
self.OctShift['ARS05-MOCT-4130']=[0.012, 0.002, 0.026, 0.003]
|
||||
self.OctShift['ARS05-MOCT-4260']=[0.0, 0.018, 0.011, 0.02]
|
||||
self.OctShift['ARS05-MOCT-4540']=[-0.001, 0.029, -0.009, 0.027]
|
||||
self.OctShift['ARS05-MOCT-4630']=[-0.005, 0.014, 0.009, 0.006]
|
||||
self.OctShift['ARS05-MOCT-4760']=[0.003, 0.004, -0.008, 0.027]
|
||||
self.OctShift['ARS05-MOCT-5040']=[-0.0, 0.012, 0.002, 0.021]
|
||||
self.OctShift['ARS05-MOCT-5150']=[-0.006, 0.005, 0.003, 0.006]
|
||||
self.OctShift['ARS05-MOCT-5550']=[0.008, 0.001, 0.008, -0.002]
|
||||
self.OctShift['ARS05-MOCT-5660']=[0.002, 0.002, 0.001, 0.016]
|
||||
self.OctShift['ARS05-MOCT-5760']=[0.006, 0.019, 0.017, 0.033]
|
||||
self.OctShift['ARS06-MOCT-1230']=[0.006, -0.007, 0.001, 0.001]
|
||||
self.OctShift['ARS06-MOCT-1330']=[0.005, 0.027, 0.0, 0.018]
|
||||
self.OctShift['ARS06-MOCT-1440']=[0.0, 0.016, -0.013, 0.018]
|
||||
self.OctShift['ARS06-MOCT-1840']=[0.008, 0.007, 0.011, 0.016]
|
||||
self.OctShift['ARS06-MOCT-1950']=[0.004, 0.014, -0.009, 0.033]
|
||||
self.OctShift['ARS06-MOCT-2230']=[0.004, 0.008, -0.011, -0.0]
|
||||
self.OctShift['ARS06-MOCT-2360']=[0.004, 0.001, 0.02, 0.007]
|
||||
self.OctShift['ARS06-MOCT-2450']=[0.005, 0.041, 0.002, 0.04]
|
||||
self.OctShift['ARS06-MOCT-2730']=[-0.008, 0.024, 0.009, 0.041]
|
||||
self.OctShift['ARS06-MOCT-2860']=[-0.01, 0.024, -0.019, 0.028]
|
||||
self.OctShift['ARS06-MOCT-2950']=[-0.006, 0.022, 0.005, 0.024]
|
||||
self.OctShift['ARS06-MOCT-4040']=[0.003, -0.008, -0.001, 0.002]
|
||||
self.OctShift['ARS06-MOCT-4130']=[0.003, 0.028, -0.018, 0.055]
|
||||
self.OctShift['ARS06-MOCT-4260']=[-0.013, 0.007, -0.026, -0.0]
|
||||
self.OctShift['ARS06-MOCT-4540']=[-0.005, 0.004, -0.007, 0.006]
|
||||
self.OctShift['ARS06-MOCT-4630']=[0.004, 0.037, 0.004, 0.063]
|
||||
self.OctShift['ARS06-MOCT-4760']=[-0.0, 0.044, -0.006, 0.043]
|
||||
self.OctShift['ARS06-MOCT-5040']=[0.012, 0.019, 0.008, 0.032]
|
||||
self.OctShift['ARS06-MOCT-5150']=[0.002, 0.011, 0.002, 0.009]
|
||||
self.OctShift['ARS06-MOCT-5550']=[0.013, 0.022, -0.0, 0.03]
|
||||
self.OctShift['ARS06-MOCT-5660']=[0.008, 0.019, 0.014, 0.037]
|
||||
self.OctShift['ARS06-MOCT-5760']=[0.013, 0.028, -0.0, 0.035]
|
||||
self.OctShift['ARS07-MOCT-1230']=[0.003, 0.012, 0.009, 0.013]
|
||||
self.OctShift['ARS07-MOCT-1330']=[-0.007, 0.001, 0.003, 0.003]
|
||||
self.OctShift['ARS07-MOCT-1440']=[0.009, 0.01, 0.014, 0.015]
|
||||
self.OctShift['ARS07-MOCT-1840']=[-0.001, 0.009, -0.004, 0.017]
|
||||
self.OctShift['ARS07-MOCT-1950']=[-0.005, 0.032, 0.004, 0.026]
|
||||
self.OctShift['ARS07-MOCT-2230']=[0.013, -0.004, 0.01, 0.004]
|
||||
self.OctShift['ARS07-MOCT-2360']=[-0.009, 0.023, -0.019, 0.023]
|
||||
self.OctShift['ARS07-MOCT-2450']=[-0.011, 0.016, -0.013, 0.019]
|
||||
self.OctShift['ARS07-MOCT-2730']=[0.003, 0.034, 0.0, 0.035]
|
||||
self.OctShift['ARS07-MOCT-2860']=[0.003, 0.024, 0.003, 0.022]
|
||||
self.OctShift['ARS07-MOCT-2950']=[-0.012, 0.031, -0.003, 0.106]
|
||||
self.OctShift['ARS07-MOCT-4040']=[0.0, 0.01, -0.002, 0.013]
|
||||
self.OctShift['ARS07-MOCT-4130']=[0.0, 0.005, -0.013, 0.009]
|
||||
self.OctShift['ARS07-MOCT-4260']=[-0.002, 0.04, 0.004, 0.052]
|
||||
self.OctShift['ARS07-MOCT-4540']=[0.011, -0.009, -0.004, 0.009]
|
||||
self.OctShift['ARS07-MOCT-4630']=[-0.004, 0.012, -0.009, 0.019]
|
||||
self.OctShift['ARS07-MOCT-4760']=[-0.001, 0.016, -0.011, 0.021]
|
||||
self.OctShift['ARS07-MOCT-5040']=[0.008, 0.01, -0.003, 0.003]
|
||||
self.OctShift['ARS07-MOCT-5150']=[-0.011, 0.02, -0.002, 0.023]
|
||||
self.OctShift['ARS07-MOCT-5550']=[-0.007, 0.023, 0.001, 0.024]
|
||||
self.OctShift['ARS07-MOCT-5660']=[-0.014, 0.021, -0.02, 0.023]
|
||||
self.OctShift['ARS07-MOCT-5760']=[-0.007, 0.013, -0.006, 0.012]
|
||||
self.OctShift['ARS08-MOCT-1230']=[0.011, 0.012, 0.008, 0.049]
|
||||
self.OctShift['ARS08-MOCT-1330']=[-0.001, -0.007, -0.007, -0.009]
|
||||
self.OctShift['ARS08-MOCT-1440']=[-0.008, 0.001, 0.005, -0.006]
|
||||
self.OctShift['ARS08-MOCT-1840']=[-0.005, -0.003, -0.007, 0.013]
|
||||
self.OctShift['ARS08-MOCT-1950']=[0.007, 0.011, 0.011, 0.001]
|
||||
self.OctShift['ARS08-MOCT-2230']=[-0.007, -0.005, 0.002, -0.011]
|
||||
self.OctShift['ARS08-MOCT-2360']=[0.0, -0.007, -0.009, -0.007]
|
||||
self.OctShift['ARS08-MOCT-2450']=[-0.004, 0.012, -0.007, 0.03]
|
||||
self.OctShift['ARS08-MOCT-2730']=[0.011, 0.022, 0.015, 0.036]
|
||||
self.OctShift['ARS08-MOCT-2860']=[-0.006, 0.012, -0.006, 0.013]
|
||||
self.OctShift['ARS08-MOCT-2950']=[0.002, 0.006, 0.001, 0.017]
|
||||
self.OctShift['ARS08-MOCT-4040']=[-0.002, 0.018, -0.008, 0.039]
|
||||
self.OctShift['ARS08-MOCT-4130']=[-0.002, 0.041, -0.012, 0.041]
|
||||
self.OctShift['ARS08-MOCT-4260']=[-0.011, 0.013, -0.022, 0.013]
|
||||
self.OctShift['ARS08-MOCT-4540']=[-0.008, -0.002, -0.016, -0.004]
|
||||
self.OctShift['ARS08-MOCT-4630']=[-0.01, -0.01, -0.006, -0.014]
|
||||
self.OctShift['ARS08-MOCT-4760']=[0.012, 0.021, 0.01, 0.018]
|
||||
self.OctShift['ARS08-MOCT-5040']=[0.01, 0.018, 0.02, 0.008]
|
||||
self.OctShift['ARS08-MOCT-5150']=[-0.002, 0.003, -0.005, 0.014]
|
||||
self.OctShift['ARS08-MOCT-5550']=[0.011, 0.001, 0.007, 0.005]
|
||||
self.OctShift['ARS08-MOCT-5660']=[-0.0, 0.037, 0.004, 0.036]
|
||||
self.OctShift['ARS08-MOCT-5760']=[-0.008, 0.007, -0.02, 0.017]
|
||||
self.OctShift['ARS09-MOCT-1230']=[-0.005, -0.01, 0.0, -0.002]
|
||||
self.OctShift['ARS09-MOCT-1330']=[-0.008, -0.028, 0.011, -0.01]
|
||||
self.OctShift['ARS09-MOCT-1440']=[-0.007, 0.001, -0.015, 0.007]
|
||||
self.OctShift['ARS09-MOCT-1840']=[-0.003, 0.04, -0.01, 0.039]
|
||||
self.OctShift['ARS09-MOCT-1950']=[0.006, 0.007, -0.002, 0.025]
|
||||
self.OctShift['ARS09-MOCT-2230']=[-0.003, -0.005, -0.008, 0.001]
|
||||
self.OctShift['ARS09-MOCT-2360']=[0.01, 0.03, 0.016, 0.043]
|
||||
self.OctShift['ARS09-MOCT-2450']=[-0.002, 0.018, 0.001, 0.005]
|
||||
self.OctShift['ARS09-MOCT-2730']=[0.01, -0.008, 0.009, -0.004]
|
||||
self.OctShift['ARS09-MOCT-2860']=[-0.005, 0.024, -0.008, 0.022]
|
||||
self.OctShift['ARS09-MOCT-2950']=[-0.002, 0.004, 0.0, 0.008]
|
||||
self.OctShift['ARS09-MOCT-4040']=[0.002, -0.0, 0.019, -0.011]
|
||||
self.OctShift['ARS09-MOCT-4130']=[0.001, 0.006, 0.011, 0.003]
|
||||
self.OctShift['ARS09-MOCT-4260']=[0.004, -0.015, -0.003, -0.009]
|
||||
self.OctShift['ARS09-MOCT-4540']=[-0.007, 0.008, 0.001, 0.022]
|
||||
self.OctShift['ARS09-MOCT-4630']=[0.015, -0.023, 0.015, -0.013]
|
||||
self.OctShift['ARS09-MOCT-4760']=[-0.003, -0.002, 0.013, 0.004]
|
||||
self.OctShift['ARS09-MOCT-5040']=[-0.002, 0.005, -0.007, 0.009]
|
||||
self.OctShift['ARS09-MOCT-5150']=[0.005, 0.03, -0.004, 0.036]
|
||||
self.OctShift['ARS09-MOCT-5550']=[0.002, -0.003, 0.0, -0.006]
|
||||
self.OctShift['ARS09-MOCT-5660']=[0.012, 0.002, 0.007, -0.016]
|
||||
self.OctShift['ARS09-MOCT-5760']=[-0.009, 0.029, -0.022, 0.051]
|
||||
self.OctShift['ARS10-MOCT-1230']=[0.0, 0.039, 0.005, 0.033]
|
||||
self.OctShift['ARS10-MOCT-1330']=[0.002, 0.015, 0.002, 0.009]
|
||||
self.OctShift['ARS10-MOCT-1440']=[0.005, 0.021, -0.006, 0.037]
|
||||
self.OctShift['ARS10-MOCT-1840']=[-0.009, 0.001, -0.017, 0.015]
|
||||
self.OctShift['ARS10-MOCT-1950']=[0.01, 0.018, -0.007, 0.033]
|
||||
self.OctShift['ARS10-MOCT-2230']=[0.001, -0.005, 0.002, -0.007]
|
||||
self.OctShift['ARS10-MOCT-2360']=[0.002, 0.013, 0.003, 0.02]
|
||||
self.OctShift['ARS10-MOCT-2450']=[-0.001, 0.027, 0.001, 0.028]
|
||||
self.OctShift['ARS10-MOCT-2730']=[0.011, -0.005, 0.009, -0.0]
|
||||
self.OctShift['ARS10-MOCT-2860']=[0.005, 0.018, 0.005, 0.019]
|
||||
self.OctShift['ARS10-MOCT-2950']=[-0.011, -0.001, -0.023, 0.003]
|
||||
self.OctShift['ARS10-MOCT-4040']=[-0.011, 0.03, 0.004, 0.035]
|
||||
self.OctShift['ARS10-MOCT-4130']=[-0.002, -0.002, 0.003, 0.007]
|
||||
self.OctShift['ARS10-MOCT-4260']=[0.001, 0.011, 0.004, 0.01]
|
||||
self.OctShift['ARS10-MOCT-4540']=[0.003, 0.027, 0.004, 0.041]
|
||||
self.OctShift['ARS10-MOCT-4630']=[0.015, 0.007, 0.013, 0.01]
|
||||
self.OctShift['ARS10-MOCT-4760']=[0.002, 0.02, 0.006, 0.031]
|
||||
self.OctShift['ARS10-MOCT-5040']=[0.014, 0.005, 0.009, -0.002]
|
||||
self.OctShift['ARS10-MOCT-5150']=[-0.008, 0.025, -0.004, 0.023]
|
||||
self.OctShift['ARS10-MOCT-5550']=[-0.014, 0.016, -0.016, 0.025]
|
||||
self.OctShift['ARS10-MOCT-5660']=[0.007, 0.025, 0.006, 0.024]
|
||||
self.OctShift['ARS10-MOCT-5760']=[-0.011, 0.003, -0.028, -0.007]
|
||||
self.OctShift['ARS11-MOCT-1230']=[-0.002, 0.022, -0.003, 0.021]
|
||||
self.OctShift['ARS11-MOCT-1330']=[0.001, 0.024, 0.007, 0.017]
|
||||
self.OctShift['ARS11-MOCT-1440']=[-0.006, 0.006, -0.011, 0.0]
|
||||
self.OctShift['ARS11-MOCT-1840']=[-0.007, 0.002, 0.014, 0.018]
|
||||
self.OctShift['ARS11-MOCT-1950']=[-0.01, 0.031, 0.011, 0.037]
|
||||
self.OctShift['ARS11-MOCT-2230']=[0.004, 0.028, 0.004, 0.033]
|
||||
self.OctShift['ARS11-MOCT-2360']=[-0.003, 0.01, 0.002, 0.018]
|
||||
self.OctShift['ARS11-MOCT-2450']=[0.002, 0.02, -0.008, 0.04]
|
||||
self.OctShift['ARS11-MOCT-2730']=[-0.009, 0.013, -0.008, 0.036]
|
||||
self.OctShift['ARS11-MOCT-2860']=[0.002, 0.01, -0.004, 0.001]
|
||||
self.OctShift['ARS11-MOCT-2950']=[0.002, -0.007, -0.006, -0.008]
|
||||
self.OctShift['ARS11-MOCT-4040']=[0.004, 0.01, -0.003, 0.007]
|
||||
self.OctShift['ARS11-MOCT-4130']=[0.001, 0.012, 0.012, 0.011]
|
||||
self.OctShift['ARS11-MOCT-4260']=[0.01, 0.022, 0.008, 0.03]
|
||||
self.OctShift['ARS11-MOCT-4540']=[0.007, 0.011, 0.007, -0.0]
|
||||
self.OctShift['ARS11-MOCT-4630']=[-0.005, 0.03, -0.003, 0.026]
|
||||
self.OctShift['ARS11-MOCT-4760']=[0.003, 0.032, 0.003, 0.025]
|
||||
self.OctShift['ARS11-MOCT-5040']=[0.004, -0.01, 0.011, -0.01]
|
||||
self.OctShift['ARS11-MOCT-5150']=[-0.011, 0.01, -0.003, 0.004]
|
||||
self.OctShift['ARS11-MOCT-5550']=[0.002, 0.02, -0.004, 0.015]
|
||||
self.OctShift['ARS11-MOCT-5660']=[0.002, 0.01, 0.018, 0.004]
|
||||
self.OctShift['ARS11-MOCT-5760']=[-0.006, 0.001, -0.01, 0.005]
|
||||
self.OctShift['ARS12-MOCT-1230']=[-0.013, 0.033, 0.0, 0.041]
|
||||
self.OctShift['ARS12-MOCT-1330']=[0.006, 0.023, -0.0, 0.023]
|
||||
self.OctShift['ARS12-MOCT-1440']=[0.015, 0.026, 0.021, 0.032]
|
||||
self.OctShift['ARS12-MOCT-1840']=[-0.008, 0.001, -0.014, -0.012]
|
||||
self.OctShift['ARS12-MOCT-1950']=[-0.003, 0.04, 0.003, 0.042]
|
||||
self.OctShift['ARS12-MOCT-2230']=[0.008, -0.008, 0.033, 0.009]
|
||||
self.OctShift['ARS12-MOCT-2360']=[0.001, -0.014, -0.009, -0.002]
|
||||
self.OctShift['ARS12-MOCT-2450']=[-0.01, 0.032, -0.005, 0.043]
|
||||
self.OctShift['ARS12-MOCT-2730']=[-0.009, 0.016, 0.007, 0.023]
|
||||
self.OctShift['ARS12-MOCT-2860']=[0.004, 0.02, 0.0, 0.009]
|
||||
self.OctShift['ARS12-MOCT-2950']=[0.002, 0.009, 0.001, 0.014]
|
||||
self.OctShift['ARS12-MOCT-4040']=[0.013, -0.01, 0.02, 0.005]
|
||||
self.OctShift['ARS12-MOCT-4130']=[0.006, 0.028, -0.009, 0.022]
|
||||
self.OctShift['ARS12-MOCT-4260']=[0.002, 0.033, -0.005, 0.033]
|
||||
self.OctShift['ARS12-MOCT-4540']=[-0.005, 0.028, -0.015, 0.028]
|
||||
self.OctShift['ARS12-MOCT-4630']=[0.007, 0.03, 0.011, 0.025]
|
||||
self.OctShift['ARS12-MOCT-4760']=[-0.012, 0.01, 0.002, 0.013]
|
||||
self.OctShift['ARS12-MOCT-5040']=[0.003, -0.005, -0.005, 0.008]
|
||||
self.OctShift['ARS12-MOCT-5150']=[-0.003, 0.035, -0.005, 0.034]
|
||||
self.OctShift['ARS12-MOCT-5550']=[-0.004, 0.024, -0.005, 0.027]
|
||||
self.OctShift['ARS12-MOCT-5660']=[0.006, 0.012, 0.017, 0.021]
|
||||
self.OctShift['ARS12-MOCT-5760']=[0.008, 0.017, 0.022, 0.027]
|
||||
|
||||
|
||||
|
||||
def KL2I(self, TYPE, KL, CrossTalk=None):
|
||||
|
||||
def Single(TYPE,KL):
|
||||
# TYPE can be NAME of the magnet, for example, 'ARSnn-MQUA-iiii'
|
||||
# KL is integrated field in European notation (OPA, tracy)
|
||||
|
||||
if TYPE[-1]=='I' or TYPE[-1]=='O':
|
||||
TYPE=TYPE.replace('I','').replace('O','')
|
||||
|
||||
|
||||
if TYPE not in self.TF.keys():
|
||||
warnings.warn('Transfer function for '+TYPE+' is not found...')
|
||||
return None
|
||||
|
||||
|
||||
[HEL,ML,Imax,Ilin,b0,b1,b2,b3,R]=self.TF[TYPE]
|
||||
|
||||
|
||||
|
||||
# Copied from SwissFEL OM. Need to check
|
||||
G = self.brho*KL/ML
|
||||
|
||||
I=Imax*(abs(G)*R -b0)/b1
|
||||
|
||||
if abs(I)>Imax:
|
||||
warnings.warn('Warning: In OMSLS2Magnet.KL2I, the given KL resulted in I>Imax, and thus Imax is returned.')
|
||||
return np.sign(KL)*Imax
|
||||
|
||||
|
||||
if abs(I)>Ilin:
|
||||
#coeff=[b3/(Imax-Ilin)**3,b2/(Imax-Ilin)**2,b1/Imax,b0-G*R+b1*Ilin/Imax]
|
||||
#I=KL/abs(KL)*(np.roots(coeff)[0]+Ilin)
|
||||
coeff=[b3/(Imax-Ilin)**3,b2/(Imax-Ilin)**2,b1/Imax,b0-(abs(G)*R-b1*Ilin/Imax)]
|
||||
rt=np.roots(coeff)
|
||||
if len(rt)==1:
|
||||
rt=rt[0]
|
||||
else:
|
||||
rtind=np.argmin(np.abs(np.abs(rt)-(abs(I)-Ilin)))
|
||||
rt=abs(rt[rtind])
|
||||
I=(rt+Ilin)
|
||||
|
||||
|
||||
if not b0:
|
||||
I=np.sign(KL)*I
|
||||
|
||||
|
||||
if CrossTalk:
|
||||
Gct = self.brho*self.TF0[CrossTalk]/ML
|
||||
Ict=Imax*(Gct*R -b0)/b1
|
||||
I=I-Ict
|
||||
|
||||
|
||||
|
||||
return I
|
||||
|
||||
|
||||
if type(KL)==list or type(KL)==np.ndarray:
|
||||
return [Single(TYPE,kl) for kl in KL]
|
||||
else:
|
||||
return Single(TYPE,KL)
|
||||
|
||||
|
||||
|
||||
def I2KL(self, TYPE, I, CrossTalk=None):
|
||||
|
||||
def Single(TYPE,I):
|
||||
|
||||
|
||||
|
||||
if TYPE[-1]=='I' or TYPE[-1]=='O':
|
||||
TYPE=TYPE.replace('I','').replace('O','')
|
||||
|
||||
|
||||
if TYPE not in self.TF.keys():
|
||||
warnings.warn('Transfer function for '+TYPE+' is not found...')
|
||||
return None
|
||||
|
||||
|
||||
[HEL,ML,Imax,Ilin,b0,b1,b2,b3,R]=self.TF[TYPE]
|
||||
|
||||
if CrossTalk:
|
||||
#KL=KL+self.TF0[CrossTalk]
|
||||
|
||||
Gct = self.brho*self.TF0[CrossTalk]/ML
|
||||
Ict=Imax*(Gct*R -b0)/b1
|
||||
I=I+Ict
|
||||
|
||||
|
||||
|
||||
|
||||
if abs(I)>Imax:
|
||||
warnings.warn('Warning: In OMSLS2Magnet.I2KL, the given I is >Imax, and thus KL at Imax is returned.')
|
||||
|
||||
I=np.sign(I)*Imax
|
||||
|
||||
|
||||
if abs(I)<=Ilin:
|
||||
G = (b0 + b1*abs(I)/Imax)/R
|
||||
else:
|
||||
G = (b0 + b1*abs(I)/Imax + b2*((abs(I)-Ilin)**2/(Imax-Ilin)**2) + b3*((abs(I)-Ilin)**3/(Imax-Ilin)**3))/R
|
||||
if I==0:
|
||||
K = G/self.brho
|
||||
else:
|
||||
K = np.sign(I)*G/self.brho
|
||||
KL = K*ML
|
||||
|
||||
|
||||
|
||||
|
||||
return KL
|
||||
|
||||
|
||||
if type(I)==list or type(I)==np.ndarray:
|
||||
return [Single(TYPE,i) for i in I]
|
||||
else:
|
||||
return Single(TYPE,I)
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user