3 % Composite
function space
for composition of FE
function spaces on
6 properties (SetAccess =
private, Dependent)
8 % polynomial degree, possibly vector of dimrange > 1
11 % dimension of range space
17 % number of DOFs per grid element
20 % grid of type .gridbase
23 % determinant of reference mapping
28 l2_inner_product_matrix;
29 h10_inner_product_matrix;
32 properties (SetAccess =
private)
34 % a cell array of length dimrange, i-th entry is a 1 x ndofs_per_element(dimrange=i) matrix
37 % number of grid cells
41 properties (Access = private, Hidden)
43 % vectors of length size(this)
55 % varargin: either parameters for IdMapNode constructor or
56 % list of function spaces following
id-strings: (df1, id1,
59 if iscell(varargin{1})
60 superclass_args = varargin;
62 superclass_args{1} = varargin(2:2:end);
63 superclass_args{2} = varargin(1:2:end-1);
68 consistency_check(cfs);
70 cfs.dim_offsets = zeros(length(cfs), 1);
71 cfs.ldof_offsets = zeros(length(cfs), 1);
72 cfs.gdof_offsets = zeros(length(cfs), 1);
74 cfs.dim_offsets(i) = cfs.dim_offsets(i-1) + cfs.values{i-1}.dimrange;
75 cfs.ldof_offsets(i) = cfs.ldof_offsets(i-1) + cfs.values{i-1}.ndofs_per_element;
76 cfs.gdof_offsets(i) = cfs.gdof_offsets(i-1) + cfs.values{i-1}.ndofs;
79 cfs.dof_ids_local = cellfun(...
80 @(fs, offset) cellfun(@(vec) vec+offset, fs.dof_ids_local(:),
'UniformOutput',
false), ...
81 cfs.values(:), num2cell(cfs.ldof_offsets(:)),
'UniformOutput',
false);
83 cfs.dof_ids_local = cat(1, cfs.dof_ids_local{:});
85 cfs.nelements = cfs.grid.nelements;
88 function this = set(
this, index, value)
90 if index == (length(this)+1)
91 this.dim_offsets = [this.dim_offsets; this.dim_offsets(end) + value.dimrange];
92 this.ldof_offsets = [this.ldof_offsets; this.ldof_offsets(end) + value.ndofs_per_element];
93 this.gdof_offsets = [this.gdof_offsets; this.gdof_offsets(end) + value.ndofs];
94 elseif index > (length(this) + 1)
97 this = set@
DataTree.IdMapNode(this, index, value);
98 consistency_check(this);
100 for i = 1:length(this) - index
101 this.dim_offsets(index+i) = this.dim_offsets(index+i-1) + cfs.values{index+i-1}.dimrange;
102 this.ldof_offsets(index+i) = this.ldof_offsets(index+i-1) + cfs.values{index+i-1}.ndofs_per_element;
103 this.gdof_offsets(index+i) = this.gdof_offsets(index+i-1) + cfs.values{index+i-1}.ndofs;
107 function consistency_check(
this)
108 % grids have to be identical
109 for i = 2:length(
this)
110 if this.values{1}.grid ~= this.values{i}.grid;
111 error(
'Grids inconsistent in CompositeFunctionSpace.');
116 function pdeg =
get.pdeg(
this)
118 pdeg = cellfun(@(fs)fs.pdeg(:)
', this.values, 'UniformOutput
', false);
119 pdeg = cat(2, pdeg{:});
122 function dimrange = get.dimrange(this)
123 % sum of children dimensions
124 dimrange = this.dim_offsets(end) + this.values{end}.dimrange;
127 function ndofs = get.ndofs(this)
128 % sum of ndofs of children
129 ndofs = this.gdof_offsets(end) + this.values{end}.ndofs;
132 function ndofs_per_element = get.ndofs_per_element(this)
133 % sum of ndofs_per_element of children
134 ndofs_per_element = this.ldof_offsets(end) + this.values{end}.ndofs_per_element;
137 function grid = get.grid(this)
145 function detDF = get.detDF(this)
153 function dofs_lcoord = get.dofs_lcoord(this)
154 dofs_lcoord = cellfun(@(fs) fs.dofs_lcoord, this.values, 'UniformOutput
', false);
155 dofs_lcoord = cat(1, dofs_lcoord{:});
158 function dofs_edges_llcoord = get.dofs_edges_llcoord(this)
159 dofs_edges_llcoord = cellfun(@(fs) fs.dofs_edges_llcoord, ...
160 this.values, 'UniformOutput
', false);
161 dofs_edges_llcoord = cat(1, dofs_edges_llcoord{:});
164 function l2_inner_product_matrix = get.l2_inner_product_matrix(this)
165 l2_inner_product_matrix = cellfun(@(fs) fs.l2_inner_product_matrix, ...
166 this.values, 'UniformOutput
', false);
167 l2_inner_product_matrix = blkdiag(l2_inner_product_matrix{:});
170 function h10_inner_product_matrix = get.h10_inner_product_matrix(this)
171 h10_inner_product_matrix = cellfun(@(fs) fs.h10_inner_product_matrix, ...
172 this.values, 'UniformOutput
', false);
173 h10_inner_product_matrix = blkdiag(h10_inner_product_matrix{:});
176 function res = evaluate_basis(this, lcoord)
177 % evaluation of all basis functions in local coordinate
179 for i = 1:length(this)
180 res = blkdiag(res, evaluate_basis(this.values{i}, lcoord));
182 %res = cellfun(@(fs) evaluate_basis(fs, lcoord), this.values, 'UniformOutput
', false);
183 %res = blkdiag(res{:});
186 function res = evaluate_scalar_basis_derivative(this, lcoord, ncomp)
187 % evaluation of the gradient of a scalar basis in local coordinate
188 child_ind = find(this.dim_offsets < ncomp, 1, 'last
');
189 res = evaluate_scalar_basis_derivative(this.values{child_ind}, ...
190 lcoord, ncomp - this.dim_offsets(child_ind));
193 function res = evaluate_basis_function(this, lcoord, i)
194 % evaluation of i-th basis function in local coordinate
195 child_ind = find(this.ldof_offsets < i, 1, 'last
');
196 res = zeros(this.dimrange, 1);
197 res(this.dim_offsets(child_ind) + (1:this.values{child_ind}.dimrange)) ...
198 = evaluate_basis_function(this.values{child_ind}, lcoord, i - this.ldof_offsets(child_ind));
201 function res = evaluate_basis_function_derivative(this, lcoord, i)
202 % evaluation of the gradient of i-th basis function in local
204 child_ind = find(this.ldof_offsets < i, 1, 'last
');
205 res = zeros(this.dimrange, 2); % R^2
206 res(this.dim_offsets(child_ind) + (1:this.values{child_ind}.dimrange), :) ...
207 = evaluate_basis_function_derivative(this.values{child_ind}, ...
208 lcoord, i - this.ldof_offsets(child_ind));
211 function res = get_global_dof_index(this, varargin)
212 % returns entries of global-dof-map for several elements and several
215 res = zeros(this.nelements, this.ndofs_per_element);
216 for i = 1:length(this)
217 res(:, this.ldof_offsets(i)+(1:this.values{i}.ndofs_per_element)) ...
218 = get_global_dof_index(this.values{i}) + this.gdof_offsets(i);
224 if ~strcmp(einds, ':
')
227 res = zeros(l, length(gids));
228 for i = 1:length(gids)
229 child_ind = find(this.ldof_offsets < gids(i), 1, 'last
');
230 res(:, i) = get_global_dof_index(this.values{child_ind}, ...
231 einds, gids(i) - this.ldof_offsets(child_ind)) + this.gdof_offsets(child_ind);
236 function res = get_dof_ids_global(this, ncomp)
237 % returns global dof ids belonging to one component (indices into
240 res = get_dof_ids_global(this.values{ncomp(1)}, ncomp(2:end)) + this.gdof_offsets(ncomp(1));
241 elseif length(ncomp) == 1
242 res = get_dof_ids_global(this.values{ncomp}, []) + this.gdof_offsets(ncomp);
248 function df = interpol_local(this, func, params)
254 dofs_tmp = cell(1, length(this));
255 for i = 1:length(this)
256 func_tmp = @(varargin)feval(...
257 @(y) y(:, this.dim_offsets(i)+(1:this.values{i}.dimrange)), ...
259 df_tmp = interpol_local(this.values{i}, func_tmp, params);
260 dofs_tmp{i} = df_tmp.dofs(:);
263 df = Fem.DiscFunc([], this);
264 df.dofs = cat(1, dofs_tmp{:});
Data Tree element which can be filtered by ids
Composite function space for composition of FE function spaces on same grid.
Abstract class for implementing finite elements. Fem info classes implementing this interface are com...