% Add an optic to the model.
%
% [opt, sn] = addOptic(opt, type, name, m, qm, inNames, outNames)
%
% An optic is a general optical component (mirror, lens, etc.).
% Each type of optic has a fixed number of inputs and outputs
% and a set of parameters which characterize a given instance.
% Optics provide names, coupling coefficients, and basis
% parameters for their input nodes.
%
% Fields are:
%  type, tn = type name and number
%  name, sn = name and serial number of this optic
%  inNames = cell array of input names (Nin x 1)
%  outNames = cell array of output names (Nout x 1)
%  in = vector of input node serial numbers (Nin x 1)
%  out = vector of output node serial numbers (Nout x 1)
%  qm = input to output basis transform matrix (Nout x Nin transforms)
%  qx, qy = input and output basis (Nout x 1)
%  m = input to output coupling matrix (Nout x Nin)
%  d = dl/dx internal link length dependence on optic position (Nout x Nin)
%  mechTF = mechanical transfer functions (see setMechTF)
%  p = type specific parameters

function [opt, sn] = addOptic(opt, type, name, m, d, qm, inNames, outNames)

  % increment optic serial number
  sn = opt.Noptic + 1;
  opt.Noptic = sn;

  % create optic struct
  tn = opt.types.(type);
  [N, M] = size(m);
  newOptic = struct('type', type, 'tn', tn, 'name', name, 'sn', sn, ...
		    'Nin', M, 'Nout', N, ...
                    'inNames', [], 'outNames', [], ...
                    'in', zeros(M, 1), 'out', zeros(N, 1), ...
                    'qm', qm, 'qx', zeros(N, 1), 'qy', zeros(N, 1), ...
                    'm', m, 'd', d, 'pos', 0, ...
                    'mechTF', [], 'p', []);

  % set in and out names
  newOptic.inNames = inNames;
  newOptic.outNames = outNames;

  % add optic
  opt.optic(sn, 1) = newOptic;
