%%%%%%%%  ARTIFICIAL NEURAL NETWORK BASED ON QUALIKIZ REGRESSION
%%%%%%%   ITG WITH KINETIC ELECTRONS. 4D INPUTS
%%%%%%%   APPROX 6 ORDERS OF MAGNITUDE FASTER THAN QUALIKIZ
%%%%%%%   ALSO CALCULATES GRADIENTS WITH RESPECT TO INPUTS
%%%%%%%%  JONATHAN CITRIN, JUAN REDONDO, SARAH BRETON, CLARISSE BOURDELLE, FREDERIC IMBEAUX

%%%%%%%%% WARNING, NETWORK VALIDITY RANGE: Ati [2 12]; ti/te [0.3 3]; q [1 5]; s [0.1 3]
%%%%%%%%% IN PRACTICE THE REGULARIZED NETWORKS CAN OFTEN REASONABLY EXTRAPOLATE, BUT CAVEAT EMPTOR!

%%%%%%%%% TRANSPORT MODEL DEVELOPED FOR USE IN RAPTOR (F. FELICI et al) and METIS (J.F. Artaud et al)

%%%%%%% Cleaned up version by F. Felici 2018 - to be cleaned up further

function varargout = QLKNN4Dkin(QLKNN_inputs,net,pp)
% #codegen

if nargout>1 % calculate derivatives?
  calcder = true;
else
  calcder = false;
end

if nargin==0 || isempty('QLKNN_network')
end

if nargin==0
  % call to get default parameters, common for all networks
  [QLKNN_network,QLKNN_params] = load_QLKNN('QLKNN4Dkin');
  QLKNN_params = appendRAPTORInterfaceParameters4D(QLKNN_params);

  varargout{1} = QLKNN_network;
  varargout{2} = QLKNN_params;
  return
end

nInputs = 4; % hard-coded number if inputs for this network
assert(size(QLKNN_inputs,2)==nInputs);

%% Impose constraints
[inputs_constrained,imask] = impose_input_constraints(QLKNN_inputs,net,pp);

%% Evaluate network
if ~calcder
  [out] = evaluate_4Dkin(net,pp,inputs_constrained);
else
  [out,dout_din] = evaluate_4Dkin(net,pp,inputs_constrained);
end

%% Apply input masks to outputs
if calcder
    dout_din = apply_imask(dout_din,imask);
end

%% Assign outputs
if ~calcder
  varargout{1} = out;
else
  varargout{1} = out;
  varargout{2} = dout_din;
end

return

return
