ATSETTILTDIPOLE sets the entrance and exit rotation matrices of an element or a group of elements in THERING RING=ATSETTILTDIPOLE(RING,ELEMINDEX, PSI) ELEMINDEX contains indexes of elements to be rotated PSI - angle(s) of rotation in RADIANS POSITIVE PSI corresponds to a CORKSCREW (right) rotation of the ELEMENT looking in the direction of the beam. (or CORKSCREW, aligned with s-axis) rotation of the ELEMENT The misalgnment matrixes are stored in fields R1 and R2 R1 = [ cos(PSI) sin(PSI); -sin(PSI) cos(PSI) ] R2 = R1' the rotated dipole gives a kick in the vertical and horizontal plane. ATSETTILTDIPOLE(ELEMINDEX, PSI) Uses the global variable THERING See also ATSETSHIFT ATSETTILT
0001 function ring=atsettiltdipole(varargin) 0002 %ATSETTILTDIPOLE sets the entrance and exit rotation matrices 0003 % of an element or a group of elements in THERING 0004 % 0005 % RING=ATSETTILTDIPOLE(RING,ELEMINDEX, PSI) 0006 % ELEMINDEX contains indexes of elements to be rotated 0007 % PSI - angle(s) of rotation in RADIANS 0008 % POSITIVE PSI corresponds to a CORKSCREW (right) 0009 % rotation of the ELEMENT looking in the direction of the beam. 0010 % (or CORKSCREW, aligned with s-axis) rotation of the ELEMENT 0011 % The misalgnment matrixes are stored in fields R1 and R2 0012 % R1 = [ cos(PSI) sin(PSI); -sin(PSI) cos(PSI) ] 0013 % R2 = R1' 0014 % 0015 % the rotated dipole gives a kick in the vertical and horizontal plane. 0016 % 0017 % ATSETTILTDIPOLE(ELEMINDEX, PSI) Uses the global variable THERING 0018 % 0019 % See also ATSETSHIFT ATSETTILT 0020 0021 global THERING 0022 if ~iscell(varargin{1}) 0023 THERING=atsettilt(THERING,varargin{:}); 0024 else 0025 [ring,idx,rot]=deal(varargin{:}); 0026 0027 if length(rot) == 1 0028 rot=rot*ones(size(idx)); 0029 elseif length(rot) ~= length(idx) 0030 error('AT:length','Vector lengths are incompatible: %i/%i.',length(idx),length(rot)) 0031 end 0032 0033 % tic; 0034 % for i = 1:length(idx) 0035 % ring{idx(i)}=attiltelemdip(ring{idx(i)},rot(i)); 0036 % end 0037 % toc 0038 %tic; 0039 ring(idx)=cellfun(@(el,rot)attiltelemdip(el,rot),ring(idx),num2cell(rot(:)),'un',0); 0040 %toc 0041 0042 end 0043 0044 end 0045 0046 function elem = attiltelemdip(elem,rots) 0047 %ATTILTELEMdip set new rotation parameters 0048 %NEWELEM=ATTILTELEMdip(OLDELEM,ROTS) 0049 % 0050 % ROTS - rotation angle in RADIANS 0051 % POSITIVE ROTS corresponds to a CORKSCREW (right) 0052 % rotation of the ELEMENT looking in the direction of the beam. 0053 % (or CORKSCREW, aligned with s-axis) rotation of the ELEMENT 0054 % The rotation matrixes are stored in fields R1 and R2 0055 % R1 = [ cos(PSI) sin(PSI); -sin(PSI) cos(PSI) ] 0056 % R2 = R1' 0057 %See also: atshiftelem, atmodelem 0058 0059 if ~isfield(elem,'BendingAngle')% rotate reference 0060 0061 C=cos(rots); 0062 S=sin(rots); 0063 RM = diag([C C C C 1 1]); 0064 RM(1,3) = S; 0065 RM(2,4) = S; 0066 RM(3,1) = -S; 0067 RM(4,2) = -S; 0068 elem.R1=RM; 0069 elem.R2=RM'; 0070 0071 else% rotate multipoles 0072 0073 % bending angle 0074 bb=-elem.BendingAngle/elem.Length; 0075 0076 % horizontal kick 0077 elem.('PolynomB')(1)=-(1-cos(rots)).*bb; 0078 % vertical kick 0079 elem.('PolynomA')(1)=sin(rots).*bb; 0080 0081 % rotate all other multipole components ( combined function magnets) 0082 Lpb=length(elem.('PolynomB')); 0083 0084 elem=padpol(elem); 0085 0086 rotm=-rots*[2:Lpb]; 0087 0088 elem.('PolynomB')(2:end)=cos(rotm).*elem.('PolynomB')(2:end)-sin(rotm).*elem.('PolynomA')(2:end); 0089 elem.('PolynomA')(2:end)=sin(rotm).*elem.('PolynomB')(2:end)+cos(rotm).*elem.('PolynomA')(2:end); 0090 0091 end 0092 0093 elem.RotAboutS=rots; 0094 0095 end 0096 0097 0098 0099 function a=padpol(a) 0100 0101 if isfield(a,'PolynomB') 0102 0103 lpa=length(a.PolynomA); 0104 lpb=length(a.PolynomB); 0105 0106 if lpa<lpb 0107 a.PolynomA=[a.PolynomA,zeros(1,lpb-lpa)]; 0108 elseif lpa>lpb 0109 a.PolynomB=[a.PolynomB,zeros(1,lpa-lpb)]; 0110 end 0111 0112 end 0113 end