rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
demos_parabolic.m
1 function res = demos_parabolic(step)
2 %
3 % step 1: simple simulation with implicit Euler and plot of results
4 % step 2: instability of expl. Euler
5 % step 3: smoothing effect of impl. Euler
6 % step 4: error convergence table for theta-scheme
7 
8 % 6.1.2015 B. Haasdonk
9 
10 if nargin < 1
11  step = 1;
12 end;
13 
14 switch step
15  case 1 % example of stable implicit Euler
16  disp('Example of Implicit Euler for Heat-Equation')
17  % initialize model:
18  params = [];
19  params.theta = 1.0; params.K = 100;
20  % params.theta = 0; params.K = 1300; params.T = 1; % stable!
21  % params.theta = 0; params.K = 1200; params.T = 1; % instable!
22  % params.theta = 0.5; params.K = 100;
23 
24  model = parabolic_model(params);
25 % disp('temporary setting rhs to 0, comment this line out for real model')
26 % model.source_function = @(X,model) zeros(size(X,1),1);
27 
28 % generate grid and fem matrices:
29  model_data = gen_model_data(model);
30  % perform full simulation
31  sim_data = detailed_simulation(model, model_data);
32  % plot results and provide slider
33  plot_params = [];
34  plot_params.height_factor = 0.5;
35  plot_sim_data(model,model_data,sim_data,plot_params);
36 
37  case 2 % demo of instability with explicit Euler
38 
39  disp('Example of Instability by Explicit Euler, CFL violation')
40  % initialize model:
41  params = [];
42  params.theta = 0.0; params.K = 100;
43  % params.theta = 0; params.K = 1300; params.T = 1; % stable!
44  % params.theta = 0; params.K = 1200; params.T = 1; % instable!
45  % params.theta = 0.5; params.K = 100;
46 
47  model = parabolic_model(params);
48 % disp('temporary setting rhs to 0, comment this line out for real model')
49 % model.source_function = @(X,model) zeros(size(X,1),1);
50 
51 % generate grid and fem matrices:
52  model_data = gen_model_data(model);
53  % perform full simulation
54  sim_data = detailed_simulation(model, model_data);
55  % plot results and provide slider
56  plot_params = [];
57  plot_params.clim_tight = 1;
58  plot_params.height_factor = 0.5;
59  plot_sim_data(model,model_data,sim_data,plot_params);
60 
61  case 3 % demo of smoothing property of noisy initial data
62 
63  disp('Example of smoothing property of heat equation')
64  % initialize model:
65  params = [];
66  params.theta = 1.0; params.K = 500;
67  params.xnumintervals = 40;
68  params.ynumintervals = 40;
69  % params.theta = 0; params.K = 1300; params.T = 1; % stable!
70  % params.theta = 0; params.K = 1200; params.T = 1; % instable!
71  % params.theta = 0.5; params.K = 100;
72 
73  model = parabolic_model(params);
74  model.source_function = @(X,model) zeros(size(X,1),1);
75  model.init_value_function = @(X,model) sin(2*pi*X(:,1)) .* sin(2*pi*X(:,2)) ...
76  + 0.2 * sin(20*pi*X(:,1)) .* sin(20*pi*X(:,2)) ...;
77 
78 % generate grid and fem matrices:
79  model_data = gen_model_data(model);
80  % perform full simulation
81  sim_data = detailed_simulation(model, model_data);
82  % plot results and provide slider
83  plot_params = [];
84  plot_params.clim_tight = 1;
85  plot_params.height_factor = 0.5;
86  plot_sim_data(model,model_data,sim_data,plot_params);
87 
88  case 4 % error convergence tables
89  disp('Error convergence table for theta-scheme')
90 
91  params = [];
92  thetas = [1.0,0.5,0.0,0.0];
93  Ks = [10,10,10,640]; % coarse number of timesteps
94 
95  i_s = [0,1,2,3,4]; % refinement steps
96 
97  for mi = 1:length(thetas);
98  theta = thetas(mi);
99  K = Ks(mi);
100  disp('===================================================================')
101  disp(['convergence study for theta = ',num2str(theta),', K0 = ',num2str(K)]);
102  disp('-----------------------------------------------------------------')
103  disp(' delta_t | delta_x = delta_y | ||u(t^K)-u_h^K||_L2 ')
104  disp('-----------------------------------------------------------------')
105  for ni = 1:length(i_s);
106  params.theta = theta;
107  params.K = Ks(mi)*2^i_s(ni);
108  params.xnumintervals = 4*2^i_s(ni);
109  params.ynumintervals = 4*2^i_s(ni);
110  % params.theta = 0; params.K = 1300; params.T = 1; % stable!
111  % params.theta = 0; params.K = 1200; params.T = 1; % instable!
112  % params.theta = 0.5; params.K = 100;
113  model = parabolic_model(params);
114  % generate grid and fem matrices:
115  model_data = gen_model_data(model);
116  % perform full simulation
117  sim_data = detailed_simulation(model, model_data);
118  % plot results and provide slider
119  %plot_sim_data(model,model_data,sim_data,[]);
120  err = l2_error_at_end_time(model,model_data,sim_data);
121  disp([' ',num2str(model.delta_t,'%10.5f'),' | ',...
122  num2str(1/params.xnumintervals,'%10.5f'),' | ', ...
123  num2str(err,'%10.5f')]);
124  end;
125  end;
126 
127  otherwise
128  error('step number unknown');
129 end;
130 
131 function model = parabolic_model(params);
132 %default settings, can be overridden by params
133 model.source_function = @(X,model) sin(pi*X(:,1)).*sin(2*pi*X(:,2)).* ...
134  (-5*pi*sin(5*pi*model.t) + 5 * pi*pi *cos(5*pi*model.t));
135 model.init_value_function = @(X,model) sin(pi*X(:,1)) .* sin(2*pi*X(:,2));
136 model.exact_solution = @(X,model) sin(pi*X(:,1)).*sin(2*pi*X(:,2)).* cos(5*pi*model.t);
137 
138 %model.source_function = @(X,model) 100*sin(pi*X(:,1)).*sin(2*pi*X(:,1)).*sin(5*pi*model.t);
139 %model.init_value_function = @(X,model) sin(2.5*pi*X(:,1)).*sin(2.5*pi*X(:,1)) ...
140 % .* (X(:,1)<0.6) .*(X(:,1)>0.4) ...
141 % .* (X(:,2)<0.6) .*(X(:,2)>0.4);
142 model.xnumintervals = 10;
143 model.ynumintervals = 10;
144 model.xrange = [0,1];
145 model.yrange = [0,1];
146 model.bnd_rect_corner1 = [-1,-1];
147 model.bnd_rect_corner2 = [2,2];
148 model.bnd_rect_index = [-1];
149 model.t = 0;
150 model.T = 1;
151 model.K = 100; % number of timesteps
152 model.gen_model_data = @my_gen_model_data;
153 model.detailed_simulation = @my_detailed_simulation;
154 model.plot_sim_data = @my_plot_sim_data;
155 
156 %copy fields from params
157 fs = fields(params);
158 for i=1:length(fs)
159  model = setfield(model,fs{i},getfield(params,fs{i}));
160 end;
161 % compute dependent parameters
162 model.delta_t = model.T/model.K;
163 
164 % prepare temporary rbmatlab information for matrices/grid generation;
165 tmp_model = lin_stat_model_default;
166 tmp_model.has_diffusivity = 1;
167 tmp_model.has_source = 1;
168 tmp_model.has_dirichlet_values = 1;
169 tmp_model.pdeg = 1; % linear finite elements
170 tmp_model.dimrange = 1; % scalar finite elements;
171 tmp_model.qdeg = 2; % quadrature order
172 %copy fields from model
173 fs = {'xnumintervals','ynumintervals','xrange','yrange'};
174 for i=1:length(fs)
175  tmp_model = setfield(tmp_model,fs{i},getfield(model,fs{i}));
176 end;
177 tmp_model.gridtype = 'triagrid';
178 tmp_model.c_dir = 0;
179 tmp_model.diffusivity_tensor = @(glob,params) ...
180  [ones(1,size(glob,1));...
181  zeros(1,size(glob,1));...
182  zeros(1,size(glob,1));...
183  ones(1,size(glob,1))]';
184 tmp_model.source = @(glob,model) ...
185  model.source_function(glob,model);
186 tmp_model.dirichlet_values = @(glob,model) ...
187  zeros(1,size(glob,1));
188 
189 tmp_model = elliptic_discrete_model(tmp_model);
190 
191 model.rbmatlab_model = tmp_model;
192 
193 function model_data = my_gen_model_data(model);
194 % function generating the grid and the FEM-matrices
195 model_data = [];
196 
197 % construct grid and finite element information
198 tmp_model_data = gen_model_data(model.rbmatlab_model);
199 tmp_model = model.rbmatlab_model;
200 % extract information required for our problem
201 [A_diff , A_adv, A_reac, A_dirichlet, A_neumann, A_robin] = ...
202  fem_matrix_parts_assembly(tmp_model,tmp_model_data.df_info);
203 model_data.A = spalloc(tmp_model_data.df_info.ndofs,tmp_model_data.df_info.ndofs,10);
204 model_data.A = A_diff + A_adv + A_reac + A_neumann + A_robin + A_dirichlet;
205 model_data.M = tmp_model_data.df_info.l2_inner_product_matrix;
206 dirichlet_gids = tmp_model_data.df_info.dirichlet_gids;
207 
208 model_data.M(dirichlet_gids,:)= 0;
209 model_data.M(:,dirichlet_gids)= 0;
210 model_data.M(dirichlet_gids,dirichlet_gids)= eye(length(dirichlet_gids));
211 model_data.grid = tmp_model_data.grid;
212 model_data.ndofs = tmp_model_data.df_info.ndofs;
213 model_data.df_info = tmp_model_data.df_info;
214 
215 function sim_data = my_detailed_simulation(model,model_data);
216 % function realizing theta-scheme. Result is stored matrix sim_data.U
217 sim_data = [];
218 sim_data.U = NaN * ones(model_data.ndofs,model.K+1);
219 delta_t = model.delta_t;
220 theta = model.theta;
221 M = model_data.M;
222 A = model_data.A;
223 % initial data projection as first solution column:
224 init_value_vector = project_function(model,model_data, ...
225  model.init_value_function);
226 uk = M\init_value_vector;
227 sim_data.U(:,1) = uk;
228 t = 0;
229 model.t = t;
230 model.rbmatlab_model.t = t;
231 f_function = @(X,tmp_model) model.source_function(X,tmp_model);
232 fk = project_function(model,model_data, f_function);
233 for k = 0:model.K-1;
234  t = t+ delta_t;
235  model.t = t;
236  model.rbmatlab_model.t = t;
237  fkplus1 = project_function(model,model_data,f_function);
238 
239  % solve theta scheme LGS system
240  S = M + theta* delta_t * A;
241  rhs = (M - (1-theta)*delta_t * A) * uk ...
242  + delta_t * theta * fkplus1 + delta_t * (1-theta)*fk;
243  ukplus1 = S\rhs;
244 
245  % store result and prepare next iteration
246  sim_data.U(:,k+2) = ukplus1;
247  fk = fkplus1;
248  uk = ukplus1;
249  if isnan(norm(uk))
250  return;
251  end;
252 end;
253 
254 function p = my_plot_sim_data(model,model_data,sim_data,plot_params);
255 plot_params.axis_equal = 1;
256 plot_params.axis_tight = 1;
257 df = femdiscfunc([],model_data.df_info);
258 plot_params.plot = @(grid,data, plot_params) my_plot_slice(grid,data,plot_params,df);
259 p = plot_sequence(sim_data.U, model_data.grid, plot_params);
260 %p = plot(model_data.grid,plot_params);
261 
262 function p = my_plot_slice(grid,data,plot_params,df)
263 df.dofs = data;
264 plot(df,plot_params);
265 if isfield(plot_params,'height_factor')
266  view(-53,22)
267 % V = [0.5736 -0.8192 0.0000 0.1228
268 % 0.5481 0.3838 1.4735 -1.2027
269 % 0.6087 0.4263 -1.3267 12.3230
270 % 0 0 0 1.0000]
271 % view(V);
272  set(gca,'Zlim',[-0.5,0.5]);
273 xlabel('x_1');
274 ylabel('x_2');
275 end;
276 
277 function f_vector = project_function(model,model_data,f_function);
278 % function providing the vector of l2 inner products of basis
279 % functions and the given function f_function
280 tmp_model = model.rbmatlab_model;
281 tmp_model.source = @(varargin) ...
282  discrete_volume_values(f_function,varargin{:});
283 [r_source, r_dirichlet, r_neumann, r_robin] = ...
284  fem_rhs_parts_assembly(tmp_model,model_data.df_info);
285 f_vector = r_source + r_neumann + r_robin + r_dirichlet;
286 f_vector(model_data.df_info.dirichlet_gids) = 0;
287 
288 function err = l2_error_at_end_time(model,model_data,sim_data)
289 model.t = model.T;
290 model.rbmatlab_model.t = model.T;
291 exact_solution_projection = project_function(model,model_data, ...
292  model.exact_solution);
293 exact_solution_vector = model_data.M\exact_solution_projection;
294 errsqr = (exact_solution_vector- sim_data.U(:,end))' * model_data.M * ...
295  (exact_solution_vector - sim_data.U(:,end));
296 err = sqrt(errsqr);
function p = plot_sim_data(model, model_data, sim_data, plot_params)
function performing the plot of the simulation results as specified in model.
Definition: plot_sim_data.m:17