1 function res = demos_parabolic(step)
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
15 case 1 % example of stable implicit Euler
16 disp(
'Example of Implicit Euler for Heat-Equation')
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;
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);
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
34 plot_params.height_factor = 0.5;
37 case 2 % demo of instability with
explicit Euler
39 disp(
'Example of Instability by Explicit Euler, CFL violation')
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;
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);
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
57 plot_params.clim_tight = 1;
58 plot_params.height_factor = 0.5;
61 case 3 % demo of smoothing
property of noisy initial data
63 disp(
'Example of smoothing property of heat equation')
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;
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)) ...;
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
84 plot_params.clim_tight = 1;
85 plot_params.height_factor = 0.5;
88 case 4 % error convergence tables
89 disp(
'Error convergence table for theta-scheme')
92 thetas = [1.0,0.5,0.0,0.0];
93 Ks = [10,10,10,640]; % coarse number of timesteps
95 i_s = [0,1,2,3,4]; % refinement steps
97 for mi = 1:length(thetas);
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
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')]);
128 error('step number unknown');
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);
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];
151 model.K = 100; % number of timesteps
152 model.gen_model_data = @my_gen_model_data;
153 model.detailed_simulation = @my_detailed_simulation;
156 %copy fields from params
159 model = setfield(model,fs{i},getfield(params,fs{i}));
161 % compute dependent parameters
162 model.delta_t = model.T/model.K;
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'};
175 tmp_model = setfield(tmp_model,fs{i},getfield(model,fs{i}));
177 tmp_model.gridtype =
'triagrid';
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));
189 tmp_model = elliptic_discrete_model(tmp_model);
191 model.rbmatlab_model = tmp_model;
193 function model_data = my_gen_model_data(model);
194 % function generating the grid and the FEM-matrices
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;
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;
215 function sim_data = my_detailed_simulation(model,model_data);
216 % function realizing theta-scheme. Result is stored matrix sim_data.U
218 sim_data.U = NaN * ones(model_data.ndofs,model.K+1);
219 delta_t = model.delta_t;
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;
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);
236 model.rbmatlab_model.t = t;
237 fkplus1 = project_function(model,model_data,f_function);
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;
245 % store result and prepare next iteration
246 sim_data.U(:,k+2) = ukplus1;
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);
262 function p = my_plot_slice(grid,data,plot_params,df)
264 plot(df,plot_params);
265 if isfield(plot_params,'height_factor
')
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
272 set(gca,'Zlim
',[-0.5,0.5]);
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;
288 function err = l2_error_at_end_time(model,model_data,sim_data)
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));
function p = plot_sim_data(model, model_data, sim_data, plot_params)
function performing the plot of the simulation results as specified in model.