def _fit_tune_chrom(ring, index, func, refpts1, refpts2, newval, tol=1.0e-12, dp=0, niter=3): def _get_resp(ring, index, func, refpts, attname, delta, dp=0): set_value_refpts(ring, refpts, attname, delta, index=index, increment=True) datap = func(ring, dp=dp) set_value_refpts(ring, refpts, attname, -2*delta, index=index, increment=True) datan = func(ring, dp=dp) set_value_refpts(ring, refpts, attname, delta, index=index, increment=True) data = numpy.subtract(datap, datan)/(2*delta) return data delta = 1e-6*10**(index) val = func(ring, dp=dp) dq1 = _get_resp(ring, index, func, refpts1, 'PolynomB', delta, dp=dp) dq2 = _get_resp(ring, index, func, refpts2, 'PolynomB', delta, dp=dp) J = [[dq1[0], dq2[0]], [dq1[1], dq2[1]]] dk = numpy.linalg.solve(J, numpy.subtract(newval, val)) set_value_refpts(ring, refpts1, 'PolynomB', dk[0], index=index, increment=True) set_value_refpts(ring, refpts2, 'PolynomB', dk[1], index=index, increment=True) val = func(ring, dp=dp) sumsq = numpy.sum(numpy.square(numpy.subtract(val, newval))) if sumsq > tol and niter > 0: _fit_tune_chrom(ring, index, func, refpts1, refpts2, newval, tol=tol, dp=dp, niter=niter-1) else: return
def set_cavity_phase(ring, method=ELossMethod.INTEGRAL, refpts=None, cavpts=None, copy=False): """ Adjust the TimeLag attribute of RF cavities based on frequency, voltage and energy loss per turn, so that the synchronous phase is zero. An error occurs if all cavities do not have the same frequency. !!!!WARNING!!!: This function changes the time reference, this should be avoided PARAMETERS ring lattice description KEYWORDS method=ELossMethod.INTEGRAL method for energy loss computation. See "get_energy_loss". cavpts=None Cavity location. If None, use all cavities. This allows to ignore harmonic cavities. copy=False If True, returns a shallow copy of ring with new cavity elements. Otherwise, modify ring in-place. """ # refpts is kept for backward compatibility if cavpts is None and refpts is not None: warn(FutureWarning('You should use "cavpts" instead of "refpts"')) cavpts = refpts elif cavpts is None: cavpts = get_cells(ring, checktype(RFCavity)) timelag, ts = get_timelag_fromU0(ring, method=method, cavpts=cavpts) set_value_refpts(ring, cavpts, 'TimeLag', timelag, copy=copy)
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)
def _fit(ring, index, func, refpts1, refpts2, newval, J, dp=0): val = func(ring, dp=dp) dk = numpy.linalg.solve(J, numpy.subtract(newval, val)) set_value_refpts(ring, refpts1, 'PolynomB', dk[0], index=index, increment=True) set_value_refpts(ring, refpts2, 'PolynomB', dk[1], index=index, increment=True) val = func(ring, dp=dp) sumsq = numpy.sum(numpy.square(numpy.subtract(val, newval))) return sumsq
def _get_resp(ring, index, func, refpts, attname, delta, dp=0): set_value_refpts(ring, refpts, attname, delta, index=index, increment=True) datap = func(ring, dp=dp) set_value_refpts(ring, refpts, attname, -2*delta, index=index, increment=True) datan = func(ring, dp=dp) set_value_refpts(ring, refpts, attname, delta, index=index, increment=True) data = numpy.subtract(datap, datan)/(2*delta) return data