atclean.m 4.96 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
function r2=atclean(r1,varargin)
%NEWRING=ATCLEAN(RING) Removes unwanted fields and checks element lengths
%
%ATCLEAN removes BetaCode and other unnecessary fields, rounds the drift
%lengths, checks the consistency of PolynomA, PolynomB, MaxOrder, sets
%dipole and quadrupole PassMethods, sets NumIntSteps to 20.
%Verbosity can be set with the GLOBVAL.verbosity global variable:
%   1 : removed elements, adjusted drifts
%   2 : adjusted Polynom and NumIntSteps, removed fields
%
%ATCLEAN(...,'remove',famnames)
%   remove elements identified by the family names (cell array)
%
%ATCLEAN(...,'reduce',true)
%   Remove elements with PassMethod='IdentityPass' and merge adjacent
%   similar elements. RFCavities and RingParams are kept
%
%ATCLEAN(...,'reduce',true,'keep',pattern)
%   Remove elements with PassMethod='IdentityPass' and merge adjacent
%   similar elements, but keeps elements with FamName matching "pattern"
%   Pattern may be a logical mask. (Default: Class=='Monitor').
%
%ATCLEAN(...,'MaxOrder',n)
%   Limit the order of polynomial field expansion to n at maximum. Default 999
%
%ATCLEAN(...,'NumIntSteps',m)
%   Set the NumIntSteps integration parameter to at least m. Default 20
%
%ATCLEAN(...,'cleanfields',cleanfunction)
%   Select the field cleaning function. Called as
%       newel=cleanfunction(el,options...)
%   Default: @atcleanelkeep, which keeps only required+optional fields
%
%ATCLEAN(...,'QuadFields',quadfields)
%   Set quadrupoles fields to the specified ones. Default: {}
%
%ATCLEAN(...,'BendFields',bendfields)
%   Set bending magnet fields to the specified ones. Default: {}

[remove,options]=getoption(varargin,'remove',{});
[quadfields,options]=getoption(options,'QuadFields',{});
[bendfields,options]=getoption(options,'BendFields',{});
[cleanfunc,options]=getoption(options,'cleanfields',@atcleanelkeep);
[reduce,options]=getoption(options,'reduce',false);
[keep,options]=getoption(options,'keep','');
[max_order,options]=getoption(options,'MaxOrder',999);
[num_int_steps,options]=getoption(options,'NumIntSteps',20);

quads=atgetcells(r1,'Class','Quadrupole');
bends=atgetcells(r1,'Class','Bend');
mults=atgetcells(r1,'MaxOrder')  & ~quads & ~bends;

resourceprintf(0,'Set quadrupole %s\n',quadfields)
r1(quads)=setelemfields(r1(quads),max_order,num_int_steps,quadfields{:});
resourceprintf(0,'Set dipole %s\n',bendfields)
r1(bends)=setelemfields(r1(bends),max_order,num_int_steps,bendfields{:});
r1(mults)=setelemfields(r1(mults),max_order,num_int_steps);

if ~isempty(remove)
    sup=cellfun(@(name) atgetcells(r1,'FamName',name),remove,'UniformOutput',false);
    sup=any(cat(2,sup{:}),2);
    removed=cellfun(@(el) el.FamName,r1(sup),'UniformOutput',false);
    dfprintf(1,'Remove %s\n',removed{:});
else
    sup=false(size(r1));
end
r2=cellfun(@(el) cleanfunc(el,options{:}),r1(~sup),'UniformOutput',false);

if reduce            % Simplify the lattice
    cav=atgetcells(r2,'Class','RFCavity$|^RingParam');
    if isempty(keep)
        keep=atgetcells(r2,'Class','Monitor');
    elseif ~islogical(keep)
        keep=atgetcells(r2,'FamName',keep);
    else
        keep=keep(~sup);
    end
    r2=atreduce(r2,cav | keep);
end

    function mach=setelemfields(mach,max_order,num_int_steps,varargin)
        mach=cellfun(@setel,mach,'UniformOutput',false);
        function el=setel(el)
            for i=1:2:length(varargin)
                el.(varargin{i})=varargin{i+1};
            end
            el=checkpoly(el,max_order,num_int_steps);
        end
    end

    function el=checkpoly(el,mx_order,num_int_steps)
        try
            mino=max([1,find(abs(el.PolynomA)>0,1,'last'),find(abs(el.PolynomB)>0,1,'last')])-1;
            la=mino+1-length(el.PolynomA);
            lb=mino+1-length(el.PolynomB);
            if la > 0
                el.PolynomA=[el.PolynomA zeros(1,la)];
                dfprintf(1,'%s: PolynomA lengthened\n',el.FamName);
            elseif lb > 0
                el.PolynomB=[el.PolynomB zeros(1,lb)];
                dfprintf(1,'%s: PolynomB lengthened\n',el.FamName);
            end
            maxo=min([mino, mx_order]);
            if el.MaxOrder > maxo
                el.MaxOrder=maxo;
                dfprintf(2,'%s: MaxOrder reduced: %d\n',el.FamName,el.MaxOrder);
            end
            inis=el.NumIntSteps;
            if inis > 50 || inis < num_int_steps
                el.NumIntSteps=num_int_steps;
                dfprintf(2,'%s: NumIntStep %d -> %d\n',el.FamName,inis,el.NumIntSteps);
            end
        catch err
            warning('atclean:CheckPolyFailed','Cannot check polynoms on %s:%s',...
                el.FamName,err.message);
        end
    end

    function dfprintf(level,varargin)
        global GLOBVAL
        if (level==0) || (isfield(GLOBVAL,'verbosity') && level <= GLOBVAL.verbosity)
            fprintf(varargin{:});
        end
    end

    function resourceprintf(level,format,options)
        if ~isempty(options)
            optlist=sprintf(', %s',options{1:2:end});
            dfprintf(level,format,optlist(3:end));
        end
    end
end