rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
DiscFunc.m
1 classdef DiscFunc < handle
2  % represents a continous piecewise polynomial function of arbitrary
3  % dimension. Can be used for all finite elements (discrete function
4  % information class) implementing IFeminfo (e.g. Fem.Lagrange.DefaultInfo)
5  %
6  % `dofs` correspond to the values of the nodes.
7  % `df_info` is an object of discrete function information.
8 
9  % Bernard Haasdonk 11.1.2011
10  % IM 29.11.2012
11 
12  properties
13 
14  % polynomial degree
15  pdeg;
16 
17  % dimension of range space
18  dimrange;
19 
20  % grid of type .gridbase
21  grid;
22 
23  % discrete function information of type .IFemInfo
24  df_info;
25 
26  % DOF vector
27  dofs;
28 
29  % number of elements
30  nelements;
31 
32  % number of DOFs
33  ndofs;
34 
35  % number of DOFs per grid element
36  ndofs_per_element;
37 
38  % global coordinate of DOFs
39  dofs_global_coordinate;
40  end
41 
42  methods
43 
44  function df = DiscFunc(dofs, df_info)
45  % constructor, dofs possibly [], grid required!
46  %
47  % parameters:
48  % dofs: a vector of #'df.ndofs' global degress of freedom for the
49  % discrete function, if '==[]' a zero vector is created.
50  % df_info: object of type .IFemInfo describing the structure of the
51  % underlying discrete function space
52  %
53  % required fields of df_info:
54  % pdeg: polynomial degree of lagrange functions
55  % dimrange: dimension of the range
56  % grid.nelements: @copybrief gridbase.nelements
57 
58  df.pdeg = df_info.pdeg;
59  df.dimrange = df_info.dimrange;
60  df.grid = df_info.grid;
61  df.df_info = df_info;
62  df.dofs=dofs;
63 
64  % dependent:
65  df.nelements = df_info.grid.nelements;
66  df.ndofs = df_info.ndofs;
67  df.ndofs_per_element = df_info.ndofs_per_element;
68  if isempty(dofs)
69  df.dofs = zeros(df.ndofs,1);
70  end
71 
72  df.dofs_global_coordinate = zeros(df.ndofs, 2);
73  for i = 1:df.ndofs_per_element
74  df.dofs_global_coordinate(df_info.get_global_dof_index(':', i), :) ...
75  = local2global(df.grid, 1:df.nelements, df_info.dofs_lcoord(i, :), []);
76  end
77  end
78 
79  function cdf = get_component(this, ncomp)
80  % extraction of component of vectorial fem function
81  % ncomp can be vector
82 
83  cdf_info = get(this.df_info, ncomp);
84  indices = this.df_info.get_dof_ids_global(ncomp);
85  cdf = Fem.DiscFunc(this.dofs(indices), cdf_info);
86  end
87 
88  function p = plot(this, params)
89  % plot as colormap,
90  % todo: ids as titles. enhanced subplots
91 
92  if nargin<2
93  params = [];
94  end
95 
96  if this.dimrange > 1
97 
98  for i = 1:length(this.df_info)
99 
100  df = get_component(this, i);
101  if df.dimrange == 1
102  params.title = this.df_info.idmap{i};
103  if i > 1
104  figure,
105  end
106  end
107  p = plot(df, params);
108  end
109  else
110 
111  p = plot_discfunc(this, params);
112  if isfield(params, 'title')
113  title(params.title);
114  end
115  end
116  end
117 
118  function res = evaluate(this, einds, lcoord, varargin)
119  % local evaluate on several elements
120 
121  if isa(einds, 'gridbase') % for compatibility reasons
122 
123  einds = lcoord;
124  lcoord = varargin{1};
125  end
126 
127  % indices (all dimensions)
128  if strcmp(einds, ':')
129  gids = this.df_info.get_global_dof_index();
130  else
131  gids = this.df_info.get_global_dof_index(...
132  einds, 1:this.ndofs_per_element);
133  end
134 
135  % get values and compute
136  d = this.dofs(gids);
137  d = d(:);
138  d = reshape(d, size(gids, 1), this.ndofs_per_element);
139  basis_values = evaluate_basis(this.df_info, lcoord);
140  res = d * basis_values;
141  end
142 
143  function res = evaluate_derivative(this, einds, lcoord)
144  % computes the gradient in local coordinate
145  % res(:, i, j) is the x_i derivative of the j-th component
146 
147  % indices (all dimensions)
148  if strcmp(einds, ':')
149  gids = this.df_info.get_global_dof_index();
150  JIT = this.grid.JIT;
151  else
152  gids = this.df_info.get_global_dof_index(...
153  einds, 1:this.ndofs_per_element);
154  JIT = this.grid.JIT(einds, :, :);
155  end
156 
157  % get values
158  d = this.dofs(gids);
159 
160  res = zeros(size(gids, 1), 2, this.dimrange);
161  for i = 1:this.dimrange
162 
163  grad_hat_basis = evaluate_scalar_basis_derivative(this.df_info, lcoord, i);
164 
165  % basis gradients on elements
166  gradx_basis = JIT(:, 1, 1) * grad_hat_basis(:, 1)' ...
167  + JIT(:, 1, 2) * grad_hat_basis(:, 2)';
168  grady_basis = JIT(:, 2, 1) * grad_hat_basis(:, 1)' ...
169  + JIT(:, 2, 2) * grad_hat_basis(:, 2)';
170 
171  res(:, 1, i) = sum(gradx_basis .* d(:, this.df_info.dof_ids_local{i}), 2);
172  res(:, 2, i) = sum(grady_basis .* d(:, this.df_info.dof_ids_local{i}), 2);
173  end
174  end
175 
176  function res = l2_norm(this)
177  % computes the l2-norm
178 
179  res_sqr = this.dofs(:)' * ...
180  this.df_info.l2_inner_product_matrix * this.dofs(:);
181 
182  if res_sqr < 0
183  res_sqr = 0;
184  end
185 
186  res = sqrt(res_sqr);
187  end
188 
189  function res = h10_norm(this)
190  % computes h10-norm
191 
192  res_sqr = this.dofs(:)' * ...
193  this.df_info.h10_inner_product_matrix * this.dofs(:);
194 
195  if res_sqr < 0
196  res_sqr = 0;
197  end
198 
199  res = sqrt(res_sqr);
200  end
201 
202  function res = h1_norm(this)
203  % computes h1-norm
204 
205  res_sqr = this.dofs(:)' * ...
206  (this.df_info.l2_inner_product_matrix + ...
207  this.df_info.h10_inner_product_matrix) * this.dofs(:);
208 
209  if res_sqr < 0
210  res_sqr = 0;
211  end
212 
213  res = sqrt(res_sqr);
214  end
215 
216  function res = subsref(this, S)
217  % This method enables indexation of discrete functions
218  %
219  % redirects arguments to evaluate function, so
220  % @code
221  % df(einds, lcoord) == df.evaluate(einds, lcoord)
222  % @endcode
223 
224  % t = S.type;
225  % keyboard;
226  if S(1).type~='('
227  res = builtin('subsref', this, S);
228  else
229  res = this.evaluate(S.subs{:});
230  end
231  end
232 
233  % copy
234  function cdf = copy(this)
235 
236  cdf = Fem.DiscFunc(this.dofs, this.df_info);
237  end
238 
239  % addition
240  function df3 = plus(df1, df2)
241 
242  df3 = Fem.DiscFunc([], df1.df_info);
243  df3.dofs = df1.dofs + df2.dofs;
244  end
245 
246  % subtraction
247  function df3 = minus(df1, df2)
248 
249  df3 = Fem.DiscFunc([], df1.df_info);
250  df3.dofs = df1.dofs - df2.dofs;
251  end
252 
253  % negative
254  function df2 = uminus(df1)
255 
256  df2 = Fem.DiscFunc([], df1.df_info);
257  df2.dofs = -df1.dofs;
258  end
259 
260  % multiplication
261  function df2 = mtimes(factor, df1)
262 
263  df2 = Fem.DiscFunc([], df1.df_info);
264  df2.dofs = factor * df1.dofs;
265  end
266  end
267 end
scalar Lagrange FE functions on triangular grid
Definition: DefaultInfo.m:19
nelements
number of elements
Definition: DiscFunc.m:78
Base class for all grid classes.
Definition: gridbase.m:17
nelements
number of overall elements (leaf + nonleaf)
Definition: gridbase.m:30
represents a continous piecewise polynomial function of arbitrary dimension. Can be used for all fini...
Definition: DiscFunc.m:18