rbmatlab  1.13.10
 All Classes Namespaces Files Functions Variables Groups Pages
rbf_elliptic.m
Go to the documentation of this file.
1 function res = rbf_elliptic(step,params);
2 %function res = rbf_elliptic(step,params);
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.
7 %
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
14 %
15 % step 2 % working example for poisson
16 %
17 % step 3 % working example for difficult ellipic model
18 %
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
21 
22 res = [];
23 
24 if (nargin < 1) | (isempty(step))
25  step = 2; % default: show working example of poisson model
26 end;
27 
28 if (nargin < 2)
29  params = [];
30 end;
31 
32 switch step
33  case 1
34  % check if plots are required
35  if isfield(params,'no_plots')
36  no_plots = params.no_plots;
37  else % default: plotting on
38  no_plots = 0;
39  end;
40 
41  % set gamma of rbf-kernel
42  if isfield(params,'gamma')
43  gamma = params.gamma;
44  else % default
45  gamma = 50;
46 % gamma = 0.01;
47  end;
48 
49  % set gamma of rbf-kernel
50  if isfield(params,'colpoints_choice')
51  colpoints_choice = params.colpoints_choice;
52  else
53  colpoints_choice = 2;
54  end;
55 
56  % set model type
57  if isfield(params,'model_choice')
58  model_choice = params.model_choice;
59  else
60  model_choice = 1; % poisson
61  %model_choice = 2; % elliptic
62  end;
63 
64  % set refinement steps
65  if isfield(params,'refinements')
66  refinements = params.refinements;
67  else
68  refinements = 2;
69  end;
70 
71  if model_choice == 1
72  model = praktikum_poisson_model(params);
73  elseif model_choice == 2
74  model = praktikum_ellipt_model(params);
75  end;
76 
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)
86  %ds = (1e-3)*gamma;
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];
91 
92 % collocation centers for unit square
93 switch colpoints_choice
94  case 1 % random points for unit square
95  if model_choice ==2
96  error('random points not implemented for l-shape domain')
97  end;
98  rand('seed',101); % initialize random number generator
99  n_int = 15 * 2^refinements;
100  n_dir = 8 * 2^refinements; % dividable by 4
101  n_neu = 0;
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);
106 
107  X_dir = [x_dir, x_zero;
108  x_zero, x_dir;
109  x_dir,x_ones;
110  x_ones,x_dir];
111  %X_neu = rand_uniform(n_neu,{[0,1]})';
112  X_neu = zeros(0,2);
113  N_neu = model.normals(X_neu);
114  case 2 % choose points from grid for unit square and l-shape
115  if model_choice == 1
116  p.xnumintervals = 2*2^refinements;
117  p.ynumintervals = 2*2^refinements;
118  p.xrange = [0,1];
119  p.yrange = [0,1];
120  else
121  p.xnumintervals = 5*2^refinements;
122  p.ynumintervals = 5*2^refinements;
123  p.xrange = [-1,1];
124  p.yrange = [-1,1];
125  end;
126  grid = triagrid(p);
127  Xall = [grid.X(:), grid.Y(:)];
128  if model_choice == 2
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
132  % due
133  % to f singularity
134  Xremove = [Xremove;Xremove0];
135  keep_points(Xremove) = 0;
136  Xall = Xall(find(keep_points),:);
137  end;
138  bt = model.boundary_type(Xall);
139 % keyboard;
140  i_int = find(bt == 0);
141  i_dir = find(bt == -1);
142  i_neu = find(bt == -2);
143 
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);
151 
152  otherwise('colpoint_choice unknown')
153  end;
154 
155  X = [X_int;X_dir;X_neu];
156  n = size(X,1);
157  if n~=(n_int+n_dir+n_neu)
158  error('error in system dimension!');
159  end;
160 
161  % definition of elementary functions
162  % evaluation of all basis functions in single point:
163  % (phi_i(x),...,phi_n(x))
164  phi_vec = @(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|)
170  % +
171  % 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)) ...
177  % + 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(:);
187 
188  % evaluation of all (a * grad phi_j * n) in single point with
189  % normal n
190  %grad_phi_vec = @(x) ...
191  % kernel(sum((repmat(x(:)',n,1)-X).^2,2));
192 
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:
206  ds = (1e-3)*gamma;
207  minus_div_a_grad_phi_vec = @(x) ...
208  - ...
209  ((a_grad_phi_vec(x+[ds/2,0])-...
210  a_grad_phi_vec(x-[ds/2,0]))/ds) * [1;0] ...
211  - ...
212  ((a_grad_phi_vec(x+[0,ds/2])-...
213  a_grad_phi_vec(x-[0,ds/2]))/ds) * [0;1];
214 
215  % assemble system, sorry one loop, can be removed later
216  A_int = zeros(n_int,n);
217  for i = 1:n_int;
218  A_int(i,:) = minus_div_a_grad_phi_vec(X_int(i,:))';
219  end;
220  A_dir = zeros(n_dir,n);
221  for i = 1:n_dir;
222  A_dir(i,:) = phi_vec(X_dir(i,:))';
223  end;
224  A_neu = zeros(n_neu,n);
225  for i = 1:n_neu;
226  A_neu(i,:) = a_grad_phi_n_vec(X_neu(i,:),N_neu(i,:))';
227  end;
228 % keyboard;
229 
230  A = [A_int; A_dir; A_neu];
231 
232  b_int = model.source(X_int);
233  b_dir = model.dirichlet_values(X_dir);
234  b_neu = model.neumann_values(X_neu);
235  b = [b_int;b_dir;b_neu];
236 % keyboard;
237 
238  % solve system
239  lambda = A\b;
240 % lambda = bicgstab(A,b);
241 
242  % discrete function
243  %u(x) = sum_i lambda_i phi_i(x)
244  u_h = @(x) lambda' * phi_vec(x);
245 
246  % evaluation of discrete function in collocation points
247  u = zeros(n,1);
248  % sorry, one loop, can be removed later...
249  for i = 1:n;
250  u(i) = u_h(X(i,:));
251  end;
252 
253  % error to exact solution
254  u_exact = model.solution(X);
255  max_err = max(abs(u-u_exact));
256 
257  % plots if required
258  if ~no_plots
259  % right hand side
260  figure, plot3(X(:,1),X(:,2),b,'*');
261  title('right hand side of eqn system');
262  % matrix
263  figure, pcolor(A);
264  colorbar;
265  title('matrix of eqn system');
266  % discrete solution
267  bt = model.boundary_type(X);
268  dir_ind = find(bt==-1);
269  neu_ind = find(bt==-2);
270  legends = {'int','dir','neu'};
271  if isempty(neu_ind)
272  legends = {'int','dir'};
273  end;
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')
278  legend(legends);
279  % exact 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');
284  legend(legends);
285  % error
286  figure, plot3(X(:,1),X(:,2),u-u_exact,'*');
287  title('error');
288  disp(['L-infty error: ',num2str(max_err)])
289  end;
290 
291  % return results
292  res.u_h = u_h;
293  res.err = max_err;
294  res.cond = cond(A);
295 
296  case 2 % working example for poisson on unit square
297  params = [];
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;
307  % call collocation
308  res = rbf_elliptic(1,params);
309 % res = rbf_elliptic(4,params);
310 
311  case 3 % working example for difficult l-shaped domain with ellipic model
312  params = [];
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;
320  % call collocation
321  res = rbf_elliptic(1,params);
322 % res = rbf_elliptic(4,params);
323 
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);
332  params.no_plots = 1;
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;
338  end;
339  figure,plot(gammas,errs);
340  set(gca,'Xscale','log');
341  set(gca,'Yscale','log');
342  xlabel('gamma');
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');
348  xlabel('gamma');
349  ylabel('cond(A)');
350  title('condition number over gamma');
351  res.gammas = gammas;
352  res.errs = errs;
353  res.conds = conds;
354  [e,i] = min(errs);
355  res.gamma_opt = gammas(i(1));
356  disp(['optimal gamma:',num2str(res.gamma_opt),...
357  ', linfty-error : ',num2str(e)]);
358  otherwise
359  error('step unknown')
360 end;
361 
362 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% auxiliary functions %%%%%%%%%%%%%%%%%%%%%%%%%
363 
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));
368 res = repmat(...
369  kernel_derivative(xdiffnorms).* (xdiffnorms.^(-1)), ...
370  1,2)...
371  .*xdiffs;
372 % by factor 0/0 (division by zero) a nan can appear, det to 0:
373 i = find(isnan(res));
374 res(i) = 0;