Пример #1
0
def tapering(ring, multipoles=True, niter=1, **kwargs):
    """
    Scales magnet strength with local energy to cancel the closed orbit
    and optics errors due to synchrotron radiations. PolynomB is used for
    dipoles such that the machine geometry is maintained. This is the ideal
    tapering scheme where magnets and multipoles components (PolynomB and
    PolynomA) are scaled individually.
    !!! WARNING: This method works only for lattices without errors and
    corrections: if not all corrections and field errors will also be
    scaled !!!
    tapering(ring) or ring.tapering()
    PARAMETERS
        ring            lattice description.

    KEYWORDS
        multipoles=True scale all multipoles
        niter=1         number of iteration
        XYStep=1.0e-8   transverse step for numerical computation
        DPStep=1.0E-6   momentum deviation used for computation of orbit6
    """

    xy_step = kwargs.pop('XYStep', DConstant.XYStep)
    dp_step = kwargs.pop('DPStep', DConstant.DPStep)
    dipoles = get_refpts(ring, Dipole)
    b0 = get_value_refpts(ring, dipoles, 'BendingAngle')
    k0 = get_value_refpts(ring, dipoles, 'PolynomB', index=0)
    ld = get_value_refpts(ring, dipoles, 'Length')

    for i in range(niter):
        _, o6 = find_orbit6(ring,
                            refpts=range(len(ring) + 1),
                            XYStep=xy_step,
                            DPStep=dp_step)
        dpps = (o6[dipoles, 4] + o6[dipoles + 1, 4]) / 2
        set_value_refpts(ring,
                         dipoles,
                         'PolynomB',
                         b0 / ld * dpps + k0 * (1 + dpps),
                         index=0)

    if multipoles:
        mults = get_refpts(ring, Multipole)
        k0 = get_value_refpts(ring, dipoles, 'PolynomB', index=0)
        _, o6 = find_orbit6(ring,
                            refpts=range(len(ring) + 1),
                            XYStep=xy_step,
                            DPStep=dp_step)
        dpps = (o6[mults, 4] + o6[mults + 1, 4]) / 2
        for dpp, el in zip(dpps, ring[mults]):
            el.PolynomB *= 1 + dpp
            el.PolynomA *= 1 + dpp
        set_value_refpts(ring, dipoles, 'PolynomB', k0, index=0)
Пример #2
0
def fast_ring(ring, split_inds=[]):
    all_rings = rearrange(ring, split_inds=split_inds)
    ringnorad, ringrad = merge_rings(all_rings)

    ibegs = get_refpts(ringnorad, 'xbeg')
    iends = get_refpts(ringnorad, 'xend')
    markers = numpy.sort(numpy.concatenate((ibegs, iends)))

    _, orbit4 = ringnorad.find_sync_orbit(dct=0.0, refpts=markers)
    _, orbit6 = ringrad.find_orbit6(refpts=markers)

    detuning_elem = gen_detuning_elem(ringnorad, orbit4[-1])
    detuning_elem_rad = detuning_elem.deepcopy()
    detuning_elem_rad.T1 = -orbit6[-1]
    detuning_elem_rad.T2 = orbit6[-1]

    for counter, ring_slice in enumerate(all_rings):

        ibeg = get_refpts(ring_slice, 'xbeg')[0]
        iend = get_refpts(ring_slice, 'xend')[0]
        cavs = ring_slice[:ibeg]
        ring_slice = ring_slice[ibeg:iend]
        ring_slice_rad = ring_slice.deepcopy()

        if ring_slice.radiation:
            ring_slice.radiation_off(quadrupole_pass='******')
        else:
            ring_slice_rad.radiation_on(quadrupole_pass='******')

        lin_elem = gen_m66_elem(ring_slice, orbit4[2 * counter],
                                orbit4[2 * counter + 1])
        lin_elem.FamName = lin_elem.FamName + '_' + str(counter)

        qd_elem = gen_quantdiff_elem(ring_slice_rad, orbit=orbit6[2 * counter])
        qd_elem.FamName = qd_elem.FamName + '_' + str(counter)
        lin_elem_rad = gen_m66_elem(ring_slice_rad, orbit6[2 * counter],
                                    orbit6[2 * counter + 1])
        lin_elem_rad.FamName = lin_elem_rad.FamName + '_' + str(counter)

        [ringnorad.append(cav) for cav in cavs]
        ringnorad.append(lin_elem)
        [ringrad.append(cav) for cav in cavs]
        ringrad.append(lin_elem_rad)
        ringrad.append(qd_elem)

    ringnorad.append(detuning_elem)
    ringrad.append(detuning_elem_rad)
    del ringnorad[:markers[-1] + 1]
    del ringrad[:markers[-1] + 1]

    return ringnorad, ringrad
Пример #3
0
def rearrange(ring, split_inds=[]):
    iends = numpy.concatenate((split_inds, [len(ring) + 1]))
    ibegs = numpy.concatenate(([0], iends[:-1]))
    iends = iends[iends != 0]
    ibegs = ibegs[ibegs != len(ring) + 1]
    all_rings = [ring[int(ibeg):int(iend)] for ibeg, iend in zip(ibegs, iends)]

    for ring_slice in all_rings:
        # replace cavity with length > 0 with drift
        # set cavity length to 0 and move to start
        icav = get_refpts(ring_slice, RFCavity)
        for i in numpy.arange(len(icav)):
            cav_elem = ring_slice.pop(int(icav[i]))
            if cav_elem.Length != 0:
                cavdrift = Drift('CavDrift', cav_elem.Length)
                ring_slice.insert(icav[i], cavdrift)
                icav = icav + 1
                cav_elem.Length = 0.0
            ring_slice.insert(0, cav_elem)

        # merge all cavities with the same frequency
        icav = get_refpts(ring_slice, RFCavity)
        all_freq = numpy.array([ring_slice[ic].Frequency for ic in icav])
        all_volt = numpy.array([ring_slice[ic].Voltage for ic in icav])
        uni_freq = numpy.unique(all_freq)

        for ii in numpy.arange(len(uni_freq)):
            fr = uni_freq[ii]
            cavmsk = all_freq == fr
            vol = numpy.sum(all_volt[cavmsk])
            ring_slice[ii].Frequency = fr
            ring_slice[ii].Voltage = vol

        for pp in numpy.arange(len(icav) - len(uni_freq)):
            ring_slice.pop(len(uni_freq))

        ring_slice.insert(len(uni_freq), Marker('xbeg'))
        ring_slice.append(Marker('xend'))
    return all_rings
Пример #4
0
def gen_m66_elem(ring, o4b, o4e):
    """
    converts a ring to a linear 6x6 matrix tracking elemtn
    """

    dip_inds = get_refpts(ring, Bend)
    theta = numpy.array([ring[ind].BendingAngle for ind in dip_inds])
    lendp = numpy.array([ring[ind].Length for ind in dip_inds])
    allS = ring.get_s_pos()
    s = numpy.diff(numpy.array([allS[0], allS[-1]]))[0]
    I2 = numpy.sum(numpy.abs(theta * theta / lendp))
    m66_mat, _ = find_m66(ring, [], o4b)
    if ring.radiation is False:
        m66_mat = symplectify(m66_mat)  # remove for damping
    lin_elem = M66('Linear', m66_mat, T1=-o4b, T2=o4e, Length=s, I2=I2)
    return lin_elem