classdef NCFBalancedTruncationOptions < ltioptions.Generic
   % getrom options for NCF balanced truncattion.
   
   % Copyright 2023 The MathWorks, Inc.
   properties
      % Order of reduced model.
      Order double {mustBeInteger,mustBeNonnegative} = [];
      % Maximum approximation error.
      MaxError double {mustBeNonempty,mustBeNonnegative} = 0;
      % Minimum state energy.
      MinEnergy double {mustBeNonempty,mustBeNonnegative} = 0;
   end

   methods
            
       function [orders,minOrder,maxOrder] = resolveOrder(this,Info,WARN)
         % Info = mor.util.BalancedTruncationCache
         nns = Info.Split(1);  % # unstable modes
         ns = Info.Split(2);   % # stable modes
         g = Info.Sigma;
         nx = length(g);
         g = g(nns+1:nns+ns,:);
         nnz = sum(g >= Info.ZeroTol);  % # stable, nonzero HSV
         WARN = (nargin<3 || WARN);
         minOrder = nns;
         maxOrder = nns+nnz;

         % Resolve order
         SELCRIT = [~isempty(this.Order);any(this.MaxError>0);any(this.MinEnergy>0)];
         switch sum(SELCRIT)
            case 0
               orders = maxOrder;  % returns balanced realization
            case 1
               if SELCRIT(1)
                  orders = min(this.Order(:),nx);
               elseif SELCRIT(2)
                  nsys = numel(this.MaxError);
                  orders = zeros(nsys,1);
                  for ct=1:nsys
                     r = find(Info.Error>this.MaxError(ct),1,'last');
                     if ~isempty(r)
                        orders(ct) = r;
                     end
                  end
               else
                  nsys = numel(this.MinEnergy);
                  orders = zeros(nsys,1);
                  for ct=1:nsys
                     r = find(Info.Energy>this.MinEnergy(ct),1,'last');
                     if ~isempty(r)
                        orders(ct) = r;
                     end
                  end
               end
            otherwise
               error(message('Control:transformation:getrom4'))
         end
         % Validate order
         orders = orders-minOrder;
         if WARN  % no warnings in IDENT
            if any(orders<0)
               warning(message('Control:transformation:ModelReductionMinOrder',minOrder,minOrder))
            elseif any(orders>nnz)
               warning(message('Control:transformation:ModelReductionMaxOrder',maxOrder))
            end
         end
         orders = max(0,min(orders,nnz)); % effective orders for stable part
      end

   end



   methods (Access = protected)
      function cmd = getCommandName(~)
         cmd = 'getrom';
      end
   end

end

