⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mesh2d.m

📁 一个功能强大的非结构网格划分程序,可实现网格的自动剖分,及局部加密与质量控制
💻 M
📖 第 1 页 / 共 2 页
字号:
function [p,t] = mesh2d(node,edge,hdata,options)

%  MESH2D: 2D unstructured triangular mesh generation.
%
% A 2D unstructured triangular mesh is generated based on a piecewise-
% linear geometry input. An iterative method is implemented to optimise 
% mesh quality. General multiply connected domains and element size 
% functions can be specified.
%
% Returns the final coordinates of the nodes p, and their triangulation t
% (with a counter-clockwise node ordering).
%
%  SHORT SYNTAX:
%
%  [p,t] = mesh2d(node);
%
% NODE defines the geometry nodes via an Nx2 array:
%
%  node  = [x1 y1; x2 y2; etc], geometry nodes specified in consectutive
%                               order, such that NODE(2,:) is joined with
%                               NODE(1,:) etc.
%
% An element size function is automatically generated based on the 
% complexity of the geometry. Generally this produces meshes with the 
% fewest number of triangles.
%
%  LONG SYNTAX:
%
%  [p,t] = mesh2d(node,edge,hdata,options);
%
% Blank arguments can be passed using the empty placeholder "[]".
%
% EDGE defines the connectivity between the points in NODE as a list of
% edges:
%
%   edge = [n1 n2; n2 n3; etc], connectivity between nodes to form
%                               geometry edges. If EDGE is specified it is
%                               not required that NODE be consectutive.
%
% HDATA is a structure for user defined element size information. HDATA can 
% include the following fields:
%
%  hdata.hmax  = h0;                   Max allowable global element size.
%  hdata.edgeh = [e1,h1; e2,h2; etc];  Element size on specified geometry 
%                                      edges.
%  hdata.fun   = 'fun' or @fun;        User defined size function.
%  hdata.args  = {arg1, arg2, etc};    Additional arguments for HDATA.FUN.
%
% Calls to user specified functions must accept vectorised input of the 
% form H = FUN(X,Y,ARGS{:}), where X,Y are the xy coordinates where the
% element size will be evaluated and ARGS are optional additional arguments 
% as passed by HDATA.ARGS.
%
% An automatic size function is always generated to ensure that the
% geometry is adequately resolved. The overall size function is the minimum
% of the user specified and automatic functions.
%
% OPTIONS is a structure array that allows some of the "tuning" parameters
% used in the solver to be modified:
%
%   options.mlim   - Specifies the maximum allowable change in edge length
%                    per iteration that must be obtained [default = 0.05
%                    (5%)]. Larger values should accelerate convergence,
%                    but could decrease mesh quality.
%   options.maxit  - Specifies the maximum number of iterations the
%                    algorithm will perform [default = 20].
%   options.dhmax  - Specifies the maximum allowable (relative) gradient in
%                    the size function [default = 0.3].
%   options.output - Displays the mesh and the mesh statistics upon
%                    completion [default = true].
%
% EXAMPLE:
%
%   meshdemo                  % Will run the standard demos
%   mesh_collection(n)        % Will run some additional demos
%
% See also REFINE, SMOOTHMESH, DELAUNAYN


% Mesh2d is a delaunay based algorithm with a "Laplacian-like" smoothing
% operation built into the mesh generation process. 
% 
% An unbalanced quadtree decomposition is used to evaluate the element size 
% distribution required to resolve the geometry. The quadtree is 
% triangulated and used as a backgorund mesh to store the element size 
% data.  
%
% The main method attempts to optimise the node location and mesh topology 
% through an iterative process. In each step a constrained delaunay 
% triangulation is generated with a series of "Laplacian-like" smoothing 
% operations used to improve triangle quality. Nodes are added or removed 
% from the mesh to ensure the required element size distribution is 
% approximated.  
%
% The optimisation process generally returns well shaped meshes with no
% small angles and smooth element size variations. Mesh2d shares some 
% similarities with the Distmesh code: 
%
%   [1] P.-O. Persson, G. Strang, A Simple Mesh Generator in MATLAB.
%       SIAM Review, Volume 46 (2), pp. 329-345, June 2004
%
%   Darren Engwirda : 2005-07
%   Email           : d_engwirda@hotmail.com
%   Last updated    : 08/07/2007 with MATLAB 7.0
%
% Mesh2d is Copyright (C) 2007 Darren Engwirda. See "copyright.m" for full 
% details.
%
% Please email me any un-meshable geometries, meshing benchmarks or
% suggestions!

tic
wbar = waitbar(0,'Forming geometry faces');

% Error checks
if nargin<4
   options = [];
   if nargin<3
      hdata = [];
      if nargin<2
         edge = [];
         if nargin<1
            error('Wrong number of inputs');
         end
      end
   end
elseif nargin>4
   error('Wrong number of inputs');
end
if nargout>2
   error('Wrong number of outputs');
end

% Get user options
[mlim,maxit,dhmax,output] = getoptions(options);

% Check geometry
[node,edge,hdata] = checkgeometry(node,edge,hdata);                        % Error checking for geometry
edgexy = [node(edge(:,1),:), node(edge(:,2),:)];                           % Geometry as edge endpoints [x1,y1,x2,y2]

% QUADTREE DECOMPOSITION
%  PH    : Background mesh nodes
%  TH    : Background mesh triangles
%  HH    : Size function value at PH
[ph,th,hh] = quadtree(edgexy,hdata,dhmax,wbar);

waitbar(0,wbar,'Initialising mesh');

% INITIALISE MESH
%  P     : Initial nodes
%  T     : Initial triangulation
%  WNDX  : Closest edge for each node as indices into EDGEXY
%  TNDX  : Enclosing triangle for each node as indices into TH
%  FIX   : Indices of FIXED nodes in P
[p,t,wndx,tndx,fix,fixed] = initmesh(ph,th,node,edge,edgexy);

% MAIN LOOP
retri = false;
subit = 3;
for iter = 1:maxit

   % Re-triangulation
   if retri
      t = MyDelaunayn(p);                                                  % Delaunay triangulation via QHULL
      pc = (p(t(:,1),:)+p(t(:,2),:)+p(t(:,3),:))/3;                        % Centroids
      t = t(inpoly(pc,node,edge),:);                                       % Take triangles with internal centroids
   end
   
   [e,bnd] = getedges(t,size(p,1));                                        % Unique edges and boundary nodes
%    %将fix=0的值去掉
%    if(fix(1)==0)
%        fix(1)=1;
%    end
   bnd(fix) = false;                                                       % Don't flag fixed nodes
   bnd = find(bnd);

   nume = size(e,1);
   S = sparse(e(:),[1:nume,1:nume],1,size(p,1),nume);                      % Sparse node-to-edge connectivity matrix

   tndx = mytsearch(ph(:,1),ph(:,2),th,p(:,1),p(:,2),tndx);                % Find enclosing triangle in background mesh for nodes
   h = tinterp(ph,th,hh,p,tndx);                                           % Size function at nodes via linear interpolation
   h = 0.5*(h(e(:,1))+h(e(:,2)));                                          % from the background mesh. Average to edge midpoints.
   
   % Inner smoothing iterations
   L = max(sqrt(sum((p(e(:,1),:)-p(e(:,2),:)).^2,2)),eps);                 % Edge length
   done = false;
   subit = max(subit,iter);                                                % Increment sub-iters with outer iters to aid convergence
   for subiter = 1:subit   
      r = sqrt(L./h);                                                      % Ratio of actual to desired edge length

      pm = 0.5*[r,r].*( p(e(:,1),:)+p(e(:,2),:) );                         % Edge midpoints, size function weighted

      W = max(S*r,eps);                                                    % Size function weighting
      p = (S*pm)./[W,W];                                                   % Weighted Laplacian-like smoothing
      p(fix,:) = fixed;                                                    % Don't update fixed nodes

      [p,wndx] = project2poly(p,bnd,edgexy,wndx);                          % Project bnd nodes onto the closest geometry edge
      
      Lnew = max(sqrt(sum((p(e(:,1),:)-p(e(:,2),:)).^2,2)),eps);           % Edge length
      move = norm((Lnew-L)./L,inf);                                        % Percentage change
      L = Lnew;

      if move<mlim                                                         % Test convergence
         done = true;
         break
      end
   end
   
   msg = ['Generating mesh (Iteration ',num2str(iter),')'];                % Show progress
   waitbar(mlim/max(move,eps),wbar,msg);

   r = L./h;
   if done && max(r)<3                                                     % Main loop convergence
      break
   end

   % Nodal density control
   retri = false;
   if iter<maxit
      test = find(r<=0.5);                                                 % Remove both nodes for edges with r<0.5
      hang = sum(S,2)<2;                                                   % Remove nodes connected to less than 2 edges
      if ~isempty(test) || any(hang)
         prob = false(size(p,1),1);                                        % True for nodes to be removed
         prob(e(test,:)) = true;                                           % Edges with r<0.5
         prob(hang) = true;
         prob(fix) = false;                                                % Make fixed nodes work
         pnew = p(~prob,:);                                                % New node list

         tmp_wndx = wndx(~prob);
         tmp_tndx = tndx(~prob);
         
         j = zeros(size(p,1),1);                                           % Re-index fix to make fixed nodes work
         j(~prob) = 1;
         j = cumsum(j);
         fix = j(fix);
         
         retri = true;
      else
         pnew = p;                                                         % No nodes removed
         tmp_wndx = wndx;
         tmp_tndx = tndx;
      end
      test = find(r>=2);                                                   % Add node at midpoint for edges with r>=2
      if ~isempty(test)
         p = [pnew; 0.5*(p(e(test,1),:)+p(e(test,2),:))];
         wndx = [tmp_wndx; zeros(length(test),1)];
         tndx = [tmp_tndx; zeros(length(test),1)];
         retri = true;
      else
         p = pnew;                                                         % No nodes added
         wndx = tmp_wndx;
         tndx = tmp_tndx;
      end
   end

end
close(wbar)

if iter==maxit
   disp('WARNING: Maximum number of iterations reached. Solution did not converge!')
   disp('Please email the geometry and settings to d_engwirda@hotmail.com')
end

[p,t] = fixmesh(p,t);                                                      % Ensure triangulation unique and
                                                                           % CCW node ordered
tfinal = toc;
if output

   figure('Name','Mesh')
   patch('faces',t,'vertices',p,'facecolor','None','edgecolor','b')
   hold on
   patch('faces',edge,'vertices',node,'facecolor','None','edgecolor','r')
   axis equal off; hold off

   % Mesh measures
   q = quality(p,t);
   
   disp(struct('Iterations',       iter, ...
               'Time',             tfinal, ...
               'Triangles',        size(t,1), ...
               'Nodes',            size(p,1), ...
               'Mean_quality',     mean(q), ...
               'Min_quality',      min(q)) );
               %'Mean_size_ratio',  mean(r), ...
               %'Min_size_ratio',   min(r), ...
               %'Max_size_ratio',   max(r)) );
end


%% SUB-FUNCTIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [p,t,wndx,tndx,fix,fixed] = initmesh(p,t,node,edge,edgexy)

% Initialise the nodes, triangulation and data structures for the mesh 
% based on the quadtree data and geometry.

in = inpoly(p,node,edge);                                                  % True for internal nodes
tin = any(in(t),2);                                                        % True for triangles with at least one internal node
ok = false(size(p,1),1);                                                   % Nodes considered approximately internal
ok(t(tin,:)) = true;

fixed = node;
ndx = tsearch(p(:,1),p(:,2),t,fixed(:,1),fixed(:,2));                      % Find enclosing triangle for fixed nodes

% At this stage some nodes have been accepted that are not inside the 
% geometry. This is done because the quadtree triangulation will overlap 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -