function Controller = mpcblocklinearizationExplicit(blockdata)
% Provide linearization result for MPC block

%   Authors: R. Chen
%   Copyright 1986-2011 The MathWorks, Inc.

blk = blockdata.BlockName;
empcobjname = strtrim(get_param(blk,'empcobj'));
if isempty(empcobjname) || strcmp(get_param(blk,'state_inport'),'on')
   % when design from scratch at the block dialog, we should just return
   % linearization results (open-loop with 0 dc gain)
   Controller = blockdata.BlockLinearization;
else
   % non-empty MPC controller is in the base workspace
   % get i/o port dimensions
   InportDims = localGetPortNumber(blockdata.BlockLinearization.InputName);
   OutportDims = localGetPortNumber(blockdata.BlockLinearization.OutputName);
   TotalInports = sum(InportDims);
   TotalOutports = sum(OutportDims);
   % check whether MD inport is on
   AvailableBlocks = get_param(blk,'Blocks');
   md_inport = ismember('md',AvailableBlocks);
   % get MPC
   empcobj = slResolve(empcobjname,blk);
   mpcobj = empcobj.MPC;
   % get linear MPC
   if md_inport
      % MO, REF and MD
      sys = ss(mpcobj,'rv');
   else
      % only MO and REF
      sys = ss(mpcobj,'r');
   end
   [nx, nu] = size(sys.B);
   ny = size(sys.C,1);
   % append it with right i/o dimensions
   Controller = ss(sys.A,[sys.B zeros(nx,TotalInports-nu)],[sys.C;zeros(TotalOutports-ny,nx)],...
            [sys.D zeros(ny,TotalInports-nu);zeros(TotalOutports-ny,TotalInports)],...
            'Ts',sys.Ts,'TimeUnit',sys.TimeUnit,'StateName',sys.StateName,'StateUnit',sys.StateUnit,...
            'InputName',[sys.InputName;repmat({''},TotalInports-nu,1)],...
            'InputUnit',[sys.InputUnit;repmat({''},TotalInports-nu,1)],...
            'OutputName',[sys.OutputName;repmat({''},TotalOutports-ny,1)],...
            'OutputUnit',[sys.OutputUnit;repmat({''},TotalOutports-ny,1)]);
end

function dims = localGetPortNumber(Names)
% get dimension of each port
ports = zeros(size(Names));
for ct=1:length(Names)
   str = strtok(Names{ct},'(');
   ind = strfind(str,'/');
   ports(ct) = str2double(str(ind+1:end));
end
[~, ind] = unique(ports);
dims = diff([ind;length(Names)+1]);


