Preliminary LoopTickle documentation Disclaimer: LoopTickle is still work in progress, so there are still some unused files included in the distribution. == LoopTickle description == LoopTickle is an add-on to optickle that allows closing control loops and provides a series of plotting functions for things like transfer functions and noise budgets at various ports. Looptickle needs to get the interferometer AC response matrix sigAC from optickle. The LoopTickle configuration file then defines control filters and correction pathes as well as several displacement and sensing noises. The control filters and correction pathes are converted into one control matrix H, such that the whole interferometer can be described by the diagram below (all arrows are vectors). <---- H <------------ | | |- | displacement ---> ---> sigAC ---> ---> ---> sensing ports signals/noises + +^ | | sensing noises The various high level functions described below use this schematic to calculate transfer function and noise contributions at different ports. -------- Example demoAdvLIGO.m is an example of how to use LoopTickle: % add appropriate pathes addpath('./Optickle'); addpath('./lib/Filter'); addpath('./lib/Plot'); addpath('../bench61'); % define frequency vector Nsweep=201; f = logspace(0, 4, Nsweep)'; % set up Optickle opt=optAdLIGO_9_45NS_lofi12cm; % calculate optickle fields [sigDC, sigAC, mechTF, fDC, fAC] = compute(opt, [], f); % set up LoopTickle loopt=looptickle(opt,f,fDC,'looptAdvLIGO'); % load some nice definitions for plotting startup % LoopTickle is all set up now. The following functions can be called % in any desired order. openLoopGain(loopt,sigAC,loopt.LOOPNAMES); noiseBudget(loopt,sigAC,loopt.LOOPNAMES); lengthCoupling(loopt,sigAC,loopt.LOOPNAMES,loopt.LOOPNAMES,0,1); closedLoopGain(loopt,sigAC,loopt.LOOPNAMES); getSense(loopt,sigAC,loopt.LOOPNAMES); getResponse(loopt,sigAC,loopt.LOOPNAMES); -------- === Description of LoopTickle configuration file === looptAdvLIGO.m is an example configuration file. The configuration file needs to specify the following entries of the loopt structure (as of May 9): loopt.LOOPNAMES : Cell list of loop names (strings) loopt.SENSE : Cell list of optickle sensing ports numbers. Multiple sensing ports possible, specified as row vector. loopt.CTRLINMTRX : Cell list of input matrix (scalar if only one port, otherwise row vector) loopt.DRIVE : Cell list of optickle actuation optic numbers (column vector). loopt.CTRLOUTMTRX: Cell list of actuation output matrix (column vector). Note that this also defines the degree of freedom, i.e. for DARM=Lx-Ly we have [0.5;-0.5], but for CARM=(Lx+Ly)/2 we have [1;1]. For the same reason correction pathes with flat response should not be included here. loopt.CORR : Cell list of a vector of correction path structs. Each correction path struct has the following fields: filter.p : list of filter poles filter.z : list of filter zeros filter.k : filter gain Note: The filter definition follows the more reasonable convention use e.g. in Matt's filter toolbox, iLIGO or FOTON, (NOT the MATLAB definition with negative angular frequencies.) DRIVE : optickle actuation optic numbers CORROUTMTRX: actuation output matrix loopt.CTRLFLTER : Cell list of control filter structs each struct has the following fields (see also note under loopt.CORR): p : list of filter poles z : list of filter zeros k : filter gain loopt.plot.watt.axis: Cell list of lower and upper limit on y-axis for plotting [Watts] loopt.plot.meter.axis: Cell list of lower and upper limit on y-axis for plotting [meters] -------- === High level LoopTickle functions description === function [varargout]=openLoopGain(loopt,M,loopnames,varargin) % % calculates olg for degree of freedoms specified in loopnames, % with all other loops closed (i.e. a new control matrix H' that does not % include the loop of interest is calculated and used for closing the % other loops.) % Examples: % openLoopGain(loopt,sigAC,{'CARM','DARM'},) % --> plot CARM and DARM OLG % olg=openLoopGain(loopt,sigAC,'CARM') % --> return CARM OLG % [olg,sensing]=openLoopGain(loopt,sigAC,'CARM') % --> return CARM OLG and plant-only TF (i.e. OLG w/o control filter) function [varargout]=closedLoopGain(loopt,M,loopnames,varargin) % % calculates clg for one degree of freedom, with all other loops closed % Examples: % closedLoopGain(loopt,sigAC,{'CARM','SRCL'},) % --> plot CARM & SRCL CLG % clg=closedLoopGain(loopt,sigAC,'CARM') % --> return CARM CLG function [varargout]=getSense(loopt,M,loopnames,varargin) % % calculates the sensing function in Watt/m for % the length control loop error signal % % Examples: % getSense(loopt,sigAC,{'CARM','DARM'},) % --> plot CARM & DARM sensing function % sensing=getSense(loopt,sigAC,'CARM') % --> return CARM sensing function function [varargout]=getResponse(loopt,M,loopnames,varargin) % % calculates the response function in m/Watt for % the length control loop error signal % % Examples: % getResponse(loopt,sigAC,{'CARM','DARM'},) % --> plot CARM & DARM response % resp=getResponse(loopt,sigAC,'CARM') % --> return CARM response function [varargout]=lengthCoupling(loopt,M,fromLoops,toLoops,closeFlag,calFlag,varargin) % % calculates the LSC matrix x-couplings from the 'fromLoops' to the % 'toLoops' % closeFlag specifies whether the control loops are closed or not. % calFlag specifies whether the coupling is calibrated in % meters/meter (true) or Watts/meter (false) % % Examples: % lengthCoupling(loopt,sigAC,{'PRCL','MICH'},'DARM',0,1,) % --> plot coupling from 'PRCL' and 'MICH' to 'DARM' % coupl=lengthCoupling(loopt,sigAC,{'PRCL','MICH'},'DARM',0,1) % --> return coupling from 'PRCL' and 'MICH' to 'DARM' function noiseBudget(loopt,M,loopnames,calFlag,varargin) % % plots a noise budget for port 'loopnames' that includes % all previously added noise sources % calFlag=0: calibrated in Watts % calFlag=1: calibrated in meters % calFlag=2: calibrated in strain (actually just divides meters by 4000, % i.e. is only meaningful for DARM.) % function loopt=addSensingNoise(loopt,name,x,SENSMTRX,PORTS,COHERENT) % adds a sensing noise to the loopticle model % % Example % loopt=addSensingNoise(loopt,'MyNewNoise',x,[1],[nDARM]) % loopt=addSensingNoise(loopt,'MyNewNoise',x,'DARM') % x is in Watts/rtHz % % COHERENT specifies whether the noise from the different inputs is % summed coherently or incoherently. Default is % coherently, i.e. true, making SENSMTRX a true inputput matrix. % Note that contributions from different addSensingNoise calls are % ALLWAYS summed incoherently function loopt=addDisplacementNoise(loopt,name,x,ACTMTRX,OPTICS,COHERENT) % adds a displacement noise to the loopticle model % % Example % loopt=addDisplacementNoise(loopt,'MyNewNoise',x,[1;1],[nEX;nEY]) % x is in meter/rtHz % % COHERENT specifies whether the noise from the optics specified in % ACTMTRX and OPTICS is summed coherently or incoherently. Default is % coherently, i.e. true, making ACTMTRX a true output matrix. % Note that contributions from different addDisplacementNoise calls % are ALLWAYS summed incoherently. function loopt=importBench6(loopt,opt,ifo,src) % % Imports the displacement noises from bench % (only displacement noises, NOT IFO parameter are loaded) % note that bench works in strain^2, while LoopTickle works in meters % This function is currently called by default in looptickle.m. function loopt=addNaiveShot(loopt,opt,fDC,loopname) % adds naive shot noise (no quantum effects) to the loopticle model % % Example % loopt=addNaiveShot(loopt,opt,'DARM') % % This function is currently called by default for all control loops in % looptickle.m. --------