From 75f15da22e2215531e739d2a8be0d551147c9787 Mon Sep 17 00:00:00 2001
From: Thomas Lambert <t.lambert@uliege.be>
Date: Fri, 26 May 2023 21:54:34 +0200
Subject: [PATCH] feat(Result): add perf summary

---
 src/classes/@Result/Result.m    | 63 ++++++++++++++++++++++++++++++++-
 src/classes/@Result/summarize.m | 46 ++++++++++++++++++++++++
 src/rotare.m                    |  3 +-
 3 files changed, 109 insertions(+), 3 deletions(-)
 create mode 100644 src/classes/@Result/summarize.m

diff --git a/src/classes/@Result/Result.m b/src/classes/@Result/Result.m
index 7a58485..325e083 100644
--- a/src/classes/@Result/Result.m
+++ b/src/classes/@Result/Result.m
@@ -47,10 +47,20 @@ classdef Result < handle
         indfact (1, :) OperRotor   % Results obtained with the indFact solver
         indvel (1, :) OperRotor    % Results obtained with the indVel solver
         stahlhut (1, :) OperRotor  % Results obtained with the stalhlut solver
-        operPts (:, 4) table       % Table of operating points for each individual result
+        operPts table              % Table of operating points for each individual result
         ModExt (1, 1) struct       % Modelling enstension options (losses, etc)
     end
 
+    properties (Dependent)
+        cT
+        cP
+        cQ
+    end
+
+    properties (Constant, Hidden)
+        SOLVERS = {'leishman', 'indfact', 'indvel', 'stahlhut'} % List of allowed solvers
+    end
+
     methods
 
         function self = Result()
@@ -60,8 +70,59 @@ classdef Result < handle
             % Currently empty on purpose. Results are to be assigned manually.
         end
 
+        % ---------------------------------------------
+        % Set methods
+        function set.operPts(self, val)
+            % Note: A bug in Matlab prevents the user of variable names when  size checks are added
+            % in the property definition. https://stackoverflow.com/q/48423003
+            self.operPts = val;
+            self.operPts.Properties.VariableNames = {'Alt', 'V_ax', 'RPM', 'Coll'};
+        end
+
+        % ---------------------------------------------
+        % Get methods for dependent properties
+        function cT = get.cT(self)
+            cT = maketable(self, 'cT');
+        end
+
+        function cQ = get.cQ(self)
+            cQ = maketable(self, 'cQ');
+        end
+
+        function cP = get.cP(self)
+            cP = maketable(self, 'cP');
+        end
+
+        % ---------------------------------------------
         % Other methods
         save(self, SaveOpts)  % Save the results to file
+        summaryTable = summarize(self, propList) % Summarize results
+    end
+end
 
+function resTable = maketable(self, prop)
+    % MAKETABLE Gather properties from all solvers and all operating points in a table
+
+    resTable = table('Size', [size(self.operPts, 1), 4], ...
+                     'VariableTypes', {'double', 'double', 'double', 'double'});
+
+    propName = cell(1, 4);
+    for i = 1:length(self.SOLVERS)
+        propName{i} = [prop, '_', self.SOLVERS{i}];
     end
+
+    resTable.Properties.VariableNames = propName;
+
+    for iOp = 1:size(self.operPts, 1)
+        for iSolv = 1:length(self.SOLVERS)
+            solver = self.SOLVERS{iSolv};
+
+            if ~isempty(self.(solver))
+                resTable.(iSolv)(iOp) = self.(solver)(iOp).(prop);
+            else
+                resTable.(iSolv)(iOp) = NaN;
+            end
+        end
+    end
+
 end
diff --git a/src/classes/@Result/summarize.m b/src/classes/@Result/summarize.m
new file mode 100644
index 0000000..c453e98
--- /dev/null
+++ b/src/classes/@Result/summarize.m
@@ -0,0 +1,46 @@
+function summaryTable = summarize(self, propList)
+    % SUMMARIZE Summarize results into a single clean table.
+    %   This method outputs a table with the operating conditions and the final values found for
+    %   various properties.
+    % -----
+    %
+    % Syntax:
+    %   Result.summarize() Outputs a table with all available data (cT, cQ, cP).
+    %
+    %   Result.summarize(propList) Outputs a table with only the data listed in propList.
+    %
+    % Inputs:
+    %   propList : (optional) Array with the names of the properties to ouptut. {'cT', 'cQ', 'cP'}
+    %
+    % Outputs:
+    %   summaryTable : Table with the operating points and the corresponding rotor performance.
+    %
+    % See also: rotare, Result, template.
+    %
+    % <a href="https://gitlab.uliege.be/rotare/documentation">Complete documentation (online)</a>
+
+    % ----------------------------------------------------------------------------------------------
+    % (c) Copyright 2022-2023 University of Liege
+    % Author: Thomas Lambert <t.lambert@uliege.be>
+    % ULiege - Aeroelasticity and Experimental Aerodynamics
+    % MIT License
+    % Repo: https://gitlab.uliege.be/rotare/rotare
+    % Docs: https://gitlab.uliege.be/rotare/documentation
+    % Issues: https://gitlab.uliege.be/rotare/rotare/-/issues
+    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+    % Defaults and constants
+    ALLOWED_PROPERTIES = {'cT', 'cQ', 'cP'};
+
+    if nargin < 2
+        propList = ALLOWED_PROPERTIES;
+    end
+
+    propTable = table;
+    for i = 1:length(propList)
+        propTable = [propTable, self.(propList{i})];
+    end
+    summaryTable = [self.operPts, propTable];
+
+    self.operPts;
+end
diff --git a/src/rotare.m b/src/rotare.m
index 57290c8..3bf7b9a 100644
--- a/src/rotare.m
+++ b/src/rotare.m
@@ -156,8 +156,7 @@ function [Results] = rotare(configFile)
     end
 
     % Add context to the Results and save if needed
-    Results.operPts =  array2table(operPoints, ...
-                                   'VariableNames', {'Alt', 'V_ax', 'RPM', 'Coll'});
+    Results.operPts =  array2table(operPoints);
     Results.ModExt = Mod.Ext;
     if Sim.Save.autosave
         Results.save(Sim.Save);
-- 
GitLab