Mercurial > hg > ltpda
comparison m-toolbox/classes/@ssm/assemble.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0afece42f48 |
---|---|
1 % assembles embedded subsytems, with exogenous inputs | |
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
3 % | |
4 % DESCRIPTION: assemble assembles embedded subsytems, closes loop | |
5 % (endogenous inputs disappear) leaving outputs and exogenous | |
6 % inputs. SSM content is copied. | |
7 % | |
8 % CALL: sys = ltpda_ss_assemble(sys_array) | |
9 % | |
10 % INPUTS: sys_array - array or list of systems to assemble | |
11 % | |
12 % OUTPUTS: sys - assembled system | |
13 % | |
14 % <a href="matlab:utils.helper.displayMethodInfo('ssm', 'assemble')">Parameters Description</a> | |
15 % | |
16 % VERSION: $Id: assemble.m,v 1.60 2011/04/08 08:56:22 hewitson Exp $ | |
17 % | |
18 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
19 | |
20 function varargout = assemble( varargin ) | |
21 | |
22 %% Check if this is a call for parameters | |
23 if utils.helper.isinfocall(varargin{:}) | |
24 varargout{1} = getInfo(varargin{3}); | |
25 return | |
26 end | |
27 | |
28 %%% Internal call: Only one object + don't look for a plist | |
29 internal = strcmp(varargin{end}, 'internal'); | |
30 | |
31 %% send starting message | |
32 import utils.const.* | |
33 utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename); | |
34 | |
35 %% collecting input | |
36 in_names = cell(size(varargin)); | |
37 for ii = 1:nargin,in_names{ii} = inputname(ii);end | |
38 | |
39 % Collect all SSMs and plists | |
40 [sys, ssm_invars] = utils.helper.collect_objects(varargin(:), 'ssm', in_names); | |
41 | |
42 Nsys = numel(sys); | |
43 | |
44 % We want to force a copy - this is not a modify method | |
45 if nargout ~= 1 | |
46 error('### assemble cannot be used as a modifier. Please give exactly one output variable.'); | |
47 end | |
48 | |
49 %% Decide on a deep copy or a modify, depending on the output | |
50 sys_array = copy(sys, true); | |
51 | |
52 %% begin function body | |
53 sys_out = ssm; | |
54 | |
55 %% checking there is not problem with the timesteps | |
56 | |
57 for i=2:Nsys | |
58 if ~(sys_array(i-1).timestep == sys_array(i).timestep) | |
59 error(['At least two ssm have incompatible timestep fields : ' ... | |
60 num2str(sys_array(i-1).timestep) ' for ''' sys_array(i-1).name ''' and '... | |
61 num2str(sys_array(i).timestep) ' for ''' sys_array(i).name '''' ]); | |
62 end | |
63 end | |
64 | |
65 %% merging ss data : ss* output* *input | |
66 names = cell(1,0); | |
67 inputs = ssmblock.initObjectWithSize(1,0); | |
68 outputs = ssmblock.initObjectWithSize(1,0); | |
69 states = ssmblock.initObjectWithSize(1,0); | |
70 params = plist; | |
71 numparams = plist; | |
72 | |
73 sssizes = zeros(1,0); | |
74 ssposition = zeros(1,0); | |
75 outputsizes = zeros(1,0); | |
76 outputposition = zeros(1,0); | |
77 inputsizes = zeros(1,0); | |
78 inputposition = zeros(1,0); | |
79 | |
80 for i=1:Nsys | |
81 params.combine(sys_array(i).params); | |
82 numparams.combine(sys_array(i).numparams); | |
83 inputs = inputs.combine(sys_array(i).inputs, false) ; | |
84 outputs = [outputs, sys_array(i).outputs] ; | |
85 states = [states, sys_array(i).states] ; | |
86 | |
87 names = [names sys_array(i).name ]; %#ok<*AGROW> | |
88 sssizes = [sssizes sys_array(i).sssizes ]; | |
89 ssposition = [ssposition i*ones(1,sys_array(i).Nss) ]; | |
90 outputsizes = [outputsizes sys_array(i).outputsizes ]; | |
91 outputposition = [outputposition i*ones(1,sys_array(i).Noutputs) ]; | |
92 inputsizes = [inputsizes sys_array(i).inputsizes ]; | |
93 inputposition = [inputposition i*ones(1,sys_array(i).Ninputs) ]; | |
94 end | |
95 | |
96 %% data already good to store | |
97 sys_out.params = params; | |
98 sys_out.numparams = numparams; | |
99 sys_out.outputs = outputs; | |
100 sys_out.states = states; | |
101 | |
102 %% non redundancy checks : not necessary anymore on the I/O fields | |
103 % to be added on subfields ?? | |
104 | |
105 %% building A, and C matrices | |
106 amats = {}; | |
107 cmats = {}; | |
108 for i=1:Nsys | |
109 Namats = size(amats,2); | |
110 amats = ... | |
111 [amats cell(Namats, sys_array(i).Nss) ; ... | |
112 cell(sys_array(i).Nss, Namats) sys_array(i).amats ] ; | |
113 cmats = ... | |
114 [cmats cell(size(cmats,1), sys_array(i).Nss) ; ... | |
115 cell(sys_array(i).Noutputs, size(cmats,2)) sys_array(i).cmats ] ; | |
116 end | |
117 | |
118 %% construction of B_xx and D_xx matrices | |
119 inputs_ext = ssmblock.initObjectWithSize(1,0); | |
120 | |
121 B_in = cell( numel(sssizes), numel(outputsizes) ); | |
122 D_in = cell( numel(outputsizes), numel(outputsizes) ); | |
123 B_ext = cell( numel(sssizes), 0 ); | |
124 D_ext = cell( numel(outputsizes), 0 ); | |
125 inputsizes = []; | |
126 Ninputs = 0; | |
127 for i_sys=1:Nsys | |
128 for i_input = 1:numel(sys(i_sys).inputs) | |
129 % current input of a subsystem | |
130 input_name = sys_array(i_sys).inputs(i_input).name; | |
131 % does the input match a local output ? | |
132 [pos_output, sum_output] = findBlockWithNames(outputs, input_name, false); | |
133 % check it is not already in the external input list | |
134 [pos_input, sum_input] = findBlockWithNames(inputs_ext, input_name, false); | |
135 | |
136 if sum_output>0 | |
137 %% if it is an internal input | |
138 % put at the correct place in the B_in and D_in matrices | |
139 B_in(ssposition==i_sys, pos_output) = sys_array(i_sys).bmats(:,i_input); | |
140 D_in(outputposition==i_sys, pos_output) = sys_array(i_sys).dmats(:,i_input); | |
141 % checking sizes match | |
142 for i_out = pos_output | |
143 Nin = sys_array(i_sys).inputs(i_input).Nports; | |
144 if ~( Nin == outputs(i_out).Nports) | |
145 error(['I/O sizes not matching between input "' sys_array(i_sys).inputs(i_input).name , ... | |
146 '" of system "' sys_array(i_sys).name ' of size ' num2str(Nin) ... | |
147 '" and the output of size ' num2str(outputs(i_out).Nports) ... | |
148 ' of the system "' sys_array(outputposition(pos_output)).name '"'] ) | |
149 end | |
150 end | |
151 else | |
152 %% if it is external | |
153 % if it is not there, add to the input plist | |
154 if sum_input == 0 | |
155 % extend the size of the input fields | |
156 inputs_ext = [inputs_ext sys_array(i_sys).inputs(i_input)]; | |
157 inputsizes = [inputsizes sys_array(i_sys).inputsizes(i_input)]; | |
158 B_ext = [B_ext cell(size(B_ext,1),1)]; | |
159 D_ext = [D_ext cell(size(D_ext,1),1)]; | |
160 Ninputs = Ninputs +1; | |
161 | |
162 pos_input = numel(inputs_ext); | |
163 end | |
164 % put at the correct place in the B_ext and D_ext matrices | |
165 B_ext(ssposition==i_sys, pos_input) = sys_array(i_sys).bmats(:,i_input); | |
166 D_ext(outputposition==i_sys, pos_input) = sys_array(i_sys).dmats(:,i_input); | |
167 end | |
168 end | |
169 end | |
170 sys_out.inputs = inputs_ext; | |
171 | |
172 B_ext = ssm.blockMatFillDiag(B_ext, sssizes, inputsizes); | |
173 D_ext = ssm.blockMatFillDiag(D_ext, outputsizes, inputsizes); | |
174 B_in = ssm.blockMatFillDiag(B_in, sssizes, outputsizes); | |
175 D_in = ssm.blockMatFillDiag(D_in, outputsizes, outputsizes); | |
176 cmats = ssm.blockMatFillDiag(cmats, outputsizes, sssizes); | |
177 %% flattening and getting constant feedthrough | |
178 D_in_f = ssm.blockMatFusion(D_in, outputsizes,outputsizes); | |
179 G = (eye(size(D_in_f)) - D_in_f); | |
180 if isnumeric(G) | |
181 id_D_inv = inv(G); | |
182 else | |
183 id_D_inv = evalin(symengine, ['inverse(' char(G) ')']); | |
184 end | |
185 id_D_inv = ssm.blockMatRecut(id_D_inv, outputsizes, outputsizes); | |
186 | |
187 sys_out.amats = ssm.blockMatAdd(amats, ssm.blockMatMult(B_in, ssm.blockMatMult(id_D_inv, cmats, outputsizes, sssizes) , sssizes , sssizes )); | |
188 sys_out.bmats = ssm.blockMatAdd(B_ext, ssm.blockMatMult(B_in, ssm.blockMatMult(id_D_inv, D_ext, outputsizes, inputsizes) , sssizes , inputsizes )); | |
189 sys_out.cmats = ssm.blockMatMult(id_D_inv, cmats, outputsizes , sssizes ); | |
190 sys_out.dmats = ssm.blockMatMult(id_D_inv, D_ext, outputsizes , inputsizes ); | |
191 | |
192 %% building new name and strings | |
193 name = 'assemble( '; | |
194 for i = 1:Nsys | |
195 if i==1 | |
196 name = [name, sys_array(i).name ]; %#ok<AGROW> | |
197 elseif i<=Nsys | |
198 name = [name,' + ', sys_array(i).name]; %#ok<AGROW> | |
199 end | |
200 end | |
201 name = [name ' )']; | |
202 sys_out.name = name; | |
203 | |
204 %% getting timestep and checking consitency | |
205 for i=1:Nsys | |
206 if i == 1 | |
207 sys_out.timestep = sys_array(i).timestep; | |
208 elseif ~ sys_out.timestep == sys_array(i).timestep | |
209 error(['error because systems 1 and ',num2str(i),... | |
210 ' named ',sys_array(i).name,' and ',sys_array(i).name,... | |
211 ' have different timesteps :',... | |
212 num2str(sys_array(i).timestep),' and ',num2str(sys_array(i).timestep) ]); | |
213 end | |
214 end | |
215 | |
216 %% setting history and validating | |
217 if ~internal | |
218 sys_out.addHistory(ssm.getInfo(mfilename), plist , ssm_invars(:), [sys_array(:).hist] ); | |
219 validate(sys_out); | |
220 end | |
221 | |
222 %% parsing output | |
223 varargout = {sys_out}; | |
224 end | |
225 | |
226 | |
227 | |
228 | |
229 | |
230 %-------------------------------------------------------------------------- | |
231 % Get Info Object | |
232 %-------------------------------------------------------------------------- | |
233 function ii = getInfo(varargin) | |
234 | |
235 if nargin == 1 && strcmpi(varargin{1}, 'None') | |
236 sets = {}; | |
237 pl = []; | |
238 else | |
239 sets = {'Default'}; | |
240 pl = getDefaultPlist; | |
241 end | |
242 % Build info object | |
243 ii = minfo(mfilename, 'ssm', 'ltpda', utils.const.categories.op, '$Id: assemble.m,v 1.60 2011/04/08 08:56:22 hewitson Exp $', sets, pl); | |
244 ii.setModifier(false); | |
245 ii.setArgsmin(2); | |
246 end | |
247 | |
248 %-------------------------------------------------------------------------- | |
249 % Get Default Plist | |
250 %-------------------------------------------------------------------------- | |
251 function pl = getDefaultPlist() | |
252 pl = plist(); | |
253 end | |
254 |