% Add a source to the model.
%
% [opt, sn] = addSource(opt, name, z, z0, a)
%
% Sources illuminate the optics.  They can also be used
% as a phase modulator (i.e., driving the source results
% in phase modulation of its output).
%
% Paramters:
% z - distance to waist (negative if beam is converging)
% z0 - beam range = (waist size)^2 * pi / lambda
% vMod - modulation frequencies and amplitudes (N x 2)
%
% A source has no inputs and 1 output.
% Output:
% 1, out, fr = output
%
% Example:
% % input frequency and amplitude
% Pin = 1;				% input power
% fMod = 26e6;				% modulation frequency
% gMod = 0.2;				% modulation depth
% nMod = (-2:2)';				% sideband indices
% vMod = [nMod * fMod, sqrt(Pin) * bessel(nMod, gMod)];
%
% % add the source to the Optickle model
% [opt, nSrc] = addSource(opt, 'Source', vMod);

% modal stuff for next version
%  %op = inv(opt.optic(nIX).qm(2, 1).x);		% back through IX lens
%  [z0, z1] = cavHG(lCav, Ri, Re);		% cavity mode
%  op = focusOpHG(1 / Ri * 0.45);		% back through IX lens
%  op = shiftOpHG(-dSrc) * op;			% back to source
%  q = applyOpHG(op, z1 + i * z0);

function [opt, sn] = addSource(opt, name, vMod)

  % check model for existing source
  if opt.snSource ~= 0
    disp('Optickle models currently support only one source.');
    error('Source Exists: %s (%d) is the current source.', ...
          opt.optic(opt.snSource).name, opt.snSource);
  end
  
  % transfer matrices
  m = zeros(1, 0);
  d = zeros(1, 0);

  % basis transform matrix
  qm = repmat(nullOpHG, 1, 0);
  
  % add source
  type = 'Source';
  inNames = {};
  outNames = {{'out' 'fr'}};
  [opt, sn] = addOptic(opt, type, name, m, d, qm, inNames, outNames);
  opt.snSource = sn;
  
  % save source power info
  opt.optic(sn).p = vMod;
