rbmatlab 0.10.01
models/poisson_model.m
00001 function model = poisson_model(params);
00002 %function model = poisson_model(params)
00003 %
00004 % small example of a model, i.e. a structure describing the data
00005 % functions and geometry information of a general elliptic equation consisting 
00006 % of diffusion, convection, reaction equation:
00007 %
00008 % - div ( a(x) grad u(x)) + div (b(x) u(x)) + c(x) u(x) = f(x)    on Omega
00009 %                                                 u(x)) = g_D(x)  on Gamma_D
00010 %                                   a(x) (grad u(x)) n) = g_N(x)  on Gamma_N
00011 %          alpha(x) u(x) +  beta(x) a(x) (grad u(x)) n) = g_R(x)  on Gamma_R
00012 %
00013 %                                   s = l(u) linear output functional
00014 % 
00015 %  Here, we denote the functions as
00016 %                   u: scalar 'solution' (if known, for validation purpose)
00017 %                   f: scalar 'source'
00018 %                   a: tensor valued 'diffusivity_tensor'
00019 %                   b: vector valued 'velocity'
00020 %                   c: scalar 'reaction'
00021 %                 g_D: scalar 'dirichlet_values'
00022 %                 g_N: scalar 'neumann_values'
00023 %                 g_R: scalar 'robin_values'
00024 %               alpha: scalar 'robin_alpha'
00025 %                beta: scalar 'robin_beta'
00026 %
00027 % Each function allows the evaluation in many points
00028 % simultaneuously by
00029 %
00030 %        model.source(glob)
00031 % or     model.source(glob,params)
00032 %
00033 % where glob is a n times 2 matrix of row-wise points. The result
00034 % is a n times 1 vector of resulting values of f.
00035 %
00036 %        model.diffusivity_tensor(glob)
00037 % or     model.diffusivity_tensor(glob,params)
00038 %
00039 % where glob is a n times 2 matrix of row-wise points. The result
00040 % is a n times 4 matrix of resulting values of diffusivity, where
00041 % the values of a are sorted in matlab-order as [a_11, a_21, a_12, a_22];
00042 %
00043 % additionally, the model has a function, which determines, whether
00044 % a point lies on a Dirichlet, Neumann or Robin boundary:
00045 %        
00046 %           model.boundary_type(glob)
00047 %                0 no boundary (inner edge or point)
00048 %               -1 indicates Dirichlet-boundary
00049 %               -2 indicates Neumann-boundary
00050 %               -3 indicates Robin-boundary
00051 %
00052 % Additionally, the normals in a boundary point can be requested by
00053 %
00054 %           model.normals(glob)
00055 % Here, glob are assumed to be boundary points lying ON THE
00056 % INTERIOR of an edge, such that the outer unit normal is well-defined.
00057 %
00058 % The latter 2 methods boundary_type() and normals() need not be
00059 % implemented for grid-based methods, as the normals simply can be
00060 % obtained by the grid. The methods are only required, if using
00061 % meshless methods with data functions that use normals. 
00062 %
00063 % The output functional must be specified 
00064 %           s = model.output_functional(model, model_data, u)
00065 % where u is a dof vector of the discrete solution. model_data is
00066 % assumed to contain the grid 
00067 % 
00068 % possible fields of params:
00069 %     numintervals: the unit square is divided into numintervals
00070 %                   intervals per side. default is 10;
00071 %
00072 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00073 %
00074 % The data functions given in this model are the simple poisson
00075 % equation with Gamma_D = boundary(Omega), Gamma_N = {}, Gamma_R = {}
00076 %
00077 %    -div (grad u) = f
00078 %            u = 0   on   Gamma_D
00079 %
00080 % with exact solution u(x) = 16 x_1(1-x_1)x_2(1-x_2), 
00081 % i.e. f(x) = 32 (x_1 + x_2 - x_1^2 - x_2^2)
00082 
00083 % B. Haasdonk 23.11.2010
00084 
00085 if nargin == 0 
00086   params = [];
00087 end;
00088 
00089 if ~isfield(params,'numintervals')
00090   params.numintervals = 10; % 2 x 2 grid! with 8 triangles
00091 end;
00092 
00093 if ~isfield(params,'pdeg')
00094   params.pdeg = 2; % 2 x 2 grid! with 8 triangles
00095 end;
00096 
00097 if ~isfield(params,'qdeg')
00098   params.qdeg = 2; % 2 x 2 grid! with 8 triangles
00099 end;
00100 
00101 model = [];
00102 model.rb_problem_type = 'lin_elliptic';
00103 
00104 %%%%%%% data function specification:
00105 
00106 % if any of the following flags is set, the corresponding function
00107 % pointers must be provided below.
00108 
00109 model.has_reaction = 1;
00110 %model.has_reaction = 0;
00111 model.has_source = 1;
00112 model.has_reaction = 1;
00113 %model.has_reaction = 0;
00114 model.has_advection = 1;
00115 %model.has_advection = 0;
00116 model.has_diffusivity = 1;
00117 model.has_output_functional = 1;
00118 model.has_dirichlet_values = 1;
00119 model.has_neumann_values = 1;
00120 %model.has_neumann_values = 0;
00121 %model.has_robin_values = 1;
00122 model.has_robin_values = 1;
00123 
00124 % solution is known:
00125 model.solution = @(glob,params) ...
00126             16 * glob(:,1).*(1-glob(:,1)).*glob(:,2).*(1-glob(:,2));
00127 % for debugging: f = 1; u = -1/4 (x^2+y^2)
00128 %model.solution = @(glob,params) ...
00129 %            -0.25 * (glob(:,1).^2+glob(:,2).^2);
00130 
00131 % params is an optional parameter, perhaps useful later
00132 model.source = @(glob,params) ...
00133             32 * (glob(:,1)+ glob(:,2)- glob(:,1).^2 - glob(:,2).^2);
00134 % for debugging: f = 1; u = -0.25* (x^2+y^2)
00135 %model.source = @(glob,params) ...
00136 %    ones(size(glob,1),1);
00137 
00138 model.reaction = @(glob,params) zeros(size(glob,1),1);
00139 model.velocity = @(glob,params) zeros(size(glob,1),2);
00140 model.diffusivity_tensor = @(glob,params) ...
00141     [ones(size(glob,1),1),...
00142      zeros(size(glob,1),1),...
00143      zeros(size(glob,1),1),...
00144      ones(size(glob,1),1)];
00145 %model.diffusivity_gradient = @(glob,params) zeros(size(glob,1),2);
00146 model.reaction = @(glob,params) zeros(size(glob,1),1);
00147 
00148 %  Dirichlet everywhere, see function below.
00149 %model.dirichlet_values = @(glob,params) zeros(size(glob,1),1);
00150 model.dirichlet_values = @(glob,params) ...
00151     params.solution(glob,params);
00152 model.neumann_values = @(glob,params) zeros(size(glob,1),1);
00153 model.robin_values = @(glob,params) zeros(size(glob,1),1);
00154 model.robin_alpha = @(glob,params) zeros(size(glob,1),1);
00155 model.robin_beta = @(glob,params) zeros(size(glob,1),1);
00156 
00157 % output functional, e.g. average over unit-square:
00158 model.output_functional = @output_functional_volume_integral;
00159 model.output_function = @output_function_box_mean;
00160 model.sbox_xmin = 0;
00161 model.sbox_ymin = 0;
00162 model.sbox_xmax = 1;
00163 model.sbox_ymax = 1;
00164 model.output_integral_qdeg = 0; % midpoint integration
00165 % later, e.g. for thermal block:
00166 %model.output_functional = @output_functional_boundary_integral;
00167 %model.output_function = @output_function_dirichlet_indicator;
00168 
00169 %%%%%%% geometry specification and discretization:
00170 
00171 model.gridtype = 'triagrid';
00172 model.xnumintervals = params.numintervals;
00173 model.ynumintervals = params.numintervals;
00174 model.xrange = [0,1];
00175 model.yrange = [0,1];
00176 
00177 % numerics settings:
00178 model.pdeg = params.pdeg; % degree of polynomial functions
00179 model.qdeg = params.qdeg; % quadrature degree
00180 model.dimrange = 1; % scalar solution
00181 
00182 % The following 2 methods boundary_type() and normals() need not be
00183 % implemented for grid-based methods, as the normals simply can be
00184 % obtained by the grid. The methods are only required, if using
00185 % meshless methods with data functions that use normals. 
00186 model.boundary_type = @my_boundary_type;
00187 model.normals = @my_normals;
00188 
00189 %%%%%%% auxiliary functions:
00190 
00191 % all edges of unit square are dirichlet, other inner
00192 % note this function is not used by grid-based methods
00193 function res = my_boundary_type(glob,params)
00194 res = zeros(size(glob,1),1);
00195 i  = find(glob(:,1)<=1e-10);
00196 i  = [i, find(glob(:,1)>=1-1e-10)];
00197 i  = [i, find(glob(:,2)<=1e-10)];
00198 i  = [i, find(glob(:,2)>=1-1e-10)];
00199 res(i) = -1;
00200 
00201 function res = my_normals(glob,params);
00202 res = zeros(size(glob,1),2); % each row one normal
00203 i  = find(glob(:,1)>1-1e-10);
00204 res(i,1)= 1.0;
00205 i  = find(glob(:,1)<-1+1e-10);
00206 res(i,1)= -1.0;
00207 i  = find(glob(:,2)>1-1e-10);
00208 res(i,2)= 1.0;
00209 i  = find(glob(:,2)<-1+1e-10);
00210 res(i,2)= -1.0;
00211 % remove diagonal normals
00212 i = find (sum(abs(res),2)>1.5);
00213 res(i,1)= 0;
00214 
00215 
00216 
All Classes Namespaces Files Functions Variables