%LIUPTCV  TCV LIUQE configuration parameters
% P = LIUPTCV(SHOT,'PAR',VAL,...) returns a structure P with configuration
% parameters from the RESULTS tree for SHOT, optionally replacing or adding
% parameters with specified values. See also LIUP.
%
% LIUQE-TCV:specific parameters:
% .psrc        Determines MDS subtree for LIUQE parameters (default:LIUQE corresponding to \RESULTS::PARAMETERS:*)
% .reff        If reff=-1, use 3D flux loops measurements (geometry not implemented yet). Use ideal loop conversion otherwise.
% .xrtc        If xrtc=1, use signals from RTC tree
%
% [+MEQ MatlabEQuilibrium Toolbox+] Swiss Plasma Center EPFL Lausanne 2022. All rights reserved.

function P = liuptcv(shot,varargin)
 P = meqptcv(shot); % get TCV defaults
 % custom TCV-specific parameters (not yet in MDS tree)
 P.psrc = 'LIUQE.M';
 P.reff = 0;
 P.xrtc = 0;
 P.ivesm = 1; % use vessel measurements
 
 % RESULTS or PCS tree, kA to A, Wb/rad to Wb
 legacy = false;
 iarg = find(strcmp(varargin(1:2:end),'psrc'));
 if ~isempty(iarg), P.psrc = varargin{2*iarg(end)};end
 switch upper(P.psrc)
  case 'LIUQE.M' , src = '\RESULTS::EQUIL_PARAM:';
  case 'LIUQE.M2', src = '\RESULTS::EQUIL_PARAM_2:';
  case 'LIUQE.M3', src = '\RESULTS::EQUIL_PARAM_3:';
  case 'LIUQE'   , src = '\RESULTS::PARAMETERS:';    legacy = true;
  case 'LIUQE2'  , src = '\RESULTS::PARAMETERS_2:';  legacy = true;
  case 'LIUQE3'  , src = '\RESULTS::PARAMETERS_3:';  legacy = true;
  case 'RTLIUQE' , src = '\PCS::TOP.RTLIUQE_1.PARAMETERS:';
  case 'RTLIUQE2', src = '\PCS::TOP.RTLIUQE_2.PARAMETERS:';
  case 'RTLIUQE3', src = '\PCS::TOP.RTLIUQE_3.PARAMETERS:';
  case 'DEFAULT' , src = '';
  otherwise, error('LIUQE:liuptcv:invPsrc','Unknown source for TCV parameter tree: "%s"',P.psrc)
 end
 P = liuptcv_default(P);
 if ~isempty(src)
  % Open shot
  meqmdsopen(shot,'TCV_SHOT')
  P.shot = mdsdata('$SHOT');
  param_case = {'wIa'  ,'wIu'  ,'wIp'  ,'wBm'  ,'wFf'  ,...
                 'Iaerr','Iuerr','Iperr','Bmerr','Fferr',...
                 'Fterr','Ipmin','Ipmeas','nFW','iqR'};
  for n = deblank(mdsdata('GETNCI($1//"*","NODE")',src)')
   % Restore case-sensitive parameter name
   match = strcmpi(n{1},param_case);
   if any(match), param = param_case{match}; % Cannot match 2 at once
   else,          param = lower(n{1});
   end
   %
   [P.(param),stat] = mdsdata([src n{1}]);
   assert(isodd(stat),'LIUQE:MDS:Cannot read parameter node %s',upper(n{1}))
   if endsWith(param,'fct') && ~isempty(P.(param))
    P.(param) = str2func(P.(param));
   end
  end
  if legacy, P = liuptcv_legacy_update(P);
  else,      P = liuptcv_psitbx_update(P);
  end
 end
 
 % overwrites/adds parameters
 deprecated = [liuptcv_legacy_deprecated(),liuptcv_psitbx_deprecated()];
 for k = 1:2:length(varargin)
  switch varargin{k}
   case deprecated
    warning('Parameter "%s" is deprecated and will be ignored.\nType ''help liup;help meqp'' for a list of valid parameters',varargin{k});
    continue;
   otherwise
    P.(varargin{k}) = varargin{k+1};
  end
 end

end

function P = liuptcv_default(P)

 P.b0 = 1.43;
 P.bfct = @bfabmex; % @bfabmex
 P.bfp = [1;2];     % [\parameters:naas,\parameters:nbbs]
 P.Bmerr = 0.01;    % \parameters:berr *
 P.Iaerr = 200;     % \parameters:cerr *
 P.Iuerr = 200;     % \parameters:cerr *
 P.chimax = 3;
 P.dasm = 2;
 P.elomin = 1.1;
 P.fdz = 1e-5;
 P.fetype = 'bil';
 P.Fferr = 0.0012*2*pi;  % \parameters:ferr*2*pi
 P.idml = 1;        % \parameters:idml
 P.idoublet = 0;
 P.infct = '';
 P.inp = [];
 P.ipm = 0;
 P.Ipmeas = 0;      % \parameters:uc1 *
 P.ipmi = 0;
 P.ipmo = 0;
 P.iqR = [];
 P.isaddl = 1;      % \parameters:isaddl *
 P.itera = 100;
 P.iterfrz = 50;
 P.iterh = 30;
 P.iterq = 0;
 P.iters = 48;
 P.itert = 0;
 P.lasy = 0;
 P.ndom = 1;
 P.nelem = 10;
 P.nFW = 1;
 P.nolim = 0;        % \parameters:nolim *
 P.noq = 32;
 P.npq = 18;
 P.nr = 27;          % \parameters:nr *
 P.nu = [];
 P.nthg = 129;
 P.nz = 32;          % \parameters:nz *
 P.Iperr = 24000;    % \parameters:plcerr *
 P.Ipmin = 15000;    % \parameters:plcumin *
 P.pq = (1:40).'/40;
 P.pql = 0.2;
 P.pqu = sqrt(0.95);
 P.psichco = 5e-5;   % \parameters:psichco *
 P.r0 = 0.88;
 P.reff = 0;
 P.rip = NaN;
 P.rn = [];
 P.rop = NaN;
 P.selu = 'sx';
 P.stab = 1;
 P.stabcint = 1;
 P.stabder = 1;
 P.stabint = 1;
 P.stabz = 1;
 P.Fterr = 1.27e-4;
 P.itercs = 20;
 P.tolcs = 1e-4;
 P.tolh = 1e-3;
 P.wIp = 1;         % \parameters:uc2 *
 P.wIa = ones(19,1);% \parameters:uuu[0:18]
 P.wIu = ones(38,1);% \parameters:uuu[19:56]
 P.wBm = ones(38,1);% \parameters:vvv[0:37]
 P.wFf = ones(38,1);P.wFf(10:12) = 0;% \parameters:www[0:37]
 P.wreg = 2e-6;
 P.wregadapt = 15;
 P.xdoma = 0;
 P.zfct = @(P,rst,z0,zA,dz) dz;
 P.zlp = NaN;
 P.zn = [];
 P.zup = NaN;
 
 % These parameters are provided by meqptcv
 % P.ri = NaN;        % \parameters:ri *
 % P.ro = NaN;        % \parameters:ro *
 % P.zl = NaN;        % -\parameters:zu *
 % P.zu = NaN;        % \parameters:zu *
 
 P.idens = 0;       % \parameters:idens *
 P.ifara = 0;       % \parameters:ifara *
 P.iinv = 0;        % \parameters:iinv *
 P.ipolarimetry = 0;% \parameters:ipolarimetry *
 P.ipres = 0;       % \parameters:pres *
 
end

function P = liuptcv_legacy_update(P)

 P.Iaerr = 1000*P.cerr; P.Iuerr = 1000*P.cerr; P.Iperr = 1000*P.plcerr; P.Ipmin = 1000*P.plcumin;
 P.Fferr = 2*pi*P.ferr; P.stab = 2*pi*P.stab;
 P.zl = -P.zu;
 P.selu = 's'; % vessel representation;
 P.ivesm = 1; % use vessel measurements
 P.Fterr = 0.13e-3;
 P.pq = (1:40)/40;
 P.npq = 40;
 P.ilim = double(~P.nolim);
 
 P.bfp = [P.naas P.nbbs];
 P.Bmerr = P.berr;
 P.wBm = P.vvv;
 P.wFf = P.www;
 P.wIp = P.uc2;
 P.wIa = P.uuu(1:19);
 P.wIu = P.uuu(20:end);
 P.Ipmeas = P.uc1;
 
 % TCV specific checks
 msge = 'LIUQE:TCVparameterNotSupported:%s %g';
 assert(P.idens   ==   0,msge,'IDENS ~= 0'  )
 assert(P.ifara   ==   0,msge,'IFARA ~= 0'  )
 assert(P.ipres   ==   0,msge,'IPRES ~= 0'  )
 assert(P.Ipmeas  ==   0,msge,'IPMEAS ~= 0' )
 assert(P.iinv    ==   0,msge,'IINV ~= 0'   )
 assert(P.itera   ~= 300,msge,'ITERA = 300' )
 assert(P.itera   ~= 888,msge,'ITERA = 888' )
 assert(P.itera   >    0,msge,'ITERA < 1'   )
 assert(P.ncufit  ~=   0,msge,'NCUFIT = 0'  )
 assert(P.nolim   ==   0,msge,'NOLIM ~= 0'  )
 assert(P.ibousou ==   1,msge,'IBOUSOU ~= 1')
 
 %% Check and remove deprecated parameters
 deprecated = liuptcv_legacy_deprecated();
 P=rmfield(P,deprecated);
 
end

function P = liuptcv_psitbx_update(P)
 
 % Parameters for cubic spline interpolation
 P.tolcs = P.tol;
 P.itercs = P.iter;

 %% Check and remove deprecated parameters
 deprecated = liuptcv_psitbx_deprecated();
 P=rmfield(P,deprecated);

end

function list = liuptcv_legacy_deprecated()
 
 % Deprecated legacy (FORTRAN) parameters
 list = {'ibousou','mei','ncosei','ncufit','nlimi','npsi','psirat',...
         'berr','cerr','ferr','plcerr','plcumin','uuu','vvv','www','uc1','uc2',...
         'naas','nbbs','nolim'};

end

function list = liuptcv_psitbx_deprecated()

 % Deprecated psitbx parameters
 list = {'iter','tol'};

end
 
