3 %
function computing the local-to-global dof map of a fem discrete
function
5 %
'gid = global_dof_index(elid,lagrange_node)' yields the global
6 % index of the first dof of the basis
function corresponding to the given
7 % Lagrange node and element
'elid'.
'gid:(gid+dimrange-1)' are the subsequent
8 % dof indices of the vectorial
function in the lagrange node. first all dofs
9 % in nodes are counted, then all dofs in element interior, then the dofs on
12 % The Lagrange nodes
'l_1,...,l_m' with
'm=0.5*(pdeg+1)*(pdeg+2)' are sorted in
25 % v_1 = l_1 v_2 = l_(pdeg+1)
28 % where
'v_1,v_2,v_3' denote the sorting of the triangles corners.
30 % Bernard Haasdonk 11.1.2011
33 %
if ~isfield(params,
'debug')
37 % generate global dof index map
for scalar
function
39 nlagrange_nodes = (params.pdeg+1)*(params.pdeg+2)/2;
40 global_dof_index_scalar = zeros(grid.nelements,nlagrange_nodes);
41 lind_finished = zeros(1,nlagrange_nodes);
43 % 3 Lagrangenodes correspond to corners,
44 % global dof numbers: 1:nvertices
46 lind_v2 = 1+params.pdeg;
47 lind_v3 = (params.pdeg+1)*(params.pdeg+2)/2;
48 linds_corner = [lind_v1,lind_v2,lind_v3];
49 global_dof_index_scalar(:,linds_corner) = ...
51 lind_finished(linds_corner) = 1;
53 % Lagrangenodes of interior:
for each element
54 % global dof numbers: (nvertices+1):(nvertices+nlangr_interior*nelements)
55 lagrange_nodes = lagrange_nodes_lcoord(params.pdeg);
56 linds_interior = find(...
57 ((1-lagrange_nodes(:,1)-lagrange_nodes(:,2))>eps) & ...
58 (lagrange_nodes(:,1)>eps) & ...
59 (lagrange_nodes(:,2)>eps) ...
62 if ~isempty(linds_interior)
63 gidtmp = (1:(length(linds_interior)*grid.nelements))+grid.nvertices;
64 gidtmp = reshape(gidtmp,length(linds_interior),grid.nelements)';
65 global_dof_index_scalar(:,linds_interior) = gidtmp;
66 lind_finished(linds_interior) = 1;
69 % Lagrangenodes on edges: are remaining ones
71 % nvertices + nlangr_interior*nelements + 1
72 % until nvertices + nlangr_interior*nelements + nedges_interior * (pdeg-1)
73 linds_edges = cell(3,1);
74 linds_edges{1} = find( ...
75 (lagrange_nodes(:,2)<eps) & ...
76 ((1-lagrange_nodes(:,1)-lagrange_nodes(:,2))>eps) & ...
77 (lagrange_nodes(:,1)>eps) ...
80 linds_edges{2} = find( ...
81 ((1-lagrange_nodes(:,1)-lagrange_nodes(:,2))<eps) & ...
82 (lagrange_nodes(:,1)>eps) & ...
83 (lagrange_nodes(:,2)>eps) ...
86 linds_edges{3} = find( ...
87 (lagrange_nodes(:,1)<eps) & ...
88 ((1-lagrange_nodes(:,1)-lagrange_nodes(:,2))>eps) & ...
89 (lagrange_nodes(:,2)>eps) ...
91 %
switch order of 3rd edge dofs, such that all are counterclockwise
92 linds_edges{3} = linds_edges{3}(end:-1:1);
94 % insert
new nodes
for edges with element index larger than
95 % neighbour => boundary and inner edges treated once.
97 offset = (length(linds_interior)*grid.nelements)+grid.nvertices;
99 elids{i} = find(grid.NBI(:,i)<(1:grid.nelements)
');
100 gidtmp = (1:(length(linds_edges{i})*length(elids{i})))+offset;
101 gidtmp = reshape(gidtmp,length(linds_edges{i}),length(elids{i}))';
102 global_dof_index_scalar(elids{i},linds_edges{i}) = gidtmp;
103 offset = offset + (length(linds_edges{i})*length(elids{i}));
106 % set correct gid
for elements with index smaller than neighbour
107 not_elids = cell(3,1);
108 lind_inv_edges = cell(3,1); % invert order
110 % not_elids{i} satisfies
111 % grid.NBI(not_elids{i},i)>not_elids{i});
112 % hence, not_elids{i} are the number of the
113 % elements, with index smaller than neighbour
114 % and the nieghbours are accessable over local edge number i
115 not_elids{i} = find(grid.NBI(:,i)>(1:grid.nelements)
');
116 lind_inv_edges{i} = linds_edges{i}(end:-1:1);
119 % loop over all different local edge number combinations
120 for j = 1:3 % edge number on lower element index side
121 not_elids_neighbour = grid.NBI(not_elids{j},j);
123 % if ~isequal(grid.NBI(not_elids_neighbour,j),not_elids{j});
124 % disp('problem in dof enumeration!
');
128 for i = 1:3 % edge number on larger element index side
129 subind_i = find(grid.NBI(not_elids_neighbour,i)==not_elids{j});
130 gidtmp = global_dof_index_scalar(...
131 not_elids_neighbour(subind_i), ...
133 global_dof_index_scalar(...
134 not_elids{j}(subind_i),...
135 lind_inv_edges{j}) = ...
142 lind_finished(linds_edges{i}) = 1;
146 if ~isempty(find(lind_finished==0))
147 error('not all lagrange indices treated!!!
');
150 if ~isempty(find(global_dof_index_scalar == 0))
151 error('not all global dof numbers set!!
');
154 % map for vectorial function simple scaling keeping 1 fix:
155 global_dof_index = (global_dof_index_scalar -1)* params.dimrange+1;
157 % check: local dofs mapped to identical global dofs must have
158 % identical global coordinates of lagrange point.
159 %disp('implement test!
');
function global_dof_index = fem_global_dof_index(params,triagrid grid)
function computing the local-to-global dof map of a fem discrete function