rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fem_global_dof_index.m
Go to the documentation of this file.
1 function global_dof_index = fem_global_dof_index(params,grid)
2 %function global_dof_index = fem_global_dof_index(params,grid)
3 % function computing the local-to-global dof map of a fem discrete function
4 %
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
10 % edge-interiors.
11 %
12 % The Lagrange nodes 'l_1,...,l_m' with 'm=0.5*(pdeg+1)*(pdeg+2)' are sorted in
13 % the following order
14 % @verbatim
15 % l_m = v_3
16 % *
17 % |\
18 % | \
19 % | \
20 % * *
21 % | \
22 % | \
23 % |______\
24 % * * *
25 % v_1 = l_1 v_2 = l_(pdeg+1)
26 % @endverbatim
27 %
28 % where 'v_1,v_2,v_3' denote the sorting of the triangles corners.
29 
30 % Bernard Haasdonk 11.1.2011
31 
32 
33 %if ~isfield(params,'debug')
34 %params.debug = 0;
35 %end;
36 
37  % generate global dof index map for scalar function
38 
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);
42 
43  % 3 Lagrangenodes correspond to corners,
44  % global dof numbers: 1:nvertices
45  lind_v1 = 1;
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) = ...
50  grid.VI;
51  lind_finished(linds_corner) = 1;
52 
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) ...
60  );
61 
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;
67  end;
68 
69  % Lagrangenodes on edges: are remaining ones
70  % global dof numbers:
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) ...
78  );
79 
80  linds_edges{2} = find( ...
81  ((1-lagrange_nodes(:,1)-lagrange_nodes(:,2))<eps) & ...
82  (lagrange_nodes(:,1)>eps) & ...
83  (lagrange_nodes(:,2)>eps) ...
84  );
85 
86  linds_edges{3} = find( ...
87  (lagrange_nodes(:,1)<eps) & ...
88  ((1-lagrange_nodes(:,1)-lagrange_nodes(:,2))>eps) & ...
89  (lagrange_nodes(:,2)>eps) ...
90  );
91  % switch order of 3rd edge dofs, such that all are counterclockwise
92  linds_edges{3} = linds_edges{3}(end:-1:1);
93 
94  % insert new nodes for edges with element index larger than
95  % neighbour => boundary and inner edges treated once.
96  elids = cell(3,1);
97  offset = (length(linds_interior)*grid.nelements)+grid.nvertices;
98  for i=1:3
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}));
104  end;
105 
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
109  for i = 1:3
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);
117  end;
118 
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);
122 % if params.debug
123 % if ~isequal(grid.NBI(not_elids_neighbour,j),not_elids{j});
124 % disp('problem in dof enumeration!');
125 % keyboard;
126 % end;
127 % end;
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), ...
132  linds_edges{i});
133  global_dof_index_scalar(...
134  not_elids{j}(subind_i),...
135  lind_inv_edges{j}) = ...
136  gidtmp;
137  end;
138  end;
139 
140  % mark finished
141  for i = 1:3
142  lind_finished(linds_edges{i}) = 1;
143  end;
144 
145  % checks:
146  if ~isempty(find(lind_finished==0))
147  error('not all lagrange indices treated!!!');
148  end;
149 
150  if ~isempty(find(global_dof_index_scalar == 0))
151  error('not all global dof numbers set!!');
152  end;
153 
154  % map for vectorial function simple scaling keeping 1 fix:
155  global_dof_index = (global_dof_index_scalar -1)* params.dimrange+1;
156 
157  % check: local dofs mapped to identical global dofs must have
158  % identical global coordinates of lagrange point.
159  %disp('implement test!');
160  %keyboard;
161 
function global_dof_index = fem_global_dof_index(params,triagrid grid)
function computing the local-to-global dof map of a fem discrete function