Home > atphysics > ParameterSummaryFunctions > atlinopt.m

atlinopt

PURPOSE ^

ATLINOPT performs linear analysis of the COUPLED lattices

SYNOPSIS ^

function [lindata, varargout] = atlinopt(RING,DP,varargin)

DESCRIPTION ^

ATLINOPT            performs linear analysis of the COUPLED lattices

 LinData = ATLINOPT(RING,DP,REFPTS) is a MATLAB structure array with fields

   ElemIndex   - ordinal position in the RING
   SPos        - longitudinal position [m]
   ClosedOrbit - closed orbit column vector with
                 components x, px, y, py (momentums, NOT angles)
   Dispersion  - dispersion orbit position vector with
                 components eta_x, eta_prime_x, eta_y, eta_prime_y
                 calculated with respect to the closed orbit with
                 momentum deviation DP. Only if chromaticity is required.
   M44         - 4x4 transfer matrix M from the beginning of RING
                 to the entrance of the element for specified DP [2]
   A           - 2x2 matrix A in [3]
   B           - 2x2 matrix B in [3]
   C           - 2x2 matrix C in [3]
   gamma       - gamma parameter of the transformation to eigenmodes
   mu          - [ mux, muy] horizontal and vertical betatron phase
   beta        - [betax, betay] vector
   alpha       - [alphax, alphay] vector

   All values are specified at the entrance of each element specified in REFPTS.
   REFPTS is an array of increasing indexes that  select elements
   from the range 1 to length(LINE)+1. Defaults to 1 (initial point)
   See further explanation of REFPTS in the 'help' for FINDSPOS

 [LinData,NU] = ATLINOPT() returns a vector of linear tunes
   [nu_u , nu_v] for two normal modes of linear motion [1]

 [LinData,NU, KSI] = ATLINOPT() returns a vector of chromaticities ksi = d(nu)/(dP/P)
   [ksi_u , ksi_v] - derivatives of [nu_u , nu_v]

 LinData = ATLINOPT(RING,DP,REFPTS,ORBITIN) does not search for closed orbit.
        instead ORBITIN is used

 Difference with linopt: Fractional tunes 0<=tune<1
              Dispersion output (if chromaticity is required)
              Alpha output
              Phase advance output
              Option to skip closed orbit search

 See also ATX ATMODUL FINDSPOS TWISSRING TUNECHROM

   [1] D.Edwars,L.Teng IEEE Trans.Nucl.Sci. NS-20, No.3, p.885-888, 1973
   [2] E.Courant, H.Snyder
   [3] D.Sagan, D.Rubin Phys.Rev.Spec.Top.-Accelerators and beams, vol.2 (1999)

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [lindata, varargout] = atlinopt(RING,DP,varargin)
0002 %ATLINOPT            performs linear analysis of the COUPLED lattices
0003 %
0004 % LinData = ATLINOPT(RING,DP,REFPTS) is a MATLAB structure array with fields
0005 %
0006 %   ElemIndex   - ordinal position in the RING
0007 %   SPos        - longitudinal position [m]
0008 %   ClosedOrbit - closed orbit column vector with
0009 %                 components x, px, y, py (momentums, NOT angles)
0010 %   Dispersion  - dispersion orbit position vector with
0011 %                 components eta_x, eta_prime_x, eta_y, eta_prime_y
0012 %                 calculated with respect to the closed orbit with
0013 %                 momentum deviation DP. Only if chromaticity is required.
0014 %   M44         - 4x4 transfer matrix M from the beginning of RING
0015 %                 to the entrance of the element for specified DP [2]
0016 %   A           - 2x2 matrix A in [3]
0017 %   B           - 2x2 matrix B in [3]
0018 %   C           - 2x2 matrix C in [3]
0019 %   gamma       - gamma parameter of the transformation to eigenmodes
0020 %   mu          - [ mux, muy] horizontal and vertical betatron phase
0021 %   beta        - [betax, betay] vector
0022 %   alpha       - [alphax, alphay] vector
0023 %
0024 %   All values are specified at the entrance of each element specified in REFPTS.
0025 %   REFPTS is an array of increasing indexes that  select elements
0026 %   from the range 1 to length(LINE)+1. Defaults to 1 (initial point)
0027 %   See further explanation of REFPTS in the 'help' for FINDSPOS
0028 %
0029 % [LinData,NU] = ATLINOPT() returns a vector of linear tunes
0030 %   [nu_u , nu_v] for two normal modes of linear motion [1]
0031 %
0032 % [LinData,NU, KSI] = ATLINOPT() returns a vector of chromaticities ksi = d(nu)/(dP/P)
0033 %   [ksi_u , ksi_v] - derivatives of [nu_u , nu_v]
0034 %
0035 % LinData = ATLINOPT(RING,DP,REFPTS,ORBITIN) does not search for closed orbit.
0036 %        instead ORBITIN is used
0037 %
0038 % Difference with linopt: Fractional tunes 0<=tune<1
0039 %              Dispersion output (if chromaticity is required)
0040 %              Alpha output
0041 %              Phase advance output
0042 %              Option to skip closed orbit search
0043 %
0044 % See also ATX ATMODUL FINDSPOS TWISSRING TUNECHROM
0045 %
0046 %   [1] D.Edwars,L.Teng IEEE Trans.Nucl.Sci. NS-20, No.3, p.885-888, 1973
0047 %   [2] E.Courant, H.Snyder
0048 %   [3] D.Sagan, D.Rubin Phys.Rev.Spec.Top.-Accelerators and beams, vol.2 (1999)
0049 
0050 
0051 global NUMDIFPARAMS
0052 
0053 NE = length(RING);
0054 if nargin >= 3
0055     if islogical(varargin{1})
0056         REFPTS=varargin{1}(:);
0057         REFPTS(end+1:NE+1)=false;
0058         isel=1:sum(REFPTS);
0059     elseif isnumeric(varargin{1})
0060         isel=varargin{1};
0061         [r2,ir2]=sort(isel(:));
0062         REFPTS=setelems(false(NE+1,1),r2);
0063         isel(ir2)=1:numel(isel);
0064     else
0065         error('REFPTS must be numeric or logical');
0066     end
0067 else
0068     REFPTS=setelems(false(NE+1,1),1);
0069     isel=1;
0070 end
0071 
0072 spos = findspos(RING,REFPTS);
0073 [M44, MS, orb] = findm44(RING,DP,REFPTS,varargin{2:end});
0074 
0075 % Calculate A,B,C, gamma at the first element
0076 M =M44(1:2,1:2);
0077 N =M44(3:4,3:4);
0078 m =M44(1:2,3:4);
0079 n =M44(3:4,1:2);
0080 
0081 % 2-by-2 symplectic matrix
0082 S = [0 1; -1 0];
0083 H = m + S*n'*S';
0084 t = trace(M-N);
0085 
0086 g = sqrt(1 + sqrt(t*t/(t*t+4*det(H))))/sqrt(2);
0087 G = diag([g g]);
0088 C = -H*sign(t)/(g*sqrt(t*t+4*det(H)));
0089 A = G*G*M  -  G*(m*S*C'*S' + C*n) + C*N*S*C'*S';
0090 B = G*G*N  +  G*(S*C'*S'*m + n*C) + S*C'*S'*M*C;
0091 [MSA,MSB,gamma,CL,AL,BL]=cellfun(@analyze,num2cell(MS,[1 2]),'UniformOutput',false);
0092 
0093 
0094 [BX,AX,MX]=lop(reshape(cat(3,MSA{:}),2,2,[]),A);
0095 [BY,AY,MY]=lop(reshape(cat(3,MSB{:}),2,2,[]),B);
0096 
0097 %tunes = [MX(end),MY(end)]/2/pi;
0098 
0099 if nargout >= 2
0100     cos_mu_x = trace(A)/2;
0101     cos_mu_y = trace(B)/2;
0102     tns = acos([cos_mu_x cos_mu_y])/2/pi;
0103     if A(1,2) < 0, tns(1)=1-tns(1); end
0104     if B(1,2) < 0, tns(2)=1-tns(2); end
0105     varargout{1}=tns;
0106 end
0107 
0108 dispargs={};
0109 if nargout >= 3
0110     if isfield(NUMDIFPARAMS,'DPStep')
0111         dDP = NUMDIFPARAMS.DPStep';
0112     else
0113         dDP =  1e-6;
0114     end
0115     refs=false(1,length(RING)+1);
0116     % Calculate tunes for DP+dDP
0117     [orbP,o1P]=findorbit4(RING,DP+0.5*dDP,REFPTS);
0118     [orbM,o1M]=findorbit4(RING,DP-0.5*dDP,REFPTS);
0119     dispersion = (orbP-orbM)/dDP;
0120     [LD, tunesP] = atlinopt(RING,DP+0.5*dDP,refs,o1P); %#ok<ASGLU>
0121     [LD, tunesM] = atlinopt(RING,DP-0.5*dDP,refs,o1M); %#ok<ASGLU>
0122     varargout{2} = (tunesP - tunesM)/dDP;
0123     dispargs={'Dispersion',num2cell(dispersion,1)'};
0124 end
0125 ld = struct('ElemIndex',num2cell(find(REFPTS)),...
0126     'SPos',num2cell(spos)',...
0127     'ClosedOrbit',num2cell(orb,1)',...
0128     dispargs{:},...
0129     'M44',squeeze(num2cell(MS,[1 2])),...
0130     'gamma',gamma(:),...
0131     'C',squeeze(CL),...
0132     'A',squeeze(AL),...
0133     'B',squeeze(BL),...
0134     'beta',num2cell([BX,BY],2),...
0135     'alpha',num2cell([AX,AY],2),...
0136     'mu',num2cell([MX,MY],2));
0137 
0138 lindata=reshape(ld(isel),size(isel));
0139 
0140     function [MSA,MSB,gamma,CL,AL,BL]=analyze(MS)
0141         M12 =MS(1:2,1:2);
0142         N12 =MS(3:4,3:4);
0143         m12 =MS(1:2,3:4);
0144         n12 =MS(3:4,1:2);
0145         
0146         gamma = sqrt(det(n12*C+G*N12));
0147         MSA = (G*M12-m12*S*C'*S')/gamma;
0148         MSB = (n12*C+G*N12)/gamma;
0149         
0150         CL=(M12*C+G*m12)*S*MSB'*S';
0151         AL=MSA*A*S*MSA'*S';
0152         BL=MSB*B*S*MSB'*S';
0153     end
0154 
0155     function mask=setelems(mask,idx)
0156         mask(idx)=true;
0157     end
0158 
0159     function UP = BetatronPhaseUnwrap(P)
0160         % unwrap negative jumps in betatron
0161         %JUMPS = [0; diff(P)] < -1.e-5;
0162         JUMPS = [0; diff(P)] < -1.e-3;
0163         UP = P+cumsum(JUMPS)*2*pi;
0164     end
0165 
0166     function [beta,alpha,phase]=lop(MS,A0)
0167         sinmu = sign(A0(1,2))*sqrt(-A0(1,2)*A0(2,1)-(A0(1,1)-A0(2,2))^2/4);
0168         ax = (A0(1,1)-A0(2,2))/2/sinmu;
0169         bx = A0(1,2)/sinmu;
0170         bbb=squeeze(MS(1,2,:));
0171         aaa=squeeze(MS(1,1,:))*bx-bbb*ax;
0172         
0173         beta = (aaa.^2 + bbb.^2)/bx;
0174         alpha = -(aaa.*squeeze(MS(2,1,:)*bx-MS(2,2,:)*ax) + bbb.*squeeze(MS(2,2,:)))/bx;
0175         try
0176             phase = atan2(bbb,aaa);
0177         catch %#ok<CTCH>
0178             phase=NaN(size(beta));
0179         end
0180         phase = BetatronPhaseUnwrap(phase);
0181     end
0182 
0183 end

Generated on Thu 24-Aug-2017 18:47:33 by m2html © 2005