rbmatlab 0.10.01
grid/@triagrid/triagrid.m
00001 classdef triagrid < gridbase
00002   % A triangular conforming grid in two dimensions.
00003   %
00004   % General geometrical information is stored including neighbour
00005   % information. Therefore also boundary neighbour relations can be
00006   % specified. Boundary edges can be marked by "painting rectangles": the
00007   % edges with midpoints within such a rectangle are marked accordingly.
00008   % By this boundary edges can be marked for later special use.  Much
00009   % (partially redundant) information is stored in the grid, which might be
00010   % useful in simulations.
00011 
00012   properties
00013     % number of interior edges
00014     nedges_interior;
00015 
00016     % number of boundary edges
00017     nedges_boundary;
00018   end;
00019 
00020   methods
00021 
00022     function grid= triagrid(varargin)
00023       %function triagrid(varargin)
00024       % constructor of a triangular conform grid in 2 dimensions with following
00025       % Synopsis:
00026       %
00027       % - triagrid() : construction of a default triagrid (2d unit square,
00028       %              loaded from file, -1 as outer neighbour indices)
00029       % - @link triagrid() triagrid(tgrid) @endlink : copy-constructor
00030       % - @link triagrid() triagrid(params) @endlink : in this case either
00031       %    -# the field grid_initfile is existent in params. Then the file is read
00032       %       and a pointlist p and a triangle. Procedure is then executing the
00033       %       following constructor
00034       %    -# a structured equidistant triangle grid is generated
00035       %        - 'params.xnumintervals' : number of elements along x directions
00036       %        - 'params.ynumintervals' : number of elements along y directions
00037       %        - 'params.xrange,yrange' : intervals covered along the axes
00038       %        .
00039       %        with the optional fields
00040       %        - 'params.bnd_rect_corner1' : coordinates of lower corner of to
00041       %        be marked boundaries
00042       %        - 'params.bnd_rect_corner2' : coordinates of upper corner of to
00043       %        be marked boundaries
00044       %        - 'params.bnd_rect_index': integer index to be set on the edges
00045       %        in the above  defined rectangle. Should not be positive integer
00046       %        in the range of the number of elements. use negative indices for
00047       %        certain later discrimination.
00048       %        .
00049       %        For the last three optional boundary settings, also multiple
00050       %        rectangles can be straightforwardly defined by accepting matrix
00051       %        of columnwise corners1, corners2 and a vector of indices for the
00052       %        different rectangles.
00053       % - @link triagrid() triagrid(p,t,params) @endlink : generate triagrid from
00054       %   triangle-data with certain options.
00055       %       - p is assumed to be a 2 x npoints matrix with coordinates
00056       %       - t is assumed to be a XX x ntriangles matrix, but only first three
00057       %         rows are used == vertex indices, in clockwise order as default, all
00058       %         nondefined edges are set to -1, then the following "rectangles" are
00059       %         set as specified in params
00060       %
00061       % Using this class, grids from PDETOOLS can be used:
00062       %
00063       %     pdetools
00064       %     %%% => generate your grid and export 'p' and 't' to MATLAB workspace
00065       % @code
00066       %     save('mygrid','p','t')
00067       %     grid = triagrid(struct('grid_initfile','mygrid'));
00068       % @endcode
00069       %
00070       % perhaps later: constructor by duneDGF-file?
00071       % perhaps later: contructor-flag: full vs non-full
00072       %                 => only compute redundant information if required.
00073       %
00074       % Parameters:
00075       %  'varargin' : variable number of input arguments, see above for description
00076       %  of possible configurations.
00077       %
00078       % Return values:
00079       %  'grid' : generated triagrid
00080       %
00081       % generated fields of grid:
00082       % nelements: number of elements
00083       % nvertices: number of vertices
00084       % nneigh: 3
00085       % A    : vector of element area
00086       % Ainv : vector of inverted element area
00087       % X    : vector of vertex x-coordinates
00088       % Y    : vector of vertex y-coordinates
00089       % VI   : matrix of vertex indices: 'VI(i,j)' is the global index of j-th
00090       %        vertex of element i
00091       % CX   : vector of centroid x-values
00092       % CY   : vector of centroid y-values
00093       % NBI  : 'NBI(i,j) = ' element index of j-th neighbour of element i
00094       %        boundary faces are set to -1 or negative values are requested by
00095       %        'params.boundary_type'
00096       % INB  : 'INB(i,j) = ' local edge number in 'NBI(i,j)' leading from
00097       %        element 'NBI(i,j)' to element 'i', i.e. satisfying
00098       %        'NBI(NBI(i,j), INB(i,j)) = i'
00099       % EL   : 'EL(i,j) = ' length of edge from element 'i' to neighbour 'j'
00100       % DC   : 'DC(i,j) = ' distance from centroid of element i to NB j
00101       %        for boundary elements, this is the distance to the reflected
00102       %        element (for use in boundary treatment)
00103       % NX   : 'NX(i,j) = ' x-coordinate of unit outer normal of edge from el
00104       %        'i' to NB 'j'
00105       % NY   : 'NY(i,j) = ' y-coordinate of unit outer normal of edge from el
00106       %        'i' to NB 'j'
00107       % ECX  : 'ECX(i,j) = ' x-coordinate of midpoint of edge from el 'i' to NB 'j'
00108       % ECY  : 'ECY(i,j) = ' y-coordinate of midpoint of edge from el 'i' to NB 'j'
00109       % SX   : vector of x-coordinates of point `S_i` (for rect: identical to
00110       %        centroids)
00111       % SY   : vector of y-coordinate of point `S_j` (for rect: identical to
00112       %        centroids)
00113       % ESX  : 'ESX(i,j) = ' x-coordinate of point `S_{ij}` on edge el i to NB j
00114       % ESY  : 'ESY(i,j) = ' y-coordinate of point `S_{ij}` on edge el i to NB j
00115       % DS   : 'DS(i,j) = ' distance from `S_i` of element i to `S_j` of NB j
00116       %        for boundary elements, this is the distance to the reflected
00117       %        element (for use in boundary treatment)
00118       % hmin : minimal element-diameter
00119       % alpha: geometry bound (simultaneously satisfying `\alpha \cdot h_i^d
00120       %        \leq A(T_i)`, `\alpha \cdot \mbox{diam}(T_i) \leq h_i^{d-1}` and
00121       %        `\alpha \cdot  h_i \leq `dist(midpoint `i` to any neigbour) )
00122       % JIT  : Jacobian inverse transposed 'JIT(i,:,:)' is a 2x2-matrix of the Jac.
00123       %        Inv. Tr. on element 'i'
00124       %
00125       % \note for diffusion-discretization with FV-schemes, points `S_i` must exist,
00126       % such that `S_i S_j` is perpendicular to edge 'i j', the intersection points
00127       % are denoted `S_{ij}`
00128       %
00129 
00130       % Bernard Haasdonk 9.5.2007
00131 
00132       %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00133       % copy constructor
00134       if (nargin==1) & isa(varargin{1},'triagrid')
00135         grid = triagrid; % create default triagrid
00136 
00137         fnames = fieldnames(varargin{1});
00138         for i=1:length(fnames)
00139           grid.(fnames{i}) = varargin{1}.(fnames{i});
00140         end
00141 
00142       else
00143 
00144         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00145         % default constructor: unit square
00146         if (nargin==0)
00147           %    p = [0.0   0.5  1.0   0.0    0.5   1.0   0.0    0.5    1.0; ...
00148           %      0.0   0.0  0.0   0.5    0.5   0.5   1.0    1.0    1.0 ];
00149           %     t = [1   2  2  3  4  5  5  6; ...
00150           %       2   5  3  6  5  8  6  9; ...
00151           %       4   4  5  5  7  7  8  8] ;
00152           params = [];
00153           load 2dsquaretriang;
00154 
00155           % mark boundary in rectangle from [-1,-1] to [+2,+2] with index -1
00156           params.bnd_rect_corner1 = [-1,-1]';
00157           params.bnd_rect_corner2 = [2 2]';
00158           params.bnd_rect_index = [-1];
00159         elseif nargin==1
00160           params = varargin{1};
00161           if isfield(params,'grid_initfile') || isprop(params, 'grid_initfile')
00162             tmp = load(params.grid_initfile);
00163             t = tmp.t(1:3,:);
00164             p = tmp.p;
00165           else
00166             nx = params.xnumintervals;
00167             ny = params.ynumintervals;
00168             nvertices =(nx+1)*(ny+1);
00169 
00170             dx = (params.xrange(2)-params.xrange(1))/nx;
00171             dy = (params.yrange(2)-params.yrange(1))/ny;
00172 
00173             % set vertex coordinates
00174             vind = (1:(nx+1)*(ny+1));
00175             X = mod(vind-1,nx+1) * dx + params.xrange(1);
00176             Y = floor((vind-1)/(nx+1))*dy  + params.yrange(1);
00177             p = [X(:)'; Y(:)'];
00178 
00179             % identify triangles:
00180             % ----
00181             % | /|
00182             % |/ |
00183             % ----
00184 
00185             all_ind = 1:(nx+1)*(ny+1);
00186             % index vector of lower left corners, i.e. not last col/row
00187             lc_ind = find((mod(all_ind,nx+1)~=0) & (all_ind < (nx+1)*ny));
00188             t1 = [lc_ind;lc_ind+1;lc_ind+2+nx]; % lower triangles
00189             t2 = [lc_ind;lc_ind+nx+2;lc_ind+nx+1]; % upper triangles
00190             t = [t1,t2];
00191           end;
00192         else % read p-e-t information from varargin
00193           p =varargin{1};
00194           t =varargin{2};
00195           if size(t,1)>3
00196             t = t(1:3,:);
00197           end;
00198           params = varargin{3};
00199         end;
00200 
00201         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00202         % construct from p,t and params
00203 
00204         if ~isfield(params,'verbose') && ~isprop(params, 'verbose')
00205           params.verbose = 0;
00206         end;
00207 
00208       %  nx = params.xnumintervals;
00209       %  ny = params.ynumintervals;
00210 
00211         grid.nelements = size(t,2);
00212         grid.nvertices = size(p,2);
00213         grid.nneigh= 3;
00214 
00215         % set vertex coordinates
00216         grid.X = p(1,:)';
00217         grid.Y = p(2,:)';
00218 
00219         % set element vertex indices: numbering counterclockwise
00220         % counterclockwise, edge j connects vertex j and j+1
00221 
00222         grid.VI = t';
00223 
00224         % get areas of grid-cells after VI and X,Y are available
00225         %
00226         %  A(a b c) = 0.5 |Det ((b-a) (c-a)) |
00227         grid.A = abs(area_triangle(...
00228             [grid.X(grid.VI(:,1)), ...
00229              grid.Y(grid.VI(:,1))], ...
00230             [grid.X(grid.VI(:,2)), ...
00231              grid.Y(grid.VI(:,2))], ...
00232             [grid.X(grid.VI(:,3)), ...
00233              grid.Y(grid.VI(:,3))]));
00234         grid.A = grid.A(:);
00235       %  a11 = grid.X(grid.VI(:,2))-grid.X(grid.VI(:,1));
00236       %  a21 = grid.Y(grid.VI(:,2))-grid.Y(grid.VI(:,1));
00237       %  a12 = grid.X(grid.VI(:,3))-grid.X(grid.VI(:,1));
00238       %  a22 = grid.Y(grid.VI(:,3))-grid.Y(grid.VI(:,1));
00239       %  grid.A = 0.5 * (a11.*a22 - a21.*a12);
00240         grid.Ainv = grid.A.^(-1);
00241 
00242         % midpoint coordinates of grid-cells
00243         % equals cog of corners
00244 
00245         % coordinates of vertices: XX(elnum, vnum)
00246         XX = reshape(grid.X(grid.VI(:)),size(grid.VI));
00247         YY = reshape(grid.Y(grid.VI(:)),size(grid.VI));
00248         grid.CX = mean(XX,2);
00249         grid.CY = mean(YY,2);
00250 
00251         % edge-vectors: [DX(el,edge) DX (el,edge)]
00252         DX = [XX(:,2:3), XX(:,1)] - XX;
00253         DY = [YY(:,2:3), YY(:,1)] - YY;
00254 
00255         % matrix with edge-lengths
00256         grid.EL = sqrt(DX.^2 + DY.^2);
00257 
00258         % matrix with (unit) normal components
00259         grid.NX =   grid.EL.^(-1) .* DY;
00260         grid.NY = - grid.EL.^(-1) .* DX;
00261 
00262         % matrix with edge-midpoint-coordinates
00263         % this computation yields epsilon-differing edge-midpoints on
00264         % neighbouring elements, perhaps solve later.
00265         grid.ECX = XX + DX * 0.5;
00266         grid.ECY = YY + DY * 0.5;
00267 
00268         %%% determine indices of neighbouring elements, default: -1
00269         NBI = -1 * ones(grid.nelements, grid.nneigh);
00270         INB = zeros(grid.nelements, grid.nneigh);
00271         % and now it gets complicated...
00272 
00273         % setup edge list e(1,i), e(2,i) are the point indices of the i-th edge
00274         %                 eid(i) is the element number, which has the edge
00275         %                 led(i) : local edge number, which is the edge
00276         %                          e(:,i) in eid(i)
00277         ee = zeros(2,grid.nelements*3);
00278         % li = [1 2 2 3 3 1 4 5 5 6 6 4 ... ]
00279         li = 1:grid.nelements*3;
00280         li = [li;li];
00281         li = reshape(li,6,grid.nelements);
00282         li = [li(2:end,:); li(1,:)];
00283         li = reshape(li,2,grid.nelements*3);
00284         ee = t(li);
00285         ee = sort(ee); % now smallest vindex above
00286         elid = repmat(1:grid.nelements,3,1);
00287         elid = elid(:)';
00288         led = repmat((1:3)',1,grid.nelements);
00289         led = led(:)';
00290 
00291         % generate sort key from both indices
00292         key = ee(1,:) + grid.nvertices * ee(2,:);
00293         [keysort, ind] = sort(key);
00294         ee_sort = ee(:,ind);
00295         elid_sort = elid(ind);
00296         led_sort = led(ind);
00297 
00298         % find indices of duplicates by simple forward difference
00299         %  => these are inner edges!
00300 
00301         diff = keysort(1:end-1) - [keysort(2:end)];
00302         inner_edges = find(diff==0);
00303 
00304         % prepare entries in NBI: for all i in inner_edges
00305         % NBI(elid_sort(i),led_sort(i)) = elid_sort(i+1);
00306         % INB(elid_sort(i),led_sort(i)) = led_sort(i+1);
00307         % und umgekehrt!
00308 
00309         li = sub2ind(size(NBI),...
00310                elid_sort(inner_edges),...
00311                led_sort(inner_edges));
00312         NBI(li) = elid_sort(inner_edges+1);
00313         INB(li) = led_sort(inner_edges+1);
00314         li = sub2ind(size(NBI),...
00315                elid_sort(inner_edges+1),...
00316                led_sort(inner_edges+1));
00317         NBI(li) = elid_sort(inner_edges);
00318         INB(li) = led_sort(inner_edges);
00319 
00320       %  % find all element-pairs, which have a common edge
00321       %  % i.e. neighs(i,1) and neighs(i,2) are two elements, which
00322       %  % have the same edge i, where this edge is the
00323       %  % eind(i,1)-th edge (1..3) in the first element
00324       %  % eind(i,2)-th edge (1..3) in the first element
00325       %
00326       %  nedges = max(t(:));
00327       %  ehist = hist(t(:),1:nedges);
00328       %  if max(ehist)>3
00329       %    error('edge occuring in more than 2 triangles!!');
00330       %  end;
00331       %  inner_edges = find(ehist==2);
00332       %  neighs = zeros(length(inner_edges),2);
00333       %  eind = zeros(length(inner_edges),2);
00334       %
00335       %  % somehow map edge-numbers => triangle numbers
00336       %  % need two of them, as occasionally global and local edge numbers
00337       %  % can coincide:
00338       %  % edgemap1(i,locedgenum) = elementno    if edge i is local edge in elementno
00339       %  % edgemap2(i,locedgenum) = elementno    if edge i is local edge in elementno
00340       %
00341       %  edgemap1 = nan * ones(nedges,grid.nneigh);%
00342       %
00343       %  [locedgenum,triangnum] = ind2sub(size(t),1:length(t(:)));
00344       %  li = sub2ind(size(edgemap1),t(:),locedgenum(:));
00345       %  edgemap1(li) = triangnum; % here due to duplicates, only the last
00346       %                            % entry is taken
00347       %
00348       %  % remove these entries from t and repeat for 2nd edgemap
00349       %  t2 = t;
00350       %  [edgenum,locedgenum] = find(~isnan(edgemap1));
00351       %  li = sub2ind(size(edgemap1),edgenum(:),locedgenum(:));
00352       %
00353       %  li2 = sub2ind(size(t2),locedgenum(:),edgemap1(li));
00354       %  t2(li2) = 0;
00355       %
00356       %
00357       %  edgemap2 = nan * ones(nedges,grid.nneigh);
00358       %  nonzeros = find(t2~=0);
00359       %
00360       %  [locedgenum,triangnum] = ind2sub(size(t2),1:length(nonzeros));
00361       %  li = sub2ind(size(edgemap2),t2(nonzeros),locedgenum(:));
00362       %  edgemap2(li) = triangnum;
00363       %  % now together edgemap1 and edgemap 2 represent the edge information.
00364       %
00365       %  % extract inner edges
00366       %  edgemap = [edgemap1(inner_edges,:), edgemap2(inner_edges,:)];
00367       %  % check, that exactly two entries per row are non-nan
00368       %  entries = sum(~isnan(edgemap),2);
00369       %  if (min(entries)~=2) | max(entries)~=2
00370       %    disp('error in neighbour detection, please check');
00371       %    keyboard;
00372       %  end;
00373       %
00374       %  [mi, imi] = min(edgemap,[],2);
00375       %  [ma, ima] = max(edgemap,[],2);
00376       %  neighs = [mi, ma];
00377       %  eind = [imi, ima];
00378       %
00379       %  % then fill NBI and INB in a vectorized way, i.e.
00380       %  % for all edges:
00381       %  % NBI(neighs(i,1), eind(i,1)) = neighs(i,2);
00382       %  % NBI(neighs(i,2), eind(i,2)) = neighs(i,1);
00383       %  % INB(neighs(i,1), eind(i,1)) = eind(i,2);
00384       %  % INB(neighs(i,2), eind(i,2)) = eind(i,1);
00385       %
00386       %  l1 = sub2ind( size(NBI), neighs(:,1) , eind(:,1));
00387       %  l2 = sub2ind( size(NBI), neighs(:,2) , eind(:,2));
00388       %  NBI(l1) = neighs(:,2);
00389       %  NBI(l2) = neighs(:,1);
00390       %  INB(l1) = eind(:,2);
00391       %  INB(l2) = eind(:,1);
00392 
00393         % search non-inner boundaries and their midpoints
00394 
00395         li = find(NBI==-1);
00396         SX = grid.ECX(li(:));
00397         SY = grid.ECY(li(:));
00398 
00399         % default-boundary = -1
00400         bnd_ind = -1 * ones(length(li),1);
00401 
00402         if isfield(params,'bnd_rect_index') || isprop(params, 'bnd_rect_index')
00403           if isfield(params,'boundary_type') || isprop(params, 'boundary_type')
00404             error(['Do not specify both bnd_rect_index and boundary_type', ...
00405                    '�in triagrid construction!']);
00406           end;
00407           if (max(params.bnd_rect_index)>0)
00408             error('boundary indices must be negative!');
00409           end;
00410           if size(params.bnd_rect_corner1,1) == 1
00411             params.bnd_rect_corner1 = params.bnd_rect_corner1';
00412           end;
00413           if size(params.bnd_rect_corner2,1) == 1
00414             params.bnd_rect_corner2 = params.bnd_rect_corner2';
00415           end;
00416           for i = 1:length(params.bnd_rect_index)
00417             indx = (SX > params.bnd_rect_corner1(1,i)) & ...
00418              (SX < params.bnd_rect_corner2(1,i)) & ...
00419              (SY > params.bnd_rect_corner1(2,i)) & ...
00420              (SY < params.bnd_rect_corner2(2,i));
00421             bnd_ind(indx) = params.bnd_rect_index(i);
00422           end;
00423         else
00424           if isfield(params,'boundary_type') || isprop(params, 'boundary_type')
00425             bnd_ind = params.boundary_type([SX(:),SY(:)],params);
00426           end;
00427         end;
00428 
00429         NBI(li) = bnd_ind'; % set neighbours to boundary
00430 
00431         grid.NBI = NBI;
00432         grid.INB = INB;
00433 
00434         % check grid consistency:
00435         nonzero = find(NBI>0); % vector with vector-indices
00436         [i,j] = ind2sub(size(NBI), nonzero); % vectors with matrix indices
00437         NBIind = NBI(nonzero); % vector with global neighbour indices
00438         INBind = INB(nonzero);
00439         i2 = sub2ind(size(NBI),NBIind, INBind);
00440         i3 = NBI(i2);
00441         if ~isequal(i3,i)
00442       %    plot_element_data(grid,grid.NBI,params);
00443           disp('neighbour indices are not consistent!!');
00444           keyboard;
00445         end;
00446 
00447         % matrix with centroid-distances
00448         grid.DC = nan * ones(size(grid.CX,1),grid.nneigh);
00449         nonzero = find(grid.NBI>0);
00450         [elind, nbind] = ind2sub(size(grid.NBI),nonzero);
00451 
00452         CXX = repmat(grid.CX(:),1,grid.nneigh);
00453         CYY = repmat(grid.CY(:),1,grid.nneigh);
00454 
00455         CXN = CXX;
00456         CXN(nonzero) = grid.CX(grid.NBI(nonzero));
00457 
00458         CYN = CYY;
00459         CYN(nonzero) = grid.CY(grid.NBI(nonzero));
00460 
00461         DC = sqrt((CXX-CXN).^2 + (CYY - CYN).^2);
00462 
00463         grid.DC(nonzero) = DC(nonzero);
00464 
00465         % computation of boundary distances: twice the distance to the border
00466 
00467         nondef = find(isnan(grid.DC));
00468         nondef = nondef(:)';
00469         [elind, nind] = ind2sub(size(grid.DC),nondef);
00470         nind_plus_one = nind + 1;
00471         i = find(nind_plus_one > grid.nneigh);
00472         nind_plus_one(i) = 1;
00473         nondef_plus_one = sub2ind(size(grid.DC),elind,nind_plus_one);
00474         nondef_plus_one = nondef_plus_one(:)';
00475 
00476         d = zeros(length(nondef),1);
00477 
00478         q = [grid.CX(elind)'; grid.CY(elind)'];
00479         p1 = [grid.X(grid.VI(nondef)), ...
00480         grid.Y(grid.VI(nondef))];
00481         p2 = [grid.X(grid.VI(nondef_plus_one)), ...
00482         grid.Y(grid.VI(nondef_plus_one))];
00483 
00484         grid.DC(nondef) = 2 * dist_point_line(q,p1,p2);
00485 
00486         % make entries of ECX, ECY exactly identical for neighbouring elements!
00487         % currently by construction a small eps deviation is possible.
00488         %averaging over all pairs is required
00489         nonzero = find(grid.NBI>0); % vector with vector-indices
00490         [i,j] = ind2sub(size(grid.NBI), nonzero); % vectors with matrix indices
00491         NBIind = NBI(nonzero); % vector with global neighbour indices
00492         INBind = INB(nonzero); % vector with local edge indices
00493         i2 = sub2ind(size(NBI),NBIind, INBind);
00494         % determine maximum difference in edge-midpoints, but exclude
00495         % symmetry boundaries by relative error < 0.0001
00496         diffx = abs(grid.ECX(nonzero)-grid.ECX(i2));
00497         diffy = abs(grid.ECY(nonzero)-grid.ECY(i2));
00498         fi = find ( (diffx/(max(grid.X)-min(grid.X)) < 0.0001) &  ...
00499               (diffy/(max(grid.Y)-min(grid.Y)) < 0.0001) );
00500 
00501         %disp(max(diffx));
00502         %disp(max(diffy));
00503         %  => 0 ! :-)
00504         % keyboard;
00505 
00506         grid.ECX(nonzero(fi)) = 0.5*(grid.ECX(nonzero(fi))+ grid.ECX(i2(fi)));
00507         grid.ECY(nonzero(fi)) = 0.5*(grid.ECY(nonzero(fi))+ grid.ECY(i2(fi)));
00508 
00509         % for diffusion discretization: Assumption of points with
00510         % orthogonal connections to edges. Distances and intersections
00511         % determined here. For triangles, this can simply be the
00512         % circumcenters and the corresponding intersections
00513 
00514         q = [grid.X(grid.VI(:,1)), ...
00515              grid.Y(grid.VI(:,1))];
00516         p1 = [grid.X(grid.VI(:,2)), ...
00517               grid.Y(grid.VI(:,2))];
00518         p2 = [grid.X(grid.VI(:,3)), ...
00519               grid.Y(grid.VI(:,3))];
00520         S = circumcenter_triangle(q,p1,p2);
00521         grid.SX = S(:,1);
00522         grid.SY = S(:,2);
00523 
00524         % compute DS for inner edges (identical as DC computation!)
00525         grid.DS = nan * ones(size(grid.CX,1),grid.nneigh);
00526         nonzero = find(grid.NBI>0);
00527         [elind, nbind] = ind2sub(size(grid.NBI),nonzero);
00528 
00529         SXX = repmat(grid.SX(:),1,grid.nneigh);
00530         SYY = repmat(grid.SY(:),1,grid.nneigh);
00531 
00532         SXN = SXX;
00533         SXN(nonzero) = grid.SX(grid.NBI(nonzero));
00534 
00535         SYN = SYY;
00536         SYN(nonzero) = grid.SY(grid.NBI(nonzero));
00537 
00538         DS = sqrt((SXX-SXN).^2 + (SYY - SYN).^2);
00539 
00540         grid.DS(nonzero) = DS(nonzero);
00541 
00542         % computation of boundary distances: twice the distance to the border
00543 
00544         nondef = find(isnan(grid.DS));
00545         nondef = nondef(:)';
00546         [elind, nind] = ind2sub(size(grid.DS),nondef);
00547         nind_plus_one = nind + 1;
00548         i = find(nind_plus_one > grid.nneigh);
00549         nind_plus_one(i) = 1;
00550         nondef_plus_one = sub2ind(size(grid.DS),elind,nind_plus_one);
00551         nondef_plus_one = nondef_plus_one(:)';
00552 
00553         d = zeros(length(nondef),1);
00554 
00555         q = [grid.SX(elind)'; grid.SY(elind)'];
00556         p1 = [grid.X(grid.VI(nondef)), ...
00557         grid.Y(grid.VI(nondef))];
00558         p2 = [grid.X(grid.VI(nondef_plus_one)), ...
00559         grid.Y(grid.VI(nondef_plus_one))];
00560 
00561 %        keyboard;
00562 
00563         grid.DS(nondef) = 2 * dist_point_line(q,p1,p2);
00564 
00565         if ~isempty(find(isnan(grid.DS)))
00566           error('nans produced in grid generation!');
00567         end;
00568         
00569         % intersections of S_i are the centroids of edges
00570         grid.ESX = grid.ECX;
00571         grid.ESY = grid.ECY;
00572 
00573         % compute geometry constants for CFL-condition
00574         h = max(grid.EL,[],2); % elementwise maximum edgelength
00575         grid.hmin = min(h);
00576         % alpha1 * h_j^2 <= |T_j|
00577         alpha1 = min(grid.A .* h.^(-2));
00578         % alpha2 * |boundary T_j| <= h_j
00579         b = sum(grid.EL,2);
00580         alpha2 = min(h .* b.^(-1));
00581         % alpha3 h_j <= d_jl, d_jl distance of circumcenters
00582         alpha3 = min(min(grid.DS,[],2) .* h.^(-1));
00583         grid.alpha = min([alpha1,alpha2,alpha3]);       
00584 
00585 %        if grid.alpha<=0
00586 %          disp(['Caution: Grid-geometry constant alpha less/equal zero', ...
00587 %          ' problematic ' ...
00588 %          ' in automatic CFL-conditions!']);
00589 %        end;
00590 
00591         % DF = [(p2-p1) (p3-p1)] a 2x2 matrix
00592         DF = zeros(grid.nelements,2,2); % jacobian
00593         DF(:,1,1) = XX(:,2)-XX(:,1);
00594         DF(:,2,1) = YY(:,2)-YY(:,1);
00595         DF(:,1,2) = XX(:,3)-XX(:,1);
00596         DF(:,2,2) = YY(:,3)-YY(:,1);
00597         DetDF = DF(:,1,1).*DF(:,2,2)- DF(:,2,1).*DF(:,1,2); % determinant
00598         DetDFinv = DetDF.^(-1);
00599         JIT = zeros(grid.nelements,2,2);
00600         % inversetransposed of A = (a,b; c,d) is A^-1 = 1/det A (d,-c; -b,a);
00601         JIT(:,1,1)=DF(:,2,2).*DetDFinv;
00602         JIT(:,1,2)=-DF(:,2,1).*DetDFinv;
00603         JIT(:,2,1)=-DF(:,1,2).*DetDFinv;
00604         JIT(:,2,2)=DF(:,1,1).*DetDFinv;
00605 
00606         % test:
00607         if (size(JIT,1)>=5) &(max(max(abs(...
00608             transpose(reshape(JIT(5,:,:),2,2))*...
00609             reshape(DF(5,:,:),2,2)-eye(2)...
00610             )))>1e-5)
00611           error('error in JIT computation!');
00612         end;
00613 
00614         % JIT:
00615         grid.JIT = JIT; % perhaps later also store area, etc.
00616 
00617         grid.nedges_boundary = length(find(grid.NBI<0));
00618 
00619         grid.nedges_interior = 0.5*(3*grid.nelements - grid.nedges_boundary);
00620         if ~isequal(ceil(grid.nedges_interior), ...
00621                     grid.nedges_interior);
00622           error('number of inner edges odd!!!');
00623         end;
00624 
00625       end
00626     end
00627 
00628     demo(dummy);
00629 
00630     display(grid);
00631 
00632     gridp = gridpart(grid,eind);
00633 
00634     lcoord = llocal2local(grid, faceinds, llcoord);
00635 
00636     glob = local2global(grid, einds, loc, params);
00637 
00638     p = plot(gird, params);
00639 
00640     grid = set_nbi(grid, nbind, values);
00641 
00642     function gcopy = copy(grid)
00643       % @copybrief gridbase copy
00644       %
00645       % Return values:
00646       %   gcopy: object of type triagrid. This is a deep copy of the current instance.
00647       %
00648 
00649       gcopy = triagrid(grid);
00650     end
00651 
00652   end
00653 
00654   methods(Static)
00655 
00656       [C, G] = aff_trafo_glob2loc(x0, y0);
00657 
00658       [C, G] = aff_trafo_loc2glob(x0, y0);
00659 
00660       [C, G] = aff_trafo_orig2ref(x0, y0, varargin);
00661 
00662       loc = global2local(grid, elementid, glob);
00663 
00664       micro2macro = micro2macro_map(microgrid, macrogrid);
00665   end
00666 end
00667 
All Classes Namespaces Files Functions Variables