comparison m-toolbox/classes/@ssm/modifyTimeStep.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 % MODIFYTIMESTEP modifies the timestep of a ssm object
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %
4 % DESCRIPTION: MODIFYTIMESTEP modifies the timestep of a ssm object, and updates
5 % the A and B matrices supposing there is no aliasing.
6 %
7 % CALL: sys = modifyTimeStep(sys,pl)
8 %
9 % INPUTS:
10 % sys - (array of) ssm objects
11 % pl - A plist or numeric value giving new timestep value (param name 'newtimestep')
12 %
13 % OUTPUTS:
14 % sys - (array of) ssm
15 %
16 % <a href="matlab:utils.helper.displayMethodInfo('ssm', 'modifyTimeStep')">Parameters Description</a>
17 %
18 % VERSION: $Id: modifyTimeStep.m,v 1.11 2011/04/08 08:56:23 hewitson Exp $
19 %
20 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
21
22 function varargout = modifyTimeStep(varargin)
23
24 %% Check if this is a call for parameters
25 if utils.helper.isinfocall(varargin{:})
26 varargout{1} = getInfo(varargin{3});
27 return
28 end
29
30 %% send starting message
31 import utils.const.*
32 utils.helper.msg(msg.PROC3, 'running %s/%s', mfilename('class'), mfilename);
33
34 %% collecting input
35 in_names = cell(size(varargin));
36 for ii = 1:nargin,in_names{ii} = inputname(ii);end
37
38 [sys, ssm_invars, rest] = utils.helper.collect_objects(varargin(:), 'ssm', in_names);
39 [pl, invars2, rest] = utils.helper.collect_objects(rest(:), 'plist');
40 % override with a numeric input value
41 if ~isempty(rest)
42 % if the user inputs a single numerical value, we use it
43 if isnumeric(rest{1}) && numel(rest{1}) == 1
44 if ~isa(pl, 'plist') % perhaps we dont' have a plist yet
45 pl = plist();
46 end
47 pl.pset('newtimestep', rest{1}); % set newtimestep
48 else
49 pl = combine(pl, plist(rest{:}));
50 end
51 end
52 pl = combine(pl, getDefaultPlist());
53
54 %%% Internal call: Only one object + don't look for a plist
55 internal = strcmp(varargin{end}, 'internal');
56
57 %% dealing with user custom inputs
58
59 Nsys = numel(sys);
60
61 %% begin function body
62
63 %% building output depending on options
64 sys = copy(sys,nargout);
65 newtimestep = find(pl,'newtimestep');
66 outputAntiAlias = find(pl, 'outputAntiAlias');
67 if numel(newtimestep)~=1
68 error('parameter "newtimestep" should be of size 1x1')
69 end
70
71 for i = 1:Nsys
72 if ~sys(i).isnumerical
73 error(['error in modifTimeStep because system "',sys(i).name, '" should be numerical to be modified' ]);
74 end
75
76 %% retrieving input data
77 timestep = sys(i).timestep;
78 sssizes = sys(i).sssizes;
79 inputsizes = sys(i).inputsizes;
80
81 amat = ssm.blockMatFusion(sys(i).amats, sssizes, sssizes);
82 bmat = ssm.blockMatFusion(sys(i).bmats, sssizes, inputsizes);
83 if outputAntiAlias
84 outputsizes = sys(i).outputsizes;
85 cmat = ssm.blockMatFusion(sys(i).cmats, outputsizes, sssizes);
86 dmat = ssm.blockMatFusion(sys(i).dmats, outputsizes, inputsizes);
87 end
88
89 %% take different actions depending on old and new timestep
90 if timestep == newtimestep
91 action = 'DoNothing';
92 elseif newtimestep == 0
93 action = 'MakeContinuous';
94 str = 'warning because system is sent back to continuous time';
95 utils.helper.msg(utils.const.msg.MNAME, str);
96 elseif timestep == 0
97 action = 'Discretize';
98 elseif floor(newtimestep/timestep) == newtimestep/timestep
99 action = 'TakeMultiple';
100 elseif newtimestep > timestep
101 action = 'MakeLonger';
102 else
103 action = 'MakeShorter';
104 str = 'warning because system is sent back to shorter time step';
105 utils.helper.msg(utils.const.msg.MNAME, str);
106 end
107
108 %% proceed with matrix modifications
109
110 amat_input = zeros(size(amat));
111 if isequal(action,'DoNothing')
112 %% same timestep : do nothing
113 amat_2 = amat;
114 bmat_2 = bmat;
115 elseif isequal(action,'Discretize')
116 %% from continuous to discrete
117 amat_2 = expm(amat * newtimestep);
118 amat_input = ExpInt(amat, newtimestep);
119 bmat_2 = real(amat_input * bmat);
120 if outputAntiAlias
121 cmat_2 = cmat * 0.5*(eye(size(amat_2)) + amat_2);
122 dmat_2 = dmat + cmat*0.5*bmat_2;
123 sys(i).cmats = ssm.blockMatRecut(real(cmat_2), outputsizes, sssizes);
124 sys(i).dmats = ssm.blockMatRecut(real(dmat_2), outputsizes, inputsizes);
125 end
126 elseif isequal(action,'MakeContinuous')
127 %% for discrete to continuous
128 [V, E] = eig(amat);
129 amat_2 = real(V * (diag(log(diag(E)))/timestep) * V^(-1));
130 amat_input = ExpInt(amat_2, timestep);
131 amat_input_inv = (amat_input)^(-1);
132 bmat_2 = real(amat_input_inv * bmat);
133 if outputAntiAlias
134 cmat_2 = cmat * (0.5*(eye(size(amat)) + amat))^-1;
135 dmat_2 = dmat - cmat_2*0.5*bmat;
136 sys(i).cmats = ssm.blockMatRecut(real(cmat_2), outputsizes, sssizes);
137 sys(i).dmats = ssm.blockMatRecut(real(dmat_2), outputsizes, inputsizes);
138 end
139 elseif isequal(action,'TakeMultiple')
140 %% discrete to discrete with a multiple
141 multiple = newtimestep/timestep;
142 amat_2 = amat^multiple;
143 for i_step = 1:multiple
144 amat_input = amat_input + amat^(i_step-1);
145 end
146 bmat_2 = real(amat_input * bmat);
147 if outputAntiAlias
148 cmat_0 = cmat * (0.5*(eye(size(amat)) + amat))^-1;
149 cmat_2 = cmat_0 * 0.5*(eye(size(amat_2)) + amat_2);
150 dmat_2 = dmat + cmat_0*0.5*bmat_2 - cmat_0*0.5*bmat;
151 sys(i).cmats = ssm.blockMatRecut(real(cmat_2), outputsizes, sssizes);
152 sys(i).dmats = ssm.blockMatRecut(real(dmat_2), outputsizes, inputsizes);
153 end
154 elseif isequal(action,'MakeLonger')||isequal(action,'MakeShorter')
155 %% discrete to discrete with no multiple relationship
156 [V, E] = eig(amat);
157 amat_c = real(V * (diag(log(diag(E)))/timestep) * V^(-1));
158 amat_2 = expm( amat * newtimestep/timestep);
159 amat_input_1 = ExpInt(amat_c, timestep);
160 amat_input_2 = ExpInt(amat_c, newtimestep);
161 bmat_2 = real(amat_input_2 * (amat_input_1)^(-1) * bmat);
162 if outputAntiAlias
163 cmat_0 = cmat * (0.5*(eye(size(amat)) + amat))^-1;
164 cmat_2 = cmat_0 * 0.5*(eye(size(amat_2)) + amat_2);
165 dmat_2 = dmat + cmat_0*0.5*bmat_2 - cmat_0*0.5*bmat;
166 sys(i).cmats = ssm.blockMatRecut(real(cmat_2), outputsizes, sssizes);
167 sys(i).dmats = ssm.blockMatRecut(real(dmat_2), outputsizes, inputsizes);
168 end
169 end
170 amat_2 = real(amat_2);
171 bmat_2 = real(bmat_2);
172 %% Save Matrix modifications
173 sys(i).amats = ssm.blockMatRecut(amat_2, sssizes, sssizes);
174 sys(i).bmats = ssm.blockMatRecut(bmat_2, sssizes, inputsizes);
175 sys(i).timestep = newtimestep;
176 if ~internal
177 sys(i).addHistory(getInfo('None'), pl, ssm_invars(i), sys(i).hist );
178 end
179 end
180 if nargout == numel(sys)
181 for ii = 1:numel(sys)
182 varargout{ii} = sys(ii);
183 end
184 else
185 varargout{1} = sys;
186 end
187 end
188
189 function A_int = ExpInt(A, t)
190 niter = 35;
191 A1 = A*t;
192 A2 = eye(size(A))*t;
193 A_int = zeros(size(A));
194 for i=1:niter
195 A_int = A_int + A2;
196 A2 = A1*A2/(i+1);
197 end
198 end
199
200
201 %--------------------------------------------------------------------------
202 % Get Info Object
203 %--------------------------------------------------------------------------
204 function ii = getInfo(varargin)
205
206 if nargin == 1 && strcmpi(varargin{1}, 'None')
207 sets = {};
208 pl = [];
209 else
210 sets = {'Default'};
211 pl = getDefaultPlist;
212 end
213 % Build info object
214 ii = minfo(mfilename, 'ssm', 'ltpda', utils.const.categories.op, '$Id: modifyTimeStep.m,v 1.11 2011/04/08 08:56:23 hewitson Exp $', sets, pl);
215 end
216
217 %--------------------------------------------------------------------------
218 % Get Default Plist
219 %--------------------------------------------------------------------------
220 function pl = getDefaultPlist()
221 pl = plist();
222
223 p = param({'newtimestep', 'Specify the desired new timestep.'}, paramValue.EMPTY_DOUBLE);
224 pl.append(p);
225
226 p = param({'outputAntiAlias', 'Uses a linear averaging method to compute the systems output.'}, paramValue.TRUE_FALSE);
227 pl.append(p);
228
229 end
230
231