% Optickle Model
%
% class fields are:
%
% optic - an array of optics
% Noptic - number of optics
% link - an array of links
% Nlink - number of links
% probe - an array of probes
% Nprobe - number of probes
% snSource - field source index
% lambda - carrier wave length
% h - Plank constant
% c - speed of light
% k - carrier wave-number
%
% ======== Optics
% 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 linkts.
%
% Basic parameters are:
% type, tn = type and type number
% name, sn = name and serial number of this optic
% Nin, Nout = number of outputs and inputs
% inNames = cell array of input names (MxP)
% outNames = cell array of output names (NxQ)
% in = vector of input link serial numbers (Mx1)
% out = vector of output link serial numbers (Nx1)
% qm = input to output basis transform matrix (NxM)
% qx = output basis vector, x-axis (Nx1)
% qy = output basis vector, y-axis (Nx1)
% m = input to output coupling matrix (NxM)
% d = dl/dpos internal link length dependence on optic position (NxM)
% pos = position offset (see setPosOffset)
% mechTF = mechanical transfer functions (see setMechTF)
% p = type specific parameters
%
% Types of optics are listed below:
%   Source - a field source (0 inputs, 1 output)
%   Sink - a field sink, used for detectors (1 inputs, 0 output)
%
%   Mirror - a general curved mirror (2 inputs, 4 outputs)
%   BeamSplitter - a beam-splitter (4 inputs, 8 outputs)
%
%   Lens - a thin lens, used for basis transforms (1 input, 1 output)
%   Telescope - a hypothetical pair of lenses (1 input, 1 output)
%
% ======== Links
% Links are connections between optics.
% 
% sn = serial number of this link
% snParent, nParent = serial number and input number of parent
% snSource, nSource = serial number and port number of source link
% len - the length of the link
%
% ======== Probes
% Probes convert fields to signals.  Each probe produces two complex
% numbers, one transfer coefficient for each RF phase.
% 
% name, sn = name and serial number of this probe
% nField = index of the sampled field
% freq = demodulation frequency
% phase = demodulation phase offset (degrees)

function opt = Optickle(varargin)

  newOptic = struct('type', [], 'tn', 0, 'name', [], 'sn', 0, ...
                    'Nin', 0, 'Nout', 0, ...
                    'inNames', {}, 'outNames', {}, ...
                    'in', [], 'out', [], ...
                    'qm', [], 'qx', [], 'qy', [], ...
                    'm', [], 'd', [], 'pos', 0, ...
                    'mechTF', [], 'p', []);

  newLink = struct('sn', 0, 'len', 0, ...
                   'snSource', 0, 'portSource', 0, ...
                   'snSink', 0, 'portSink', 0);

  newProbe = struct('sn', 0, 'name', [], 'nField', 0, ...
                    'freq', 0, 'phase', 0);

  opt = struct('optic', newOptic, 'Noptic', 0, ...
               'link', newLink, 'Nlink', 0, ...
               'probe', newProbe, 'Nprobe', 0, ...
               'snSource', 0, 'lambda', 0, ...
               'c', 0, 'h', 0, 'k', 0, ...
               'types', []);

  opt.types.Source = 1;
  opt.types.Sink = 2;
  opt.types.Mirror = 3;
  opt.types.BeamSplitter = 4;
  opt.types.Modulator = 5;
  opt.types.Lens = 6;
  opt.types.Telescope = 7;
  
  opt = class(opt, 'Optickle');

  errstr = 'Don''t know what to do with ';	% for argument error messages
  switch( nargin )
   case 0					% default constructor
    opt.lambda = 1064e-9;
   case 1
    arg = varargin{1};
    if( isnumeric(arg) & length(arg) == 1)	% set lambda
      opt.lambda = arg;
    elseif( ~isa(arg, 'Optickle') )		% copy constructor
      error([errstr 'a %s.'], class(arg));
    end
   otherwise					% wrong number of input args
    error([errstr '%d input arguments.'], nargin);
  end

  opt.h = 6.62606891e-34;			% Plank constant [J*s]
  opt.c = 299792458;				% speed of light [m/s]
  opt.k = 2 * pi / opt.lambda;			% wave number [1/m]
