function ATLATTICE = readmad(FILENAME) %READMAD reads the file output of MAD commands % TWISS, STRUCTURE, SURVEY. % % READMAD reads the MAD file header to determine the number of elements % in the lattice, symmetry flag, the number of supperperiods etc. % % Then it interprets the entry for each element in the MAD output file. % The topology of the lattice is completely determined by % Length, Bending Angle, and Ttilt Angle in each element % % READMAD uses MAD TYPES and the values of to determine % which pass-method function in AT to use. % % MAD TYPE | AT PassMethod % ---------------------------------- % DRIFT | DriftPass % SBEND | BendLinearPass, BendLinearFringeTiltPass, BndMPoleSymplectic4Pass % QUADRUPOLE | QualdLinearPass % SEXTUPOLE | StrMPoleSymplectic4Pass % OCTUPOLE | StrMPoleSymplectic4Pass % MULTIPOLE | !!! Not implemented, in future - ThinMPolePass % RFCAVITY | ThinCavityPass % KICKER | CorrectorPass % HKICKER | CorrectorPass % VKICKER | CorrectorPass % MONITOR | IdentityPass % HMONITOR | IdentityPass % VMONITOR | IdentityPass % MARKER | IdentityPass % ----------------------------------- % all others | Length=0 -> IdentityPass, Length~=0 -> DriftPass [fid, errmsg] = fopen(FILENAME,'r'); if fid==-1 error('Could not open file'); end warnlevel = warning; warning on global READMADCAVITYFLAG READMADCAVITYFLAG = 0; LINE1 = fgetl(fid); LINE2 = fgetl(fid); S = LINE1(9:16); nonspaceindex = find(~isspace(S) & (S~=0)); MADFILETYPE = S(nonspaceindex); % The possiblilites for MADFILETYPE are % TWISS,SURVEY,STRUCTUR,ENVELOPE NSUPER = str2double(LINE1(41:48)); S = LINE1(56); SYMFLAG = eq(S,'T'); NPOS = str2double(LINE1(57:64)); disp(['MAD output file: ',FILENAME]); disp(' '); disp(['MAD file type: ',MADFILETYPE]); disp(['Symmetry flag: ',num2str(SYMFLAG)]); disp(['Number of superperiods: ',num2str(NSUPER)]); disp(['Number of elements : ',num2str(NPOS)]); disp(' '); % Allocate cell array to store AT lattice % MAD files heve one extra entry for the beginning of the lattice ATNumElements = NPOS-1; ATLATTICE = cell(1,ATNumElements); switch MADFILETYPE case {'STRUCTUR','SURVEY'} NumLinesPerElement = 4; case {'TWISS','CHROM'} NumLinesPerElement = 5; case 'ENVELOPE' NumLinesPerElement = 8; end ELEMENTDATA = cell(1,NumLinesPerElement); % Skip the INITIAL element in MAD file for i = 1:NumLinesPerElement; LINE = fgetl(fid); end for i = 1:ATNumElements % Read the first 2 lines of the element entry for j= 1:NumLinesPerElement ELEMENTDATA{j}=fgetl(fid); end ATLATTICE{i}=mad2at(ELEMENTDATA,MADFILETYPE); end fclose(fid); warning(warnlevel); disp(' '); disp(['AT cell array was successfully created from MAD output file ',FILENAME]); disp('Some information may be not available in MAD otput files') disp('Some elements may have to be further modified to be consistent with AT element models') disp(' '); disp('For RF cavities READMAD creates elements that use DriftPass or IdentityPass (if Length ==0)'); disp('Use CAVITYON(ENERGY) [eV] in order to turn them into cavities'); % --------------------------------------------------------------------------- function atelem = mad2at(elementdata,madfiletype) global READMADCAVITYFLAG MADTYPE = elementdata{1}(1:4); atelem.FamName = deblank(elementdata{1}(5:20)); atelem.Length = str2double(elementdata{1}(21:32)); % Type specific switch MADTYPE case 'DRIF' atelem.PassMethod = 'DriftPass'; case {'MARK','MONI','HMON','VMON'} atelem.PassMethod = 'IdentityPass'; case 'RFCA' % Note MAD determines the RF frequency from the harmonic number HARMON % defined by MAD stetement BEAM, and the total length of the closed orbit if ~READMADCAVITYFLAG warning('MAD lattice contains RF cavities') READMADCAVITYFLAG = 1; end atelem.Frequency = 1e6*str2double(elementdata{2}(17:32)); % MAD uses MHz atelem.Voltage = 1e6*str2double(elementdata{2}(33:48)); atelem.PhaseLag = str2double(elementdata{2}(49:64)); if atelem.Length atelem.PassMethod = 'DriftPass'; else atelem.PassMethod = 'IdentityPass'; end case 'SBEN' K1 = str2double(elementdata{1}(49:64)); K2 = str2double(elementdata{1}(65:80)); atelem.BendingAngle = str2double(elementdata{1}(33:48)); atelem.ByError = 0; atelem.MaxOrder = 3; atelem.NumIntSteps = 10; atelem.TiltAngle = str2double(elementdata{2}(1:16)); atelem.EntranceAngle = str2double(elementdata{2}(17:32)); atelem.ExitAngle = str2double(elementdata{2}(33:48)); atelem.K = K1; atelem.PolynomB = [0 K1 K2 0]; atelem.PolynomA = [0 0 0 0]; atelem.T1 = zeros(1,6); atelem.T2 = zeros(1,6); atelem.R1 = eye(6); atelem.R2 = eye(6); if atelem.BendingAngle if K2 atelem.PassMethod = 'BndMPoleSymplectic4Pass'; elseif atelem.TiltAngle atelem.PassMethod = 'BendLinearFringeTiltPass' else atelem.PassMethod = 'BendLinearPass'; end else if K2 atelem.PassMethod = 'StrMPoleSymplectic4Pass'; elseif K1 atelem.PassMethod = 'QuadLinearPass'; else atelem.PassMethod = 'DriftPass'; end end case 'QUAD' K1 = str2double(elementdata{1}(49:64)); atelem.MaxOrder = 3; atelem.NumIntSteps = 10; atelem.K = K1; atelem.PolynomB = [0 K1 0 0]; atelem.PolynomA = [0 0 0 0]; atelem.T1 = zeros(1,6); atelem.T2 = zeros(1,6); TILT = str2double(elementdata{2}(1:16)); atelem.R1 = mksrollmat(TILT); atelem.R2 = mksrollmat(-TILT); atelem.PassMethod = 'QuadLinearPass'; case 'SEXT' % MAD multipole strength coefficients K(n) are defined without 1/n! % Adjust to match AT K2 = str2double(elementdata{1}(65:80))/2; atelem.MaxOrder = 3; atelem.NumIntSteps = 10; atelem.PolynomB = [0 0 K2 0]; atelem.PolynomA = [0 0 0 0]; atelem.T1 = zeros(1,6); atelem.T2 = zeros(1,6); TILT = str2double(elementdata{2}(1:16)); atelem.R1 = mksrollmat(TILT); atelem.R2 = mksrollmat(-TILT); atelem.PassMethod = 'StrMPoleSymplectic4Pass'; case 'OCTU' % MAD multipole strength coefficients K(n) are defined without 1/n! % Adjust to match AT K3 = str2double(elementdata{2}(17:32))/6; atelem.MaxOrder = 3 ; atelem.NumIntSteps = 10; atelem.PolynomB = [0 0 0 K3]; atelem.PolynomA = [0 0 0 0]; atelem.T1 = zeros(1,6); atelem.T2 = zeros(1,6); TILT = str2double(elementdata{2}(1:16)); atelem.R1 = mksrollmat(TILT); atelem.R2 = mksrollmat(-TILT); atelem.PassMethod = 'StrMPoleSymplectic4Pass'; otherwise if atelem.Length atelem.PassMethod = 'DriftPass'; else atelem.PassMethod = 'IdentityPass'; end end