% Display the DARM loop and a few noises.
%
% [sigDC, sigAC, mechTF] = respDARM(f, sigAC, mechTF)
% f - frequency vector for plots
% sigAC and mechTF - from compute
%
% This is an EXAMPLE loop for DARM and some noise projections.  The loop
% is certainly not good, and the noise projections are almost certainly
% wrong, but this should show how Optickle can be used.
%
% Example:

function respDARM(opt, f,  mechTF, fDC,sigAC)

f = logspace(0, 4, 100)';
 opt = opt40;
 [sigDC, sigAC, mechTF, fDC] = compute(opt, [], f);
 %respDARM(opt, f, sigAC, mechTF, fDC);
%
    
opt = opt40;

  % probe names and numbers
  oprb = opt.probe;
  prbNames = {oprb.name};

  % some parameters
  wE = 2 * pi * 0.7;			% resonance of end mirror (rad/s)
  mE = 40;				% mass of end mirror (kg)
  gAct = 1e-6;				% actuator DC gain (m/V)
  gSensor = 1;				% sensor DC gain (V/W)
  fUGF = 200;				% unity gain of servo (Hz)
  nSig = strmatch('AS Q2', prbNames);	% which signal to use
  nEX = getDriveIndex(opt, 'EX');
  nEY = getDriveIndex(opt, 'EY');
  nAS = getFieldAt(opt, 'AS', 'in');
  
  dampedRes = [-0.1 + 1i, -0.1 - 1i];
  
  % ==== Optical transfer functions
  % hSens is from mirror position to sensor signal (W/m)
  hAX = squeeze(sigAC(nSig, nEX, :));
  hAY = squeeze(sigAC(nSig, nEY, :));
  hSig = (hAX - hAY);

  % ==== Technical transfer functions
  w = 2 * pi * f;

  % tranfer function from actuator voltage to free mirror position (m/V)
  tfAct = zpk([], wE * dampedRes, gAct / mE);
  hAct = squeeze(freqresp(tfAct, w));

  % tranfer function from optical RF to sensor voltage (V/W)
  tfSensor = zpk([], 1e6 * dampedRes, gSensor * 1e12);
  hSensor = squeeze(freqresp(tfSensor, w));

  % servo transfer function (V/V)
  tfServo = zpk(-2 * pi * [30 100], -2 * pi * [1e-3 300 1e3], 1);

  % set servo gain to make the desired UGF.
  [sDC, sAC, mTF] = compute(opt, [], fUGF);
  h0 = (mTF(nEX, nEX) + mTF(nEY, nEY)) / 2;
  h1 = (sAC(nSig, nEX) - sAC(nSig, nEY));
  h2 = freqresp(tfAct * tfServo * tfSensor, 2 * pi * fUGF);
  tfServo = tfServo / abs(h0 * h1 * h2);  
  hServo = squeeze(freqresp(tfServo, w));

  % hLoop is the open loop TF
  hLoop = hSensor .* hSig .* hAct .* hServo;
  subplot(2, 1, 1)
  loglog(f, abs(hLoop))
  title('DARM open loop gain')
  xlabel('Hz')
  grid on
  
  % === Noise propagation to the error point

  % a flat "shot" noise
  % see also Buonanno & Chen gr-qc/0102012
  %   http://www.iop.org/EJ/article/0264-9381/18/15/102/q115l2.html
  % or Bench
  %   http://www.its.caltech.edu/~rana/aLIGO/Bench/bench33.m
  Phv = opt.h * opt.c / opt.lambda;
  Pas = sum(abs(fDC(nAS, :))).^2;
  aSensor = sqrt(Phv / Pas) * abs(1 ./ hSig);

  % a flat actuation noise (force) on then mirror
  aAct = 4e-8 * abs(hAct);

  % incoherent sum
  aSum = sqrt(aSensor.^2 + aAct.^2);
  
  subplot(2, 1, 2)
  loglog(f, [aSum, aSensor, aAct]);
  title('A few noises')
  legend('Sum', 'Sensor', 'Actuator')
  xlabel('Hz')
  ylabel('m/rtHz')
  a0 = axis;
  a0(3:4) = [1e-21 1e-17];
  axis(a0);
  grid on
