rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
dare_advection_diffusion.m
2 % Implicit Euler discretization of a finite-difference convection-diffusion
3 % model.
4 %
5 % This model is constructed in such a way, that it can follow a given
6 % trajectory - or at least it tries to follow it. Use the SIMULATE function
7 % to simulate!
8 %
9 % Andreas Schmidt, 2016
10 
11  properties
12  mu = [1 1 3];
13  mu_names = {'mu_diffusion', 'mu_adv_y', 'lambda_tracking'};
14  mu_ranges = { [0.1, 2], [0,10], [1, 10]};
15 
16  n0;
17  dt = 0.05;
18  end
19 
20  methods
21  function this = dare_advection_diffusion(n)
22  this.n = n*n + 1;
23  this.n0 = n;
24  this.m = 1;
25  this.p = 1;
26 
27  this.RB_orthonormalize_E = false;
28  this.RB_error_indicator = 'normalized_residual';
29  this.RB_pod_tolerance = 0.85;
30  this.RB_greedy_tolerance = 1e-3;
31  this.RB_M_train = ParameterSampling.Uniform(6);
32  end
33 
34  function r = E_comp(this)
35  r = {speye(this.n), ...
36  blkdiag(this.my_2d_matrix(this.n0, '0', '0', '0', '1'),0) ...
37  blkdiag(this.my_2d_matrix(this.n0, '0', '-1', '0', '0'),0)};
38  end
39  function r = E_coeff(this)
40  r = [1, -this.dt*this.mu(1), -this.dt*this.mu(2)];
41  end
42 
43  function r = A_comp(this)
44  C = this.C();
45  r = {[speye(this.n-1), zeros(this.n-1,1); -C 1]};
46  end
47  function r= A_coeff(this)
48  r = 1;
49  end
50 
51  function r = B_comp(this)
52  v = this.my_2d_vector(this.n0, '( (x>=0.2)&(x<=0.6)&(y>=0.4)&(y<=0.6) )');
53  r = {[10*1/numel(nonzeros(v))*v;0]};
54  end
55  function r = B_coeff(this)
56  r = this.dt;
57  end
58 
59  function r = C(this)
60  v = this.my_2d_vector(this.n0, '1')';
61  r = v/numel(nonzeros(v));
62  end
63 
64  function r = C_comp(this)
65  r = {[this.C(), 0], [zeros(1,this.n-1) 1]};
66  end
67  function r = C_coeff(this)
68  r = [1 this.mu(3)];
69  end
70  function r = R_coeff(this)
71  r = 0.01;
72  end
73 
74  function s = get_ss(this, model_data, dsim)
75  % GET_SS Get the state space model for simulation purpose
76  % If dsim is provided, a closed-loop simulation is performed.
77  [E,A,B,C,~,R] = this.assemble(model_data);
78  outputName = {'y(t)', 'u(t)'};
79  C = this.C();
80 
81  if exist('dsim','var') && ~isempty(dsim)
82  K = inv(R+B'*dsim.Z*dsim.Z'*B)*B'*dsim.Z*dsim.Z'*A;
83  A = A - B*K;
84  C = [C 0; K];
85  else
86  C = [C 0; 0*C];
87  end
88 
89  s = dss(A, [B, [zeros(this.n-1,1); 1]], C, [], full(E),this.dt, ...
90  'InputName', {'u(t)', 'r(t)'}, ...
91  'OutputName', outputName);
92  end
93 
94  function [t,y,u,r,x] = simulate(this, model_data, T, r, sim, x0)
95  % SIMULATE - Simulate the system for a given time
96  % T ...... final time
97  % r ...... reference value or vector
98  % sim .... simulation used for feedback
99  %
100  % This function returns the following vectors:
101  % t ....... time span for simulation
102  % y ....... output value
103  % u ....... control signal
104  % r ....... the reference signal
105  % x .......
106  if nargin < 5, sim = []; end
107  if nargin < 6, x0 = zeros(this.n,1); end
108 
109  t = (0:this.dt():T)';
110  if isa(r, 'function_handle'), r = r(t); end
111  if length(r) == 1, r = ones(length(t),1)*r; end
112 
113  ss = this.get_ss(model_data, sim);
114 
115  [y_,t,x] = lsim(ss, [0*t, r], t, x0);
116  y = y_(:,1);
117  u = y_(:,2);
118  end
119 
120  end
121 
122  methods(Access=protected)
123  function [A, name] = my_2d_matrix(this,n0,fx_str,fy_str,g_str,mu_str)
124  %
125  % Generates the stiffness matrix A for the finite difference
126  % discretization (equidistant grid) of the PDE
127  %
128  % mu* laplace(u) - fx du/dx - fy du/dy - g u = r.h.s. on Omega
129  %
130  % u = 0 on dOmega
131  %
132  % Omega = (0,1)x(0,1) (unit square).
133  %
134  % This function is just used as an easy way to generate test problems
135  % rather than to solve PDEs.
136  %
137  % Calling sequence:
138  %
139  % [A, name] = fdm_2d_matrix( n0, fx_str, fy_str, g_str )
140  %
141  % Input:
142  %
143  % n0 number of inner grid points in each dimension;
144  % fx_str string describing the function fx in the space variables
145  % 'x' and 'y', e.g., fx_str = 'sin(x+2*y)+3';
146  % fy_str string describing the function fy in the space variables
147  % 'x' and 'y';
148  % g_str string describing the function g in the space variables
149  % 'x' and 'y'.
150  %
151  % Output:
152  %
153  % A n-x-n sparse stiffness matrix, where n = n0^2;
154  % name string describing the problem.
155  %
156  %
157  % LYAPACK 1.0 (Thilo Penzl, May 1999)
158 
159  % Input data not completely checked!
160 
161  na = nargin;
162 
163  if na~=5
164  mu_str = '1';
165  end
166 
167  name = ['FDM-2D: fx=',fx_str,'; fy=',fy_str,'; g=',g_str];
168 
169  n2 = n0*n0;
170 
171  h = 1.0/(n0+1);
172 
173  h2 = h*h;
174 
175  t1 = 4.0/h2;
176  t2 = -1.0/h2;
177  t3 = 1.0/(2.0*h);
178 
179  len = 5*n2-4*n0;
180  I = zeros(len,1);
181  J = zeros(len,1);
182  S = zeros(len,1);
183  ptr = 0; % Pointer
184  i = 0; % Row Number
185 
186  for iy = 1:n0
187  y = iy*h;
188  for ix = 1:n0
189  x = ix*h;
190 
191  i = i+1;
192  fxv = eval(fx_str);
193  fyv = eval(fy_str);
194  gv = eval(g_str);
195  mu = eval(mu_str);
196 
197  if iy>1
198  ptr = ptr+1; % A(i,i-n)
199  I(ptr) = i;
200  J(ptr) = i-n0;
201  S(ptr) = mu*t2-fyv*t3;
202  end
203 
204  if ix>1
205  ptr = ptr+1; % A(i,i-1)
206  I(ptr) = i;
207  J(ptr) = i-1;
208  S(ptr) = mu*t2-fxv*t3;
209  end
210 
211  ptr = ptr+1; % A(i,i)
212  I(ptr) = i;
213  J(ptr) = i;
214  S(ptr) = mu*t1+gv;
215 
216  if ix<n0
217  ptr = ptr+1; % A(i,i+1)
218  I(ptr) = i;
219  J(ptr) = i+1;
220  S(ptr) = mu*t2+fxv*t3;
221  end
222 
223  if iy<n0
224  ptr = ptr+1; % A(i,i+n0)
225  I(ptr) = i;
226  J(ptr) = i+n0;
227  S(ptr) = mu*t2+fyv*t3;
228  end
229 
230  end
231  end
232 
233  A = -sparse(I,J,S,n2,n2);
234  end
235 
236  function v = my_2d_vector(this,n0,f_str)
237  %
238  % Generates a vector v which contains the values of a function f(x,y)
239  % on an equidistant grid in the interior of the unit square. The grid
240  % points are numbered consistently with those used in the function
241  % 'fdm_2d_matrix'.
242  %
243  % This function is just used as an easy way to generate test problems
244  % rather than to solve PDEs.
245  %
246  % Calling sequence:
247  %
248  % v = fdm_2d_vector( n0, f_str)
249  %
250  % Input:
251  %
252  % n0 number of inner grid points in each dimension;
253  % f_str string describing the function f in the space variables 'x'
254  % and 'y', e.g., f_str = 'sin(x+2*y)+3'.
255  %
256  % Output:
257  %
258  % v vector of order n = n0^2 containing the values of f(x,y).
259  %
260  %
261  % LYAPACK 1.0 (Thilo Penzl, May 1999)
262 
263  % Input data not completely checked!
264 
265  na = nargin;
266 
267  if na~=2
268  error('Wrong number of input parameters.');
269  end
270 
271  h = 1.0/(n0+1);
272 
273  n2 = n0*n0;
274 
275  v = zeros(n2,1);
276 
277  i = 0;
278 
279  for iy = 1:n0
280  y = iy*h;
281  for ix = 1:n0
282  x = ix*h;
283  i = i+1;
284  v(i) = eval(f_str);
285  end
286  end
287  end
288  end
289 end
MODEL Main class for the DARE model.
Definition: Model.m:18
Parameter sampling sets.
Definition: Interface.m:1
Implicit Euler discretization of a finite-difference convection-diffusion model.
Implementation of the parametric discrete-time algebraic Riccati equation.
Definition: Kernel.m:1