3 %
function for meshless collocation of fem-problem. step can be
4 % used to choose several cases. step=1 does not need to be called
5 % directly but is used by the other steps. So call step=2, 3 and
6 % change options there.
8 % step 1: single solve. params.gamma can be set,
9 % params.colpoints_choice can be set to 1(random) or 2(structured).
10 % params.model_choice = 1 (poisson) or 2 (singular elliptic)
11 % If params.no_plots is set, then no plots
12 % and no screen output are performed. Output fields are
13 % res.u_h and the l2-error res.err and condition number res.cond
15 % step 2 % working example for poisson
17 % step 3 % working example for difficult ellipic model
19 % step 4 % determine errors and matrix conditions over a range of gammas
20 % and plot of error by repeated calls of step 1. Finds optimal gamma
24 if (nargin < 1) | (isempty(step))
25 step = 2; %
default: show working example of poisson model
34 % check
if plots are required
35 if isfield(params,
'no_plots')
36 no_plots = params.no_plots;
37 else % default: plotting on
41 % set gamma of rbf-kernel
42 if isfield(params,'gamma')
49 % set gamma of rbf-kernel
50 if isfield(params,'colpoints_choice')
51 colpoints_choice = params.colpoints_choice;
57 if isfield(params,'model_choice')
58 model_choice = params.model_choice;
60 model_choice = 1; % poisson
61 %model_choice = 2; % elliptic
64 % set refinement steps
65 if isfield(params,'refinements')
66 refinements = params.refinements;
72 model = praktikum_poisson_model(params);
73 elseif model_choice == 2
74 model = praktikum_ellipt_model(params);
77 % scalar argument and scalar valued rbf kernel and derivatives
78 % function can be called in many points s simultaneous.
79 % s is scalar (vectorial if many points)
80 kernel = @(s) exp(-gamma * s.^2);
81 kernel_derivative = @(s) -2*gamma * s.*exp(-gamma * s.^2);
82 %kernel_2nd_derivative = @(s) -2*gamma*exp(-gamma * s.^2).* ...
83 % (- 2 *gamma * s + 1);
84 % numerical gradient determination by central difference of a function f
85 % x is 1x2-vec (or matrix n x 2 if many points)
87 % num_gradient = @(f,x) [(f([x(:,1),x(:,2)+ds/2]) ...
88 % -f([x(:,1),x(:,2)-ds/2]))/ds, ...
89 % (f([x(:,1)+ds/2,x(:,2)]) ...
90 % -f([x(:,1)-ds/2,x(:,2)]))/ds];
92 % collocation centers for unit square
93 switch colpoints_choice
94 case 1 % random points for unit square
96 error('random points not implemented for l-shape domain')
98 rand('seed',101); % initialize random number generator
99 n_int = 15 * 2^refinements;
100 n_dir = 8 * 2^refinements; % dividable by 4
102 X_int = rand(n_int,2);
103 x_dir = rand(n_dir/4,1);
104 x_zero = zeros(size(x_dir,1),1);
105 x_ones = ones(size(x_dir,1),1);
107 X_dir = [x_dir, x_zero;
111 %X_neu = rand_uniform(n_neu,{[0,1]})
';
113 N_neu = model.normals(X_neu);
114 case 2 % choose points from grid for unit square and l-shape
116 p.xnumintervals = 2*2^refinements;
117 p.ynumintervals = 2*2^refinements;
121 p.xnumintervals = 5*2^refinements;
122 p.ynumintervals = 5*2^refinements;
127 Xall = [grid.X(:), grid.Y(:)];
129 keep_points = ones(size(Xall,1),1);
130 Xremove = find( (Xall(:,1)>1e-10) & (Xall(:,2)>1e-10));
131 Xremove0 = find( sum(Xall.^2,2)<0.26^2);% remove origin ball
134 Xremove = [Xremove;Xremove0];
135 keep_points(Xremove) = 0;
136 Xall = Xall(find(keep_points),:);
138 bt = model.boundary_type(Xall);
140 i_int = find(bt == 0);
141 i_dir = find(bt == -1);
142 i_neu = find(bt == -2);
144 n_int = length(i_int);
145 n_dir = length(i_dir);
146 n_neu = length(i_neu);
147 X_int = Xall(i_int,:);
148 X_dir = Xall(i_dir,:);
149 X_neu = Xall(i_neu,:);
150 N_neu = model.normals(X_neu);
152 otherwise('colpoint_choice unknown
')
155 X = [X_int;X_dir;X_neu];
157 if n~=(n_int+n_dir+n_neu)
158 error('error in system dimension!
');
161 % definition of elementary functions
162 % evaluation of all basis functions in single point:
163 % (phi_i(x),...,phi_n(x))
165 kernel(sqrt(sum((repmat(x(:)',n,1)-X).^2,2)));
166 % auxiliary
function grad_phi_vec_aux defined at end of file
167 grad_phi_vec = @(x) ...
168 grad_phi_vec_aux(x,kernel_derivative,n,X);
169 % d_11 phi + d_22 phi = kernel''(|x-xi|)
172 % (2-(x1+x2-xi1-xi2)|x-xi|)/|x-xi|^2
173 %div_grad_phi_vec = @(x) ...
174 % kernel_2nd_derivative(sqrt(sum((repmat(x(:)',n,1)-X).^2,2))) ...
175 % + kernel_derivative(sqrt(sum((repmat(x(:)',n,1)-X).^2,2))) .* ...
176 % ((-sum(X,2)+x(1)+x(2)).*sqrt(sum((repmat(x(:)',n,1)-X).^2,2)) ...
178 % .* sqrt(sum((repmat(x(:)',n,1)-X).^2,2)).^(-2);
179 % evaluation of all (a * grad phi_j) in single point numerical derivative
180 %a_grad_phi_vec = @(x) ...
181 % model.diffusivity(x(:)
') * (num_gradient(phi_vec,x(:)'));
182 % evaluation of all (a * grad phi_j) in single point
183 a_grad_phi_vec = @(x) ...
184 model.diffusivity(x(:)
') * grad_phi_vec(x(:)');
185 a_grad_phi_n_vec = @(x,n) ...
186 a_grad_phi_vec(x) * n(:);
188 % evaluation of all (a * grad phi_j * n) in single point with
190 %grad_phi_vec = @(x) ...
191 % kernel(sum((repmat(x(:)
',n,1)-X).^2,2));
193 %evaluation of all - a div grad phi_i(x) in single point x
194 %minus_a_div_grad_phi_vec = @(x) ...
195 % - model.diffusivity(x(:)') * ...
196 % div_grad_phi_vec(x);
197 %evaluation of all - (grad a) (grad phi_i(x)) in single point x
198 %minus_grad_a_grad_phi_vec = @(x) ...
199 % - sum(repmat(model.diffusivity_gradient(x(:)'),size(X,1),1)...
200 % .*grad_phi_vec(x),2);
201 %evaluation of all (- div (a grad phi_i(x))) in single point x
202 %minus_div_a_grad_phi_vec = @(x) ...
203 % minus_grad_a_grad_phi_vec(x)+ minus_a_div_grad_phi_vec(x);
204 %evaluation of all (- div (a grad phi_i(x))) in single point x
205 %numerical derivation:
207 minus_div_a_grad_phi_vec = @(x) ...
209 ((a_grad_phi_vec(x+[ds/2,0])-...
210 a_grad_phi_vec(x-[ds/2,0]))/ds) * [1;0] ...
212 ((a_grad_phi_vec(x+[0,ds/2])-...
213 a_grad_phi_vec(x-[0,ds/2]))/ds) * [0;1];
215 % assemble system, sorry one loop, can be removed later
216 A_int = zeros(n_int,n);
218 A_int(i,:) = minus_div_a_grad_phi_vec(X_int(i,:))';
220 A_dir = zeros(n_dir,n);
222 A_dir(i,:) = phi_vec(X_dir(i,:))';
224 A_neu = zeros(n_neu,n);
226 A_neu(i,:) = a_grad_phi_n_vec(X_neu(i,:),N_neu(i,:))';
230 A = [A_int; A_dir; A_neu];
232 b_int = model.source(X_int);
234 b_neu = model.neumann_values(X_neu);
235 b = [b_int;b_dir;b_neu];
240 % lambda = bicgstab(A,b);
243 %u(x) = sum_i lambda_i phi_i(x)
244 u_h = @(x) lambda' * phi_vec(x);
246 % evaluation of discrete function in collocation points
248 % sorry, one loop, can be removed later...
253 % error to exact solution
254 u_exact = model.solution(X);
255 max_err = max(abs(u-u_exact));
260 figure, plot3(X(:,1),X(:,2),b,'*');
261 title('right hand side of eqn system');
265 title('matrix of eqn system');
267 bt = model.boundary_type(X);
268 dir_ind = find(bt==-1);
269 neu_ind = find(bt==-2);
270 legends = {
'int',
'dir',
'neu'};
272 legends = {
'int',
'dir'};
274 figure, plot3(X(:,1),X(:,2),u,
'*');
275 hold on, plot3(X(dir_ind,1),X(dir_ind,2),u(dir_ind),
'ro');
276 hold on, plot3(X(neu_ind,1),X(neu_ind,2),u(neu_ind),
'go');
277 title(
'discrete solution')
280 figure, plot3(X(:,1),X(:,2),u_exact,'*');
281 hold on, plot3(X(dir_ind,1),X(dir_ind,2),u_exact(dir_ind),'ro');
282 hold on, plot3(X(neu_ind,1),X(neu_ind,2),u_exact(neu_ind),'go');
283 title('exact solution');
286 figure, plot3(X(:,1),X(:,2),u-u_exact,'*');
288 disp(['L-infty error: ',num2str(max_err)])
296 case 2 % working example for poisson on unit square
298 params.model_choice = 1; % poisson
299 % params.gamma = 0.0063; % for ref = 0;
300 % params.refinements = 0;
301 % params.gamma = 0.063; % for ref = 1;
302 % params.refinements = 1;
303 params.gamma = 0.794; % for ref = 2;
304 params.refinements = 2;
305 params.all_dirichlet_boundary = 0;
306 % params.all_dirichlet_boundary = 1;
309 % res = rbf_elliptic(4,params);
311 case 3 % working example for difficult l-shaped domain with ellipic model
313 params.model_choice = 2; % elliptic l-shaped
314 % params.gamma = 0.001; % optimal for refinements 0
315 params.gamma = 31.62; % optimal for refinements 1
316 % params.gamma = 80; % optimal for refinements 2
317 params.refinements = 1;
318 params.all_dirichlet_boundary = 1;
319 % params.all_dirichlet_boundary = 0;
321 res = rbf_elliptic(1,params);
322 % res = rbf_elliptic(4,params);
324 case 4 % determine errors and matrix conditions over a range of gammas
325 % range of gamma between 0.001 and 10, log-equidistant
326 gamma_log = log(10)*(-3:(1/10):3);
327 gammas = exp(gamma_log);
328 errs = zeros(size(gammas));
329 conds = zeros(size(gammas));
330 for gamma_index = 1:length(gammas);
331 params.gamma = gammas(gamma_index);
333 params.colpoints_choice = 2;
334 % solve for given parameter
335 res = rbf_elliptic(1,params);
336 errs(gamma_index) = res.err;
337 conds(gamma_index) = res.cond;
339 figure,plot(gammas,errs);
340 set(gca,'Xscale','log');
341 set(gca,'Yscale','log');
343 ylabel('l_\infty-error');
344 title('error over gamma');
345 figure,plot(gammas,conds);
346 set(gca,'Xscale','log');
347 set(gca,'Yscale','log');
350 title('condition number over gamma');
355 res.gamma_opt = gammas(i(1));
356 disp(['optimal gamma:',num2str(res.gamma_opt),...
357 ', linfty-error : ',num2str(e)]);
359 error('step unknown')
362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% auxiliary functions %%%%%%%%%%%%%%%%%%%%%%%%%
364 % small auxiliary function used for computing grad_phi_vec
365 function res = grad_phi_vec_aux(x,kernel_derivative,n,X)
366 xdiffs = repmat(x(:)',n,1)-X;
367 xdiffnorms = sqrt(sum(xdiffs.^2,2));
369 kernel_derivative(xdiffnorms).* (xdiffnorms.^(-1)), ...
372 % by factor 0/0 (division by zero) a nan can appear, det to 0:
373 i = find(isnan(res));