## Copyright (C) 2009 Carlo de Falco <carlo DOT defalco AT gmail DOT com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; If not, see <http://www.gnu.org/licenses/>.


## -*- texinfo -*-
## @deftypefn {Function File} {[@var{var}, @var{t}, @var{x}] =} osc_output_get (@var{data}, @var{output}, @var{var_name} )  
## Get a table of the values of the variable @var{var_name} at times
## @var{t} and at points @var{x} from the raw output of a transient
## simulation @var{output}.
##
## Available variable names:
## @itemize @minus
## @item @code{"electron density"}
## @item @code{"hole density"}
## @item @code{"time derivative of electron density"}
## @item @code{"time derivative of hole density"}
## @item @code{"charge pair density"}
## @item @code{"average pair density"}
## @item @code{"electric potential"}
## @item @code{"time derivative of electric potential"}
## @item @code{"electric field"}
## @item @code{"contact current"}
## @item @code{"contact conduction current"}
## @item @code{"contact displacement current"}
## @end itemize
## @end deftypefn

## Author: Carlo de Falco <carlo DOT defalco AT gmail DOT com>

function [var, t, x] = osc_output_get (data, output, var_name)

  if (nargin !=3)
    print_usage ();
    return;
  endif

  persistent e0 = physical_constant("electric constant");
  persistent q  = physical_constant("elementary charge");
  persistent Kb = physical_constant("boltzmann constant");


  switch var_name
    case "electron density"
      var = output.y(:,1:data.Nx)*data.sc(1);
      t   = data.t;
      x   = data.x;
    case "time derivative of electron density"
      var = output.ydot(:,1:data.Nx)*data.sc(1);
      t   = data.t;
      x   = data.x;
    case "hole density"
      var = output.y(:,[1:data.Nx]+data.Nx)*data.sc(2);
      t   = data.t;
      x   = data.x;
    case "time derivative of hole density"
      var = output.ydot(:,[1:data.Nx]+data.Nx)*data.sc(2);
      t   = data.t;
      x   = data.x;
    case "charge pair density"
      var = output.y(:,[1:data.Nx]+2*data.Nx)*data.sc(3);
      t   = data.t;
      x   = data.x;
    case {"average pair density", "average electron density", "average hole density"}
      switch var_name
	case "average pair density"
	  XX  = output.y(:,[1:data.Nx]+2*data.Nx)*data.sc(3);
	case "average electron density"
	  XX  = output.y(:,1:data.Nx)*data.sc(1);
	case "average hole density"
	  XX  = output.y(:,[1:data.Nx]+data.Nx)*data.sc(2);
      endswitch
      hh  = repmat(diff(data.x), 1, data.Nt).';
      var = sum((hh.*(XX(:,1:end-1)+XX(:,2:end))/(2*data.L)),2);
      t   = data.t;
      x   = [];
    case "electric potential"
      var  = repmat(data.d0.', data.Nt, 1)*data.sc(4);
      var(:,2:end-1) = output.y(:,[1:data.Nx-2]+3*data.Nx)*data.sc(4);
      t   = data.t;
      x   = data.x;
    case "time derivative of electric potential"
      var  = repmat(data.d0.', data.Nt, 1)*data.sc(4);
      var(:,2:end-1) = output.ydot(:,[1:data.Nx-2]+3*data.Nx)*data.sc(4);
      t   = data.t;
      x   = data.x;
    case "electric field"
      V  = osc_output_get (data, output, "electric potential");
      hh  = repmat(diff(data.x), 1, data.Nt).';
      var = ((V(:,1:end-1)-V(:,2:end))./(hh));
      t   = data.t;
      x   = (data.x(2:end)+data.x(1:end-1))/2;
    case "contact conduction current"
      E  = osc_output_get (data, output, "electric field");
      n  = osc_output_get (data, output, "electron density");
      p  = osc_output_get (data, output, "hole density");
      X  = osc_output_get (data, output, "charge pair density");
      dn = osc_output_get (data, output, "time derivative of electron density");
      dp = osc_output_get (data, output, "time derivative of hole density");
      
      for it=1:data.Nt
        

	  un = data.un(data, E(it,:));
          k1  = data.gamma(data, E(it,:));
          k2  = data.kdiss(data, E(it,:));
	  Dn = un*Kb*data.temp/q;
	  Cn = -un;
	  M1 = bim1a_rhs (data.x, k1.', (n(it,:).*p(it,:)).');
          M2 = bim1a_rhs (data.x, k2.', X(it,:).');
          Mn = bim1a_rhs (data.x, ones(length(data.x)-1,1), dn(it,:).');
	  An = bim1a_advection_diffusion (data.x, Dn.', ones(data.Nx,1),  ...
			                  ones(data.Nx,1), (Cn .* E(it,:)./Dn).');
	  divn = q*(An * n(it,:)'+M1-M2+Mn);
	  jn   = -divn([1 end]);
	  
	  up = data.up(data, E(it,:));
	  Dp = up*Kb*data.temp/q;
	  Cp = up;
          Mp = bim1a_rhs (data.x,  ones(length(data.x)-1,1), dp(it,:).');
	  Ap =  bim1a_advection_diffusion (data.x, Dp.', ones(data.Nx,1),  ...
			      ones(data.Nx,1), (Cp .* E(it,:)./Dp).');
          divp = q*(Ap * p(it,:)'+M1-M2+Mp);
	  jp   = divp([1 end]);
	
	  var(:,it) = jn+jp;
      endfor
      t = data.t;
      x = [];
    case "contact displacement current"
      Vdot  = osc_output_get (data, output, "time derivative of electric potential");
      n  = osc_output_get (data, output, "time derivative of electron density");
      p  = osc_output_get (data, output, "time derivative of hole density");
      Dd = data.er*e0;
      A = bim1a_advection_diffusion (data.x, Dd, ones(size(data.x)), ones(size(data.x)), 0);
      M = bim1a_reaction (data.x, ones(length(data.x)-1,1), ones(size(data.x)));
      div = A*Vdot.' + q * M * (n - p).';
      var = div([1 end], :);
      t = data.t;
      x = [];
    case "contact current"
      Icond  = osc_output_get (data, output, "contact conduction current");
      Idisp  = osc_output_get (data, output, "contact displacement current");
      var = Icond+Idisp;
      t = data.t;
      x = [];
    otherwise
      error(sprintf("unknown variable: %s", var_name))
  endswitch

endfunction
