Skip to content
atclean.m 5.12 KiB
Newer Older
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
            if strcmp(el.Class, 'Multipole')
                mino=max(length(el.PolynomA),length(el.PolynomB))-1;
            else
                mino=max([1,find(abs(el.PolynomA)>0,1,'last'),find(abs(el.PolynomB)>0,1,'last')])-1;
            end
            
            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