diff --git a/SClocoLib.m b/SClocoLib.m index 9ca78a6..d27f400 100644 --- a/SClocoLib.m +++ b/SClocoLib.m @@ -248,11 +248,11 @@ % The following options can be given as name/value-pairs: % % `'dipCompensation'` (1):: -% Used for combined function quadrupoles (see `SCsetMags2SetPoints`). If this flag is set and if +% Used for combined function quadrupoles (see `SCsetMags2SetPoints`). If this flag is set and if % there is a horizontal CM registered in the considered magnet, the CM is used to compensate % the bending angle difference if the applied quadrupole setpoints differs from the design value. % `'damping'` (1):: -% Damping factor applied to each lattice correction step, e.g. `0.7` meaning that the correction +% Damping factor applied to each lattice correction step, e.g. `0.7` meaning that the correction % is only applied with 70% of it's calculated amplitude. % % RETURN VALUE @@ -280,7 +280,7 @@ % mitigated by using the optional 'CMcalOffsets'. The option 'meanToZero' helps to deal with cases % where e.g. all fitted horizontal CM kicks are 2% too large while all horizontal BPM gains are 2% % too low. -% +% % INPUTS % ------ % `SC`:: @@ -320,7 +320,7 @@ % SYNOPSIS % -------- % `SC = SClocoLib('applyOrbitCorrection', SC [, options])` -% +% % DESCRIPTION % ----------- % Applies orbit feedback using *SCfeedbackRun*. @@ -364,7 +364,7 @@ % % DESCRIPTION % ----------- -% Applies a chromaticity correction using two sextupole families. The absolute initial +% Applies a chromaticity correction using two sextupole families. The absolute initial % setpoint variation wihtin one family remains unchanged. Note: % this is not beam based but assumes the chromaticities can be measured reasonably well. % @@ -416,7 +416,7 @@ % % DESCRIPTION % ----------- -% Applies a tune correction using two quadrupole families. The absolute initial +% Applies a tune correction using two quadrupole families. The absolute initial % setpoint variation wihtin one family, e.g. from LOCO remains unchanged. Note: % this is not beam based but assumes the tunes can be measured reasonably well. % @@ -452,7 +452,7 @@ % % EXAMPLES % -------- -% Match the fractional tunes in both planes to the ideal tunes using all +% Match the fractional tunes in both planes to the ideal tunes using all % magnets named `'QF'` and `'QD'` (see also *SCgetOrds*). % ------------------------------------------------------------------ % SC = SClocoLib('fitTune',SC,SCgetOrds(SC.RING,{'QF','QD'}),'FitInteger',0); @@ -498,7 +498,7 @@ function setupLOCOmodel(SC,varargin) RINGdata.CavityFrequency = mean(atgetfieldvalues(SC.IDEALRING,SC.ORD.Cavity,'Frequency')); RINGdata.CavityHarmNumber = round(mean(atgetfieldvalues(SC.IDEALRING,SC.ORD.Cavity,'HarmNumber'))); RINGdata.Lattice = SC.IDEALRING; - + % Calculate disturbed lattice properties and save initial machine state Init.SC = SC; @@ -544,7 +544,7 @@ function getBPMCMstructure(SC,CMsteps,varargin) CMData.HCMIndex = SC.ORD.CM{1}(:); CMData.VCMIndex = SC.ORD.CM{2}(:); CMData.FitKicks = 'No'; - + % Set name/pair-values in BPM/CM data structure for i=1:(length(varargin)) switch varargin{i}{1} @@ -563,8 +563,8 @@ function getBPMCMstructure(SC,CMsteps,varargin) error('Unsuported type.') end end - - + + % If CM step is given as single number, expand to the right dimensions if isnumeric(CMsteps) && length(CMsteps)==1 CMsteps = {repmat(CMsteps,length(CMData.HCMIndex),1),repmat(CMsteps,length(CMData.VCMIndex),1)}; @@ -578,8 +578,8 @@ function getBPMCMstructure(SC,CMsteps,varargin) BPMData.VBPMCoupling = zeros(size(BPMData.VBPMIndex)); CMData.HCMCoupling = zeros(size(CMData.HCMIndex)); CMData.VCMCoupling = zeros(size(CMData.VCMIndex)); - - + + % Set CM kicks in LOCO structure CMData.HCMKicks = 1E3*2*CMData.CMsteps{1}(:).*ones(size(CMData.HCMIndex)); % [mrad] CMData.VCMKicks = 1E3*2*CMData.CMsteps{2}(:).*ones(size(CMData.VCMIndex)); % [mrad] @@ -597,16 +597,16 @@ function getMeasurement(SC,CMstep,deltaRF,BPMords,CMords,varargin) LocoMeasData.RF = SC.RING{SC.ORD.Cavity(1)}.Frequency; LocoMeasData.DeltaRF = deltaRF; LocoMeasData.BPMSTD = 1E-3*ones(1,2*length(BPMords)); % [mm] - - + + [RM,Err,CMsteps] = SCgetRespMat(SC,CMstep,BPMords,CMords,varargin{:}); - + % Take only absolute amplitude and transpose to match LOCO data CMsteps = cellfun(@transpose,cellfun(@max,cellfun(@abs,CMsteps,'UniformOutput',false),'UniformOutput',false),'UniformOutput',false); - + LocoMeasData.M = 2*1000* repmat([CMsteps{1};CMsteps{2}]',size(RM,1),1) .* RM; % LocoMeasData.BPMSTD = Err; - + LocoMeasData.Eta = LocoMeasData.DeltaRF*1000 * SCgetDispersion(SC,LocoMeasData.DeltaRF,'BPMords',BPMords,'nSteps',3); % Define output arguments @@ -615,7 +615,7 @@ function getMeasurement(SC,CMstep,deltaRF,BPMords,CMords,varargin) end - + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Set up LOCO fit parameter structure @@ -675,23 +675,23 @@ function setupFitparameters(SC,RING0,RINGdata,DeltaRF,varargin) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Apply lattice correction step function applyLatticeCorrection(SC,FitParameters,varargin) - + % Parse optional arguments p = inputParser; addOptional(p,'dipCompensation',1); addOptional(p,'damping',1); parse(p,varargin{:}); - + % Loop over fit parameters for nGroup = 1:length(FitParameters.Params) % Loop over elements in group for nElem = 1:length(FitParameters.Params{nGroup}) ord = FitParameters.Params{nGroup}(nElem).ElemIndex; field = FitParameters.Params{nGroup}(nElem).SCFieldName; - + % New quadrupole setpoint setpoint = FitParameters.OrigValues(nGroup) + p.Results.damping * (FitParameters.IdealValues(nGroup)-FitParameters.Values(nGroup)); - + % Apply setpoint correction switch field case 'SetPointB' % Normal quadrupole @@ -701,8 +701,6 @@ function applyLatticeCorrection(SC,FitParameters,varargin) end end end - % Update magnets - SC = SCupdateMagnets(SC,SC.ORD.Magnet); % Define output arguments varargout{1} = SC; @@ -718,21 +716,21 @@ function applyDiagnosticCorrection(SC,CMstep,CMData,BPMData,varargin) addOptional(p,'meanToZero',0); addOptional(p,'outlierRemovalAt',[]); parse(p,varargin{:}); - + if strcmp(CMData.FitCoupling,'Yes') warning('CM roll correction not implemented yet.') end - + % Check if CM step is specified for each CM if (~iscell(CMstep) && ~length(CMstep)==1 ) || (iscell(CMstep) && ( length(CMstep{1})~=length(CMData.HCMIndex) && length(CMstep{2})~=length(CMData.VCMIndex) )) error('CM steps must be defined as single value or cell array matching the number of used HCM and VCM.') end - + % Expand CM steps to cell array if ~iscell(CMstep) CMstep = {repmat(CMstep,length(CMData.HCMIndex),1),repmat(CMstep,length(CMData.VCMIndex),1)}; end - + % Apply CM calibration error correction fields={'H','V'};SCfields={'CalErrorB','CalErrorA'}; for nDim=1:2 @@ -743,17 +741,17 @@ function applyDiagnosticCorrection(SC,CMstep,CMData,BPMData,varargin) if ~isempty(p.Results.CMcalOffsets) fitCalCM{nDim} = fitCalCM{nDim} - p.Results.CMcalOffsets{nDim}; end - + % Check for outlier removal if ~isempty(p.Results.outlierRemovalAt) fitCalCM{nDim}(abs(1-fitCalCM{nDim})>=p.Results.outlierRemovalAt) = 1; end - + % Set mean CM calibration to zero if p.Results.meanToZero==1 fitCalCM{nDim} = fitCalCM{nDim} + mean(1-fitCalCM{nDim}); end - + % Apply CM calibration correction i=1; for ord=CMData.([fields{nDim} 'CMIndex'])' @@ -761,7 +759,7 @@ function applyDiagnosticCorrection(SC,CMstep,CMData,BPMData,varargin) i=i+1; end end - + % Apply BPM calibration error correction if strcmp(BPMData.FitGains,'Yes') % Get fitted BPM calibration errors @@ -776,7 +774,7 @@ function applyDiagnosticCorrection(SC,CMstep,CMData,BPMData,varargin) if p.Results.meanToZero==1 fitCalBPM = fitCalBPM + mean(1-fitCalBPM); end - + % Apply BPM calibration error correction i=1; for ord=BPMData.BPMIndex(BPMData.([fields{nDim} 'BPMIndex']))' @@ -785,12 +783,12 @@ function applyDiagnosticCorrection(SC,CMstep,CMData,BPMData,varargin) end end end - + % Apply BPM roll error correction if strcmp(BPMData.FitCoupling,'Yes') % Get fitted BPM rolls fitRollBPM = [BPMData.VBPMCoupling-BPMData.HBPMCoupling]'/2; - + % Apply BPM calibration error correction i=1; for ord=BPMData.BPMIndex' @@ -836,9 +834,9 @@ function applyOrbitCorrection(SC,varargin) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Match chromaticity (so far not beam based) function matchChromaticity(SC,sFamOrds,chromTarget) - + warning('This function will be removed in a future release. Use ''fitChromaticity'' within this library instead') - + % Match chromaticity [tmp,~]=atmatchchromdelta(SC.RING,chromTarget(:),sFamOrds); @@ -861,7 +859,7 @@ function matchChromaticity(SC,sFamOrds,chromTarget) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Fit chromaticity (not beam based) function fitChromaticity(SC,sOrds,varargin) - + % Parse optional arguments p = inputParser; addOptional(p,'targetChrom',[]); @@ -873,55 +871,55 @@ function fitChromaticity(SC,sOrds,varargin) addOptional(p,'sepTunesDeltaK',[]); parse(p,varargin{:}); par = p.Results; - + % Select target chromaticity if isempty(par.targetChrom) [~, ~, par.targetChrom] = atlinopt(SC.IDEALRING,0,[]); end - + % Check if something went wrong if any(isnan(par.targetChrom)) fprintf('Target chromaticity must not contain NaN. Aborting.\n') varargout{1} = SC; return end - + % Copy intial SC state (for convinience) SC0 = SC; - + % Seperate tunes for fitting if ~isempty(par.sepTunesWithOrds) && ~isempty(par.sepTunesDeltaK) for nFam=1:length(par.sepTunesWithOrds) SC = SCsetMags2SetPoints(SC,par.sepTunesWithOrds{nFam},2,2,par.sepTunesDeltaK(nFam),'method','add'); end end - + % Print initial conditions if par.verbose [~, ~, xi0] = atlinopt(SC.RING,0,[]); fprintf('Fitting chromaticities from [%.3f,%.3f] to [%.3f,%.3f].\n',xi0,par.targetChrom) end - + % Initial setpoints for nFam=1:length(sOrds) for n=1:length(sOrds{nFam}) SP0{nFam}(n) = SC.RING{sOrds{nFam}(n)}.SetPointB(3); end end - + % Define fit function fun = @(x) fitFunction(SC,sOrds,x,SP0,par.targetChrom); - + % Run solver sol = fminsearch(fun,par.InitStepSize,optimset('TolX',par.TolX,'TolFun',par.TolFun)); - + % Apply solution SC = applySetpoints(SC0,sOrds,sol,SP0); - + % Print final falues if par.verbose [~, ~, xi1] = atlinopt(SC.RING,0,[]); fprintf(' Final chromaticity: [%.3f,%.3f]\n Setpoints change: [%.2f,%.2f]\n',xi1,sol) end - + % Define output arguments varargout{1} = SC; @@ -929,29 +927,29 @@ function fitChromaticity(SC,sOrds,varargin) function out = fitFunction(SC,qOrds,setpoints,SP0,target) % Apply setpoints SC = applySetpoints(SC,qOrds,setpoints,SP0); - + % Get chromaticity [~, ~, xi] = atlinopt(SC.RING,0,[]); - + % Get figure of merrit out = sqrt(mean( (xi(:) - target(:)).^2 )); end - + % Apply setpoints - function SC = applySetpoints(SC,ords,setpoints,SP0) + function SC = applySetpoints(SC,ords,setpoints,SP0) for nF=1:length(ords) SC = SCsetMags2SetPoints(SC,ords{nF},2,3,setpoints(nF)+SP0{nF},'method','abs'); end end - + end - + % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Plot status of the correction chain function fitTune(SC,qOrds,varargin) - + % Parse optional arguments p = inputParser; addOptional(p,'targetTune',[]); @@ -962,7 +960,7 @@ function fitTune(SC,qOrds,varargin) addOptional(p,'FitInteger',1); parse(p,varargin{:}); par = p.Results; - + % Select target tune if isempty(par.targetTune) if par.FitInteger @@ -972,12 +970,12 @@ function fitTune(SC,qOrds,varargin) [~, par.targetTune, ~] = atlinopt(SC.IDEALRING,0); end end - + % Print initial conditions if p.Results.verbose nu0 = getLatProps(SC,par.FitInteger); fprintf('Fitting tunes from [%.4f,%.4f] to [%.4f,%.4f].\n',nu0,par.targetTune) end - + % Initial setpoints for nFam=1:length(qOrds) for n=1:length(qOrds{nFam}) @@ -987,18 +985,18 @@ function fitTune(SC,qOrds,varargin) % Define fit function fun = @(x) fitFunction(SC,qOrds,x,SP0,par.targetTune,par.FitInteger); - + % Run solver sol = fminsearch(fun,par.InitStepSize,optimset('TolX',par.TolX,'TolFun',par.TolFun)); - + % Apply solution SC = applySetpoints(SC,qOrds,sol,SP0); - + % Print final falues if p.Results.verbose nu1 = getLatProps(SC,par.FitInteger); fprintf(' Final tune: [%.4f,%.4f]\n Setpoints change: [%.3f,%.3f]\n',nu1,sol) end - + % Define output arguments varargout{1} = SC; @@ -1006,14 +1004,14 @@ function fitTune(SC,qOrds,varargin) function out = fitFunction(SC,qOrds,setpoints,SP0,target,FitInteger) % Apply setpoints SC = applySetpoints(SC,qOrds,setpoints,SP0); - + % Calcualte lattice properties nu = getLatProps(SC,FitInteger); - + % Get figure of merrit out = sqrt(mean( (nu(:) - target(:)).^2 )); end - + % Get tunes function nu = getLatProps(SC,FitInteger) if FitInteger @@ -1023,7 +1021,7 @@ function fitTune(SC,qOrds,varargin) [~, nu, ~] = atlinopt(SC.RING,0); end end - + % Apply setpoints function SC = applySetpoints(SC,ords,setpoints,SP0) for nFam=1:length(ords) @@ -1073,12 +1071,12 @@ function plotStatus(SC,Init,BPMData,CMData) end CMroll{nDim}(i) = Init.SC.RING{ord}.MagnetRoll(1) + Init.SC.RING{ord}.SupportRoll(1); i=i+1; - end + end BPMcal{nDim} = atgetfieldvalues(Init.SC.RING(BPMData.BPMIndex(BPMData.([fields{nDim} 'BPMIndex']))),'CalError',{1,nDim})'; end - + % Plot BPM and Correctors fitCalCM = {CMData.HCMKicks(:)'./1000./CMData.CMsteps{1}(:)'/2, CMData.VCMKicks(:)'./1000./CMData.CMsteps{2}(:)'/2}; fitRollCM = {-CMData.HCMCoupling',CMData.VCMCoupling'};