Home > vbmeg > external > iso2mesh > meshrefine.m

meshrefine

PURPOSE ^

SYNOPSIS ^

function [newnode,newelem,newface]=meshrefine(node,elem,varargin)

DESCRIPTION ^

 [newnode,newelem,newface]=meshrefine(node,elem,face,opt)

 refine a tetrahedral mesh by adding new nodes or constraints

 author: Qianqian Fang, <q.fang at neu.edu>

 input parameters:
      node: existing tetrahedral mesh node list
      elem: existing tetrahedral element list
      face: (optional) existing tetrahedral mesh surface triangle list
      opt:  options for mesh refinement:
        if opt is a Nx3 array, opt is treated as a list of new nodes to
          be inserted into the mesh. the new nodes must be located on the 
          surface or inside the original mesh. external nodes are
          discarded, unless the opt.extcmdopt is specified.
        if opt is a vector with a length that equals to that of node,
          it will be used to specify the desired edge-length at each node;
          setting a node value to 0 will by-pass the refinement at this node
        if opt is a vector with a length that equals to that of elem,
          it will be used as the desired maximum element volume of each
          tetrahedron; setting to 0 will by-pass the refinement of that element.
        if opt is a struct, it can have the following fields:
          opt.newnode: same as setting opt to an Nx3 array
          opt.reratio: radius-edge ratio, by default, iso2mesh uses 1.414
          opt.maxvol: maximum element volume
          opt.sizefield: a vector specifying either the desired edge-length
              at each node, or the maximum volume constraint within each 
              tetrahedron, see above for details.
          opt.extcmdopt: by default, meshrefine can only insert nodes
              that are inside the original mesh. if one prefers to insert
              nodes that are outside of the original mesh, one can define
              this parameter to specify the meshing option (for tetgen)
              for the extended domain, i.e. the convex hull including 
              both the original and the external nodes. If not defined, 
              '-Y' option is used by default (prevent tetgen from
              inserting new nodes on the surface).
          opt.extlabel: when external nodes are inserted, the new elements
              will be assigned with an element label to group them
              together, by default, this label is 0, unless opt.extlabel
              is given
          opt.extcorelabel: when external nodes are inserted, par of the 
              new elements share the polyhedra between the inserted nodes,
              these special elements will be marked by opt.extcorelabel, 
              otherwise the label will be set to -1 

 outputs:
      newnode: node coordinates of the tetrahedral mesh
      newelem: element list of the tetrahedral mesh
      newface: mesh surface element list of the tetrahedral mesh 
             the last column denotes the boundary ID

 examples:

     [node,face,elem]=meshasphere([0 0 0],24,1,2);
     elem(:,5)=1;

     % inserting nodes that are inside the original mesh
     innernodes=double([1 1 1; 2 2 2; 3 3 3]);
     [newno,newel]=meshrefine(node,elem,innernodes);
     all(ismember(round(innernodes*1e10)*1e-10,round(newno*1e10)*1e-10,'rows'))
     plotmesh(newno,[],newel,'x>-3')

     % inserting nodes that are external to the original mesh
     extnodes=double([-5 -5 25;-5 5 25;5 5 25;5 -5 25]);
     [newno,newel]=meshrefine(node,elem,struct('newnode',extnodes,'extcmdopt','-Y'));
     figure;
     plotmesh(newno,[],newel,'x>-3')

 -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [newnode,newelem,newface]=meshrefine(node,elem,varargin)
0002 %
0003 % [newnode,newelem,newface]=meshrefine(node,elem,face,opt)
0004 %
0005 % refine a tetrahedral mesh by adding new nodes or constraints
0006 %
0007 % author: Qianqian Fang, <q.fang at neu.edu>
0008 %
0009 % input parameters:
0010 %      node: existing tetrahedral mesh node list
0011 %      elem: existing tetrahedral element list
0012 %      face: (optional) existing tetrahedral mesh surface triangle list
0013 %      opt:  options for mesh refinement:
0014 %        if opt is a Nx3 array, opt is treated as a list of new nodes to
0015 %          be inserted into the mesh. the new nodes must be located on the
0016 %          surface or inside the original mesh. external nodes are
0017 %          discarded, unless the opt.extcmdopt is specified.
0018 %        if opt is a vector with a length that equals to that of node,
0019 %          it will be used to specify the desired edge-length at each node;
0020 %          setting a node value to 0 will by-pass the refinement at this node
0021 %        if opt is a vector with a length that equals to that of elem,
0022 %          it will be used as the desired maximum element volume of each
0023 %          tetrahedron; setting to 0 will by-pass the refinement of that element.
0024 %        if opt is a struct, it can have the following fields:
0025 %          opt.newnode: same as setting opt to an Nx3 array
0026 %          opt.reratio: radius-edge ratio, by default, iso2mesh uses 1.414
0027 %          opt.maxvol: maximum element volume
0028 %          opt.sizefield: a vector specifying either the desired edge-length
0029 %              at each node, or the maximum volume constraint within each
0030 %              tetrahedron, see above for details.
0031 %          opt.extcmdopt: by default, meshrefine can only insert nodes
0032 %              that are inside the original mesh. if one prefers to insert
0033 %              nodes that are outside of the original mesh, one can define
0034 %              this parameter to specify the meshing option (for tetgen)
0035 %              for the extended domain, i.e. the convex hull including
0036 %              both the original and the external nodes. If not defined,
0037 %              '-Y' option is used by default (prevent tetgen from
0038 %              inserting new nodes on the surface).
0039 %          opt.extlabel: when external nodes are inserted, the new elements
0040 %              will be assigned with an element label to group them
0041 %              together, by default, this label is 0, unless opt.extlabel
0042 %              is given
0043 %          opt.extcorelabel: when external nodes are inserted, par of the
0044 %              new elements share the polyhedra between the inserted nodes,
0045 %              these special elements will be marked by opt.extcorelabel,
0046 %              otherwise the label will be set to -1
0047 %
0048 % outputs:
0049 %      newnode: node coordinates of the tetrahedral mesh
0050 %      newelem: element list of the tetrahedral mesh
0051 %      newface: mesh surface element list of the tetrahedral mesh
0052 %             the last column denotes the boundary ID
0053 %
0054 % examples:
0055 %
0056 %     [node,face,elem]=meshasphere([0 0 0],24,1,2);
0057 %     elem(:,5)=1;
0058 %
0059 %     % inserting nodes that are inside the original mesh
0060 %     innernodes=double([1 1 1; 2 2 2; 3 3 3]);
0061 %     [newno,newel]=meshrefine(node,elem,innernodes);
0062 %     all(ismember(round(innernodes*1e10)*1e-10,round(newno*1e10)*1e-10,'rows'))
0063 %     plotmesh(newno,[],newel,'x>-3')
0064 %
0065 %     % inserting nodes that are external to the original mesh
0066 %     extnodes=double([-5 -5 25;-5 5 25;5 5 25;5 -5 25]);
0067 %     [newno,newel]=meshrefine(node,elem,struct('newnode',extnodes,'extcmdopt','-Y'));
0068 %     figure;
0069 %     plotmesh(newno,[],newel,'x>-3')
0070 %
0071 % -- this function is part of iso2mesh toolbox (http://iso2mesh.sf.net)
0072 %
0073 
0074 exesuff=getexeext;
0075 exesuff=fallbackexeext(exesuff,'tetgen');
0076 
0077 newpt=[];
0078 sizefield=[];
0079 if(size(node,2)==4)
0080    sizefield=node(:,4);
0081    node=node(:,1:3);
0082 end
0083 opt=struct;
0084 if(length(varargin)==1)
0085     face=[];
0086     if(isstruct(varargin{1}))
0087         opt=varargin{1};
0088         else
0089         if(length(varargin{1})==size(node,1) || length(varargin{1})==size(elem,1))
0090             sizefield=varargin{1};
0091         else
0092             newpt=varargin{1};
0093         end
0094     end
0095 elseif(length(varargin)>=2)
0096     face=varargin{1};
0097     if(isstruct(varargin{2}))
0098         opt=varargin{2};
0099     else
0100         if(length(varargin{2})==size(node,1) || length(varargin{1})==size(elem,1))
0101                 sizefield=varargin{2};
0102         else
0103                 newpt=varargin{2};
0104         end
0105     end
0106 else
0107     error('meshrefine requires at least 3 inputs');
0108 end
0109 if(isstruct(opt) && isfield(opt,'newnode'))
0110     newpt=opt.newnode;
0111 end
0112 if(isstruct(opt) && isfield(opt,'sizefield'))
0113     sizefield=opt.sizefield;
0114 end
0115 
0116 % call tetgen to create volumetric mesh
0117 deletemeshfile(mwpath('pre_refine.*'));
0118 deletemeshfile(mwpath('post_refine.*'));
0119 
0120 moreopt='';
0121 setquality=0;
0122 if(isstruct(opt) && isfield(opt,'reratio'))
0123     moreopt=[moreopt sprintf(' -q %.10f ',opt.reratio)];
0124     setquality=1;
0125 end
0126 if(isstruct(opt) && isfield(opt,'maxvol'))
0127     moreopt=[moreopt sprintf(' -a %.10f ',opt.maxvol)];
0128 end
0129 
0130 externalpt=[];
0131 if(isstruct(opt) && isfield(opt,'extcmdopt'))
0132     isinside=tsearchn(node(:,1:3),elem(:,1:4),newpt(:,1:3));
0133     externalpt=newpt(isnan(isinside),:);
0134     newpt=newpt(find(isnan(isinside)==0),:);
0135 end
0136 
0137 if(~isempty(newpt))
0138     if(size(newpt,1)<4)
0139         newpt=[newpt; repmat(newpt(1,:),4-size(newpt,1),1)];
0140     end
0141     savetetgennode(newpt,mwpath('pre_refine.1.a.node'));
0142     moreopt=' -i ';
0143 end
0144 
0145 if(~isempty(sizefield))
0146     if(length(sizefield)==size(node,1))
0147         fid=fopen(mwpath('pre_refine.1.mtr'),'wt');
0148         fprintf(fid,'%d 1\n',size(sizefield,1));
0149         fprintf(fid,'%.16f\n',sizefield);
0150         fclose(fid);
0151     moreopt=[moreopt ' -qa '];
0152     else
0153         fid=fopen(mwpath('pre_refine.1.vol'),'wt');
0154         fprintf(fid,'%d\n',size(sizefield,1));
0155         fprintf(fid,'%d\t%.16f\n',[(1:size(sizefield,1))' sizefield]');
0156         fclose(fid);
0157     moreopt=[moreopt ' -qa '];
0158     end
0159 end
0160 
0161 if(size(elem,2)==3 && setquality==0)
0162     if(~isempty(newpt))
0163         error('inserting new point can not be used for surfaces');
0164     end
0165     nedge=savegts(node, elem,mwpath('pre_refine.gts'));
0166     exesuff=fallbackexeext(getexeext,'gtsrefine');
0167 elseif(size(elem,2)==3)
0168     savesurfpoly(node,elem,[],[],[],[],mwpath('pre_refine.poly'));
0169 else
0170     savetetgennode(node, mwpath('pre_refine.1.node'));
0171     savetetgenele (elem, mwpath('pre_refine.1.ele'));
0172 end
0173 
0174 fprintf(1,'refining the input mesh ...\n');
0175 
0176 if(size(elem,2)==3 && setquality==0)
0177     if(isstruct(opt) && isfield(opt,'scale'))
0178         moreopt=sprintf('%s -n %d ',moreopt,round(nedge*opt.scale));
0179     else
0180         error('you must give opt.scale value for refining a surface');
0181     end
0182 end
0183 if(isstruct(opt) && isfield(opt,'moreopt'))
0184     moreopt=[moreopt opt.moreopt];
0185 end
0186 
0187 if(size(elem,2)==3 && setquality==0)
0188     system([' "' mcpath('gtsrefine') exesuff '" ' moreopt ' < "' ...
0189           mwpath('pre_refine.gts') '" > "' mwpath('post_refine.gts') '"']);
0190     [newnode,newelem]=readgts(mwpath('post_refine.gts'));
0191     newface=newelem;
0192 elseif(size(elem,2)==3)
0193     system([' "' mcpath('tetgen') exesuff '" ' moreopt ' -p -A "' mwpath('pre_refine.poly') '"']);
0194     [newnode,newelem,newface]=readtetgen(mwpath('pre_refine.1'));
0195 elseif(~isempty(moreopt))
0196     system([' "' mcpath('tetgen') exesuff '" ' moreopt ' -r "' mwpath('pre_refine.1') '"']);
0197     [newnode,newelem,newface]=readtetgen(mwpath('pre_refine.2'));
0198 else
0199     newnode=node;
0200     newelem=elem;
0201     newface=face;
0202 end
0203 
0204 if(~isempty(externalpt)) % user request to insert nodes that are outside of the original mesh
0205     % create a mesh including the external points
0206     externalpt=unique(externalpt,'rows');
0207     allnode=[newnode;externalpt];
0208 
0209     % define the convexhull as the external surface
0210     try
0211         outface=convhull(allnode,'simplify',false);
0212     catch
0213         outface=convhulln(allnode);
0214     end
0215     outface=sort(outface,2);
0216     face=volface(newelem(:,1:4));
0217     inface=sort(face(:,1:3),2);
0218 
0219     % define the surface that bounds the newly extended convex hull space
0220     bothsides=removedupelem([outface;inface]);
0221 
0222     % define a seed point to avoid meshing the interior space
0223     holelist=surfseeds(node,face(:,1:3));
0224 
0225     % mesh the extended space
0226     ISO2MESH_TETGENOPT=jsonopt('extcmdopt','-Y',opt);
0227     if(size(bothsides,1)>=size(inface,1))
0228         [no,el]=surf2mesh(allnode,bothsides,[],[],1,10,[],holelist);
0229     else
0230         [no,el]=surf2mesh(allnode,bothsides,[],[],1,10);
0231     end
0232 
0233     [isinside,map]=ismember(round(no*1e10)*1e-10,round(allnode*1e10)*1e-10,'rows');
0234     snid=[length(newnode)+1:length(allnode)];
0235 
0236     if(~isempty(map==0))
0237         oldsize=size(allnode,1);
0238         allnode=[allnode;no(map==0,:)];
0239         map(map==0)=oldsize+1:size(allnode,1);
0240     end
0241     % merge the external space with the original mesh
0242     el2=map(el(:,1:4));
0243 
0244     % label all new elements with -1
0245     if(size(newelem,2)==5)
0246         el2(:,5)=jsonopt('extlabel',0,opt);
0247         % search elements that contain source(s) and save their id(s)
0248         iselm=ismember(el2(:,1:4),snid);
0249         el2(sum(iselm,2)>=3,5)=jsonopt('extcorelabel',-1,opt);
0250     end
0251 
0252     % merge nodes/elements and replace the original ones
0253     newnode=allnode;
0254     newelem=[newelem;el2];
0255 end
0256 
0257 % read in the generated mesh
0258 
0259 fprintf(1,'mesh refinement is complete\n');
0260

Generated on Mon 22-May-2023 06:53:56 by m2html © 2005