Exemple #1
0
def calc_emittance_coupling(accelerator):
    # I copied the code below from:
    # http://nicky.vanforeest.com/misc/fitEllipse/fitEllipse.html
    def fitEllipse(x,y):
        x = x[:,_np.newaxis]
        y = y[:,_np.newaxis]
        D =  _np.hstack((x*x, x*y, y*y, x, y, _np.ones_like(x)))
        S = _np.dot(D.T,D)
        C = _np.zeros([6,6])
        C[0,2] = C[2,0] = 2; C[1,1] = -1
        E, V = _np.linalg.eig(_np.linalg.solve(S, C))
        n = _np.argmax(_np.abs(E))
        a = V[:,n]
        b,c,d,f,g,a = a[1]/2, a[2], a[3]/2, a[4]/2, a[5], a[0]
        up    = 2*(a*f*f+c*d*d+g*b*b-2*b*d*f-a*c*g)
        down1 = (b*b-a*c)*( (c-a)*_np.sqrt(1+4*b*b/((a-c)*(a-c)))-(c+a))
        down2 = (b*b-a*c)*( (a-c)*_np.sqrt(1+4*b*b/((a-c)*(a-c)))-(c+a))
        res1 = _np.sqrt(up/down1)
        res2 = _np.sqrt(up/down2)
        return _np.array([res1, res2]) #returns the axes of the ellipse

    acc = accelerator[:]
    acc.cavity_on    = False
    acc.radiation_on = False

    orb = _tracking.findorbit4(acc)
    rin = _np.array([2e-5+orb[0],0+orb[1],1e-8+orb[2],0+orb[3],0,0],dtype=float)
    rout, *_ = _tracking.ringpass(acc, rin, nr_turns=100, turn_by_turn='closed',element_offset = 0)
    r = _np.dstack([rin[None,:,None],rout])
    ax,bx = fitEllipse(r[0][0],r[0][1])
    ay,by = fitEllipse(r[0][2],r[0][3])
    return (ay*by) / (ax*bx) # ey/ex
Exemple #2
0
def get_mcf(accelerator, order=1, energy_offset=None):
    """Return momentum compaction factor of the accelerator"""
    if energy_offset is None:
        energy_offset = _np.linspace(-1e-3,1e-3,11)

    accel=accelerator[:]
    _tracking.set4dtracking(accel)
    ring_length = _lattice.length(accel)

    dl = _np.zeros(_np.size(energy_offset))
    for i in range(len(energy_offset)):
        fp = _tracking.findorbit4(accel,energy_offset[i])
        X0 = _np.concatenate([fp,[energy_offset[i],0]]).tolist()
        T = _tracking.ringpass(accel,X0)
        dl[i] = T[0][5]/ring_length

    polynom = _np.polyfit(energy_offset,dl,order)
    a = _np.fliplr([polynom])[0].tolist()
    a = a[1:]
    if len(a) == 1:
        a=a[0]
    return a
Exemple #3
0
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