Mercurial > hg > ltpda
diff m-toolbox/classes/@ssm/validate.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m-toolbox/classes/@ssm/validate.m Wed Nov 23 19:22:13 2011 +0100 @@ -0,0 +1,329 @@ +% VALIDATE Completes and checks the content a ssm object +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% DESCRIPTION: Completes and checks the content a ssm object +% checks consitency of sizes, class appartenance of fields. +% completes some missing fields. +% +% CALL: ssmin.validate +% This function is private. To check and copy an object use +% obj = ssm(old) instead +% +% INPUT VALUES : ssmin = ssm_matrix, ssm list +% OUTPUT VALUES : one ssm matrix, copy or handle to the inputs +% +% NOTE: This private method does not add history. +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function varargout = validate(varargin) + %% starting initial checks + utils.helper.msg(utils.const.msg.MNAME, ['running ', mfilename]); + + % Collect all SSMs + sys = utils.helper.collect_objects(varargin(:), 'ssm'); + + % use the caller is method flag + callerIsMethod = utils.helper.callerIsMethod; + + % Decide on a deep copy or a modify, depending on the output + sys = copy(sys, nargout); + + %% begin function body + + for i_sys = 1:numel(sys) % going through the input + + % load some data + inputsizes = sys(i_sys).inputsizes; + statesizes = sys(i_sys).statesizes; + outputsizes = sys(i_sys).outputsizes; + + %% =========== generating missing user defined fields =========== + + % data with linear system matrices + + if (numel(sys(i_sys).inputs) ~= numel(inputsizes)) + % generating inputs if it does not already exist + sys(i_sys).inputs = ssmblock.makeBlocksWithSize(inputsizes, 'input'); + else % check subfields are completely filled + for i=1:min(numel(sys(i_sys).inputs), numel(inputsizes)) + if ~ (numel(sys(i_sys).inputs(i).ports) == inputsizes(i)) + % generating level 2 plist for each input variable + sys(i_sys).inputs(i).setPortsWithSize(inputsizes(i)); + sys(i_sys).inputs(i).ports.setName('', sys(i_sys).inputs(i).name); + end + end + end + + % generating states if it does not already exist + if (numel(sys(i_sys).states) ~= numel(statesizes)) + % generating states if it does not already exist + sys(i_sys).states = ssmblock.makeBlocksWithSize(statesizes, 'state'); + else % check subfields are completely filled + for i=1:min(numel(sys(i_sys).states), numel(statesizes)) + if ~ (numel(sys(i_sys).states(i).ports) == statesizes(i)) + % generating level 2 plist for each state variable + sys(i_sys).states(i).setPortsWithSize(statesizes(i)); + sys(i_sys).states(i).ports.setName('', sys(i_sys).states(i).name); + end + end + end + + if (numel(sys(i_sys).outputs) ~= numel(outputsizes)) + % generating outputs if it does not already exist + sys(i_sys).outputs = ssmblock.makeBlocksWithSize(outputsizes, 'output'); + else % check subfields are completely filled + for i=1:min(numel(sys(i_sys).outputs), numel(outputsizes)) + if ~ (numel(sys(i_sys).outputs(i).ports) == outputsizes(i)) + % generating level 2 plist for each output variable + sys(i_sys).outputs(i).setPortsWithSize(outputsizes(i)); + sys(i_sys).outputs(i).ports.setName('', sys(i_sys).outputs(i).name); + end + end + end + + % checking diagonal content of matrices + sys(i_sys).bmats = ssm.blockMatFillDiag(sys(i_sys).bmats, statesizes, inputsizes); + sys(i_sys).cmats = ssm.blockMatFillDiag(sys(i_sys).cmats, outputsizes, statesizes); + sys(i_sys).dmats = ssm.blockMatFillDiag(sys(i_sys).dmats, outputsizes, inputsizes); + + %% =========== checking field sizes =========== + % checking compatibility with Ninputs + if ~( numel(sys(i_sys).inputs)==size(sys(i_sys).bmats,2) ... + && numel(sys(i_sys).inputs)==size(sys(i_sys).dmats,2) ... + && numel(sys(i_sys).inputs)==numel(inputsizes) ) + error(['error in ssm ',sys(i_sys).name,' because there are ',... + num2str(size(sys(i_sys).bmats,2)),' columns in B , ',... + num2str(size(sys(i_sys).dmats,2)),' columns in D , ',... + num2str(numel(sys(i_sys).inputs)),' inputs, ',... + num2str(numel(inputsizes)),' inputsizes'] ); + end + + % checking compatibility with Nss + if ~( numel(sys(i_sys).states)==size(sys(i_sys).amats,2) ... + && numel(sys(i_sys).states)==size(sys(i_sys).amats,1) ... + && numel(sys(i_sys).states)==size(sys(i_sys).bmats,1) ... + && numel(sys(i_sys).states)==size(sys(i_sys).cmats,2) ... + && numel(sys(i_sys).states)==numel(statesizes) ) + error(['error in ssm ',sys(i_sys).name,' because there are ',... + num2str(size(sys(i_sys).amats,2)),' columns in A, ',... + num2str(size(sys(i_sys).amats,1)),' lines in A, ',... + num2str(size(sys(i_sys).bmats,1)),' lines in B, ',... + num2str(size(sys(i_sys).cmats,2)),' columns in C, ',... + num2str(numel(sys(i_sys).states)),' states, ',... + num2str(numel(statesizes)),' sssizes'] ); + end + + % checking compatibility with Noutputs + if ~( numel(sys(i_sys).outputs)==size(sys(i_sys).cmats,1) ... + && numel(sys(i_sys).outputs)==size(sys(i_sys).dmats,1) ... + && numel(sys(i_sys).outputs)==numel(outputsizes) ) + error(['error in ssm ',sys(i_sys).name,' because there are ',... + num2str(size(sys(i_sys).cmats,1)),' lines in C, ',... + num2str(size(sys(i_sys).dmats,1)),' lines in D, ',... + num2str(numel(sys(i_sys).outputs)),' outputs, ',... + num2str(numel(outputsizes)),' outputsizes'] ); + end + + % Checking compatibility with Inputsizes + for i=1:numel(sys(i_sys).inputs) % check between *inputsizes* and *inputs* plist + if ~( inputsizes(i) == numel(sys(i_sys).inputs(i).ports) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the input number ', num2str(i),... + ' named ', sys(i_sys).inputs(i).name, ... + ' and of size ', num2str(inputsizes(i)), ... + ' has a port of length ', num2str(numel(sys(i_sys).inputs(i).ports)) ]); + end + if inputsizes(i) == 0 % send a warning in case an input is empty + if ~callerIsMethod + str=['warning, input named ',sys(i_sys).inputs(i).name,... + ' has all matrices empty, should be deleted'] ; + utils.helper.msg(utils.const.msg.MNAME,str); + end + end + for j=1:numel(sys(i_sys).outputs) % check between *inputsizes* and D matrix content + if ~isequal(sys(i_sys).dmats{j,i}, []) + if ~( inputsizes(i) == size(sys(i_sys).dmats{j,i},2) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the input number ', num2str(i),... + ' named ', sys(i_sys).inputs(i).name, ... + ' and of size ', num2str(inputsizes(i)), ... + ' has a D matrix of width ', num2str(size(sys(i_sys).dmats{j,i},2)) ]); + end + end + end + for j=1:numel(sys(i_sys).states) % check between *inputsizes* and B matrix content + if ~isequal(sys(i_sys).bmats{j,i}, []) + if ~( inputsizes(i) == size(sys(i_sys).bmats{j,i},2) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the input number ', num2str(i),... + ' named ', sys(i_sys).inputs(i).name, ... + ' and of size ', num2str(inputsizes(i)), ... + ' has a B matrix of width ', num2str(size(sys(i_sys).bmats{j,i},2)) ]); + end + end + end + end + + % Checking compatibility with Outputsizes + for i=1:numel(sys(i_sys).outputs) % check between *outputsizes* and *outputs* plist + if ~( outputsizes(i) == numel(sys(i_sys).outputs(i).ports) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the output number ', num2str(i),... + ' named ', sys(i_sys).outputs(i).name, ... + ' and of size ', num2str(outputsizes(i)), ... + ' has a port of length ', num2str(numel(sys(i_sys).outputs(i).ports)) ]); + end + if outputsizes(i) == 0 % send a warning in case an output is empty + if ~callerIsMethod + str=['warning, output named ',sys(i_sys).outputs(i).name,... + ' has all matrices empty, should be deleted'] ; + utils.helper.msg(utils.const.msg.MNAME,str); + end + end + for j=1:numel(sys(i_sys).inputs) % check between *outputsizes* and D matrix content + if ~isequal(sys(i_sys).dmats{i,j}, []) + if ~( outputsizes(i) == size(sys(i_sys).dmats{i,j},1) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the output number ', num2str(i),... + ' named ', sys(i_sys).outputs(i).name, ... + ' and of size ', num2str(outputsizes(i)), ... + ' has a D matrix of height ', num2str(size(sys(i_sys).dmats{i,j},1)) ]); + end + end + end + for j=1:numel(sys(i_sys).states) % check between *outputsizes* and C matrix content + if ~isequal(sys(i_sys).cmats{i,j}, []) + if ~( outputsizes(i) == size(sys(i_sys).cmats{i,j},1) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the output number ', num2str(i),... + ' named ', sys(i_sys).outputs(i).name, ... + ' and of size ', num2str(outputsizes(i)), ... + ' has a C matrix of height ', num2str(size(sys(i_sys).cmats{i,j},1)) ]); + end + end + end + end + + % Checking compatibility with sssizes + for i=1:numel(sys(i_sys).states) % check between *statesizes* and *states* plist + if ~( statesizes(i) == numel(sys(i_sys).states(i).ports) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the state number ', num2str(i),... + ' named ', sys(i_sys).states(i).name, ... + ' and of size ', num2str(statesizes(i)), ... + ' has a port of length ', num2str(numel(sys(i_sys).states(i).ports)) ]); + end + if statesizes(i) == 0 % send a warning in case an state is empty + if ~callerIsMethod + str=['warning, state named ',sys(i_sys).states(i).name,... + ' has all matrices empty, should be deleted'] ; + utils.helper.msg(utils.const.msg.MNAME,str); + end + end + for j=1:numel(sys(i_sys).inputs) % check between *sssizes* and B matrix content + if ~isequal(sys(i_sys).bmats{i,j}, []) + if ~( statesizes(i) == size(sys(i_sys).bmats{i,j},1) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the state space number ', num2str(i),... + ' named ', sys(i_sys).states(i).name, ... + ' and of size ', num2str(statesizes(i)), ... + ' has a B matrix of height ', num2str(size(sys(i_sys).bmats{i,j},1)) ]); + end + end + end + for j=1:numel(sys(i_sys).states) % check between *sssizes* and A matrix content + if ~isequal(sys(i_sys).amats{i,j}, []) + if ~( statesizes(i) == size(sys(i_sys).amats{i,j},1) ... + && statesizes(j) == size(sys(i_sys).amats{i,j},2) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the state space position (', num2str(i), ',' , num2str(j),... + ') named ', sys(i_sys).states(i).name, ' and ', sys(i_sys).states(i).name, ... + ' and of size ', num2str([statesizes(i),statesizes(j)] ), ... + ' has a A matrix of size ', num2str(size(sys(i_sys).amats{i,j})) ]); + end + end + end + for j=1:numel(sys(i_sys).outputs) % check between *sssizes* and C matrix content + if ~isequal(sys(i_sys).cmats{j,i}, []) + if ~( statesizes(i) == size(sys(i_sys).cmats{j,i},2) ) + error(['error in ssm ', sys(i_sys).name, ... + ' because the state space number ', num2str(i),... + ' named ', sys(i_sys).states(i).name, ... + ' and of size ', num2str(statesizes(i)), ... + ' has a C matrix of width ', num2str(size(sys(i_sys).cmats{j,i},2)) ]); + end + end + end + + + + %% =========== checking redundancies =========== + % ADD CHECK FOR VARIABLE NAME REDUNDANCIES + + % Not necessary anymore for model parameters !!! + + %% =========== checking field types =========== + + Fields = {... + 'amats' 'bmats' 'cmats' 'dmats' 'isnumerical' 'timestep'... + 'inputs' ... + 'states' ... + 'outputs' ... + 'params' 'numparams' }; + Classes = {... + 'cellDoubleSym' 'cellDoubleSym' 'cellDoubleSym' 'cellDoubleSym' 'logical' 'double'... + 'ssmblock' ... + 'ssmblock' ... + 'ssmblock' ... + 'plist' 'plist'... + }; + + for f = [Fields ; Classes] + fieldcontent = sys(i_sys).(f{1}); + if strcmpi(f{2},'double') + if ~( isa(fieldcontent,'double') ) + error(['error because in ssm ',sys(i_sys).name,... + ' because field ', f{1},... + ' is of type ',class(fieldcontent), ' instead of ''double'' ']); + end + elseif strcmpi(f{2},'cellDoubleSym') % case where both double and symbolic classes are allowed inside a cell array + for i_input = 1:numel(fieldcontent) + if ~( isa(fieldcontent{i_input},'double') || isa(fieldcontent{i_input},'sym') ) + error(['error because in ssm ',sys(i_sys).name,' because element ',num2str(i_input),... + ' of field ', f{1},' is of type ',class(fieldcontent),... + ' instead of ''double'' or ''sym'' ']); + end + end + elseif strcmpi(f{2},'ssmblock') + if ~( isa(fieldcontent,'ssmblock') ) + % if the field is not a plist + error(['error because in ssm ',sys(i_sys).name,... + ' because field ', f{1},... + ' is of type ',class(fieldcontent), ' instead of ''ssmblock'' ']); + end + elseif strcmpi(f{2},'plist') + if ~( isa(fieldcontent,'plist') ) + % if the field is not a plist + error(['error because in ssm ',sys(i_sys).name,... + ' because field ', f{1},... + ' is of type ',class(fieldcontent), ' instead of ''plist'' ']); + end + elseif strcmpi(f{2},'logical') + if ~( isa(fieldcontent,'logical') ) + error(['error because in ssm ',sys(i_sys).name,... + ' because field ', f{1},... + ' is of type ',class(fieldcontent), ' instead of ''logical'' ']); + end + else + if ~isa(fieldcontent,f{2}) + error(['error because in ssm ',sys(i_sys).name,' because field ',... + f{1},' is of type ',class(fieldcontent),' instead of ', f{2}]); + end + end + end + end + if nargout > 0 + varargout = {sys}; + end + end