def get_traces(accelerator=None, m66=None, closed_orbit=None): """Return traces of 6D one-turn transfer matrix""" if m66 is None: m66 = _tracking.findm66(accelerator, indices = 'm66', closed_orbit = closed_orbit) trace_x = m66[0,0] + m66[1,1] trace_y = m66[2,2] + m66[3,3] trace_z = m66[4,4] + m66[5,5] return trace_x, trace_y, trace_z, m66, closed_orbit
def old_calc_twiss(accelerator=None, init_twiss=None, fixed_point=None, indices = 'open'): """Return Twiss parameters of uncoupled dynamics. Keyword arguments: accelerator -- Accelerator object init_twiss -- Twiss parameters at the start of first element fixed_point -- 6D position at the start of first element indices -- Open or closed Returns: tw -- list of Twiss objects m66 transfer_matrices closed_orbit """ if indices == 'open': length = len(accelerator) elif indices == 'closed': length = len(accelerator)+1 else: raise OpticsException("invalid value for 'indices' in calc_twiss") if init_twiss is not None: ''' as a transport line: uses init_twiss ''' if fixed_point is None: fixed_point = init_twiss.fixed_point else: raise OpticsException('arguments init_twiss and fixed_orbit are mutually exclusive') closed_orbit, *_ = _tracking.linepass(accelerator, particles=list(fixed_point), indices='open') m66, cumul_trans_matrices = _tracking.findm66(accelerator, closed_orbit=closed_orbit) if indices == 'closed': orb, *_ = _tracking.linepass(accelerator[-1:], particles=closed_orbit[:,-1]) closed_orbit = _np.append(closed_orbit,orb.transpose(),axis=1) mx, my = m66[0:2, 0:2], m66[2:4, 2:4] t = init_twiss t.etax = _np.array([[t.etax], [t.etapx]]) t.etay = _np.array([[t.etay], [t.etapy]]) else: ''' as a periodic system: try to find periodic solution ''' if accelerator.harmonic_number == 0: raise OpticsException('Either harmonic number was not set or calc_twiss was' 'invoked for transport line without initial twiss') if fixed_point is None: if not accelerator.cavity_on and not accelerator.radiation_on: closed_orbit = _np.zeros((6,length)) closed_orbit[:4,:] = _tracking.findorbit4(accelerator, indices=indices) elif not accelerator.cavity_on and accelerator.radiation_on: raise OpticsException('The radiation is on but the cavity is off') else: closed_orbit = _tracking.findorbit6(accelerator, indices=indices) else: closed_orbit, *_ = _tracking.linepass(accelerator, particles=list(fixed_point), indices=indices) ''' calcs twiss at first element ''' orbit = closed_orbit[:,:-1] if indices == 'closed' else closed_orbit m66, cumul_trans_matrices, *_ = _tracking.findm66(accelerator, closed_orbit=orbit) mx, my = m66[0:2,0:2], m66[2:4,2:4] # decoupled transfer matrices trace_x, trace_y, *_ = get_traces(accelerator, m66 = m66, closed_orbit=closed_orbit) if not (-2.0 < trace_x < 2.0): raise OpticsException('horizontal dynamics is unstable') if not (-2.0 < trace_y < 2.0): raise OpticsException('vertical dynamics is unstable') sin_nux = _math.copysign(1,mx[0,1]) * _math.sqrt(-mx[0,1] * mx[1,0] - ((mx[0,0] - mx[1,1])**2)/4); sin_nuy = _math.copysign(1,my[0,1]) * _math.sqrt(-my[0,1] * my[1,0] - ((my[0,0] - my[1,1])**2)/4); fp = closed_orbit[:,0] t = Twiss() t.spos = 0 t.rx, t.px = fixed_point[0], fixed_point[1] t.ry, t.py = fixed_point[2], fixed_point[3] t.de, t.dl = fixed_point[4], fixed_point[5] t.alphax = (mx[0,0] - mx[1,1]) / 2 / sin_nux t.betax = mx[0,1] / sin_nux t.alphay = (my[0,0] - my[1,1]) / 2 / sin_nuy t.betay = my[0,1] / sin_nuy ''' dispersion function based on eta = (1 - M)^(-1) D ''' Dx = _np.array([[m66[0,4]],[m66[1,4]]]) Dy = _np.array([[m66[2,4]],[m66[3,4]]]) t.etax = _np.linalg.solve(_np.eye(2,2) - mx, Dx) t.etay = _np.linalg.solve(_np.eye(2,2) - my, Dy) ''' get transfer matrices from cumulative transfer matrices ''' transfer_matrices = [] m66_prev = _np.eye(6,6) cumul_trans_matrices.append(m66) for m66_this in cumul_trans_matrices[1:]: # Matrices at start of elements inv_m66_prev = _np.linalg.inv(m66_prev) tm = _np.dot(m66_this, inv_m66_prev) #tm = _np.linalg.solve(m66_prev.T, m66_this.T).T # Fernando, you may uncomment this line when running YOUR code! aushuashuahs m66_prev = m66_this transfer_matrices.append(tm) ''' propagates twiss through line ''' tw = [t] m_previous = _np.eye(6,6) for i in range(1, length): m = transfer_matrices[i-1] mx, my = m[0:2,0:2], m[2:4,2:4] # decoupled transfer matrices Dx = _np.array([[m[0,4]],[m[1,4]]]) Dy = _np.array([[m[2,4]],[m[3,4]]]) n = Twiss() n.spos = t.spos + accelerator[i-1].length fp = closed_orbit[:,i] n.rx, n.px = fixed_point[0], fixed_point[1] n.ry, n.py = fixed_point[2], fixed_point[3] n.de, n.dl = fixed_point[4], fixed_point[5] n.betax = ((mx[0,0] * t.betax - mx[0,1] * t.alphax)**2 + mx[0,1]**2) / t.betax n.alphax = -((mx[0,0] * t.betax - mx[0,1] * t.alphax) * (mx[1,0] * t.betax - mx[1,1] * t.alphax) + mx[0,1] * mx[1,1]) / t.betax n.betay = ((my[0,0] * t.betay - my[0,1] * t.alphay)**2 + my[0,1]**2) / t.betay n.alphay = -((my[0,0] * t.betay - my[0,1] * t.alphay) * (my[1,0] * t.betay - my[1,1] * t.alphay) + my[0,1] * my[1,1]) / t.betay ''' calcs phase advance based on R(mu) = U(2) M(2|1) U^-1(1) ''' sint = mx[0,1]/_math.sqrt(n.betax * t.betax) cost = (mx[0,0] * t.betax - mx[0,1] * t.alphax)/_math.sqrt(n.betax * t.betax) dmux = _math.atan2(sint, cost) n.mux = t.mux + dmux sint = my[0,1]/_math.sqrt(n.betay * t.betay) cost = (my[0,0] * t.betay - my[0,1] * t.alphay)/_math.sqrt(n.betay * t.betay) dmuy = _math.atan2(sint, cost) n.muy = t.muy + dmuy ''' when phase advance in an element is over PI atan2 returns a negative value that has to be corrected by adding 2*PI''' if dmux < 0 and dmux < -10*_sys.float_info.epsilon: n.mux += 2*_math.pi if dmuy < 0 and dmuy < -10*_sys.float_info.epsilon: n.muy += 2*_math.pi ''' dispersion function''' n.etax = Dx + _np.dot(mx, t.etax) n.etay = Dy + _np.dot(my, t.etay) tw.append(n) t = n.make_copy() ''' converts eta format ''' for t in tw: t.etapx, t.etapy = (t.etax[1,0], t.etay[1,0]) t.etax, t.etay = (t.etax[0,0], t.etay[0,0]) return tw, m66, transfer_matrices, closed_orbit
def calctwiss( accelerator=None, indices=None, transfer_matrices=None, closed_orbit=None, twiss_in=None): """Return uncoupled Twiss parameters.""" ''' process arguments ''' if indices is None: indices = range(len(accelerator)) try: indices[0] except: indices = [indices] if transfer_matrices is None: transfer_matrices = _tracking.findm66(accelerator = accelerator, closed_orbit = closed_orbit) if twiss_in is None: twiss_in = Twiss() twiss_in.closed_orbit = closed_orbit twiss_in.mux, twiss_in.muy = 0, 0 m66 = transfer_matrices[-1] ''' calcs twiss at first element ''' mx, my = m66[0:2,0:2], m66[2:4,2:4] # decoupled transfer matrices sin_nux = _math.copysign(1,mx[0,1]) * _math.sqrt(-mx[0,1] * mx[1,0] - ((mx[0,0] - mx[1,1])**2)/4); sin_nuy = _math.copysign(1,my[0,1]) * _math.sqrt(-my[0,1] * my[1,0] - ((my[0,0] - my[1,1])**2)/4); t = Twiss() t.alphax = (mx[0,0] - mx[1,1]) / 2 / sin_nux t.betax = mx[0,1] / sin_nux t.alphay = (my[0,0] - my[1,1]) / 2 / sin_nuy t.betay = my[0,1] / sin_nuy ''' dispersion function based on eta = (1 - M)^(-1) D''' Dx = _np.array([[m66[0,4]],[m66[1,4]]]) Dy = _np.array([[m66[2,4]],[m66[3,4]]]) t.etax = _np.linalg.solve(_np.eye(2,2) - mx, Dx) t.etay = _np.linalg.solve(_np.eye(2,2) - my, Dy) if 0 in indices: tw = [t] else: tw = [] ''' propagates twiss through line ''' m_previous = _np.eye(6,6) for i in range(len(accelerator)): m_current = transfer_matrices[i-1] m = _np.dot(m_current, _np.linalg.inv(m_previous)) m_previous = m_current mx, my = m[0:2,0:2], m[2:4,2:4] # decoupled transfer matrices Dx = _np.array([[m[0,4]],[m[1,4]]]) Dy = _np.array([[m[2,4]],[m[3,4]]]) n = Twiss() n.betax = ((mx[0,0] * t.betax - mx[0,1] * t.alphax)**2 + mx[0,1]**2) / t.betax n.alphax = -((mx[0,0] * t.betax - mx[0,1] * t.alphax) * (mx[1,0] * t.betax - mx[1,1] * t.alphax) + mx[0,1] * mx[1,1]) / t.betax n.betay = ((my[0,0] * t.betay - my[0,1] * t.alphay)**2 + my[0,1]**2) / t.betay n.alphay = -((my[0,0] * t.betay - my[0,1] * t.alphay) * (my[1,0] * t.betay - my[1,1] * t.alphay) + my[0,1] * my[1,1]) / t.betay ''' calcs phase advance based on R(mu) = U(2) M(2|1) U^-1(1) ''' n.mux = t.mux + _math.asin(mx[0,1]/_math.sqrt(n.betax * t.betax)) n.muy = t.muy + _math.asin(my[0,1]/_math.sqrt(n.betay * t.betay)) ''' dispersion function ''' n.etax = Dx + _np.dot(mx, t.etax) n.etay = Dy + _np.dot(my, t.etay) if i in indices: tw.append(n) t = _copy.deepcopy(n) ''' converts eta format ''' for t in tw: t.etaxl, t.etayl = (t.etax[1,0], t.etay[1,0]) t.etax, t.etay = (t.etax[0,0], t.etay[0,0]) return tw