rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
triagrid.m
1 classdef triagrid < gridbase
2  % A triangular conforming grid in two dimensions.
3  %
4  % General geometrical information is stored including neighbour
5  % information. Therefore also boundary neighbour relations can be
6  % specified. Boundary edges can be marked by "painting rectangles": the
7  % edges with midpoints within such a rectangle are marked accordingly.
8  % By this boundary edges can be marked for later special use. Much
9  % (partially redundant) information is stored in the grid, which might be
10  % useful in simulations.
11 
12  properties
13  % number of interior edges
14  nedges_interior;
15 
16  % number of boundary edges
17  nedges_boundary;
18  end;
19 
20  methods
21 
22  function grid= triagrid(varargin)
23  %function triagrid(varargin)
24  % constructor of a triangular conform grid in 2 dimensions with following
25  % Synopsis:
26  %
27  % - triagrid() : construction of a default triagrid (2d unit square,
28  % loaded from file, -1 as outer neighbour indices)
29  % - @link triagrid() triagrid(tgrid) @endlink : copy-constructor
30  % - @link triagrid() triagrid(params) @endlink : in this case either
31  % -# the field grid_initfile is existent in params. Then the file is read
32  % and a pointlist p and a triangle. Procedure is then executing the
33  % following constructor
34  % -# a structured equidistant triangle grid is generated
35  % - 'params.xnumintervals' : number of elements along x directions
36  % - 'params.ynumintervals' : number of elements along y directions
37  % - 'params.xrange,yrange' : intervals covered along the axes
38  % .
39  % with the optional fields
40  % - 'params.bnd_rect_corner1' : coordinates of lower corner of to
41  % be marked boundaries
42  % - 'params.bnd_rect_corner2' : coordinates of upper corner of to
43  % be marked boundaries
44  % - 'params.bnd_rect_index': integer index to be set on the edges
45  % in the above defined rectangle. Should not be positive integer
46  % in the range of the number of elements. use negative indices for
47  % certain later discrimination.
48  % .
49  % For the last three optional boundary settings, also multiple
50  % rectangles can be straightforwardly defined by accepting matrix
51  % of columnwise corners1, corners2 and a vector of indices for the
52  % different rectangles.
53  % - @link triagrid() triagrid(p,t,params) @endlink : generate triagrid from
54  % triangle-data with certain options.
55  % - p is assumed to be a 2 x npoints matrix with coordinates
56  % - t is assumed to be a XX x ntriangles matrix, but only first three
57  % rows are used == vertex indices, in clockwise order as default, all
58  % nondefined edges are set to -1, then the following "rectangles" are
59  % set as specified in params
60  %
61  % Using this class, grids from PDETOOLS can be used:
62  %
63  % pdetools
64  % %%% => generate your grid and export 'p' and 't' to MATLAB workspace
65  % @code
66  % save('mygrid','p','t')
67  % grid = triagrid(struct('grid_initfile','mygrid'));
68  % @endcode
69  %
70  % perhaps later: constructor by duneDGF-file?
71  % perhaps later: contructor-flag: full vs non-full
72  % => only compute redundant information if required.
73  %
74  % Parameters:
75  % 'varargin' : variable number of input arguments, see above for description
76  % of possible configurations.
77  %
78  % Return values:
79  % 'grid' : generated triagrid
80  %
81  % generated fields of grid:
82  % nelements: number of elements
83  % nvertices: number of vertices
84  % nneigh: 3
85  % A : vector of element area
86  % Ainv : vector of inverted element area
87  % X : vector of vertex x-coordinates
88  % Y : vector of vertex y-coordinates
89  % VI : matrix of vertex indices: 'VI(i,j)' is the global index of j-th
90  % vertex of element i
91  % CX : vector of centroid x-values
92  % CY : vector of centroid y-values
93  % NBI : 'NBI(i,j) = ' element index of j-th neighbour of element i
94  % boundary faces are set to -1 or negative values are requested by
95  % 'params.boundary_type'
96  % INB : 'INB(i,j) = ' local edge number in 'NBI(i,j)' leading from
97  % element 'NBI(i,j)' to element 'i', i.e. satisfying
98  % 'NBI(NBI(i,j), INB(i,j)) = i'
99  % EL : 'EL(i,j) = ' length of edge from element 'i' to neighbour 'j'
100  % DC : 'DC(i,j) = ' distance from centroid of element i to NB j
101  % for boundary elements, this is the distance to the reflected
102  % element (for use in boundary treatment)
103  % NX : 'NX(i,j) = ' x-coordinate of unit outer normal of edge from el
104  % 'i' to NB 'j'
105  % NY : 'NY(i,j) = ' y-coordinate of unit outer normal of edge from el
106  % 'i' to NB 'j'
107  % ECX : 'ECX(i,j) = ' x-coordinate of midpoint of edge from el 'i' to NB 'j'
108  % ECY : 'ECY(i,j) = ' y-coordinate of midpoint of edge from el 'i' to NB 'j'
109  % SX : vector of x-coordinates of point `S_i` (for rect: identical to
110  % centroids)
111  % SY : vector of y-coordinate of point `S_j` (for rect: identical to
112  % centroids)
113  % ESX : 'ESX(i,j) = ' x-coordinate of point `S_{ij}` on edge el i to NB j
114  % ESY : 'ESY(i,j) = ' y-coordinate of point `S_{ij}` on edge el i to NB j
115  % DS : 'DS(i,j) = ' distance from `S_i` of element i to `S_j` of NB j
116  % for boundary elements, this is the distance to the reflected
117  % element (for use in boundary treatment)
118  % hmin : minimal element-diameter
119  % alpha: geometry bound (simultaneously satisfying `\alpha \cdot h_i^d
120  % \leq A(T_i)`, `\alpha \cdot \mbox{diam}(T_i) \leq h_i^{d-1}` and
121  % `\alpha \cdot h_i \leq `dist(midpoint `i` to any neigbour) )
122  % JIT : Jacobian inverse transposed 'JIT(i,:,:)' is a 2x2-matrix of the Jac.
123  % Inv. Tr. on element 'i'
124  %
125  % \note for diffusion-discretization with FV-schemes, points `S_i` must exist,
126  % such that `S_i S_j` is perpendicular to edge 'i j', the intersection points
127  % are denoted `S_{ij}`
128  %
129 
130  % Bernard Haasdonk 9.5.2007
131 
132  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133  % copy constructor
134  if (nargin==1) & isa(varargin{1},'triagrid')
135  grid = triagrid; % create default triagrid
136 
137  fnames = fieldnames(varargin{1});
138  for i=1:length(fnames)
139  grid.(fnames{i}) = varargin{1}.(fnames{i});
140  end
141 
142  else
143 
144  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145  % default constructor: unit square
146  if (nargin==0)
147  % p = [0.0 0.5 1.0 0.0 0.5 1.0 0.0 0.5 1.0; ...
148  % 0.0 0.0 0.0 0.5 0.5 0.5 1.0 1.0 1.0 ];
149  % t = [1 2 2 3 4 5 5 6; ...
150  % 2 5 3 6 5 8 6 9; ...
151  % 4 4 5 5 7 7 8 8] ;
152  params = [];
153  load 2dsquaretriang;
154 
155  % mark boundary in rectangle from [-1,-1] to [+2,+2] with index -1
156  params.bnd_rect_corner1 = [-1,-1]';
157  params.bnd_rect_corner2 = [2 2]';
158  params.bnd_rect_index = [-1];
159  elseif nargin==1
160  params = varargin{1};
161  if isfield(params,'grid_initfile')
162  [~, ~, ext] = fileparts(params.grid_initfile);
163  switch ext
164  case '.mat'
165  tmp = load(params.grid_initfile);
166  t = tmp.t(1:3,:);
167  p = tmp.p;
168  case '.msh'
169  [p, t] = triagrid.read_msh(params.grid_initfile);
170  otherwise
171  error('File name extension not supported in grid initialization');
172  end
173  else
174  nx = params.xnumintervals;
175  ny = params.ynumintervals;
176  nvertices =(nx+1)*(ny+1);
177 
178  dx = (params.xrange(2)-params.xrange(1))/nx;
179  dy = (params.yrange(2)-params.yrange(1))/ny;
180 
181  % set vertex coordinates
182  vind = (1:(nx+1)*(ny+1));
183  X = mod(vind-1,nx+1) * dx + params.xrange(1);
184  Y = floor((vind-1)/(nx+1))*dy + params.yrange(1);
185  p = [X(:)'; Y(:)'];
186 
187  % identify triangles:
188  % ----
189  % | /|
190  % |/ |
191  % ----
192 
193  all_ind = 1:(nx+1)*(ny+1);
194  % index vector of lower left corners, i.e. not last col/row
195  lc_ind = find((mod(all_ind,nx+1)~=0) & (all_ind < (nx+1)*ny));
196  t1 = [lc_ind;lc_ind+1;lc_ind+2+nx]; % lower triangles
197  t2 = [lc_ind;lc_ind+nx+2;lc_ind+nx+1]; % upper triangles
198  t = [t1,t2];
199  end;
200  else % read p-e-t information from varargin
201  p =varargin{1};
202  t =varargin{2};
203  if size(t,1)>3
204  t = t(1:3,:);
205  end;
206  params = varargin{3};
207  end;
208 
209  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
210  % construct from p,t and params
211 
212  if ~isfield(params,'verbose')
213  params.verbose = 0;
214  end;
215 
216  % nx = params.xnumintervals;
217  % ny = params.ynumintervals;
218 
219  grid.nelements = size(t,2);
220  grid.nvertices = size(p,2);
221  grid.nneigh= 3;
222 
223  % set vertex coordinates
224  grid.X = p(1,:)';
225  grid.Y = p(2,:)';
226 
227  % set element vertex indices: numbering counterclockwise
228  % counterclockwise, edge j connects vertex j and j+1
229 
230  grid.VI = t';
231 
232  % get areas of grid-cells after VI and X,Y are available
233  %
234  % A(a b c) = 0.5 |Det ((b-a) (c-a)) |
235  grid.A = abs(area_triangle(...
236  [grid.X(grid.VI(:,1)), ...
237  grid.Y(grid.VI(:,1))], ...
238  [grid.X(grid.VI(:,2)), ...
239  grid.Y(grid.VI(:,2))], ...
240  [grid.X(grid.VI(:,3)), ...
241  grid.Y(grid.VI(:,3))]));
242  grid.A = grid.A(:);
243  % a11 = grid.X(grid.VI(:,2))-grid.X(grid.VI(:,1));
244  % a21 = grid.Y(grid.VI(:,2))-grid.Y(grid.VI(:,1));
245  % a12 = grid.X(grid.VI(:,3))-grid.X(grid.VI(:,1));
246  % a22 = grid.Y(grid.VI(:,3))-grid.Y(grid.VI(:,1));
247  % grid.A = 0.5 * (a11.*a22 - a21.*a12);
248  grid.Ainv = grid.A.^(-1);
249 
250  % midpoint coordinates of grid-cells
251  % equals cog of corners
252 
253  % coordinates of vertices: XX(elnum, vnum)
254  XX = reshape(grid.X(grid.VI(:)),size(grid.VI));
255  YY = reshape(grid.Y(grid.VI(:)),size(grid.VI));
256  grid.CX = mean(XX,2);
257  grid.CY = mean(YY,2);
258 
259  % edge-vectors: [DX(el,edge) DX (el,edge)]
260  DX = [XX(:,2:3), XX(:,1)] - XX;
261  DY = [YY(:,2:3), YY(:,1)] - YY;
262 
263  % matrix with edge-lengths
264  grid.EL = sqrt(DX.^2 + DY.^2);
265 
266  % matrix with (unit) normal components
267  grid.NX = grid.EL.^(-1) .* DY;
268  grid.NY = - grid.EL.^(-1) .* DX;
269 
270  % matrix with edge-midpoint-coordinates
271  % this computation yields epsilon-differing edge-midpoints on
272  % neighbouring elements, perhaps solve later.
273  grid.ECX = XX + DX * 0.5;
274  grid.ECY = YY + DY * 0.5;
275 
276  %%% determine indices of neighbouring elements, default: -1
277  NBI = -1 * ones(grid.nelements, grid.nneigh);
278  INB = zeros(grid.nelements, grid.nneigh);
279  % and now it gets complicated...
280 
281  % setup edge list e(1,i), e(2,i) are the point indices of the i-th edge
282  % eid(i) is the element number, which has the edge
283  % led(i) : local edge number, which is the edge
284  % e(:,i) in eid(i)
285  ee = zeros(2,grid.nelements*3);
286  % li = [1 2 2 3 3 1 4 5 5 6 6 4 ... ]
287  li = 1:grid.nelements*3;
288  li = [li;li];
289  li = reshape(li,6,grid.nelements);
290  li = [li(2:end,:); li(1,:)];
291  li = reshape(li,2,grid.nelements*3);
292  ee = t(li);
293  ee = sort(ee); % now smallest vindex above
294  elid = repmat(1:grid.nelements,3,1);
295  elid = elid(:)';
296  led = repmat((1:3)',1,grid.nelements);
297  led = led(:)';
298 
299  % generate sort key from both indices
300  key = ee(1,:) + grid.nvertices * ee(2,:);
301  [keysort, ind] = sort(key);
302  ee_sort = ee(:,ind);
303  elid_sort = elid(ind);
304  led_sort = led(ind);
305 
306  % find indices of duplicates by simple forward difference
307  % => these are inner edges!
308 
309  diff = keysort(1:end-1) - [keysort(2:end)];
310  inner_edges = find(diff==0);
311 
312  % prepare entries in NBI: for all i in inner_edges
313  % NBI(elid_sort(i),led_sort(i)) = elid_sort(i+1);
314  % INB(elid_sort(i),led_sort(i)) = led_sort(i+1);
315  % und umgekehrt!
316 
317  li = sub2ind(size(NBI),...
318  elid_sort(inner_edges),...
319  led_sort(inner_edges));
320  NBI(li) = elid_sort(inner_edges+1);
321  INB(li) = led_sort(inner_edges+1);
322  li = sub2ind(size(NBI),...
323  elid_sort(inner_edges+1),...
324  led_sort(inner_edges+1));
325  NBI(li) = elid_sort(inner_edges);
326  INB(li) = led_sort(inner_edges);
327 
328  % % find all element-pairs, which have a common edge
329  % % i.e. neighs(i,1) and neighs(i,2) are two elements, which
330  % % have the same edge i, where this edge is the
331  % % eind(i,1)-th edge (1..3) in the first element
332  % % eind(i,2)-th edge (1..3) in the first element
333  %
334  % nedges = max(t(:));
335  % ehist = hist(t(:),1:nedges);
336  % if max(ehist)>3
337  % error('edge occuring in more than 2 triangles!!');
338  % end;
339  % inner_edges = find(ehist==2);
340  % neighs = zeros(length(inner_edges),2);
341  % eind = zeros(length(inner_edges),2);
342  %
343  % % somehow map edge-numbers => triangle numbers
344  % % need two of them, as occasionally global and local edge numbers
345  % % can coincide:
346  % % edgemap1(i,locedgenum) = elementno if edge i is local edge in elementno
347  % % edgemap2(i,locedgenum) = elementno if edge i is local edge in elementno
348  %
349  % edgemap1 = nan * ones(nedges,grid.nneigh);%
350  %
351  % [locedgenum,triangnum] = ind2sub(size(t),1:length(t(:)));
352  % li = sub2ind(size(edgemap1),t(:),locedgenum(:));
353  % edgemap1(li) = triangnum; % here due to duplicates, only the last
354  % % entry is taken
355  %
356  % % remove these entries from t and repeat for 2nd edgemap
357  % t2 = t;
358  % [edgenum,locedgenum] = find(~isnan(edgemap1));
359  % li = sub2ind(size(edgemap1),edgenum(:),locedgenum(:));
360  %
361  % li2 = sub2ind(size(t2),locedgenum(:),edgemap1(li));
362  % t2(li2) = 0;
363  %
364  %
365  % edgemap2 = nan * ones(nedges,grid.nneigh);
366  % nonzeros = find(t2~=0);
367  %
368  % [locedgenum,triangnum] = ind2sub(size(t2),1:length(nonzeros));
369  % li = sub2ind(size(edgemap2),t2(nonzeros),locedgenum(:));
370  % edgemap2(li) = triangnum;
371  % % now together edgemap1 and edgemap 2 represent the edge information.
372  %
373  % % extract inner edges
374  % edgemap = [edgemap1(inner_edges,:), edgemap2(inner_edges,:)];
375  % % check, that exactly two entries per row are non-nan
376  % entries = sum(~isnan(edgemap),2);
377  % if (min(entries)~=2) | max(entries)~=2
378  % disp('error in neighbour detection, please check');
379  % keyboard;
380  % end;
381  %
382  % [mi, imi] = min(edgemap,[],2);
383  % [ma, ima] = max(edgemap,[],2);
384  % neighs = [mi, ma];
385  % eind = [imi, ima];
386  %
387  % % then fill NBI and INB in a vectorized way, i.e.
388  % % for all edges:
389  % % NBI(neighs(i,1), eind(i,1)) = neighs(i,2);
390  % % NBI(neighs(i,2), eind(i,2)) = neighs(i,1);
391  % % INB(neighs(i,1), eind(i,1)) = eind(i,2);
392  % % INB(neighs(i,2), eind(i,2)) = eind(i,1);
393  %
394  % l1 = sub2ind( size(NBI), neighs(:,1) , eind(:,1));
395  % l2 = sub2ind( size(NBI), neighs(:,2) , eind(:,2));
396  % NBI(l1) = neighs(:,2);
397  % NBI(l2) = neighs(:,1);
398  % INB(l1) = eind(:,2);
399  % INB(l2) = eind(:,1);
400 
401  % search non-inner boundaries and their midpoints
402 
403  li = find(NBI==-1);
404  SX = grid.ECX(li(:));
405  SY = grid.ECY(li(:));
406 
407  % default-boundary = -1
408  bnd_ind = -1 * ones(length(li),1);
409 
410  if isfield(params,'bnd_rect_index')
411  if isfield(params,'boundary_type')
412  error(['Do not specify both bnd_rect_index and boundary_type', ...
413  ' in triagrid construction!']);
414  end;
415  if (max(params.bnd_rect_index)>0)
416  error('boundary indices must be negative!');
417  end;
418  if size(params.bnd_rect_corner1,1) == 1
419  params.bnd_rect_corner1 = params.bnd_rect_corner1';
420  end;
421  if size(params.bnd_rect_corner2,1) == 1
422  params.bnd_rect_corner2 = params.bnd_rect_corner2';
423  end;
424  for i = 1:length(params.bnd_rect_index)
425  indx = (SX > params.bnd_rect_corner1(1,i)) & ...
426  (SX < params.bnd_rect_corner2(1,i)) & ...
427  (SY > params.bnd_rect_corner1(2,i)) & ...
428  (SY < params.bnd_rect_corner2(2,i));
429  bnd_ind(indx) = params.bnd_rect_index(i);
430  end;
431  else
432  if isfield(params,'boundary_type')
433  bnd_ind = params.boundary_type([SX(:),SY(:)],params);
434  end;
435  end;
436 
437  NBI(li) = bnd_ind'; % set neighbours to boundary
438 
439  grid.NBI = NBI;
440  grid.INB = INB;
441 
442  % check grid consistency:
443  nonzero = find(NBI>0); % vector with vector-indices
444  [i,j] = ind2sub(size(NBI), nonzero); % vectors with matrix indices
445  NBIind = NBI(nonzero); % vector with global neighbour indices
446  INBind = INB(nonzero);
447  i2 = sub2ind(size(NBI),NBIind, INBind);
448  i3 = NBI(i2);
449  if ~isequal(i3,i)
450  % plot_element_data(grid,grid.NBI,params);
451  disp('neighbour indices are not consistent!!');
452  keyboard;
453  end;
454 
455  % matrix with centroid-distances
456  grid.DC = nan * ones(size(grid.CX,1),grid.nneigh);
457  nonzero = find(grid.NBI>0);
458  [elind, nbind] = ind2sub(size(grid.NBI),nonzero);
459 
460  CXX = repmat(grid.CX(:),1,grid.nneigh);
461  CYY = repmat(grid.CY(:),1,grid.nneigh);
462 
463  CXN = CXX;
464  CXN(nonzero) = grid.CX(grid.NBI(nonzero));
465 
466  CYN = CYY;
467  CYN(nonzero) = grid.CY(grid.NBI(nonzero));
468 
469  DC = sqrt((CXX-CXN).^2 + (CYY - CYN).^2);
470 
471  grid.DC(nonzero) = DC(nonzero);
472 
473  % computation of boundary distances: twice the distance to the border
474 
475  nondef = find(isnan(grid.DC));
476  nondef = nondef(:)';
477  [elind, nind] = ind2sub(size(grid.DC),nondef);
478  nind_plus_one = nind + 1;
479  i = find(nind_plus_one > grid.nneigh);
480  nind_plus_one(i) = 1;
481  nondef_plus_one = sub2ind(size(grid.DC),elind,nind_plus_one);
482  nondef_plus_one = nondef_plus_one(:)';
483 
484  d = zeros(length(nondef),1);
485 
486  q = [grid.CX(elind)'; grid.CY(elind)'];
487  p1 = [grid.X(grid.VI(nondef)), ...
488  grid.Y(grid.VI(nondef))];
489  p2 = [grid.X(grid.VI(nondef_plus_one)), ...
490  grid.Y(grid.VI(nondef_plus_one))];
491 
492  grid.DC(nondef) = 2 * dist_point_line(q,p1,p2);
493 
494  % make entries of ECX, ECY exactly identical for neighbouring elements!
495  % currently by construction a small eps deviation is possible.
496  %averaging over all pairs is required
497  nonzero = find(grid.NBI>0); % vector with vector-indices
498  [i,j] = ind2sub(size(grid.NBI), nonzero); % vectors with matrix indices
499  NBIind = NBI(nonzero); % vector with global neighbour indices
500  INBind = INB(nonzero); % vector with local edge indices
501  i2 = sub2ind(size(NBI),NBIind, INBind);
502  % determine maximum difference in edge-midpoints, but exclude
503  % symmetry boundaries by relative error < 0.0001
504  diffx = abs(grid.ECX(nonzero)-grid.ECX(i2));
505  diffy = abs(grid.ECY(nonzero)-grid.ECY(i2));
506  fi = find ( (diffx/(max(grid.X)-min(grid.X)) < 0.0001) & ...
507  (diffy/(max(grid.Y)-min(grid.Y)) < 0.0001) );
508 
509  %disp(max(diffx));
510  %disp(max(diffy));
511  % => 0 ! :-)
512  % keyboard;
513 
514  grid.ECX(nonzero(fi)) = 0.5*(grid.ECX(nonzero(fi))+ grid.ECX(i2(fi)));
515  grid.ECY(nonzero(fi)) = 0.5*(grid.ECY(nonzero(fi))+ grid.ECY(i2(fi)));
516 
517  % for diffusion discretization: Assumption of points with
518  % orthogonal connections to edges. Distances and intersections
519  % determined here. For triangles, this can simply be the
520  % circumcenters and the corresponding intersections
521 
522  q = [grid.X(grid.VI(:,1)), ...
523  grid.Y(grid.VI(:,1))];
524  p1 = [grid.X(grid.VI(:,2)), ...
525  grid.Y(grid.VI(:,2))];
526  p2 = [grid.X(grid.VI(:,3)), ...
527  grid.Y(grid.VI(:,3))];
528  S = circumcenter_triangle(q,p1,p2);
529  grid.SX = S(:,1);
530  grid.SY = S(:,2);
531 
532  % compute DS for inner edges (identical as DC computation!)
533  grid.DS = nan * ones(size(grid.CX,1),grid.nneigh);
534  nonzero = find(grid.NBI>0);
535  [elind, nbind] = ind2sub(size(grid.NBI),nonzero);
536 
537  SXX = repmat(grid.SX(:),1,grid.nneigh);
538  SYY = repmat(grid.SY(:),1,grid.nneigh);
539 
540  SXN = SXX;
541  SXN(nonzero) = grid.SX(grid.NBI(nonzero));
542 
543  SYN = SYY;
544  SYN(nonzero) = grid.SY(grid.NBI(nonzero));
545 
546  DS = sqrt((SXX-SXN).^2 + (SYY - SYN).^2);
547 
548  grid.DS(nonzero) = DS(nonzero);
549 
550  % computation of boundary distances: twice the distance to the border
551 
552  nondef = find(isnan(grid.DS));
553  nondef = nondef(:)';
554  [elind, nind] = ind2sub(size(grid.DS),nondef);
555  nind_plus_one = nind + 1;
556  i = find(nind_plus_one > grid.nneigh);
557  nind_plus_one(i) = 1;
558  nondef_plus_one = sub2ind(size(grid.DS),elind,nind_plus_one);
559  nondef_plus_one = nondef_plus_one(:)';
560 
561  d = zeros(length(nondef),1);
562 
563  q = [grid.SX(elind)'; grid.SY(elind)'];
564  p1 = [grid.X(grid.VI(nondef)), ...
565  grid.Y(grid.VI(nondef))];
566  p2 = [grid.X(grid.VI(nondef_plus_one)), ...
567  grid.Y(grid.VI(nondef_plus_one))];
568 
569 % keyboard;
570 
571  grid.DS(nondef) = 2 * dist_point_line(q,p1,p2);
572 
573  if ~isempty(find(isnan(grid.DS)))
574  error('nans produced in grid generation!');
575  end;
576 
577  % intersections of S_i are the centroids of edges
578  grid.ESX = grid.ECX;
579  grid.ESY = grid.ECY;
580 
581  % compute geometry constants for CFL-condition
582  h = max(grid.EL,[],2); % elementwise maximum edgelength
583  grid.hmin = min(h);
584  % alpha1 * h_j^2 <= |T_j|
585  alpha1 = min(grid.A .* h.^(-2));
586  % alpha2 * |boundary T_j| <= h_j
587  b = sum(grid.EL,2);
588  alpha2 = min(h .* b.^(-1));
589  % alpha3 h_j <= d_jl, d_jl distance of circumcenters
590  alpha3 = min(min(grid.DS,[],2) .* h.^(-1));
591  grid.alpha = min([alpha1,alpha2,alpha3]);
592 
593 % if grid.alpha<=0
594 % disp(['Caution: Grid-geometry constant alpha less/equal zero', ...
595 % ' problematic ' ...
596 % ' in automatic CFL-conditions!']);
597 % end;
598 
599  % DF = [(p2-p1) (p3-p1)] a 2x2 matrix
600  DF = zeros(grid.nelements,2,2); % jacobian
601  DF(:,1,1) = XX(:,2)-XX(:,1);
602  DF(:,2,1) = YY(:,2)-YY(:,1);
603  DF(:,1,2) = XX(:,3)-XX(:,1);
604  DF(:,2,2) = YY(:,3)-YY(:,1);
605  DetDF = DF(:,1,1).*DF(:,2,2)- DF(:,2,1).*DF(:,1,2); % determinant
606  DetDFinv = DetDF.^(-1);
607  JIT = zeros(grid.nelements,2,2);
608  % inversetransposed of A = (a,b; c,d) is A^-1 = 1/det A (d,-c; -b,a);
609  JIT(:,1,1)=DF(:,2,2).*DetDFinv;
610  JIT(:,1,2)=-DF(:,2,1).*DetDFinv;
611  JIT(:,2,1)=-DF(:,1,2).*DetDFinv;
612  JIT(:,2,2)=DF(:,1,1).*DetDFinv;
613 
614  % test:
615  if (size(JIT,1)>=5) &(max(max(abs(...
616  transpose(reshape(JIT(5,:,:),2,2))*...
617  reshape(DF(5,:,:),2,2)-eye(2)...
618  )))>1e-5)
619  error('error in JIT computation!');
620  end;
621 
622  % JIT:
623  grid.JIT = JIT; % perhaps later also store area, etc.
624 
625  grid.nedges_boundary = length(find(grid.NBI<0));
626 
627  grid.nedges_interior = 0.5*(3*grid.nelements - grid.nedges_boundary);
628  if ~isequal(ceil(grid.nedges_interior), ...
629  grid.nedges_interior);
630  error('number of inner edges odd!!!');
631  end;
632 
633  end
634  end
635 
636  demo(dummy);
637 
638  display(grid);
639 
640  gridp = gridpart(grid,eind);
641 
642  lcoord = llocal2local(grid, faceinds, llcoord);
643 
644  glob = local2global(grid, einds, loc, params);
645 
646  p = plot(gird, params);
647 
648  grid = set_nbi(grid, nbind, values);
649 
650  function gcopy = copy(grid)
651  % @copybrief gridbasecopy
652  %
653  % Return values:
654  % gcopy: object of type triagrid. This is a deep copy of the current instance.
655  %
656 
657  gcopy = triagrid(grid);
658  end
659 
660  end
661 
662  methods(Static)
663 
664  [C, G] = aff_trafo_glob2loc(x0, y0);
665 
666  [C, G] = aff_trafo_loc2glob(x0, y0);
667 
668  [C, G] = aff_trafo_orig2ref(x0, y0, varargin);
669 
670  loc = global2local(grid, elementid, glob);
671 
672  micro2macro = micro2macro_map(microgrid, macrogrid);
673 
674  [p, t] = read_msh(filename);
675  end
676 end
677 
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...
Definition: verbose.m:17
A triangular conforming grid in two dimensions.
Definition: triagrid.m:17
Base class for all grid classes.
Definition: gridbase.m:17