Beispiel #1
0
MVertex_ptr ME_Split(MEdge_ptr esplit, double *xyz) {
  MVertex_ptr vnew, v[2];
  MEdge_ptr enew;
  List_ptr elist;
  double vxyz[3];

#ifdef DEBUG
  v[0] = ME_Vertex(esplit,0);
  v[1] = ME_Vertex(esplit,1);
#endif
  
  if (xyz) {
    memcpy(vxyz,xyz,3*sizeof(double));
    elist = ME_MultiSplit(esplit,1,&vxyz);
  }
  else
    elist = ME_MultiSplit(esplit,1,NULL);

  enew = List_Entry(elist,0);
  vnew = ME_Vertex(enew,1);

#ifdef DEBUG
  if (vnew == v[0] || vnew == v[1]) {
    MSTK_Report("ME_Split","Unexpected failure to retrieve split vertex",
                MSTK_FATAL);
  }
#endif

  List_Delete(elist);

  return vnew;
}
Beispiel #2
0
  MEdge_ptr MVs_CommonEdge(MVertex_ptr v1, MVertex_ptr v2) {
    List_ptr vedges;
    MEdge_ptr edge=0;
    MVertex_ptr ev;
    int i, found, nve;

    vedges = MV_Edges(v1);
    if (!vedges)
      return 0;

    nve = List_Num_Entries(vedges);

    for (i = 0, found = 0; i < nve; i++) {
      edge = List_Entry(vedges,i);
      ev = ME_Vertex(edge,0);
      if (ev == v2) {
        found = 1;
        break;
      }
      else {
        ev = ME_Vertex(edge,1);
        if (ev == v2) {
          found = 1;
          break;
        }
      }
    }
    List_Delete(vedges);

    return (found ? edge : 0);
  }
Beispiel #3
0
  List_ptr ME_Faces_R3R4(MEdge_ptr e) {
    int i, j, nef, nvf, nv, found;
    List_ptr efaces, vfaces, fverts;
    MFace_ptr vface;
    MVertex_ptr ev[2];

    nef = 0;
    efaces = List_New(10);

    for (i = 0; i < 2; i++)
      ev[i] = ME_Vertex(e,i);

    vfaces = MV_Faces(ev[0]);
    nvf = List_Num_Entries(vfaces);

    /* Go through all faces connected to ev[0] and pick out ones which
       use this edge. Do this by checking if ev[0] and ev[1] are
       consecutive vertices in the face */
    for (i = 0; i < nvf; i++) {
      vface = List_Entry(vfaces,i);
      
      /* Get vertices of i'th face connected to ev[0] */
      fverts = MF_Vertices(vface,1,0);
      nv = MF_Num_Vertices(vface);

      /* If the j'th vertex is ev[0], check if the next or the
         previous vertex is ev[1]; If it is then the edge is used by
         the face */

      found = 0;
      for (j = 0; j < nv; j++) {
	if (ev[0] == List_Entry(fverts,j) &&
	    (ev[1] == List_Entry(fverts,(j+1)%nv) ||
	     ev[1] == List_Entry(fverts,(j+nv-1)%nv))) {
	  found = 1;
	  break;
	}
      }
      List_Delete(fverts);

      if (found) {
	List_Add(efaces,vface);
	nef++;
      }
    }
    List_Delete(vfaces);

    if (nef)
      return efaces;
    else {
      List_Delete(efaces);
      return 0;
    } 
  }
Beispiel #4
0
  int MF_UsesEdge_R4(MFace_ptr f, MEdge_ptr e) {
    MFace_Adj_R4 *adj = (MFace_Adj_R4 *) f->adj;
    int i, nv;
    MVertex_ptr v0, v1, v;

    v0 = ME_Vertex(e,0);
    v1 = ME_Vertex(e,1);
    nv = List_Num_Entries(adj->fvertices);
    for (i = 0; i < nv; i++) {
      v = List_Entry(adj->fvertices,i);
      if (v == v0) {
	if (List_Entry(adj->fvertices,(i+1)%nv) == v1) {
	  return 1;
	}
      }
      else if (v == v1) {
	if (List_Entry(adj->fvertices,(i+1)%nv) == v0) {
	  return 1;
	}
      }
    }
        
    return 0;
  }
Beispiel #5
0
MVertex_ptr ME_Collapse(MEdge_ptr e, MVertex_ptr vkeep_in, int topoflag,
                        List_ptr *deleted_entities) {
  MVertex_ptr vdel, vkeep, ev00, ev01, ev10, ev11, vert;
  MEdge_ptr edge, edge2, oldedges[3], nuedges[2];
  MFace_ptr face, face2, rface1, rface2;
  MRegion_ptr reg, reg2;
  List_ptr vedges, efaces, eregs, fedges, rfaces, fverts1, fverts2, vfaces;
  int idx1, idx2, idx3, dir, status, nfe, nrf, allfound, degenerate;
  int i, j, nfe2, nfv1, nfv2;

  status = 1;

  if (vkeep_in == NULL) {
    vdel = ME_Vertex(e,0);
    vkeep = ME_Vertex(e,1);
  }
  else {
    vkeep = vkeep_in;
    vdel = ME_OppVertex(e,vkeep);
  }

  int dimkeep, dimdel;
    
  dimkeep = MV_GEntDim(vkeep); /* Model entity dim of vertex to keep */
  dimdel = MV_GEntDim(vdel);   /* Model entity dim  of vertex to delete */
  
  if (topoflag == 1) {
    if (dimkeep == dimdel) {
      
      if (MV_GEntID(vkeep) != MV_GEntID(vdel))
        status = 0;                 /* cannot allow since it will cause 
                                       a dimensional reduction in mesh */
    }
    else if (dimdel < dimkeep) {
      
      if (vkeep_in == NULL) {
        /* If no preference was indicated on which vertex to retain,
	   we can collapse in the other direction */
        MVertex_ptr vtemp = vdel;
	vdel = vkeep;
	vkeep = vtemp;
      }
      else
        status = 0; /* can't reverse order or vertices and boundary of
                       mesh will get messed up if we go through as is */
    }
  }
  else if (vkeep_in == NULL) { 

    /* If no preference was indicated for the kept vertex and
       topological conformity with the underlying geometric model was
       not requested, we prefer to keep an external boundary vertex
       over an interior vertex or interior boundary vertex. This is
       because it is more likely that the external boundary vertex
       would have a boundary condition applied to it. If a preference
       was indicated, we just have to respect that. */

    int vdel_external = 0;

    /* Check if any edges connected to vdel have only one connected face */

    vedges = MV_Edges(vdel);    

    idx1 = 0;
    while ((edge = (MEdge_ptr) List_Next_Entry(vedges,&idx1))) {
      List_ptr efaces = ME_Faces(edge);
      int nef = List_Num_Entries(efaces);
      List_Delete(efaces);
      if (nef < 2) {
        vdel_external = 1;
        break;
      }
    }                                          
    
    List_Delete(vedges);

    /* check if any face connected to vdel has only one region
       connected to it */

    if (!vdel_external) {
      vfaces = MV_Faces(vdel);

      idx1 = 0;
      while ((face = (MFace_ptr) List_Next_Entry(vfaces,&idx1))) {
        List_ptr fregs = MF_Regions(face);
        int nfr = fregs ? List_Num_Entries(fregs) : 0;
        if (fregs) List_Delete(fregs);

        if (nfr == 1) {
          vdel_external = 0;
          break;
        }
      }

      List_Delete(vfaces);
    }

    if (vdel_external) {
      /* swap the vertices in the hope that vkeep is not also on an
         external boundary. Since we have to go through with the
         collapse anyway, there is no use of doing a detailed check
         for whether vkeep is also on an external boundary */

      MVertex_ptr vtemp = vdel;
      vdel = vkeep;
      vkeep = vtemp;
    }
    
  }


  if (status == 0)
    return NULL;   /* Cannot collapse due to constraints of topological
		   conformity with geometric model */

  *deleted_entities = List_New(10);

  /* Need to collect this in advance because the info gets messed up later */

  efaces = ME_Faces(e);
  eregs = ME_Regions(e);


  /* Replace vdel with vkeep in all edges connected to vdel */

  vedges = MV_Edges(vdel);
  idx1 = 0;
  while ((edge = List_Next_Entry(vedges,&idx1))) {
    ME_Replace_Vertex(edge,vdel,vkeep);
  }
  List_Delete(vedges);

  /* Remove edge 'e' from all faces connected to e */
  /* This part of the code is using some reliance on the internal
     implementation of MF_Edges. While unlikely, it _might_ break if
     the innards of MF_Edges are changed */

  
  idx1 = 0;
  while ((face = List_Next_Entry(efaces,&idx1))) {

    fedges = MF_Edges(face,1,0);
    nfe = List_Num_Entries(fedges);

    /* Find the edge before and after e in the face */

    oldedges[0] = oldedges[2] = NULL;
    for (i = 0; i < nfe; i++) {
      edge = List_Entry(fedges,i);
      if (edge == e) continue;

      dir = MF_EdgeDir_i(face,i);

      if (ME_Vertex(edge,dir) == vkeep)
	oldedges[0] = edge;
      else if (ME_Vertex(edge,!dir) == vkeep)
	oldedges[2] = edge;
    }
    oldedges[1] = e;

    nuedges[0] = oldedges[0];
    nuedges[1] = oldedges[2];


    /* Replace oldedges[0], oldedges[1] (=e), oldedges[2] with 
       oldedges[0], oldedges[2] since e is degenerate */

    MF_Replace_Edges(face,3,oldedges,2,nuedges);

    List_Delete(fedges);
  }



  /* Delete topologically degenerate regions */
  /* Defined as two faces of the regions having the same vertices */

  if (eregs) {
    idx1 = 0;
    while ((reg = List_Next_Entry(eregs,&idx1))) {

      rfaces = MR_Faces(reg);
      nrf = List_Num_Entries(rfaces);

      if (nrf == 4) {      
        List_ptr rverts = MR_Vertices(reg);
        if (List_Num_Entries(rverts) == 4) {
          MR_Delete(reg,0);    /* This is a tet - it will become degenerate */
        }
        List_Delete(rverts);
      }
      else {

	degenerate = 0;

	for (i = 0; i < nrf; i++) {

	  rface1 = List_Entry(rfaces,i);
	
	  fverts1 = MF_Vertices(rface1,1,0);
	  nfv1 = List_Num_Entries(fverts1);
		
	  for (j = i+1; j < nrf; j++) {
	  
	    rface2 = List_Entry(rfaces,j);

	    fverts2 = MF_Vertices(rface2,1,0);
	    nfv2 = List_Num_Entries(fverts2);
	  
	    if (nfv1 != nfv2) {
	      List_Delete(fverts2);
	      continue;             /* can't be exactly coincident */
	    }

	    allfound = 1;
	    idx2 = 0;
	    while ((vert = List_Next_Entry(fverts2,&idx2))) {
	      if (!List_Contains(fverts1,vert)) {
		allfound = 0;
		break;
	      }
	    }
	  
	    List_Delete(fverts2);
	  
	    if (allfound) {
	      degenerate = 1;
	      break;
	    }
	  
	  } /* for (j = i+1 ... */

	  List_Delete(fverts1);

	  if (degenerate) break;

	} /* for (i = 0; i < nrf;.... */

	if (degenerate) {
          List_Add(*deleted_entities,reg);
	  MR_Delete(reg,0);
        }

      } /* if (nrf == 4) .. else ... */

      List_Delete(rfaces);

    } /* while ((reg = ...)) */
  }


  /* Delete topologically degenerate faces */

  if (efaces) {
    idx1 = 0;
    while ((face = List_Next_Entry(efaces,&idx1))) {

      fedges = MF_Edges(face,1,0);

      if (List_Num_Entries(fedges) == 2) {

	/* Disconnect the regions from the face before deleting */

	List_ptr fregs = MF_Regions(face);
        if (fregs) {
          idx2 = 0;
          while ((reg = List_Next_Entry(fregs,&idx2)))
            MR_Rem_Face(reg,face);
          
          List_Delete(fregs);
        }

        List_Add(*deleted_entities,face);
	MF_Delete(face,0);
      }

      List_Delete(fedges);
    }
    List_Delete(efaces);
  }



  /* Now merge edges which have the same end vertices */
  /* Prefer to preserve edges on external boundaries over internal edges */

  vedges = MV_Edges(vkeep);
  idx1 = 0; 
  while ((edge = List_Next_Entry(vedges,&idx1))) {
    if (edge == e) continue;
    
    ev00 = ME_Vertex(edge,0);
    ev01 = ME_Vertex(edge,1);

    idx2 = 0;
    while ((edge2 = List_Next_Entry(vedges,&idx2))) {
      if (edge == e || edge == edge2) continue;

      ev10 = ME_Vertex(edge2,0);
      ev11 = ME_Vertex(edge2,1);

      if ((ev00 == ev10 && ev01 == ev11) ||
	  (ev00 == ev11 && ev10 == ev01)) {

        int external_edge, external_edge2;
        int edim = 4;
	    
        external_edge = 0;
        edim = ME_GEntDim(edge);
        if (edim == 1 || edim == 2 || edim == 4) { /* check if external edge */
          
          efaces = ME_Faces(edge);
          int nef = List_Num_Entries(efaces);
          if (nef == 1) {
            external_edge = 1;
          }
          else {
            idx3 = 0;
            while ((face = List_Next_Entry(efaces,&idx2))) {
              List_ptr fregs = MF_Regions(face);
              int nfr = fregs ? List_Num_Entries(fregs) : 0;
              if (fregs) List_Delete(fregs);
              if (nfr == 1) {
                external_edge = 1;
                break;
              }
            }
          }
          List_Delete(efaces);
          
        }
    
        external_edge2 = 0;
        edim = ME_GEntDim(edge2);
        if (edim == 1 || edim == 2 || edim == 4) { /* check if external edge */

          efaces = ME_Faces(edge2);
          int nef = List_Num_Entries(efaces);
          if (nef == 1) {
            external_edge2 = 1;
          }
          else {
            idx3 = 0;
            while ((face = List_Next_Entry(efaces,&idx2))) {
              List_ptr fregs = MF_Regions(face);
              int nfr = fregs ? List_Num_Entries(fregs) : 0;
              if (fregs) List_Delete(fregs);
              if (nfr == 1) {
                external_edge2 = 1;
                break;
              }
            }
          }
          List_Delete(efaces);
          
        }

        /* If edge2 is not external or both edges are external, go
           ahead and merge (edge2 will be deleted subject to
           topological checks if topoflag is 1) */

        if (!external_edge2 || (external_edge && external_edge2)) {
          MEs_Merge(edge,edge2,topoflag);	
          List_Rem(vedges,edge2);	
          List_Add(*deleted_entities,edge2);
          break;
        }
      }
    }
  }
  List_Delete(vedges);


  /* Merge faces with the same set of edges */
      
  vfaces = MV_Faces(vkeep);

  if (vfaces) {
    idx1 = 0;
    while ((face = List_Next_Entry(vfaces,&idx1))) {
    
      fedges = MF_Edges(face,1,0);
      nfe = List_Num_Entries(fedges);
    
      idx2 = 0;
      while ((face2 = List_Next_Entry(vfaces,&idx2))) {
	List_ptr fedges2;

	if (face2 == face) continue;

	fedges2 = MF_Edges(face2,1,0);
	nfe2 = List_Num_Entries(fedges2);

	if (nfe != nfe2) {
	  List_Delete(fedges2);
	  continue;
	}

	allfound = 1;

	for (i = 0; i < nfe2; i++) {
	  edge = List_Entry(fedges2,i);
	  if (!List_Contains(fedges,edge)) {
	    allfound = 0;
	    break;
	  }
	}
	List_Delete(fedges2);

	if (allfound) {

          List_ptr fregs = MF_Regions(face);
          int external_face = fregs ? (List_Num_Entries(fregs) == 1) : 0;
          if (fregs) List_Delete(fregs);

          List_ptr fregs2 = MF_Regions(face2);
          int external_face2 = fregs2 ? (List_Num_Entries(fregs2) == 1) : 0;
          if (fregs2) List_Delete(fregs2);

          /* Proceed with merge (which will delete face2) only if face2 is
             not an external face or both face and face2 are external */

          if (!external_face2 || (external_face && external_face2)) {
            MFs_Merge(face,face2,topoflag);	
            List_Rem(vfaces,face2);
            List_Add(*deleted_entities,face2);
            break;
          }

        }
	
      } /* while (face2 = List_Next_Entry(vfaces,... */

      List_Delete(fedges);

    } /* while (face = List_Next_Entry(vfaces,... */
    List_Delete(vfaces);
  }

  /* Now actually delete the collapse edge and the to-be-merged vertex */

  ME_Delete(e,0);
  List_Add(*deleted_entities,e);

  MV_Delete(vdel,0);
  List_Add(*deleted_entities,vdel);

  if (eregs) {
    idx1 = 0;
    while ((reg = List_Next_Entry(eregs,&idx1)))
      MR_Update_ElementType(reg);
    
    List_Delete(eregs);
  }

  return vkeep;
}
Beispiel #6
0
void MESH_Renumber(Mesh_ptr mesh, int renum_type, MType mtype) {
  MVertex_ptr mv, v0=NULL;
  MEdge_ptr me, e0=NULL;
  MFace_ptr mf, f0=NULL;
  MRegion_ptr mr, r0=NULL;
  int idx, idx2, idx3;
  int i, j;
  int done;
  MAttrib_ptr vidatt;
  List_ptr vlist;
  double xyz[3];
  double rval;
  int bandwidth, maxbandwidth1, maxbandwidth2;
  double avebandwidth1, avebandwidth2;
  void *pval;

  if (renum_type == 0) {
    if (mtype == MVERTEX || mtype == MALLTYPE) {
      int nv = 0;
      idx = 0; 
      while ((mv = MESH_Next_Vertex(mesh,&idx)))
	MV_Set_ID(mv,++nv);
    }
    
    if (mtype == MEDGE || mtype == MALLTYPE) {
      int ne = 0;
      idx = 0; 
      while ((me = MESH_Next_Edge(mesh,&idx)))
	ME_Set_ID(me,++ne);
    }
    
    if (mtype == MFACE || mtype == MALLTYPE) {
      int nf = 0;
      idx = 0; 
      while ((mf = MESH_Next_Face(mesh,&idx)))
	MF_Set_ID(mf,++nf);
    }
    
    if (mtype == MREGION || mtype == MALLTYPE) {
      int nr = 0;
      idx = 0; 
      while ((mr = MESH_Next_Region(mesh,&idx)))
	MR_Set_ID(mr,++nr);
    }
  }
  else if (renum_type == 1) {
    double minx, miny, minz;
    int minid, maxid;
    int *nadj, *newmap, *adj, *offset, nconn;
    int nalloc, depth, maxwidth;
        
#ifdef MSTK_USE_MARKERS
    int mkid = MSTK_GetMarker();
#else
    MAttrib_ptr mkatt = MAttrib_New(mesh, "mkatt", INT, MALLTYPE);
#endif

    if (mtype == MVERTEX || mtype == MALLTYPE) { 
      int nv = MESH_Num_Vertices(mesh);      
      
      /* Compute a graph of vertex connections across elements (faces
	 for surface meshes, regions for solid meshes */

      /* Start with the vertex in the lower leftmost corner */
      
      minx = miny = minz = 1.0e+12;
      v0 = NULL;
      idx = 0;
      while ((mv = MESH_Next_Vertex(mesh,&idx))) {
	MV_Coords(mv,xyz);
	if (xyz[0] <= minx && xyz[1] <= miny && xyz[2] <= minz) {
	  minx = xyz[0];
	  miny = xyz[1];
	  minz = xyz[2];
	  v0 = mv;
	}
      }


      nadj = (int *) malloc(nv*sizeof(int));
      nalloc = nv*5;
      adj = (int *) malloc(nalloc*sizeof(int));

      if (!MESH_Num_Regions(mesh)) {
        int nentries = 0;
        i = 0;
        idx = 0;
        while ((mv = MESH_Next_Vertex(mesh,&idx))) {
          List_ptr vfaces, adjvlist;
          MFace_ptr vf;
          MVertex_ptr adjv;

          adjvlist = List_New(0);
          vfaces = MV_Faces(mv);
          idx2 = 0;
          while ((vf = List_Next_Entry(vfaces,&idx2))) {
            List_ptr fverts = MF_Vertices(vf,1,0);
            idx3 = 0;
            while ((adjv = List_Next_Entry(fverts,&idx3))) {
              if (adjv != mv) {
                int vmarked;
#ifdef MSTK_USE_MARKERS
                vmarked = MEnt_IsMarked(adjv,mkid);
#else
                MEnt_Get_AttVal(adjv, mkatt, &vmarked, &rval, &pval);
#endif
                if (!vmarked) {
                  List_Add(adjvlist,adjv);
#ifdef MSTK_USE_MARKERS
                  MEnt_Mark(adjv,mkid);
#else
                  MEnt_Set_AttVal(adjv, mkatt, 1, 0.0, NULL);
#endif
                }
              }
            }
            List_Delete(fverts);
          }
          List_Delete(vfaces);
#ifdef MSTK_USE_MARKERS
          List_Unmark(adjvlist,mkid);
#endif

          nadj[i] = List_Num_Entries(adjvlist);
          
          if (nentries+nadj[i] > nalloc) {
            nalloc *= 2;
            adj = (int *) realloc(adj,nalloc*sizeof(int));
          }

          idx2 = 0;
          while ((adjv = List_Next_Entry(adjvlist,&idx2)))
            adj[nentries++] = MV_ID(adjv)-1;

          List_Delete(adjvlist);
          i++;
        }
      }
      else {
        int nentries = 0;
        i = 0;
        idx = 0;
        while ((mv = MESH_Next_Vertex(mesh,&idx))) {
          List_ptr vregions, adjvlist;
          MRegion_ptr vr;
          MVertex_ptr adjv;

          adjvlist = List_New(0);
          vregions = MV_Regions(mv);
          idx2 = 0;
          while ((vr = List_Next_Entry(vregions,&idx2))) {
            List_ptr rverts = MR_Vertices(vr);
            idx3 = 0;
            while ((adjv = List_Next_Entry(rverts,&idx3))) {
              if (adjv != mv) {
                int vmarked;
#ifdef MSTK_USE_MARKERS
                vmarked = MEnt_IsMarked(adjv,mkid);
#else
                MEnt_Get_AttVal(adjv, mkatt, &vmarked, &rval, &pval);
#endif
                if (!vmarked) {
                  List_Add(adjvlist,adjv);
#ifdef MSTK_USE_MARKERS
                  MEnt_Mark(adjv,mkid);
#else
                  MEnt_Set_AttVal(adjv, mkatt, 1, 0.0, NULL);
#endif
                }
              }
            }
            List_Delete(rverts);
          }
          List_Delete(vregions);
#ifdef MSTK_USE_MARKERS
          List_Unmark(adjvlist,mkid);
#endif

          nadj[i] = List_Num_Entries(adjvlist);

          if (nentries+nadj[i] > nalloc) {
            nalloc *= 2;
            adj = (int *) realloc(adj,nalloc*sizeof(int));
          }

          idx2 = 0;
          while ((adjv = List_Next_Entry(adjvlist,&idx2)))
            adj[nentries++] = MV_ID(adjv)-1;

          List_Delete(adjvlist);
          i++;
        }
      }

      /* Compute offsets into adj array */

      offset = (int *) malloc(nv*sizeof(int));
      offset[0] = 0;
      for (i = 1; i < nv; i++)
	offset[i] = offset[i-1] + nadj[i-1];

      /* Compute maximum bandwidth before renumbering */

      maxbandwidth1 = 0;
      avebandwidth1 = 0;
      for (i = 0; i < nv; i++) {
	int off = offset[i];
	int curid = i;
	for (j = 0; j < nadj[i]; j++) {
	  int adjid = adj[off+j];
	  int diff = abs(adjid-curid);
	  maxbandwidth1 = (diff > maxbandwidth1) ? diff : maxbandwidth1;
	  avebandwidth1 += diff;
	  nconn++;
	}
      }
      nconn = offset[nv-1]+nadj[nv-1];
      avebandwidth1 /= nconn;

      fprintf(stderr,
	      "Ave vertex ID difference on elements before renumbering: %-lf\n",
	      avebandwidth1);
      fprintf(stderr,
	      "Max vertex ID difference on elements before renumbering: %-d\n",
	      maxbandwidth1);
    
      fprintf(stderr,"\n");

      newmap = (int *) malloc(nv*sizeof(int));
      Graph_Renumber_GPS(nv, MV_ID(v0)-1, nadj, adj, newmap, &depth, &maxwidth);


      /* Compute bandwidth after renumbering */

      maxbandwidth2 = 0;
      avebandwidth2 = 0;
      for (i = 0; i < nv; i++) {
	int off = offset[i];
	int curid = newmap[i];
	for (j = 0; j < nadj[i]; j++) {
	  int adjid = newmap[adj[off+j]];
	  int diff = abs(adjid-curid);
	  maxbandwidth2 = (diff > maxbandwidth2) ? diff : maxbandwidth2;
	  avebandwidth2 += diff;
	  nconn++;
	}
      }
      nconn = offset[nv-1]+nadj[nv-1];
      avebandwidth2 /= nconn;


      if (maxbandwidth2 < maxbandwidth1 && avebandwidth2 < avebandwidth1) {

        /* Renumber */
      
        idx = 0; i = 0;
        while ((mv = MESH_Next_Vertex(mesh,&idx))) {
          MV_Set_ID(mv,newmap[i]+1);
          i++;
        }

        fprintf(stderr,
                "Ave vertex ID difference on elements after renumbering: %-lf\n",
                avebandwidth2);
        fprintf(stderr,
                "Max vertex ID difference on elements after renumbering: %-d\n",
                maxbandwidth2);    
      }
      else {
        nv = 0;
        idx = 0; 
        while ((mv = MESH_Next_Vertex(mesh,&idx)))
          MV_Set_ID(mv,++nv);

        fprintf(stderr,"Bandwidth did not improve. Keeping old numbering with gaps eliminated\n");
      }
      fprintf(stderr,"\n\n\n");
      
      free(nadj);
      free(adj);
      free(offset);
      free(newmap);

    }
 



    /* Reorder edges according to a breadth first algorithm applied to
       edges (differs from RCM in that it does not add adjacent nodes
       in ascending order of their valence) */

    if (mtype == MEDGE || mtype == MALLTYPE) {
      int ne = MESH_Num_Edges(mesh);
      MEdge_ptr ve;
      List_ptr elist;

      /************************* renumbering code ****************************/

      ne = MESH_Num_Edges(mesh);

      if (mtype == MALLTYPE) { 

	/* RCM algorithm already applied on the vertices. Use an edge
	   connected to the starting vertex as the first edge */

	List_ptr vedges = MV_Edges(v0);
	e0 = List_Entry(vedges,0);
	List_Delete(vedges);
      }
      else {
	/* Find the edge whose mid point is a minimum point */
	minx = miny = minz = 1.0e+12;
	e0 = NULL;
	idx = 0;
	while ((me = MESH_Next_Edge(mesh,&idx))) {
          double exyz[2][3];

	  MV_Coords(ME_Vertex(me,0),exyz[0]);
	  MV_Coords(ME_Vertex(me,1),exyz[1]);
	  xyz[0] = (exyz[0][0]+exyz[1][0])/2.0;
	  xyz[1] = (exyz[0][1]+exyz[1][1])/2.0;
	  xyz[2] = (exyz[0][2]+exyz[1][2])/2.0;
	  if (xyz[0] < minx && xyz[1] < miny && xyz[2] < minz) {
	    minx = xyz[0];
	    miny = xyz[1];
	    minz = xyz[2];
	    e0 = me;
	  }
	}
      }


      nadj = (int *) malloc(ne*sizeof(int));
      nalloc = ne*5;
      adj = (int *) malloc(nalloc*sizeof(int));

      if (!MESH_Num_Regions(mesh)) {
        int nentries = 0;
        i = 0;
        idx = 0;
        while ((me = MESH_Next_Edge(mesh,&idx))) {
          List_ptr efaces, adjelist;
          MFace_ptr ef;
          MEdge_ptr adje;

          adjelist = List_New(0);
          efaces = ME_Faces(me);
          idx2 = 0;
          while ((ef = List_Next_Entry(efaces,&idx2))) {
            List_ptr fedges = MF_Edges(ef,1,0);
            idx3 = 0;
            while ((adje = List_Next_Entry(fedges,&idx3))) {
              if (adje != me) {
                int emarked;
#ifdef MSTK_USE_MARKERS
                emarked = MEnt_IsMarked(adje,mkid);
#else
                MEnt_Get_AttVal(adje, mkatt, &emarked, &rval, &pval);
#endif
                if (!emarked) {
                  List_Add(adjelist,adje);
#ifdef MSTK_USE_MARKERS
                  MEnt_Mark(adje,mkid);
#else
                  MEnt_Set_AttVal(adje, mkatt, 1, 0.0, NULL);
#endif
                }
              }
            }
            List_Delete(fedges);
          }
          List_Delete(efaces);
#ifdef MSTK_USE_MARKERS
          List_Unmark(adjelist,mkid);
#endif

          nadj[i] = List_Num_Entries(adjelist);

          if (nentries+nadj[i] > nalloc) {
            nalloc *= 2;
            adj = (int *) realloc(adj,nalloc*sizeof(int));
          }

          idx2 = 0;
          while ((adje = List_Next_Entry(adjelist,&idx2)))
            adj[nentries++] = ME_ID(adje)-1;

          List_Delete(adjelist);
          i++;
        }
      }
      else {
        int nentries = 0;
        i = 0;
        idx = 0;
        while ((me = MESH_Next_Edge(mesh,&idx))) {
          List_ptr eregions, adjelist;
          MRegion_ptr er;
          MEdge_ptr adje;

          adjelist = List_New(0);
          eregions = ME_Regions(me);
          idx2 = 0;
          while ((er = List_Next_Entry(eregions,&idx2))) {
            List_ptr redges = MR_Edges(er);
            idx3 = 0;
            while ((adje = List_Next_Entry(redges,&idx3))) {
              if (adje != me) {
                int emarked;
#ifdef MSTK_USE_MARKERS
                emarked = MEnt_IsMarked(adje,mkid);
#else
                MEnt_Get_AttVal(adje, mkatt, &emarked, &rval, &pval);
#endif
                if (!emarked) {
                  List_Add(adjelist,adje);
#ifdef MSTK_USE_MARKERS
                  MEnt_Mark(adje,mkid);
#else
                  MEnt_Set_AttVal(adje, mkatt, 1, 0.0, NULL);
#endif
                }
              }
            }
            List_Delete(redges);
          }
          List_Delete(eregions);
#ifdef MSTK_USE_MARKERS
          List_Unmark(adjelist,mkid);
#endif
          
          nadj[i] = List_Num_Entries(adjelist);
          
          if (nentries+nadj[i] > nalloc) {
            nalloc *= 2;
            adj = (int *) realloc(adj,nalloc*sizeof(int));
          }
          
          idx2 = 0;
          while ((adje = List_Next_Entry(adjelist,&idx2)))
            adj[nentries++] = ME_ID(adje)-1;
          
          List_Delete(adjelist);
          i++;
        }
      }

      /* Compute offsets into adj array */

      offset = (int *) malloc(ne*sizeof(int));
      offset[0] = 0;
      for (i = 1; i < ne; i++)
        offset[i] = offset[i-1] + nadj[i-1];


      /* Compute maximum bandwidth before renumbering */

      maxbandwidth1 = 0;
      avebandwidth1 = 0;
      for (i = 0; i < ne; i++) {
        int off = offset[i];
        int curid = i;
        for (j = 0; j < nadj[i]; j++) {
          int adjid = adj[off+j];
          int diff = abs(adjid-curid);
          maxbandwidth1 = (diff > maxbandwidth1) ? diff : maxbandwidth1;
          avebandwidth1 += diff;
          nconn++;
        }
      }
      nconn = offset[ne-1]+nadj[ne-1];
      avebandwidth1 /= nconn;

      fprintf(stderr,
              "Ave edge ID difference on elements before renumbering: %-lf\n",
              avebandwidth1);
      fprintf(stderr,
              "Max edge ID difference on elements before renumbering: %-d\n",
              maxbandwidth1);
    
      fprintf(stderr,"\n");


      /* Call Graph Renumbering algorithm */

      newmap = (int *) malloc(ne*sizeof(int));
      Graph_Renumber_GPS(ne, ME_ID(e0)-1, nadj, adj, newmap, &depth, &maxwidth);


      /* Compute bandwidth after renumbering */

      maxbandwidth2 = 0;
      avebandwidth2 = 0;
      for (i = 0; i < ne; i++) {
        int off = offset[i];
        int curid = newmap[i];
        for (j = 0; j < nadj[i]; j++) {
          int adjid = newmap[adj[off+j]];
          int diff = abs(adjid-curid);
          maxbandwidth2 = (diff > maxbandwidth2) ? diff : maxbandwidth2;
          avebandwidth2 += diff;
          nconn++;
        }
      }
      nconn = offset[ne-1]+nadj[ne-1];
      avebandwidth2 /= nconn;

      if (maxbandwidth2 < maxbandwidth1 && avebandwidth2 < avebandwidth1) {
        /* Renumber */
      
        idx = 0; i = 0;
        while ((me = MESH_Next_Edge(mesh,&idx))) {
          ME_Set_ID(me,newmap[i]+1);
          i++;
        }

        fprintf(stderr,
                "Ave edge ID difference on elements after renumbering: %-lf\n",
                avebandwidth2);
        fprintf(stderr,
                "Max edge ID difference on elements after renumbering: %-d\n",
                maxbandwidth2);
        
      }
      else {
        ne = 0;
        idx = 0; 
        while ((me = MESH_Next_Edge(mesh,&idx)))
          ME_Set_ID(me,++ne);

        fprintf(stderr,"Bandwidth did not improve. Keeping old numbering with gaps eliminated\n");
      }
      fprintf(stderr,"\n\n\n");


      free(nadj);
      free(adj);
      free(offset);
      free(newmap);

    }


    /* Reorder faces according to a breadth first algorithm applied to
       edges (differs from RCM in that it does not add adjacent graph nodes
       in ascending order of their valence) */

    if (mtype == MFACE || mtype == MALLTYPE) {      
      int nf = MESH_Num_Faces(mesh);

      if (mtype == MALLTYPE) { 

        /* RCM algorithm already applied on the vertices. Use an edge
           connected to the starting vertex as the first edge */

        List_ptr vfaces = MV_Faces(v0);
        f0 = List_Entry(vfaces,0);
        List_Delete(vfaces);
      }
      else {
        /* Find the face whose mid point is a minimum point */
        minx = miny = minz = 1.0e+12;
        f0 = NULL;
        idx = 0;
        while ((mf = MESH_Next_Face(mesh,&idx))) {
          double fxyz[MAXPV2][3];
          int nfv;

          MF_Coords(mf,&nfv,fxyz);
          xyz[0] = fxyz[0][0];
          xyz[1] = fxyz[0][1];
          xyz[2] = fxyz[0][2];
          for (i = 1; i < nfv; i++) {
            xyz[0] += fxyz[i][0];
            xyz[1] += fxyz[i][1];
            xyz[2] += fxyz[i][2];
          }
          xyz[0] /= nfv; xyz[1] /= nfv; xyz[2] /= nfv;
          if (xyz[0] < minx && xyz[1] < miny && xyz[2] < minz) {
            minx = xyz[0];
            miny = xyz[1];
            minz = xyz[2];
            f0 = mf;
          }
        }
      }


      nadj = (int *) malloc(nf*sizeof(int));
      nalloc = nf*5;
      adj = (int *) malloc(nalloc*sizeof(int));

      if (!MESH_Num_Regions(mesh)) {
        int nentries = 0;
        i = 0;
        idx = 0;
        while ((mf = MESH_Next_Face(mesh,&idx))) {
          List_ptr vfaces, fverts, adjflist;
          MFace_ptr vf, adjf;
          MVertex_ptr fv;

          adjflist = List_New(0);
          fverts = MF_Vertices(mf,1,0);
          idx2 = 0;
          while ((fv = List_Next_Entry(fverts,&idx2))) {
            List_ptr vfaces = MV_Faces(fv);
            idx3 = 0;
            while ((adjf = List_Next_Entry(vfaces,&idx3))) {
              if (adjf != mf) {
                int fmarked;
#ifdef MSTK_USE_MARKERS
                fmarked = MEnt_IsMarked(adjf,mkid);
#else
                MEnt_Get_AttVal(adjf, mkatt, &fmarked, &rval, &pval);
#endif
                if (fmarked) {
                  List_Add(adjflist,adjf);
#ifdef MSTK_USE_MARKERS                  
                  MEnt_Mark(adjf,mkid);
#else
                  MEnt_Set_AttVal(adjf, mkatt, 1, 0.0, NULL);
#endif
                }
              }
            }	    
            List_Delete(vfaces);
          }
          List_Delete(fverts);
#ifdef MSTK_USE_MARKERS
          List_Unmark(adjflist,mkid);
#endif

          nadj[i] = List_Num_Entries(adjflist);

          if (nentries+nadj[i] > nalloc) {
            nalloc *= 2;
            adj = (int *) realloc(adj,nalloc*sizeof(int));
          }

          idx2 = 0;
          while ((adjf = List_Next_Entry(adjflist,&idx2)))
            adj[nentries++] = MF_ID(adjf)-1;

          List_Delete(adjflist);
          i++;
        }
      }
      else {
        int nentries = 0;
        i = 0;
        idx = 0;
        while ((mf = MESH_Next_Face(mesh,&idx))) {
          List_ptr fregions, adjflist;
          MRegion_ptr fr;
          MFace_ptr adjf;

          adjflist = List_New(0);
          fregions = MF_Regions(mf);
          idx2 = 0;
          while ((fr = List_Next_Entry(fregions,&idx2))) {
            List_ptr rfaces = MR_Faces(fr);
            idx3 = 0;
            while ((adjf = List_Next_Entry(rfaces,&idx3))) {
              if (adjf != mf) {
                int fmarked;
#ifdef MSTK_USE_MARKERS
                fmarked = MEnt_IsMarked(adjf,mkid);
#else
                MEnt_Get_AttVal(adjf, mkatt, &fmarked, &rval, &pval);
#endif
                if (fmarked) {
                  List_Add(adjflist,adjf);
#ifdef MSTK_USE_MARKERS                  
                  MEnt_Mark(adjf,mkid);
#else
                  MEnt_Set_AttVal(adjf, mkatt, 1, 0.0, NULL);
#endif
                }
              }
            }
            List_Delete(rfaces);
          }
          List_Delete(fregions);
#ifdef MSTK_USE_MARKERS
          List_Unmark(adjflist,mkid);
#endif

          nadj[i] = List_Num_Entries(adjflist);

          if (nentries+nadj[i] > nalloc) {
            nalloc *= 2;
            adj = (int *) realloc(adj,nalloc*sizeof(int));
          }

          idx2 = 0;
          while ((adjf = List_Next_Entry(adjflist,&idx2)))
            adj[nentries++] = MF_ID(adjf)-1;

          List_Delete(adjflist);
          i++;
        }
      }

      /* Compute offsets into adj array */

      offset = (int *) malloc(nf*sizeof(int));
      offset[0] = 0;
      for (i = 1; i < nf; i++)
        offset[i] = offset[i-1] + nadj[i-1];


      /* Compute maximum bandwidth before renumbering */

      maxbandwidth1 = 0;
      avebandwidth1 = 0;
      for (i = 0; i < nf; i++) {
        int off = offset[i];
        int curid = i;
        for (j = 0; j < nadj[i]; j++) {
          int adjid = adj[off+j];
          int diff = abs(adjid-curid);
          maxbandwidth1 = (diff > maxbandwidth1) ? diff : maxbandwidth1;
          avebandwidth1 += diff;
          nconn++;
        }
      }
      nconn = offset[nf-1]+nadj[nf-1];
      avebandwidth1 /= nconn;

      if (MESH_Num_Regions(mesh)) {
        fprintf(stderr,
                "Ave face ID difference on elements before renumbering: %-lf\n",
                avebandwidth1);
        fprintf(stderr,
                "Max face ID difference on elements before renumbering: %-d\n",
                maxbandwidth1);
      }
      else {
        fprintf(stderr,
                "Ave face ID difference before renumbering: %-lf\n",
                avebandwidth1);
        fprintf(stderr,
                "Max face ID difference before renumbering: %-d\n",
                maxbandwidth1);
      }
    
      fprintf(stderr,"\n");


      /* Call Graph Renumbering algorithm */

      newmap = (int *) malloc(nf*sizeof(int));
      Graph_Renumber_GPS(nf, MF_ID(f0)-1, nadj, adj, newmap, &depth, &maxwidth);


      /* Compute bandwidth after renumbering */

      maxbandwidth2 = 0;
      avebandwidth2 = 0;
      for (i = 0; i < nf; i++) {
        int off = offset[i];
        int curid = newmap[i];
        for (j = 0; j < nadj[i]; j++) {
          int adjid = newmap[adj[off+j]];
          int diff = abs(adjid-curid);
          maxbandwidth2 = (diff > maxbandwidth2) ? diff : maxbandwidth2;
          avebandwidth2 += diff;
          nconn++;
        }
      }
      nconn = offset[nf-1]+nadj[nf-1];
      avebandwidth2 /= nconn;


      if (maxbandwidth2 < maxbandwidth1 && avebandwidth2 < avebandwidth1) {
        /* Renumber */
      
        idx = 0; i = 0;
        while ((mf = MESH_Next_Face(mesh,&idx))) {
          MF_Set_ID(mf,newmap[i]+1);
          i++;
        }

        if (MESH_Num_Regions(mesh)) {
          fprintf(stderr,
                  "Ave face ID difference on elements after renumbering: %-lf\n",
                  avebandwidth2);
          fprintf(stderr,
                  "Max face ID difference on elements after renumbering: %-d\n",
                  maxbandwidth2);
        }
        else {
          fprintf(stderr,
                  "Ave face ID difference after renumbering: %-lf\n",
                  avebandwidth2);
          fprintf(stderr,
                  "Max face ID difference after renumbering: %-d\n",
                  maxbandwidth2);
        }
    
      }
      else {
        nf = 0;
        idx = 0; 
        while ((mf = MESH_Next_Face(mesh,&idx)))
          MF_Set_ID(mf,++nf);

        fprintf(stderr,"Bandwidth did not improve. Keeping old numbering with gaps eliminated\n");
      }
      fprintf(stderr,"\n\n\n");

      free(nadj);
      free(adj);
      free(offset);
      free(newmap);
    }


    if (mtype == MREGION || mtype == MALLTYPE) {
      int nr = MESH_Num_Regions(mesh);

      if (nr) {

        if (mtype == MALLTYPE) { 

          /* Renumbering algorithm already applied on the vertices. Use
             a region connected to the starting vertex as the first
             region */

          List_ptr vregions = MV_Regions(v0);
          r0 = List_Entry(vregions,0);
          List_Delete(vregions);
        }
        else {
          /* Find the region whose center point is a minimum point */
          minx = miny = minz = 1.0e+12;
          r0 = NULL;
          idx = 0;
          while ((mr = MESH_Next_Region(mesh,&idx))) {
            double rxyz[MAXPV3][3];
            int nrv;

            MR_Coords(mr,&nrv,rxyz);
            xyz[0] = rxyz[0][0];
            xyz[1] = rxyz[0][1];
            xyz[2] = rxyz[0][2];
            for (i = 1; i < nrv; i++) {
              xyz[0] += rxyz[i][0];
              xyz[1] += rxyz[i][1];
              xyz[2] += rxyz[i][2];
            }
            xyz[0] /= nrv; xyz[1] /= nrv; xyz[2] /= nrv;
            if (xyz[0] < minx && xyz[1] < miny && xyz[2] < minz) {
              minx = xyz[0];
              miny = xyz[1];
              minz = xyz[2];
              r0 = mr;
            }
          }
        }


        nadj = (int *) malloc(nr*sizeof(int));
        nalloc = nr*5;
        adj = (int *) malloc(nalloc*sizeof(int));

        int nentries = 0;
        i = 0;
        idx = 0;
        while ((mr = MESH_Next_Region(mesh,&idx))) {
          List_ptr vregions, rverts, adjrlist;
          MRegion_ptr vr, adjr;
          MVertex_ptr rv;

          adjrlist = List_New(0);
          rverts = MR_Vertices(mr);
          idx2 = 0;
          while ((rv = List_Next_Entry(rverts,&idx2))) {
            List_ptr vregions = MV_Regions(rv);
            idx3 = 0;
            while ((adjr = List_Next_Entry(vregions,&idx3))) {
              if (adjr != mr) {
                int rmarked;
#ifdef MSTK_USE_MARKERS
                rmarked = MEnt_IsMarked(adjr,mkid);
#else
                MEnt_Get_AttVal(adjr, mkatt, &rmarked, &rval, &pval);
#endif
                List_Add(adjrlist,adjr);
#ifdef MSTK_USE_MARKERS
                MEnt_Mark(adjr,mkid);
#else
                MEnt_Set_AttVal(adjr, mkatt, 1, 0.0, NULL);
#endif
              }
            }	    
            List_Delete(vregions);
          }
          List_Delete(rverts);
#ifdef MSTK_USE_MARKERS
          List_Unmark(adjrlist,mkid);
#endif

          nadj[i] = List_Num_Entries(adjrlist);

          if (nentries+nadj[i] > nalloc) {
            nalloc *= 2;
            adj = (int *) realloc(adj,nalloc*sizeof(int));
          }

          idx2 = 0;
          while ((adjr = List_Next_Entry(adjrlist,&idx2)))
            adj[nentries++] = MR_ID(adjr)-1;

          List_Delete(adjrlist);
          i++;
        }

        /* Compute offsets into adj array */

        offset = (int *) malloc(nr*sizeof(int));
        offset[0] = 0;
        for (i = 1; i < nr; i++)
          offset[i] = offset[i-1] + nadj[i-1];


        /* Compute maximum bandwidth before renumbering */

        maxbandwidth1 = 0;
        avebandwidth1 = 0;
        for (i = 0; i < nr; i++) {
          int off = offset[i];
          int curid = i;
          for (j = 0; j < nadj[i]; j++) {
            int adjid = adj[off+j];
            int diff = abs(adjid-curid);
            maxbandwidth1 = (diff > maxbandwidth1) ? diff : maxbandwidth1;
            avebandwidth1 += diff;
            nconn++;
          }
        }
        nconn = offset[nr-1]+nadj[nr-1];
        avebandwidth1 /= nconn;

        fprintf(stderr,
                "Ave region ID difference before renumbering: %-lf\n",
                avebandwidth1);
        fprintf(stderr,
                "Max region ID difference before renumbering: %-d\n",
                maxbandwidth1);
    
        fprintf(stderr,"\n");


        /* Call Graph Renumbering algorithm */

        newmap = (int *) malloc(nr*sizeof(int));
        Graph_Renumber_GPS(nr, MR_ID(r0)-1, nadj, adj, newmap, &depth, &maxwidth);

        /* Compute bandwidth after renumbering */

        maxbandwidth2 = 0;
        avebandwidth2 = 0;
        for (i = 0; i < nr; i++) {
          int off = offset[i];
          int curid = newmap[i];
          for (j = 0; j < nadj[i]; j++) {
            int adjid = newmap[adj[off+j]];
            int diff = abs(adjid-curid);
            maxbandwidth2 = (diff > maxbandwidth2) ? diff : maxbandwidth2;
            avebandwidth2 += diff;
            nconn++;
          }
        }
        nconn = offset[nr-1]+nadj[nr-1];
        avebandwidth2 /= nconn;

        if (maxbandwidth2 < maxbandwidth1 && avebandwidth2 < avebandwidth1) {

          /* Renumber */
      
          idx = 0; i = 0;
          while ((mr = MESH_Next_Region(mesh,&idx))) {
            MR_Set_ID(mr,newmap[i]+1);
            i++;
          }

          fprintf(stderr,
                  "Ave region ID difference after renumbering: %-lf\n",
                  avebandwidth2);
          fprintf(stderr,
                  "Max region ID difference after renumbering: %-d\n",
                  maxbandwidth2);
    
        }
        else {
          nr = 0;
          idx = 0; 
          while ((mr = MESH_Next_Region(mesh,&idx)))
            MR_Set_ID(mr,++nr);

          fprintf(stderr,"Bandwidth did not improve. Keeping old numbering with gaps eliminated\n");
        }
        fprintf(stderr,"\n\n\n");


        free(nadj);
        free(adj);
        free(offset);
        free(newmap);
      }
    }

#ifdef MSTK_USE_MARKERS
    MSTK_FreeMarker(mkid);
#endif
  }
  

  vidatt = MAttrib_New(mesh,"vidrcm",INT,MVERTEX);
  idx = 0;
  while ((mv = MESH_Next_Vertex(mesh,&idx))) {
    MEnt_Set_AttVal(mv,vidatt,MV_ID(mv),0.0,NULL);
  }
 

  /* We have to reset the max IDs stored in the mesh so that we can correctly
     assign IDs to new entities */

  MESH_Reset_Cached_MaxIDs(mesh);

  return;
}
Beispiel #7
0
  int MESH_CheckTopo(Mesh_ptr mesh) {
    int valid = 1;
    char mesg[256], funcname[32] = "MESH_CheckTopo";
    int idx1, idx2, idx3, idx4;
    MVertex_ptr mv;
    MEdge_ptr me, ve, fe, re;
    MFace_ptr mf, vf, ef, rf;
    MRegion_ptr mr, vr, er, fr;
    int found, done;
    int dir;
    int i, j, k;
    int nfe;
    int vid, eid, fid, rid;
    int gvid, geid, gfid, grid;
    int gvdim, gedim, gfdim, grdim;
    int maxiter = 1000;
    List_ptr vedges, vfaces, vregions;
    List_ptr efaces;
    List_ptr fverts, fedges, fregs, fregs1;
    List_ptr rverts, redges, rfaces;



    /*****************************************************************/
    /* Vertices                                                      */
    /*****************************************************************/    

    
    /* Check that edges connected to vertices reference the vertices */
    /* Also check that the classification of the vertex is consistent
       with respect to the edge */

    int first_unknown_classfn = 1;
    idx1 = 0;
    while ((mv = MESH_Next_Vertex(mesh,&idx1))) {

#ifdef MSTK_HAVE_MPI
      if (MV_PType(mv) == PGHOST) continue;
#endif      

      vid = MV_ID(mv);
      gvdim = MV_GEntDim(mv);
      gvid  = MV_GEntID(mv);

      if (gvdim == 4 && first_unknown_classfn) {
        sprintf(mesg, "Vertex %-d - classification unknown\n", vid);
        MSTK_Report(funcname, mesg, MSTK_WARN);
        first_unknown_classfn = 0;
      }
      vedges = MV_Edges(mv);
      if (!vedges) {
        sprintf(mesg,"Vertex %-d does not have any connected edges\n",vid);
        MSTK_Report(funcname,mesg,MSTK_WARN);
        continue;
      }

      idx2 = 0;
      while ((ve = List_Next_Entry(vedges,&idx2))) {
	
	eid = ME_ID(ve);
	     
	if (ME_Vertex(ve,0) != mv && ME_Vertex(ve,1) != mv) {
	  sprintf(mesg,"Vertex %-d connected to edge %-d but edge does not use vertex",vid,eid);
	  MSTK_Report(funcname,mesg,MSTK_ERROR);
	  valid = 0;
	}

      }


      if (gvdim == 1) {

	/* If vertex is classified on a model edge, then it should be
	   connected to two and only two edges that are classified on
	   the same model edge */

	int ne = 0;
	idx2 = 0;
	while ((ve = List_Next_Entry(vedges,&idx2))) {	  
	  gedim = ME_GEntDim(ve);
	  geid  = ME_GEntID(ve);	  
	  if (gedim == 1 && geid == gvid) ne++;
	}
	  
	if (ne != 2) {
	  sprintf(mesg,"Vertex %-d classified on model edge %-d but it is not \n connected to two edges classified on this model edge",vid,gvid);
	  MSTK_Report(funcname,mesg,MSTK_WARN);
	}
      }

      List_Delete(vedges);



      if (gvdim == 2) {
	MEdge_ptr e0, ecur, enxt;
	MFace_ptr fcur;
        int flipped = 0;

	/* If vertex is classified on a model face, then we should be
	   able to find a ring of faces classified on that model
	   face */

	vfaces = MV_Faces(mv);

	found = 0;
	idx2 = 0;
	while ((vf = List_Next_Entry(vfaces,&idx2))) {
	  if (MF_GEntDim(vf) == 2) {
	    found = 1;
	    break;
	  }
	}
        List_Delete(vfaces);

	if (!found) {
	  sprintf(mesg,"Vertex %-d classified on model face %-d but could not \n find connected face classified on this model face",vid,gvid);
	  MSTK_Report(funcname,mesg,MSTK_WARN);
	  valid = 0;
	}

	fcur = vf;

	fedges = MF_Edges(fcur,1,mv);
	nfe = List_Num_Entries(fedges);
	e0 = List_Entry(fedges,0);
	ecur = e0;
	enxt = List_Entry(fedges,nfe-1);
	List_Delete(fedges);
	
	done = 0; i = 0;
	while (!done) {
	  ecur = enxt;
	  efaces = ME_Faces(ecur);
	  found = 0;
	  idx3 = 0;
	  while ((ef = List_Next_Entry(efaces,&idx3))) {
	    if (ef != fcur && MF_GEntDim(ef) == 2 && MF_GEntID(ef) == gvid) {
	      fcur = ef;
	      found = 1;
	      break;
	    }
	  }
	  List_Delete(efaces);

	  if (!found) {
	    sprintf(mesg,"Could not find next boundary face connected to vertex %-d",vid);
	    MSTK_Report(funcname,mesg,MSTK_WARN);
	    valid = 0;
	    break;
	  }
	   
	  fedges = MF_Edges(fcur,1,mv);
	  nfe = List_Num_Entries(fedges);

          if (List_Entry(fedges,0) == ecur)
            enxt = List_Entry(fedges,nfe-1);
          else if (List_Entry(fedges,nfe-1) == ecur) {
            enxt = List_Entry(fedges,0);
            flipped = 1;
          }
          else {
            sprintf(mesg,"Could not find next edge while traversing around vertex %-d on model face %-d",vid,gvid);
            MSTK_Report(funcname,mesg,MSTK_ERROR);
          }

	  List_Delete(fedges);

	  if (enxt == e0)
	    done = 1;

	  if (++i > maxiter)
	    break;
	}

	if (!done) {
	  sprintf(mesg,"Vertex %-d classified on model face %-d but could not  find ring of faces classified on this model face",vid,gvid);
	  MSTK_Report(funcname,mesg,MSTK_WARN);
	}

        if (done && flipped) {
          List_ptr fregs = MF_Regions(fcur);
          if (List_Num_Entries(fregs) < 2) {
            sprintf(mesg,"Inconsistent orientations of boundary faces around vertex %-d",vid);
            MSTK_Report(funcname,mesg,MSTK_WARN);
          }
          if (fregs) List_Delete(fregs);
        }
      }


    } /* while ((mv = MESH_Next_Vertex(mesh,&idx1))) */




    /*****************************************************************/
    /* Edges                                                      */
    /*****************************************************************/    

    first_unknown_classfn = 1;
    idx1 = 0;
    while ((me = MESH_Next_Edge(mesh,&idx1))) {

#ifdef MSTK_HAVE_MPI
      if (ME_PType(me) == PGHOST) continue;
#endif

      eid = ME_ID(me);
      gedim = ME_GEntDim(me);
      geid = ME_GEntID(me);

      if (gedim == 4 && first_unknown_classfn) {
        sprintf(mesg, "Edge %-d - unknown classification", eid);
        MSTK_Report(funcname, mesg, MSTK_WARN);
        first_unknown_classfn = 0;
      }

      if (ME_Vertex(me,0) == ME_Vertex(me,1)) {
        sprintf(mesg,"Edge %-d has repeated vertices",eid);
        MSTK_Report(funcname,mesg,MSTK_ERROR);
      }

      for (i = 0; i < 2; i++) {
	MVertex_ptr ev = ME_Vertex(me,i);

	vid = MV_ID(ev);
	gvid = MV_GEntID(ev);
	gvdim = MV_GEntDim(ev);

        if (gvdim != 4 && gvdim != 4) {  /* vertex and edge classifn is known */
          if (gedim < gvdim) {
            sprintf(mesg,"Edge %-d classified on lower dimensional entity than  connected vertex %-d",eid,vid);
            MSTK_Report(funcname,mesg,MSTK_WARN);
            valid = 0;
          }
          else if (gedim == gvdim && geid != gvid) {
            sprintf(mesg,"Edge %-d and its vertex %-d classified on different entities of the same dimension",eid,vid);
            MSTK_Report(funcname,mesg,MSTK_WARN);
            valid = 0;
          }
        }

	vedges = MV_Edges(ev);
	if (!List_Contains(vedges,me)) {
	  sprintf(mesg,"Edge %-d sees vertex %-d but not vice versa",eid,vid);
	  MSTK_Report(funcname,mesg,MSTK_ERROR);
	  valid = 0;
	}
	List_Delete(vedges);

	if (gedim == 2) {
	  MFace_ptr ebf[2], fcur, fnxt;
	  MRegion_ptr rcur;
	  int nf, nfr;
	  List_ptr eregs;

	  /* Edge is classified on model face - it should be connected
	     to two and only two faces also classified on this model
	     face */

	  ebf[0] = ebf[1] = NULL;
	  nf = 0;
	  efaces = ME_Faces(me);
	  idx2 = 0;
	  while ((ef = List_Next_Entry(efaces,&idx2))) {
	    fid = MF_ID(ef);

	    if (MF_GEntDim(ef) == 2) {
	      nf++;
	      if (gedim == 2 && MF_GEntID(ef) != geid) {
		sprintf(mesg,"Face %-d connected to edge %-d classified on different model face",fid,eid);
		MSTK_Report(funcname,mesg,MSTK_WARN);
		valid = 0;
	      }

	      if (ebf[0] == NULL)
		ebf[0] = ef;
	      else
		ebf[1] = ef;
	    }
	  }
	  List_Delete(efaces);

	  if (nf != 2) {
	    sprintf(mesg,"Boundary edge %-d is not connected to exactly two\n  faces classified on the boundary",eid);
	    MSTK_Report(funcname,mesg,MSTK_ERROR);
	    valid = 0;
	  }


	  eregs = ME_Regions(me);
	  if (!eregs) 
	    continue;
	  else
	    List_Delete(eregs);

	  /* Can we go from f0 to f1 in one or two dirs? */

	  fcur = ebf[0];
          fnxt = NULL;
	  fregs = MF_Regions(fcur);
	  if (!fregs) {
	    fid = MF_ID(fcur);
	    sprintf(mesg,"Edge %-d connected to regions but face %-d is not",eid,fid);
	    MSTK_Report(funcname,mesg,MSTK_ERROR);
	    valid = 0;
	  }

	  nfr = List_Num_Entries(fregs);
	  for (i = 0; i < nfr; i++) {
	    rcur = List_Entry(fregs,i);
	  
	    rfaces = MR_Faces(rcur);
	    idx3 = 0;
	    found = 0;
	    while ((rf = List_Next_Entry(rfaces,&idx3))) {
	      if (rf != fcur && MF_UsesEntity(rf,me,1)) {
		found = 1;
		fnxt = rf;
		break;
	      }
	    }
	    List_Delete(rfaces);
	    
	    if (!found) {
	      rid = MR_ID(rcur);
	      sprintf(mesg,"Could not find second face in region %-d using edge %-d",rid,eid);
	    }
	    
	    
	    done = 0; j = 0;
	    while (!done) {
	      fcur = fnxt;
	      fid = MF_ID(fcur);
	      
	      if (fnxt == ebf[1]) {
		done = 1;
		break;
	      }
	      
	      fregs1 = MF_Regions(fcur);
	      idx3 = 0;
	      while ((fr = List_Next_Entry(fregs1,&idx3))) {
		if (fr != rcur) {
		  rcur = fr;
		  found = 1;
		  break;
		}
	      }
	      List_Delete(fregs1);

	      if (!found) {
		sprintf(mesg,"Could not find next region around edge %-d",eid);
		MSTK_Report(funcname,mesg,MSTK_ERROR);
		valid = 0;
		break;
	      }
	      
	      
	      rfaces = MR_Faces(rcur);
	      idx3 = 0;
	      found = 0;
	      while ((rf = List_Next_Entry(rfaces,&idx3))) {
		if (rf != fcur && MF_UsesEntity(rf,me,1)) {
		  found = 1;
		  fnxt = rf;
		  break;
		}
	      }
	      List_Delete(rfaces);
	      
	      if (!found) {
		rid = MR_ID(rcur);
		sprintf(mesg,"Could not find second face in region %-d using edge %-d",rid,eid);
	      }
	      
	      if (++j > maxiter)
		break;
	    } /* while (!done) */

	    if (!done) {
	      sprintf(mesg,"Could not traverse around edge %-d from face %-d to face %-d",eid,MF_ID(ebf[0]),MF_ID(ebf[1]));
	      MSTK_Report(funcname,mesg,MSTK_ERROR);
	      valid = 0;
	    }
	  } /* for (i = 0; i < nfr; i++) */
          List_Delete(fregs);

	} /* if (geid == 2) */

      } /* for (i = 0; i < 2; i++) */

    } /* while ((me = MESH_Next_Edge(mesh,&idx1))) */



    /*****************************************************************/
    /* Faces                                                      */
    /*****************************************************************/    

    first_unknown_classfn = 1;
    idx1 = 0;
    while ((mf = MESH_Next_Face(mesh,&idx1))) {

#ifdef MSTK_HAVE_MPI
      if (MF_PType(mf) == PGHOST) continue;
#endif

      fid = MF_ID(mf);
      gfid = MF_GEntID(mf);
      gfdim = MF_GEntDim(mf);

      if (gfdim == 4 && first_unknown_classfn) {
        sprintf(mesg, "Face %-d - unknown classification", fid);
        MSTK_Report(funcname, mesg, MSTK_WARN);
        first_unknown_classfn = 0;
      }

      fedges = MF_Edges(mf,1,0);

      if (List_Num_Entries(fedges) < 3) {
        sprintf(mesg,"Face %-d has less than 3 edges",fid);
        MSTK_Report(funcname,mesg,MSTK_ERROR);
      }

      idx2 = 0;
      while ((fe = List_Next_Entry(fedges,&idx2))) {
	eid = ME_ID(fe);
	geid = ME_GEntID(fe);
	gedim = ME_GEntDim(fe);

        if (gedim != 4 && gfdim != 4) {  /* Edge, Face classfn is known */
          if (gfdim < gedim) {
            sprintf(mesg,"Face %-d classified on lower order entity than edge %-d",fid,ME_ID(fe));
            MSTK_Report(funcname,mesg,MSTK_WARN);
            valid = 0;
          }
          else if (gedim == gfdim && geid != gfid) {
            sprintf(mesg,"Face %-d and edge %-d classified on different\n entities of the same dimension",fid,eid);
            MSTK_Report(funcname,mesg,MSTK_WARN);
          }
        }

	efaces = ME_Faces(fe);
	if (!List_Contains(efaces,mf)) {
	  sprintf(mesg,"Face %-d refers to edge %-d but not vice versa",fid,ME_ID(fe));
	  MSTK_Report(funcname,mesg,MSTK_ERROR);
	  valid = 0;
	}
	List_Delete(efaces);
      }
      List_Delete(fedges);
      

      fregs = MF_Regions(mf);

      if (gfdim == 3) {
	if (!fregs || List_Num_Entries(fregs) != 2) {
	  sprintf(mesg,"Interior face %-d does not have two connected regions",fid);
	  MSTK_Report(funcname,mesg,MSTK_ERROR);
	  valid = 0;
	}
      }


      if (fregs) {
	if (List_Num_Entries(fregs) == 2) {
	  if (MR_FaceDir(List_Entry(fregs,0),mf) == MR_FaceDir(List_Entry(fregs,1),mf)) {
	    sprintf(mesg,"Both regions using face %-d in the same sense",fid);
	    MSTK_Report(funcname,mesg,MSTK_ERROR);
	    valid = 0;
	  }
	}
	List_Delete(fregs);      
      }


    } /* while ((mf = MESH_Next_Face(mesh,&idx1))) */



    /*****************************************************************/
    /* Regions                                                      */
    /*****************************************************************/    

    idx1 = 0;
    while ((mr = MESH_Next_Region(mesh,&idx1))) {
      
#ifdef MSTK_HAVE_MPI
      if (MR_PType(mr) == PGHOST) continue;
#endif

      rid = MR_ID(mr);
      grid = MR_GEntID(mr);

      rfaces = MR_Faces(mr);
      int nrf = List_Num_Entries(rfaces);

      if (nrf < 4) {
        sprintf(mesg,"Region %-d has less than 4 faces",rid);
        MSTK_Report(funcname,mesg,MSTK_ERROR);
      }

      /* Check that face to region and region to face links are consistent
         with each other */
      int *rfdirs = (int *) malloc(nrf*sizeof(int));

      i = 0;
      idx2 = 0;
      while ((rf = List_Next_Entry(rfaces,&idx2))) {
	rfdirs[i] = MR_FaceDir_i(mr,i);
	if (mr != MF_Region(rf,!rfdirs[i])) {
	  sprintf(mesg,"Region %-d to face %-d dir inconsistent with \n face to region dir",rid,MF_ID(rf));
	  MSTK_Report(funcname,mesg,MSTK_ERROR);
	  valid = 0;
	}

        i++;
      }


      /* Check that faces of a region have consistent orientation in
         the region with respect to each other */
      
      for (i = 0; i < nrf; i++) {
        MFace_ptr rf, rf2;

        rf = List_Entry(rfaces,i);

        fedges = MF_Edges(rf,1,0);
        nfe = List_Num_Entries(fedges);
        
        for (j = 0; j < nfe; j++) {
          fe = List_Entry(fedges,j);
          int fedir = MF_EdgeDir_i(rf,j);
          
          /* Find adjacent face in the region */
          found = 0;
          for (k = 0; k < nrf; k++) {
            rf2 = List_Entry(rfaces,k);
            if (rf != rf2 && MF_UsesEntity(rf2,fe,MEDGE)) {
              found = 1;
              break;
            }
          }

          if (!found) {
            sprintf(mesg,"Cannot find another face in region %-d sharing edge %-d (ID = %-d) of face with ID = %-d",MR_ID(mr),j,ME_ID(fe),MF_ID(rf));
            MSTK_Report(funcname,mesg,MSTK_ERROR);
            valid = 0;
          }
          
          int fedir_adj = MF_EdgeDir(rf2,fe);
          
          /* If the two faces use the edge in opposite directions then
             the region should use the faces in the same direction and
             vice versa */

          if (((fedir_adj == fedir) && (rfdirs[i] == rfdirs[k])) ||
              ((fedir_adj != fedir) && (rfdirs[i] != rfdirs[k]))) {
            sprintf(mesg,"Region %-d faces are inconsistently oriented",MR_ID(mr));
            MSTK_Report(funcname,mesg,MSTK_ERROR);
            valid = 0;
          }
        }
        List_Delete(fedges);
           
      }
      List_Delete(rfaces);
      free(rfdirs);
    }

    return valid;

  } /* int MESH_CheckTopo */
Beispiel #8
0
  double MFs_DihedralAngle(MFace_ptr face1, MFace_ptr face2, MEdge_ptr edge) {
    int i, fnd, nfe1, fedir, nfv1, nfv2;
    double fxyz[MAXPV2][3], vec1[3], vec2[3];
    double normal1[3], normal2[3], dp, mid[3];
    MVertex_ptr fv, ev0, ev1;
    List_ptr fedges1, fedges2, fverts1, fverts2;
    

    if (!edge) {
      fedges1 = MF_Edges(face1,1,0);      
      nfe1 = List_Num_Entries(fedges1);

      fedges2 = MF_Edges(face2,1,0);

      for (i = 0, fnd = 0; i < nfe1 && !fnd; i++) {
	edge = List_Entry(fedges1,i);
	if (List_Contains(fedges2,edge)) 
	  fnd = 1;	
      }

      List_Delete(fedges1);
      List_Delete(fedges2);

      if (!fnd) {
	MSTK_Report("MFs_DihedralAngle","Faces do not share common edge",MSTK_ERROR);
	return 0.0;
      }
    }


    /* For non-convex faces, picking the three points from which to
       calculate the normal is an issue. We will pick the two points
       of the common edge and the geometric center of the face.

       THIS MAY NOT WORK IF THE GEOMETRIC CENTER IS OUTSIDE THE FACE

       Eventually we will have to find a point in the face such that
       all triangles formed by connecting the point and each of the
       edges have consistent normals */


    ev0 = ME_Vertex(edge,0); 
    ev1 = ME_Vertex(edge,1); 

    /* Normal of face 1 */

    fedir = MF_EdgeDir(face1,edge);

    fverts1 = MF_Vertices(face1,fedir,ev0);
    nfv1 = List_Num_Entries(fverts1);

    for (i = 0; i < nfv1; i++) {
      fv = List_Entry(fverts1,i); 
      MV_Coords(fv,fxyz[i]);
    }
    List_Delete(fverts1);

    MSTK_VDiff3(fxyz[1],fxyz[0],vec1);

    if (nfv1 == 3) { /* Triangles - always convex */
      MSTK_VDiff3(fxyz[2],fxyz[0],vec2);
    }
    else { /* Others - can be non-convex */

      /* use geometric center as third point */
      
      mid[0] = mid[1] = mid[2] = 0.0;
      for (i = 0; i < nfv1; i++) {
	mid[0] += fxyz[i][0];
	mid[1] += fxyz[i][1];
	mid[2] += fxyz[i][2];
      }
      mid[0] /= nfv1; mid[1] /= nfv1; mid[2] /= nfv1;

      MSTK_VDiff3(mid,fxyz[0],vec2);
    }
    
    MSTK_VCross3(vec1,vec2,normal1);
    MSTK_VNormalize3(normal1);
    

    /* Normal of face 2 */

    fedir = MF_EdgeDir(face2,edge);

    fverts2 = MF_Vertices(face2,!fedir,ev1);
    nfv2 = List_Num_Entries(fverts2);

    for (i = 0; i < nfv2; i++) {
      fv = List_Entry(fverts2,i); 
      MV_Coords(fv,fxyz[i]);
    }
    List_Delete(fverts2);

    MSTK_VDiff3(fxyz[1],fxyz[0],vec1);

    if (nfv1 == 3) { /* Triangles - always convex */
      MSTK_VDiff3(fxyz[2],fxyz[0],vec2);
    }
    else { /* Others - can be non-convex */

      /* use geometric center as third point */
      
      mid[0] = mid[1] = mid[2] = 0.0;
      for (i = 0; i < nfv2; i++) {
	mid[0] += fxyz[i][0];
	mid[1] += fxyz[i][1];
	mid[2] += fxyz[i][2];
      }
      mid[0] /= nfv2; mid[1] /= nfv2; mid[2] /= nfv2;

      MSTK_VDiff3(mid,fxyz[0],vec2);
    }
    
    MSTK_VCross3(vec1,vec2,normal2);
    MSTK_VNormalize3(normal2);

    /* We have to negate the second normal. Otherwise we will get a
       dihedral angle of 0 for two faces in a plane when it should
       be 180 */

    MSTK_VNeg3(normal2);
    

    /* Angle between normals */
    dp = MSTK_VDot3(normal1,normal2);
    
    return dp;
  }
  int MESH_BuildEdgeClassfn(Mesh_ptr mesh, int use_geometry) {
  int i, j, k, idx, idx2, fnd, fnd2, geid, geid2, gdim;
  int ngedges, ngealloc, ngef, max_loc_gfids, *loc_gfids;
  int max_gedge_id;
  int nve, nbe, nef, nsub, *geids, **gefaceids;
  double PI=3.141592, cosang, COSSHARPANG;
  MVertex_ptr ev[2];
  MEdge_ptr edge, subedge, adjedge;
  MFace_ptr eface;
  List_ptr efaces, vedges, vbedges, geedges, subedges;
  double rval;
  void *pval;

  COSSHARPANG = cos(5*PI/6);  /* 165 degrees */


  /* Verify that mesh edges on the boundary have classification
     information; if not, assign all edges to the same model edge */

  ngedges = 0; ngealloc = 10;
  geids = (int *) malloc(ngealloc*sizeof(int)); /* model edge ids */
  /* Number of model faces connected to edge followed by model face ids */
  gefaceids = (int **) malloc(ngealloc*sizeof(int *));


  /* Take stock of existing model edge information */

  max_gedge_id = 0;
  idx = 0;
  while ((edge = MESH_Next_Edge(mesh,&idx))) {
    gdim = ME_GEntDim(edge);
    if (gdim != 1)
      continue;

    geid = ME_GEntID(edge);
    if (geid) {

      /* Has this model edge been encountered? If not, add it to list
	 of model edges */

      for (i = 0, fnd = 0; i < ngedges; i++)
	if (geids[i] == geid) {
	  fnd = 1;
	  break;
	}

      if (!fnd) {
	if (geid > max_gedge_id)
	  max_gedge_id = geid;

	if (ngealloc == ngedges) {
	  ngealloc *= 2;
	  geids = (int *) realloc(geids,ngealloc*sizeof(int));
	  gefaceids = (int **)realloc(gefaceids,ngealloc*sizeof(int *));
	}

	geids[ngedges] = geid;

	efaces = ME_Faces(edge);
	nef = List_Num_Entries(efaces);

	gefaceids[ngedges] = (int *) malloc((1+nef)*sizeof(int));
        ngef = 0;
	for (i = 0; i < nef; i++) {
	  eface = List_Entry(efaces,i);
	  if (MF_GEntDim(eface) == 2) {
	    gefaceids[ngedges][1+ngef] = MF_GEntID(eface);
	    ngef++;
	  }
	}
	gefaceids[ngedges][0] = ngef;

	ngedges++;

	List_Delete(efaces);
      }

    }
  }


  /* Build new model edge information based on adjacent model region info */
  
  /* NOTE: The following cases involve some repetition and can be
     "cleverly" folded into a shorter piece of code, but then the
     method by which the individual cases are handled gets a littled
     obscured. So leave as is */

  max_loc_gfids = 10;
  loc_gfids = (int *) malloc(max_loc_gfids*sizeof(int));
  idx = 0;
  while ((edge = MESH_Next_Edge(mesh,&idx))) {
    
    gdim = ME_GEntDim(edge);
    geid = ME_GEntID(edge);

    /* Edge has no classification? Assign classification info */
    /* Edge classified as face or interior edge? Verify */
    
    efaces = ME_Faces(edge);
    nef = efaces ? List_Num_Entries(efaces) : 0;

    if (!nef) {
      /* Isolated edge (must be on model edge). Did we encounter such
	 an edge before? */

      ME_Set_GEntDim(edge,1);

      for (i = 0, fnd = 0; i < ngedges; i++) {
	if (gefaceids[i][0] == 0) {
	  fnd = 1;
	  break;
	}
      }

      if (fnd) 
	ME_Set_GEntID(edge,geids[i]);
      else {
	max_gedge_id++;
	ME_Set_GEntID(edge,max_gedge_id);
	    
	if (ngealloc == ngedges) {
	  ngealloc *= 2;
	  geids = (int *) realloc(geids,ngealloc*sizeof(int));
	  gefaceids = (int **) realloc(gefaceids,ngealloc*sizeof(int *));
	}
	    
	geids[ngedges] = max_gedge_id;
	gefaceids[ngedges] = malloc(1*sizeof(int *));
	gefaceids[ngedges][0] = 0;
      }

      continue; /* nothing else to do */
    }

    if (nef > max_loc_gfids) {      
      loc_gfids = (int *) realloc(loc_gfids,nef*sizeof(int));
      max_loc_gfids = nef;
    }

    ngef = 0;
    for (i = 0; i < nef; i++) {
      eface = List_Entry(efaces,i);
      if (MF_GEntDim(eface) == 2) {
	loc_gfids[ngef] = MF_GEntID(eface);
	ngef++;
      }
    }
    
    switch (ngef) {
    case 0:
      /* Interior edge - we took care of the case of the isolated edge b4 */

      ME_Set_GEntDim(edge,3);
      eface = List_Entry(efaces,0);
      ME_Set_GEntID(edge,MF_GEntID(eface));

      break;
    case 2: 
      if (loc_gfids[0] == loc_gfids[1]) {

	if (gdim == 1) {
	  /* Looks like during face classification, this was tagged as
	     being a sharp edge. This means that it is a sharp edge on
	     the interior of a model face (same model face on both
	     sides) */

	  ME_Set_GEntDim(edge,1);

	  /* Check if such an edge was encountered before */

	  for (i = 0, fnd = 0; i < ngedges; i++) {
	    if (gefaceids[i][0] != 2)
	      continue;

	    if ((loc_gfids[0] == gefaceids[i][0]) && 
		(gefaceids[i][0] == gefaceids[i][1])) {
	      fnd = 1;
	      break;
	    }
	  }

	  if (fnd) 
	    ME_Set_GEntID(edge,geids[i]);
	  else {
	    max_gedge_id++;
	    ME_Set_GEntID(edge,max_gedge_id);
	    
	    if (ngealloc == ngedges) {
	      ngealloc *= 2;
	      geids = (int *) realloc(geids,ngealloc*sizeof(int));
	      gefaceids = (int **) realloc(gefaceids,ngealloc*sizeof(int *));
	    }
	    
	    geids[ngedges] = max_gedge_id;
	    gefaceids[ngedges] = malloc((1+ngef)*sizeof(int *));
	    gefaceids[ngedges][0] = ngef;
	    for (i = 0; i < ngef; i++)
	      gefaceids[ngedges][1+i] = loc_gfids[i];
	    ngedges++;
	  }
	}
	else {
	  /* edge must be on model face */

	  ME_Set_GEntDim(edge,2);

	  ME_Set_GEntID(edge,loc_gfids[0]);
	}
      }
      else {
	/* edge is on model edge between two faces */

	ME_Set_GEntDim(edge,1);

	/* Check if such an edge was encountered before */
	
	for (i = 0, fnd = 0; i < ngedges; i++) {
	  if (gefaceids[i][0] != 2)
	    continue;
	  
	  if (((loc_gfids[0] == gefaceids[i][1]) && 
	       (loc_gfids[1] == gefaceids[i][2])) ||
	      ((loc_gfids[1] == gefaceids[i][1]) &&
	       (loc_gfids[0] == gefaceids[i][2])))   {
	    fnd = 1;
	    break;
	  }
	}

	if (fnd) 
	  ME_Set_GEntID(edge,geids[i]);
	else {
	  max_gedge_id++;
	  ME_Set_GEntID(edge,max_gedge_id);
	  
	  if (ngealloc == ngedges) {
	    ngealloc *= 2;
	    geids = (int *) realloc(geids,ngealloc*sizeof(int));
	    gefaceids = (int **) realloc(gefaceids,ngealloc*sizeof(int *));
	  }
	  
	  geids[ngedges] = max_gedge_id;
	  gefaceids[ngedges] = malloc((1+ngef)*sizeof(int *));
	  gefaceids[ngedges][0] = ngef;
	  for (i = 0; i < ngef; i++)
	    gefaceids[ngedges][1+i] = loc_gfids[i];
	  ngedges++;
	}
      }
      break;

    default:
      /* if ngef is 1, edge is on model edge of non-manifold model
	 face 
	 if ngef is >= 3, edge is on model edge at junction of
	 many model faces
      */
      
      ME_Set_GEntDim(edge,1);
      
      /* Check if a previously encountered model edge has this
	 combination of connected faces */
      
      for (i = 0, fnd = 0; i < ngedges; i++) {
	if (ngef != gefaceids[i][0]) 
	  continue; /* number of connected model faces is different */
	
	/* see if all the model faces of the current edge can be found
	   in the i'th model edge's faces */

	fnd2 = 0;
	for (j = 0; j < ngef; j++) {
	  
	  fnd2 = 0;
	  for (k = 0; k < ngef; k++) {
	    if (loc_gfids[j] == gefaceids[i][1+k]) {
	      fnd2 = 1;
	      break;
	    }
	  }

	  /* Did not find loc_gfid[j] in the list gefaceids[i] */

	  if (!fnd2)
	    break;
	}

	/* if a model face connected to this edge was not found in the
	   model face list of the previously processed, then the two model
	   edges are obviously different */

	if (!fnd2)
	  continue;
	else {
	  fnd = 1;
	  break;
	}
      }

      if (fnd)
	ME_Set_GEntID(edge,geids[i]);
      else {
	max_gedge_id++;
	ME_Set_GEntID(edge,max_gedge_id);
	
	if (ngealloc == ngedges) {
	  ngealloc *= 2;
	  geids = (int *) realloc(geids,ngealloc*sizeof(int));
	  gefaceids = (int **) realloc(gefaceids,ngealloc*sizeof(int *));
	}
	
	geids[ngedges] = max_gedge_id;
	gefaceids[ngedges] = malloc((1+ngef)*sizeof(int *));
	gefaceids[ngedges][0] = ngef;
	for (i = 0; i < ngef; i++)
	  gefaceids[ngedges][1+i] = loc_gfids[i];
	ngedges++;
      }
      break;
    }

    List_Delete(efaces);    /* needed efaces in case 0 */
  }
  free(loc_gfids);


  if (use_geometry == 1) {


#ifdef MSTK_USE_MARKERS
    int processedmk = MSTK_GetMarker();
    int submk = MSTK_GetMarker();
#else
    MAttrib_ptr processedatt = MAttrib_New(mesh, "processed", INT, MEDGE);
    MAttrib_ptr sublistatt = MAttrib_New(mesh, "sublist", INT, MEDGE);
#endif

    /* Now assign model edge IDs based on whether a sharp set of edges
       enclose a set of edges */

    for (i = 0; i < ngedges; i++) {

      /* Find all mesh edges with this model edge id */

      geedges = List_New(10);
      idx = 0; 
      while ((edge = MESH_Next_Edge(mesh,&idx))) {
        if (ME_GEntDim(edge) == 1 && ME_GEntID(edge) == geids[i])
          List_Add(geedges,edge);
      }

      /* Process edges of this list and subdivide them into subedges */
      /* The way we do that is 
       
         1) we put an unprocessed edge from the original list in a subedge
         list

         2) we then add its neighboring edges to subedge list if they are
         of the same color (same model edge id) and do not have a sharp
         edge separating them from the current edge

         3) we then process the next edge in the subedge list 

         4) we are done if we cannot find any more neighbors of edges in
         the subedge list to add to the subedge list

         5) we then repeat steps 1 through 4 until we are left with no
         more edges to process from the original list
       
      */
      nsub = 0;
      idx = 0;
      while ((edge = List_Next_Entry(geedges,&idx))) {
        int emarked;
#ifdef MSTK_USE_MARKERS
        emarked = MEnt_IsMarked(edge,processedmk);
#else
        MEnt_Get_AttVal(edge, processedatt, &emarked, &rval, &pval);
#endif
        if (emarked)
          continue;
        
        /* Found a edge in geedges that has not been processed */
#ifdef MSTK_USE_MARKERS
        MEnt_Mark(edge,processedmk);
#else
        MEnt_Set_AttVal(edge, processedatt, 1, 0.0, NULL);
#endif

        subedges = List_New(10);
        List_Add(subedges,edge);
#ifdef MSTK_USE_MARKERS
        MEnt_Mark(edge,submk);
#else
        MEnt_Set_AttVal(edge, sublistatt, 1, 0.0, NULL);
#endif

        idx2 = 0;
        while ((subedge = List_Next_Entry(subedges,&idx2))) {
          geid = ME_GEntID(subedge);

          ev[0] = ME_Vertex(subedge,0);
          ev[1] = ME_Vertex(subedge,1);

          for (j = 0; j < 2; j++) {
            vedges = MV_Edges(ev[j]);
            nve = List_Num_Entries(vedges);

            vbedges = List_New(nve); /* list of boundary edges cnctd 2 vert */
            for (k = 0; k < nve; k++) {
              adjedge = List_Entry(vedges,k);
              if (ME_GEntDim(adjedge) == 1)
                List_Add(vbedges,adjedge);
            }

            nbe = List_Num_Entries(vbedges);
            if (nbe == 2) {
              /* we might be on a model vertex or on a model edge */

              adjedge = List_Entry(vbedges,0);
              if (adjedge == subedge)
                adjedge = List_Entry(vbedges,1);
              geid2 = ME_GEntID(adjedge);

              if (geid == geid2) {
                /* The two edges are of the same ID. If the angle
                   between them is not sharp they can be classified as
                   being on the same subedge */
	      
                cosang = MEs_Angle(subedge,adjedge);

                if (cosang <= COSSHARPANG) {
                  /* Add edge2 to subedge list unless its already there */
                  int adjemarked;
#ifdef MSTK_USE_MARKERS
                  adjemarked = MEnt_IsMarked(adjedge,submk);
#else
                  MEnt_Get_AttVal(adjedge, sublistatt, &adjemarked, &rval, &pval);
#endif
                  if (!adjemarked) {
                    List_Add(subedges,adjedge);
#ifdef MSTK_USE_MARKERS
                    MEnt_Mark(adjedge,submk);
#else
                    MEnt_Set_AttVal(adjedge, sublistatt, 1, 0.0, NULL);
#endif
                  }
                }
                else {
                  /* The two edges make a very sharp angle. We will
                     consider the edge b/w them to be a model vertex */
                  /* Tag the edge as being on a model vertex (we don't
                     know the model vertex ID as yet) and continue */

                  MV_Set_GEntDim(ev[j],0);
                  MV_Set_GEntID(ev[j],0);
                }
              }
              else {
                /* we reached a model vertex */
                /* Tag the edge as being on a model vertex (we don't know
                   the model vertex ID as yet) and continue */

                MV_Set_GEntDim(ev[j],0);
                MV_Set_GEntID(ev[j],0);
              }
            }
            else {
              /* we reached a a model vertex */
              /* Tag the edge as being on a model vertex (we don't know
                 the model vertex ID as yet) and continue */

              ME_Set_GEntDim(ev[j],0);
              ME_Set_GEntID(ev[j],0);
            }
            List_Delete(vedges);
            List_Delete(vbedges);	  
          }

          /* Finished processing all neighbors of the edge */
        }

        /* Now we have a list of edges which we believe constitutes a
           model edge by itself. If this is the first subedge (which
           means it could also be the entire model edge originally
           considered), leave the model edge tag as it is. If not,
           assign the edges in the subedge a new model edge ID */

        if (nsub != 0) {
          max_gedge_id++;
          idx2 = 0;
          while ((subedge = List_Next_Entry(subedges,&idx2))) 
            ME_Set_GEntID(subedge,max_gedge_id);
        }
        nsub++;

        /* Done with this subedge */

#ifdef MSTK_USE_MARKERS
        idx2 = 0;
        while ((subedge = List_Next_Entry(subedges,&idx2))) {
          MEnt_Mark(subedge,processedmk);
          MEnt_Unmark(subedge,submk);
        }
#else
        idx2 = 0;
        while ((subedge = List_Next_Entry(subedges,&idx2))) {
          MEnt_Set_AttVal(subedge, processedatt, 1, 0.0, NULL);
          MEnt_Set_AttVal(subedge, sublistatt, 0, 0.0, NULL);
        }
#endif
        List_Delete(subedges);
      }

#ifdef MSTK_USE_MARKERS
      List_Unmark(geedges,processedmk);
#else
      idx2 = 0;
      while ((edge = List_Next_Entry(geedges, &idx2)))
        MEnt_Set_AttVal(edge, processedatt, 1, 0.0, NULL);
#endif
      List_Delete(geedges);
    }

#ifdef MSTK_USE_MARKERS
      MSTK_FreeMarker(processedmk);
      MSTK_FreeMarker(submk);
#else
      MAttrib_Delete(processedatt);
      MAttrib_Delete(sublistatt);
#endif
  } /* if use_geometry == 1 */

  free(geids);
  for (i = 0; i < ngedges; i++)
    free(gefaceids[i]);
  free(gefaceids);
       
  return 1;
}
Beispiel #10
0
  int MESH_ConcatSubMesh_Face(Mesh_ptr mesh, int num, Mesh_ptr *submeshes) {
    int nfv, nfe, i, j, k, ival;
    MVertex_ptr mv, new_mv, sub_mv;
    MEdge_ptr me, new_me, sub_me;
    MFace_ptr new_mf, sub_mf;
    List_ptr mfverts, mfedges;
    int add_face, idx, global_id, iloc, *loc;
    double coor[3], rval;
    void *pval;
    Mesh_ptr submesh;

    List_ptr parbndry_verts = List_New(10);
    List_ptr parbndry_edges = List_New(10);

    MEdge_ptr *fedges = (MEdge_ptr *) malloc(MAXPV2*sizeof(MEdge_ptr));
    int *fedirs = (int *) malloc(MAXPV2*sizeof(int));

    MAttrib_ptr parbndryatt = MAttrib_New(mesh, "on_parbndry", INT, MVERTEX);
    
    /* collect edges and vertices on the partition boundary */
    int num_parbndry_edges = 0;
    idx = 0;
    while ((me = MESH_Next_Edge(mesh,&idx))) 
      if (ME_PType(me) != PINTERIOR) {
        List_Add(parbndry_edges,me);
        num_parbndry_edges++;
      }
    int num_parbndry_verts = 0;
    idx = 0;
    while ((mv = MESH_Next_Vertex(mesh,&idx)))
      if (MV_PType(mv) != PINTERIOR) {
        List_Add(parbndry_verts,mv);
        MEnt_Set_AttVal(mv, parbndryatt, 1, 0.0, NULL);
        num_parbndry_verts++;
      }
    /* sort based on global ID */
    List_Sort(parbndry_edges,num_parbndry_edges,sizeof(MEdge_ptr),compareGlobalID);
    List_Sort(parbndry_verts,num_parbndry_verts,sizeof(MVertex_ptr),compareGlobalID);

    int *parbndry_vert_gids = (int *) malloc(num_parbndry_verts*sizeof(int));
    int *parbndry_edge_gids = (int *) malloc(num_parbndry_edges*sizeof(int));

    /* store them in array for binary search */
    for (i = 0; i < num_parbndry_edges; i++) {
      me = List_Entry(parbndry_edges,i);
      parbndry_edge_gids[i] = ME_GlobalID(me);
    }
    for (i = 0; i < num_parbndry_verts; i++) {
      mv = List_Entry(parbndry_verts,i);
      parbndry_vert_gids[i] = MV_GlobalID(mv);
    }

    
    /* Make list of new edges and vertices which will be updated
       with each mesh that is concatenated */
    int max_vnew = 0, max_enew = 0;
    for (i = 0; i < num; i++) {
      max_vnew += MESH_Num_Vertices(submeshes[i]);
      max_enew += MESH_Num_Edges(submeshes[i]);
    }

    int num_new_verts = 0, num_new_edges = 0; 
    int *new_vert_gids = (int *) malloc(max_vnew*sizeof(int));
    int *new_edge_gids = (int *) malloc(max_enew*sizeof(int));

    List_ptr new_verts = List_New(max_vnew);
    List_ptr new_edges = List_New(max_enew);


    /* Now process each mesh and add a layer of ghost elements from
       each of them to the main partition */
    
    for (i = 0; i < num; i++) {
      submesh = submeshes[i];
    
      MAttrib_ptr vidatt = MAttrib_New(submesh, "tempvid", POINTER, MVERTEX);
      MAttrib_ptr eidatt = MAttrib_New(submesh, "tempeid", POINTER, MEDGE);

      idx = 0;
      while ((sub_mf = MESH_Next_Face(submesh, &idx))) {
        add_face = 0;
      
        /* Find matching vertices between the submesh and main mesh */
      
        mfverts = MF_Vertices(sub_mf,1,0);
        nfv = List_Num_Entries(mfverts);
        for (j = 0; j < nfv; j++) {
          sub_mv = List_Entry(mfverts,j);
        
          /* Does the vertex have a known counterpart on the partition
           * boundary of the main mesh? */
          MEnt_Get_AttVal(sub_mv, vidatt, &ival, &rval, &mv);

          if (mv) {
            int on_parbndry=0;
            MEnt_Get_AttVal(mv, parbndryatt, &on_parbndry, &rval, &pval);
            if (on_parbndry)
              add_face = 1; 
          } else {
        
            /* Does the global ID of this vertex of the sub mesh face
             * match the global ID of a partition boundary vertex in
             * the main mesh? */
            
            global_id = MV_GlobalID(sub_mv);
            loc = (int *) bsearch(&global_id, parbndry_vert_gids, num_parbndry_verts, sizeof(int),
                                  compareINT);
            if (loc) {  /* found a match */
              add_face = 1; 
              iloc = loc - parbndry_vert_gids;
              mv = List_Entry(parbndry_verts,iloc); 
              /* here set the ghost vertex property, only necessary when the input submeshes are not consistent */
              if (MV_PType(mv) == PGHOST && MV_PType(sub_mv) != PGHOST) {
                MV_Set_GEntDim(mv,MV_GEntDim(sub_mv));
                MV_Set_GEntID(mv,MV_GEntID(sub_mv));
              }
              
              MEnt_Set_AttVal(sub_mv, vidatt, 0, 0.0, mv);
            }
          }
        }
        List_Delete(mfverts);
      
        /* Find matching edges between the submesh and main mesh */
      
        mfedges = MF_Edges(sub_mf,1,0);
        nfe = List_Num_Entries(mfedges);
        for (j = 0; j < nfe; j++) {
          sub_me = List_Entry(mfedges,j);

          /* Does the edge have a known counterpart on the partition
           * boundary of the main mesh */
          MEnt_Get_AttVal(sub_me, eidatt, &ival, &rval, &me);

          if (!me) {
            /* Does the global ID of this edge of the sub mesh face
             * match the global ID of a partition boundary edge in the
             * main mesh? */
            
            global_id = ME_GlobalID(sub_me);
            loc = (int *) bsearch(&global_id, parbndry_edge_gids, num_parbndry_edges, sizeof(int),
                                  compareINT);
            if (loc) {
              iloc = loc - parbndry_edge_gids;
              me = List_Entry(parbndry_edges,iloc); 
              /* here set the ghost edge property, only necessary when the input submeshes are not consistent */
              if (ME_PType(me) == PGHOST && ME_PType(sub_me) != PGHOST) {
                ME_Set_GEntDim(me,ME_GEntDim(sub_me));
                ME_Set_GEntID(me,ME_GEntID(sub_me));
              }
              
	      MEnt_Set_AttVal(sub_me, eidatt, 0, 0.0, me);
            }
          }
        }
        
        if (!add_face) {
          List_Delete(mfedges);
          continue;
        }

        new_mf = MF_New(mesh); /* add face */
        MF_Set_GEntDim(new_mf,MF_GEntDim(sub_mf));
        MF_Set_GEntID(new_mf,MF_GEntID(sub_mf));
        MF_Set_PType(new_mf,PGHOST);
        MF_Set_MasterParID(new_mf,MF_MasterParID(sub_mf));
        MF_Set_GlobalID(new_mf,MF_GlobalID(sub_mf));
      
        nfe = List_Num_Entries(mfedges);
        for (j = 0; j < nfe; j++) {
          sub_me = List_Entry(mfedges,j);
          global_id = ME_GlobalID(sub_me);
          fedirs[j] = MF_EdgeDir_i(sub_mf,j) == 1 ? 1 : 0;

          new_me = NULL;	  
	  MEnt_Get_AttVal(sub_me, eidatt, &ival, &rval, &new_me);

          if (!new_me) {
            /* search in the ghost layer if another edge with
             * this global ID has been added */
            loc = (int *) bsearch(&global_id, new_edge_gids, num_new_edges,
                                  sizeof(int), compareINT);
            if (loc) {
              iloc = loc - new_edge_gids;
              new_me = List_Entry(new_edges, iloc);
              MEnt_Set_AttVal(sub_me, eidatt, 0, 0.0, new_me);
            }
          }

          if (new_me) {
            if (MV_GlobalID(ME_Vertex(new_me,0)) != MV_GlobalID(ME_Vertex(sub_me,0)))
              fedirs[j] = 1 - fedirs[j];  /* if the edge dir is not the same, reverse the edge dir */
          } else  {  /* add a new edge to main mesh */
            
            new_me = ME_New(mesh);
            ME_Set_GEntDim(new_me,ME_GEntDim(sub_me));
            ME_Set_GEntID(new_me,ME_GEntID(sub_me));
            ME_Set_PType(new_me,PGHOST);
            ME_Set_MasterParID(new_me,ME_MasterParID(sub_me));
            ME_Set_GlobalID(new_me,ME_GlobalID(sub_me));
	  
            MEnt_Set_AttVal(sub_me, eidatt, 0, 0.0, new_me);
	    List_Add(new_edges, new_me);
          
            for (k = 0; k < 2; k++) {
              sub_mv = ME_Vertex(sub_me,k);
              global_id = MV_GlobalID(sub_mv);

              new_mv = NULL;
              MEnt_Get_AttVal(sub_mv, vidatt, &ival, &rval, &new_mv);
	      if (!new_mv) {
		/* search in the ghost layer if another vertex with
                 * this global ID has been added */
                loc = (int *) bsearch(&global_id, new_vert_gids, num_new_verts,
                                      sizeof(int), compareINT);
                if (loc) {
                  iloc = loc - new_vert_gids;
                  new_mv = List_Entry(new_verts, iloc);
                  MEnt_Set_AttVal(sub_mv, vidatt, 0, 0.0, new_mv);
                }
              }

              if (!new_mv) {  /* add a new vertex to main mesh */
                new_mv = MV_New(mesh);
                MV_Set_GEntDim(new_mv,MV_GEntDim(sub_mv));
                MV_Set_GEntID(new_mv,MV_GEntID(sub_mv));
                MV_Set_PType(new_mv,PGHOST);
                MV_Set_MasterParID(new_mv,MV_MasterParID(sub_mv));
                MV_Set_GlobalID(new_mv,MV_GlobalID(sub_mv));
                MV_Coords(sub_mv,coor);
                MV_Set_Coords(new_mv,coor);
	      
                MEnt_Set_AttVal(sub_mv, vidatt, 0, 0.0, new_mv);
		List_Add(new_verts, new_mv);
              }
              ME_Set_Vertex(new_me,k,new_mv);  /* set edge-vertex */
            }
          }								
          fedges[j] = new_me;
        }
        MF_Set_Edges(new_mf,nfe,fedges,fedirs); /* set face-edge */

        List_Delete(mfedges);
      }

      idx = 0;
      while ((sub_mv = MESH_Next_Vertex(submesh, &idx)))
	MEnt_Rem_AttVal(sub_mv, vidatt);
      MAttrib_Delete(vidatt);
      idx = 0;
      while ((sub_me = MESH_Next_Edge(submesh, &idx)))
	MEnt_Rem_AttVal(sub_me, eidatt);
      MAttrib_Delete(eidatt);

      /* Sort the added entity lists by GlobalID */
      num_new_edges = List_Num_Entries(new_edges);
      List_Sort(new_edges, num_new_edges, sizeof(MEdge_ptr), compareGlobalID);
      for (j = 0; j < num_new_edges; j++)
        new_edge_gids[j] = ME_GlobalID(List_Entry(new_edges, j));

      num_new_verts = List_Num_Entries(new_verts);
      List_Sort(new_verts, num_new_verts, sizeof(MVertex_ptr), compareGlobalID);
      for (j = 0; j < num_new_verts; j++)
        new_vert_gids[j] = MV_GlobalID(List_Entry(new_verts, j));
    }

    idx = 0;
    while ((mv = List_Next_Entry(parbndry_verts, &idx)))
      MEnt_Rem_AttVal(mv, parbndryatt);
    MAttrib_Delete(parbndryatt);
    
    List_Delete(parbndry_edges);
    List_Delete(parbndry_verts);
    List_Delete(new_edges);
    List_Delete(new_verts);

    free(parbndry_vert_gids);
    free(parbndry_edge_gids);
    free(new_vert_gids);
    free(new_edge_gids);

    free(fedges);
    free(fedirs);

    return 1;
  }
Beispiel #11
0
MVertex_ptr ME_Split_SimplexMesh(MEdge_ptr esplit, double *splitxyz) {
  int i, j, k, rfdir, ntets=0, ntris=0, *fdim, *fid, *rid=NULL, found;
  MVertex_ptr vsplit, ev[2], (*tetverts)[4]=NULL, (*triverts)[3]=NULL, fv;
  MVertex_ptr fvarr[3], rvarr[4];
  MFace_ptr f;
  MRegion_ptr r;
  List_ptr etets, rfaces, etris, fverts;
  Mesh_ptr mesh = ME_Mesh(esplit);

  ev[0] = ME_Vertex(esplit,0);
  ev[1] = ME_Vertex(esplit,1);

  etets = ME_Regions(esplit);
  if (etets) {
    ntets = List_Num_Entries(etets);   
    tetverts = (MVertex_ptr (*)[4]) malloc(ntets*sizeof(MVertex_ptr [4]));
    rid = (int *) malloc(ntets*sizeof(int));
  }

  for (i = 0; i < ntets; i++) {

    r = List_Entry(etets,i);

    rfaces = MR_Faces(r);

    /* Find a tet face that uses ev[0] but not ev[1] */

    found = 0;
    for (j = 0; !found && j < 4; j++) {
      f = List_Entry(rfaces,j);

      fverts = MF_Vertices(f,1,0);
      if (List_Contains(fverts,ev[0]) &&
          !List_Contains(fverts,ev[1])) {

        found = 1;
        
        /* Get the two vertices (a,b) of this face excluding ev[0] in
           such an order that ev[0],a,b,ev[1] will form a valid
           tet. This requires checking whether the face points into or
           out of this tet (look at rfdir) */

        rfdir = MR_FaceDir_i(r,j);
        for (k = 0; k < 3; k++) {
          fv = List_Entry(fverts,k);
          if (fv == ev[0]) {
            tetverts[i][0] = ev[0];
            tetverts[i][1] = rfdir ? List_Entry(fverts,(k+2)%3) : List_Entry(fverts,(k+1)%3);
            tetverts[i][2] = rfdir ? List_Entry(fverts,(k+1)%3) : List_Entry(fverts,(k+2)%3);
            tetverts[i][3] = ev[1];
          }
        }
      }
      List_Delete(fverts);

      if (found) break;
    }

    List_Delete(rfaces);
  }

  /* Now that we finished collecting info about the connected tets we
     can delete them */

  if (etets) {
    for (i = 0; i < ntets; i++)
      MR_Delete(List_Entry(etets,i),0);

    List_Delete(etets);
  }

  /* Now get the triangular face connected to the edge. For each
     triangular face, record the vertex opposite to edge esplit and
     delete the triangular face */

  etris = ME_Faces(esplit);
  if (etris) {
    ntris = List_Num_Entries(etris);
    triverts = (MVertex_ptr (*)[3]) malloc(ntris*sizeof(MVertex_ptr[3]));
    fdim = (int *) malloc(ntris*sizeof(int));
    fid = (int *) malloc(ntris*sizeof(int));
  }
  
  for (i = 0; i < ntris; i++) {
    f = List_Entry(etris,i);

    fverts = MF_Vertices(f,1,0);
    for (j = 0; j < 3; j++) {
      fv = List_Entry(fverts,j);
      if (fv != ev[0] && fv != ev[1]) {        
        triverts[i][0] = fv;
        triverts[i][1] = List_Entry(fverts,(j+1)%3);
        triverts[i][2] = List_Entry(fverts,(j+2)%3);
        fdim[i] = MF_GEntDim(f);
        fid[i] = MF_GEntID(f);
        break;
      }
    }
    List_Delete(fverts);

    MF_Delete(f,0);
  }

  if (etris) List_Delete(etris);

  /* Now split the edge itself */

  vsplit = ME_Split(esplit, splitxyz);

  /* Now for each tri face that we deleted, create two tri faces that
     incorporate the split vertex, one of the split edge vertices and
     opposite vertex */

  for (i = 0; i < ntris; i++) {

    /* First triangle */

    fvarr[0] = triverts[i][0]; 
    fvarr[1] = triverts[i][1];
    fvarr[2] = vsplit;

    f = MF_New(mesh);
    MF_Set_Vertices(f,3,fvarr);
    MF_Set_GEntDim(f,fdim[i]);
    MF_Set_GEntID(f,fid[i]);
    
    /* Second triangle */

    fvarr[0] = triverts[i][0];
    fvarr[1] = vsplit;
    fvarr[2] = triverts[i][2];

    f = MF_New(mesh);
    MF_Set_Vertices(f,3,fvarr);
    MF_Set_GEntDim(f,fdim[i]);
    MF_Set_GEntID(f,fid[i]);
  }
  if (ntris) {
    free(triverts);
    free(fdim);
    free(fid);
  }

  /* Now for each tet that we deleted, create two tets (these will use
     the split faces that are already created */

  for (i = 0; i < ntets; i++) {
    rvarr[0] = vsplit;
    rvarr[1] = tetverts[i][2];
    rvarr[2] = tetverts[i][1];
    rvarr[3] = tetverts[i][0];

    r = MR_New(mesh);
    MR_Set_Vertices(r,4,rvarr,0,NULL);
    MR_Set_GEntID(r,rid[i]);

    rvarr[0] = vsplit;
    rvarr[1] = tetverts[i][1];
    rvarr[2] = tetverts[i][2];
    rvarr[3] = tetverts[i][3];

    r = MR_New(mesh);
    MR_Set_Vertices(r,4,rvarr,0,NULL);
    MR_Set_GEntID(r,rid[i]);
  }

  if (ntets) {
    free(tetverts);
    free(rid);
  }

  return vsplit;
}
Beispiel #12
0
MFace_ptr MR_Split_with_EdgeLoop(MRegion_ptr rsplit, int nfe, MEdge_ptr *fedges) {
  Mesh_ptr mesh;
  int i, j, idx1, idx2, fedirs[MAXPV2], rfdir_adj, curdir, edir, edir_adj;;
  int gid, mkid, nrf1, nrf2, rfdirs1[MAXPF3], rfdirs2[MAXPF3];
  MEdge_ptr fe;
  MFace_ptr fnew, eface, rfarray1[MAXPF3], rfarray2[MAXPF3], curface;
  MRegion_ptr rnew[2];
  List_ptr felist, efaces;

#ifdef DEBUG
  List_ptr redges;
#endif

  gid = MR_GEntID(rsplit);

#ifdef DEBUG
  /* check to make sure we got meaningful input */
  redges = MR_Edges(rsplit);
  for (i = 0; i < nfe; i++)
    if (!List_Contains(redges,fedges[i]))
      MSTK_Report("MR_Split","Input edges are not part of the region boundary",
                  MSTK_FATAL);
  List_Delete(redges);
#endif

  mesh = MR_Mesh(rsplit);


  /* Fix a set of directions for the edges */

  fedirs[0] = 1;
  for (i = 1; i < nfe; i++) {
    MVertex_ptr vprev, v0, v1;

    vprev = ME_Vertex(fedges[i-1],fedirs[i-1]);
    v0 = ME_Vertex(fedges[i],0);
    v1 = ME_Vertex(fedges[i],1);
    if (vprev == v0)
      fedirs[i] = 1;
    else if (vprev == v1)
      fedirs[i] = 0;
    else
      MSTK_Report("MR_Split","Input edges do not form a loop as listed",
                  MSTK_FATAL);
  }

  /* Create the splitting face */

  fnew = MF_New(mesh);
  MF_Set_GEntDim(fnew,3);
  MF_Set_GEntID(fnew,gid);
  MF_Set_Edges(fnew,nfe,fedges,fedirs);


  /* Collect info for the first region */

  List_ptr processed_faces = List_New(0);

  rfarray1[0] = fnew;
  rfdirs1[0] = 1; 
  nrf1 = 1;
  List_Add(processed_faces,rfarray1[0]);

  i = 0;
  while (i < nrf1) {
    curface = rfarray1[i];
    curdir = rfdirs1[i];
    i++;

    /* Get adjacent faces in region of current face and if they are
       not already in the new region face list (not marked), then add
       them */
 
    felist = MF_Edges(curface,1,0);
    idx1 = 0; j = 0;
    while ((fe = List_Next_Entry(felist,&idx1))) {
      edir = MF_EdgeDir_i(curface,j);      
      j++;

      efaces = ME_Faces(fe);
      if (curface != fnew && List_Contains(efaces,fnew)) {
        /* we have come back to the starting or splitting face - don't
           go across this edge */
        List_Delete(efaces);
        continue;
      }

      /* Add an adjacent unprocessed face of the region to the list of 
       faces for the new region */
      idx2 = 0; 
      while ((eface = List_Next_Entry(efaces,&idx2))) { 
        if (eface == curface) continue;
        if (List_Contains(processed_faces,eface)) continue;
        if (!MR_UsesEntity(rsplit,eface,MFACE)) continue; /* does not belong to region */

        edir_adj = MF_EdgeDir(eface,fe);
        rfdir_adj = MR_FaceDir(rsplit,eface);

        /* add adjacent face based on the check that if two adjacent faces of
           region are used by the region in the same sense, then their common
           edge should be used by the two faces in opposite senses (or the opposite
           of both the conditions should be true) */

        if ((edir != edir_adj && curdir == rfdir_adj) ||
            (edir == edir_adj && curdir != rfdir_adj)) {
          rfarray1[nrf1] = eface;
          rfdirs1[nrf1] = rfdir_adj;
          List_Add(processed_faces,rfarray1[nrf1]);
          nrf1++;
          break;
        }
      }
      List_Delete(efaces);
    }
    List_Delete(felist);
  }


  /* collect info for the second region */

  rfarray2[0] = fnew;
  rfdirs2[0] = !rfdirs1[0];
  nrf2 = 1;
  List_Add(processed_faces,rfarray2[0]);
  
  i = 0;
  while (i < nrf2) {
    curface = rfarray2[i];
    curdir = rfdirs2[i];
    i++;

    /* Get adjacent faces in region of current face and if they are
       not already in the new region face list (not marked), then add
       them */
 
    felist = MF_Edges(curface,1,0);
    idx1 = 0; j = 0;
    while ((fe = List_Next_Entry(felist,&idx1))) {
      edir = MF_EdgeDir_i(curface,j);      
      j++;

      efaces = ME_Faces(fe);
      if (curface != fnew && List_Contains(efaces,fnew)) {
        /* we have come back to the starting or splitting face - don't
           go across this edge */
        List_Delete(efaces);
        continue;
      }

      
      /* Add an adjacent unprocessed face of the region to the list of 
       faces for the new region */
      idx2 = 0; 
      while ((eface = List_Next_Entry(efaces,&idx2))) { 
        if (eface == curface) continue;
        if (List_Contains(processed_faces,eface)) continue;
        if (!MR_UsesEntity(rsplit,eface,MFACE)) continue; /* does not belong to region */

        edir_adj = MF_EdgeDir(eface,fe);
        rfdir_adj = MR_FaceDir(rsplit,eface);

        /* add adjacent face based on the check that if two adjacent faces of
           region are used by the region in the same sense, then their common
           edge should be used by the two faces in opposite senses (or the opposite
           of both the conditions should be true) */

        if ((edir != edir_adj && curdir == rfdir_adj) ||
            (edir == edir_adj && curdir != rfdir_adj)) {
          rfarray2[nrf2] = eface;
          rfdirs2[nrf2] = rfdir_adj;
          List_Add(processed_faces,rfarray2[nrf2]);
          nrf2++;
          break;
        }
      }
      List_Delete(efaces);
    }
    List_Delete(felist);
  }

  /* Delete the original region */

  MR_Delete(rsplit,0);

  /* Make the two new regions */

  rnew[0] = MR_New(mesh);
  MR_Set_GEntDim(rnew[0],3);
  MR_Set_GEntID(rnew[0],gid);
  MR_Set_Faces(rnew[0],nrf1,rfarray1,rfdirs1);

  rnew[1] = MR_New(mesh);
  MR_Set_GEntDim(rnew[1],3);
  MR_Set_GEntID(rnew[1],gid);
  MR_Set_Faces(rnew[1],nrf2,rfarray2,rfdirs2);

  List_Delete(processed_faces);

  return fnew;
}
Beispiel #13
0
  int MESH_WriteToFile(Mesh_ptr mesh, const char *filename, RepType rtype, MSTK_Comm comm) {
  FILE *fp;
  char mesg[80], attname[256];
  int i, j, k, idx;
  int gdim, gid;
  int mvid, mvid0, mvid1, mvid2, mrid2, meid, mfid, mrid;
  int nav, nar, nfe, nfv, nrf, nrv, dir=0;
  int nv, ne, nf, nr;
  int natt, ncomp, ival, nent;
  double xyz[3], rval, rdummy, *rval_arr;
  void *pval, *pdummy;
  MVertex_ptr mv, mv0, mv1, mv2;
  MEdge_ptr me;
  MFace_ptr mf;
  MRegion_ptr mr, mr2;
  List_ptr adjverts, mfedges, mfverts, mrfaces, mrverts, adjregs;
  RepType reptype;
  MAttrib_ptr attrib, vidatt, eidatt, fidatt, ridatt;
  MType attentdim;
  MAttType atttype;

  char modfilename[256];
  strcpy(modfilename, filename);
  
  int rank = 0, numprocs = 1;
#ifdef MSTK_HAVE_MPI
  if (comm) {
    MPI_Comm_size((MPI_Comm)comm, &numprocs);
    MPI_Comm_rank((MPI_Comm)comm, &rank);
  }
  if (numprocs > 1) {
    int ndigits = 0;
    int div = 1;
    while (numprocs/div) {div *= 10; ndigits++;}
    sprintf(modfilename,"%s.%d.%0*d",filename,numprocs,ndigits,rank);
  }
#endif
  
  if (!(fp = fopen(modfilename,"w"))) {
    sprintf(mesg,"Cannot open file %-s for writing",modfilename);
    MSTK_Report("MESH_WriteToFile",mesg,MSTK_ERROR);
    return 0;
  }

  if (rtype != UNKNOWN_REP) {
    reptype = rtype;
  }
  else {
    reptype = MESH_RepType(mesh);
  }

  nv = MESH_Num_Vertices(mesh);
  ne = MESH_Num_Edges(mesh);
  nf = MESH_Num_Faces(mesh);
  nr = MESH_Num_Regions(mesh);

  fprintf(fp,"MSTK %-2.1lf\n",MSTK_FILE_VER);
  fprintf(fp,"%s %d %d %d %d\n",
	  MESH_rtype_str[reptype], 
	  nv, 
	  (reptype >= R1 && reptype <= R4)?0:ne, 
	  (reptype >= R1 && reptype <= R2 && nr)?0:nf, 
	  nr);

  vidatt = MAttrib_New(mesh,"vidatt",INT,MVERTEX);
  eidatt = MAttrib_New(mesh,"eidatt",INT,MEDGE);
  fidatt = MAttrib_New(mesh,"fidatt",INT,MFACE);
  ridatt = MAttrib_New(mesh,"ridatt",INT,MREGION);

  idx = 0; i = 0;
  while ((mv = MESH_Next_Vertex(mesh,&idx)))
    MEnt_Set_AttVal(mv,vidatt,++i,0.0,NULL);

  idx = 0; i = 0;
  while ((me = MESH_Next_Edge(mesh,&idx)))
    MEnt_Set_AttVal(me,eidatt,++i,0.0,NULL);

  idx = 0; i = 0;
  while ((mf = MESH_Next_Face(mesh,&idx)))
    MEnt_Set_AttVal(mf,fidatt,++i,0.0,NULL);

  idx = 0; i = 0;
  while ((mr = MESH_Next_Region(mesh,&idx)))
    MEnt_Set_AttVal(mr,ridatt,++i,0.0,NULL);
  
  
  fprintf(fp,"vertices\n");
  idx = 0;
  while ((mv = MESH_Next_Vertex(mesh,&idx))) {

    MV_Coords(mv,xyz);

    gdim = MV_GEntDim(mv);
    gid = MV_GEntID(mv);

    fprintf(fp,"%24.16lf %24.16lf %24.16lf   %d %d\n",
	    xyz[0],xyz[1],xyz[2],gdim,gid);
    
  }

  if (reptype == R2 || reptype == R4) {
    fprintf(fp,"adjvertices\n");

    idx = 0;
    while ((mv = MESH_Next_Vertex(mesh,&idx))) {

      nav = MV_Num_AdjVertices(mv);
      fprintf(fp,"%d ",nav);
      
      adjverts = MV_AdjVertices(mv);
      for (j = 0; j < nav; j++) {
	mv2 = List_Entry(adjverts,j);
	MEnt_Get_AttVal(mv2,vidatt,&mvid2,&rval,&pval);
	fprintf(fp,"%d ",mvid2);
      }
      fprintf(fp,"\n");
      List_Delete(adjverts);
    }
  }



  if (reptype <= F4 && ne) {
    fprintf(fp,"edges\n");

    idx = 0;
    while ((me = MESH_Next_Edge(mesh,&idx))) {

      mv0 = ME_Vertex(me,0);
      MEnt_Get_AttVal(mv0,vidatt,&mvid0,&rval,&pval);
      mv1 = ME_Vertex(me,1);
      MEnt_Get_AttVal(mv1,vidatt,&mvid1,&rval,&pval);

      gdim = ME_GEntDim(me);
      gid = ME_GEntID(me);

      fprintf(fp,"%d %d \t%d %d\n",mvid0,mvid1,gdim,gid);
    }
  }



  if (reptype <= F4) {

    /* For full representations, always write out faces in terms of edges */

    fprintf(fp,"faces edge\n");
    
    idx = 0;
    while ((mf = MESH_Next_Face(mesh,&idx))) {
      
      nfe = MF_Num_Edges(mf);
      fprintf(fp,"%d ",nfe);
      
      mfedges = MF_Edges(mf,1,0);
      for (j = 0; j < nfe; j++) {
	me = List_Entry(mfedges,j);
	dir = MF_EdgeDir_i(mf,j);
	MEnt_Get_AttVal(me,eidatt,&meid,&rval,&pval);
	if (dir != 1) meid = -meid;
	fprintf(fp,"%d ",meid);
      }
      List_Delete(mfedges);
      
      gdim = MF_GEntDim(mf);
      /*
	gent = MF_GEntity(mf);
	gid = gent ? -99 : 0;
      */
      gid = MF_GEntID(mf);
      
      fprintf(fp,"\t%d %d\n",gdim,gid);
    }
  }
  else {

    /* For reduced representations, R3 and R4 always write out faces
       in terms of vertices. For reduced representations, R1 and R2
       write out faces in terms of vertices only when there are no
       regions (i.e. faces are the highest level mesh entities) */

    if ((reptype > R2) || (nr == 0)) {

      fprintf(fp,"faces vertex\n");

      idx = 0;
      while ((mf = MESH_Next_Face(mesh,&idx))) {
	
	nfv = MF_Num_Edges(mf);
	fprintf(fp,"%d ",nfv);
	
	mfverts = MF_Vertices(mf,1,0);
	for (j = 0; j < nfv; j++) {
	  mv = List_Entry(mfverts,j);
	  MEnt_Get_AttVal(mv,vidatt,&mvid,&rval,&pval);
	  fprintf(fp,"%d ",mvid);
	}
	List_Delete(mfverts);

	gdim = MF_GEntDim(mf);
	gid = MF_GEntID(mf);
	
	fprintf(fp,"\t%d %d\n",gdim,gid);
      }
    }
	
  }


  if (nr) {
    if (reptype <= F4 || reptype >= R2) {
      fprintf(fp,"regions face\n");

      idx = 0;
      while ((mr = MESH_Next_Region(mesh,&idx))) {

	nrf = MR_Num_Faces(mr);
	fprintf(fp,"%d ",nrf);

	mrfaces = MR_Faces(mr);
	for (j = 0; j < nrf; j++) {
	  mf = List_Entry(mrfaces,j);
	  dir = MR_FaceDir_i(mr,j);
	  MEnt_Get_AttVal(mf,fidatt,&mfid,&rval,&pval);
	  if (dir != 1) mfid = -mfid;
	  fprintf(fp,"%d ",mfid);
	}
	List_Delete(mrfaces);
	
	gdim = MF_GEntDim(mr);
	gid = MR_GEntID(mr);

	fprintf(fp,"\t%d %d\n",gdim,gid);
      }
    }
    else {
      fprintf(fp,"regions vertex\n");

      idx = 0;
      while ((mr = MESH_Next_Region(mesh,&idx))) {

	nrv = MR_Num_Vertices(mr);
	fprintf(fp,"%d ",nrv);

	mrverts = MR_Vertices(mr);
	for (j = 0; j < nrv; j++) {
	  mv = List_Entry(mrverts,j);
	  MEnt_Get_AttVal(mv,vidatt,&mvid,&rval,&pval);
	  fprintf(fp,"%d ",mvid);
	}
	List_Delete(mrverts);
	
	gdim = MR_GEntDim(mr);
	gid = MR_GEntID(mr);

	fprintf(fp,"\t%d %d\n",gdim,gid);
      }
    }

    if (reptype == R2 || reptype == R4) {
      fprintf(fp,"adjregions\n");
      
      idx = 0;
      while ((mr = MESH_Next_Region(mesh,&idx))) {

	nar = MR_Num_Faces(mr);
	fprintf(fp,"%d ",nar);

	adjregs = MR_AdjRegions(mr);

	for (j = 0; j < nar; j++) {
	  mr2 = List_Entry(adjregs,j);
	  if ((long) mr2 == -1) 
	    fprintf(fp,"%d ",0);
	  else {
	    MEnt_Get_AttVal(mr2,ridatt,&mrid2,&rval,&pval);
	    fprintf(fp,"%d ",mrid2);
	  }
	}
	fprintf(fp,"\n");
	List_Delete(adjregs);
      }
    }
  }


  /* Write out attributes if there are more than the 4 that we created 
    in this routine */


  if ((natt = MESH_Num_Attribs(mesh)) > 4) {

    fprintf(fp,"attributes\n");

    for (i = 0; i < natt; i++) {
      
      attrib = MESH_Attrib(mesh,i);

      /* Don't write out attribs we created for the internal use of 
	 this routine */
      if (attrib == vidatt || attrib == eidatt || attrib == fidatt || 
	  attrib == ridatt) continue;
      
      MAttrib_Get_Name(attrib,attname);

      atttype = MAttrib_Get_Type(attrib);
      if (atttype == POINTER) continue;  /* cannot write it out */

      ncomp = MAttrib_Get_NumComps(attrib);

      attentdim = MAttrib_Get_EntDim(attrib);


      /* First count how many entities actually have the attribute assigned */

      nent = 0;
      switch(attentdim) {
      case MVERTEX:
	idx = 0;
	while ((mv = MESH_Next_Vertex(mesh,&idx)))
	  if (MEnt_Get_AttVal(mv,attrib,&ival,&rval,&pval)) nent++;
	break;
      case MEDGE:
	idx = 0;
	while ((me = MESH_Next_Edge(mesh,&idx)))
	  if (MEnt_Get_AttVal(me,attrib,&ival,&rval,&pval)) nent++;
	break;
      case MFACE:
	idx = 0;
	while ((mf = MESH_Next_Face(mesh,&idx)))
	  if (MEnt_Get_AttVal(mf,attrib,&ival,&rval,&pval)) nent++;	    
	break;
      case MREGION: 
	idx = 0;
	while ((mr = MESH_Next_Region(mesh,&idx)))
	  if (MEnt_Get_AttVal(mr,attrib,&ival,&rval,&pval)) nent++;
	break;
      case MALLTYPE:
	idx = 0;
	while ((mv = MESH_Next_Vertex(mesh,&idx)))
	  if (MEnt_Get_AttVal(mv,attrib,&ival,&rval,&pval)) nent++;
	idx = 0;
	while ((me = MESH_Next_Edge(mesh,&idx)))
	  if (MEnt_Get_AttVal(me,attrib,&ival,&rval,&pval)) nent++;
	idx = 0;
	while ((mf = MESH_Next_Face(mesh,&idx)))
	  if (MEnt_Get_AttVal(mf,attrib,&ival,&rval,&pval)) nent++;	    
	idx = 0;
	while ((mr = MESH_Next_Region(mesh,&idx)))
	  if (MEnt_Get_AttVal(mr,attrib,&ival,&rval,&pval)) nent++;
	break;	
      default:
	break;
      } /* switch (attentdim) */


      /* No point in writing out attribute if no entity uses it! Or is there? */

      if (!nent) continue;



      fprintf(fp,"%-s\n",attname);

      switch(atttype) {
      case INT:
	fprintf(fp,"INT\n");
	break;
      case DOUBLE:
	fprintf(fp,"DOUBLE\n");
	break;
      case VECTOR:
	fprintf(fp,"VECTOR\n");
	break;
      case TENSOR:
	fprintf(fp,"TENSOR\n");
	break;
      default:
	MSTK_Report("MESH_WriteToFile",
		    "Unrecognizable or unprintable attribute type\n",MSTK_WARN);
	continue;	
      }

      fprintf(fp,"%-d\n",ncomp);

      switch(attentdim) {
      case MVERTEX:
	fprintf(fp,"MVERTEX\n");
	break;
      case MEDGE:
	fprintf(fp,"MEDGE\n");
	break;
      case MFACE:
	fprintf(fp,"MFACE\n");
	break;
      case MREGION:
	fprintf(fp,"MREGION\n");
	break;
      case MALLTYPE:
	fprintf(fp,"MALLTYPE\n");
	break;
      default:
	MSTK_Report("Mesh_WriteToFile","Unrecognized entity type",MSTK_WARN);
	break;
      }

      fprintf(fp,"%-d\n",nent);


      switch(attentdim) {
      case MVERTEX:
	idx = 0;
	while ((mv = MESH_Next_Vertex(mesh,&idx))) {
	  if (MEnt_Get_AttVal(mv,attrib,&ival,&rval,&pval)) {
	    MEnt_Get_AttVal(mv,vidatt,&mvid,&rdummy,&pdummy);
	    fprintf(fp,"0 %-d ",mvid);
	    switch (atttype) {
	    case INT:
	      fprintf(fp," %-d",ival);
	      break;
	    case DOUBLE: 
	      fprintf(fp," %-lf ",rval);
	      break;
	    case VECTOR: case TENSOR:
	      rval_arr = (double *) pval;
	      for (k = 0; k < ncomp; k++)
		fprintf(fp," %-lf ",rval_arr[k]);
	      break;
	    default:
	      break;
	    }
	    fprintf(fp,"\n");
	  }
	}
	break;
      case MEDGE:
	idx = 0;
	while ((me = MESH_Next_Edge(mesh,&idx))) {
	  if (MEnt_Get_AttVal(me,attrib,&ival,&rval,&pval)) {
	    MEnt_Get_AttVal(me,eidatt,&meid,&rdummy,&pdummy);
	    fprintf(fp,"1 %-d ",meid);
	    switch (atttype) {
	    case INT:
	      fprintf(fp," %-d",ival);
	      break;
	    case DOUBLE: 
	      fprintf(fp," %-lf ",rval);
	      break;
	    case VECTOR: case TENSOR:
	      rval_arr = (double *) pval;
	      for (k = 0; k < ncomp; k++)
		fprintf(fp," %-lf ",rval_arr[k]);
	      break;
	    default:
	      break;
	    }
	    fprintf(fp,"\n");
	  }
	}
	break;
      case MFACE:
	idx = 0;
	while ((mf = MESH_Next_Face(mesh,&idx))) {
	  if (MEnt_Get_AttVal(mf,attrib,&ival,&rval,&pval)) {
	    MEnt_Get_AttVal(mf,fidatt,&mfid,&rdummy,&pdummy);
	    fprintf(fp,"2 %-d ",mfid);
	    switch (atttype) {
	    case INT:
	      fprintf(fp," %-d",ival);
	      break;
	    case DOUBLE: 
	      fprintf(fp," %-lf ",rval);
	      break;
	    case VECTOR: case TENSOR:
	      rval_arr = (double *) pval;
	      for (k = 0; k < ncomp; k++)
		fprintf(fp," %-lf ",rval_arr[k]);
	      break;
	    default:
	      break;
	    }
	    fprintf(fp,"\n");
	  }
	}
	break;

      case MREGION: 
	idx = 0;
	while ((mr = MESH_Next_Region(mesh,&idx))) {
	  if (MEnt_Get_AttVal(mr,attrib,&ival,&rval,&pval)) {
	    MEnt_Get_AttVal(mr,ridatt,&mrid,&rdummy,&pdummy);
	    fprintf(fp,"3 %-d ",mrid);
	    switch (atttype) {
	    case INT:
	      fprintf(fp," %-d",ival);
	      break;
	    case DOUBLE: 
	      fprintf(fp," %-lf ",rval);
	      break;
	    case VECTOR: case TENSOR:
	      rval_arr = (double *) pval;
	      for (k = 0; k < ncomp; k++)
		fprintf(fp," %-lf ",rval_arr[k]);
	      break;
	    default:
	      break;
	    }
	    fprintf(fp,"\n");
	  }
	}
	break;

      case MALLTYPE:
	idx = 0;
	while ((mv = MESH_Next_Vertex(mesh,&idx))) {
	  if (MEnt_Get_AttVal(mv,attrib,&ival,&rval,&pval)) {
	    MEnt_Get_AttVal(mv,vidatt,&mvid,&rdummy,&pdummy);
	    fprintf(fp,"0 %-d ",mvid);
	    switch (atttype) {
	    case INT:
	      fprintf(fp," %-d",ival);
	      break;
	    case DOUBLE: 
	      fprintf(fp," %-lf ",rval);
	      break;
	    case VECTOR: case TENSOR:
	      rval_arr = (double *) pval;
	      for (k = 0; k < ncomp; k++)
		fprintf(fp," %-lf ",rval_arr[k]);
	      break;
	    default:
	      break;
	    }
	    fprintf(fp,"\n");
	  }
	}
	idx = 0;
	while ((me = MESH_Next_Edge(mesh,&idx))) {
	  if (MEnt_Get_AttVal(me,attrib,&ival,&rval,&pval)) {
	    MEnt_Get_AttVal(me,eidatt,&meid,&rdummy,&pdummy);
	    fprintf(fp,"1 %-d ",meid);
	    switch (atttype) {
	    case INT:
	      fprintf(fp," %-d",ival);
	      break;
	    case DOUBLE: 
	      fprintf(fp," %-lf ",rval);
	      break;
	    case VECTOR: case TENSOR:
	      rval_arr = (double *) pval;
	      for (k = 0; k < ncomp; k++)
		fprintf(fp," %-lf ",rval_arr[k]);
	      break;
	    default:
	      break;
	    }
	    fprintf(fp,"\n");
	  }
	}
	idx = 0;
	while ((mf = MESH_Next_Face(mesh,&idx))) {
	  if (MEnt_Get_AttVal(mf,attrib,&ival,&rval,&pval)) {
	    MEnt_Get_AttVal(mf,fidatt,&mfid,&rdummy,&pdummy);
	    fprintf(fp,"2 %-d ",mfid);
	    switch (atttype) {
	    case INT:
	      fprintf(fp," %-d",ival);
	      break;
	    case DOUBLE: 
	      fprintf(fp," %-lf ",rval);
	      break;
	    case VECTOR: case TENSOR:
	      rval_arr = (double *) pval;
	      for (k = 0; k < ncomp; k++)
		fprintf(fp," %-lf ",rval_arr[k]);
	      break;
	    default:
	      break;
	    }
	    fprintf(fp,"\n");
	  }
	}
	idx = 0;
	while ((mr = MESH_Next_Region(mesh,&idx))) {
	  if (MEnt_Get_AttVal(mr,attrib,&ival,&rval,&pval)) {
	    MEnt_Get_AttVal(mr,ridatt,&mrid,&rdummy,&pdummy);
	    fprintf(fp,"3 %-d ",mrid);
	    switch (atttype) {
	    case INT:
	      fprintf(fp," %-d",ival);
	      break;
	    case DOUBLE: 
	      fprintf(fp," %-lf ",rval);
	      break;
	    case VECTOR: case TENSOR:
	      rval_arr = (double *) pval;
	      for (k = 0; k < ncomp; k++)
		fprintf(fp," %-lf ",rval_arr[k]);
	      break;
	    default:
	      break;
	    }
	    fprintf(fp,"\n");
	  }
	}
	break;	
      default:
	break;
      } /* switch (attentdim) */

    } /* for (i = 0; i < natt) */
    
  } /* if (Mesh_Num_Attribs(mesh)) */
  

  idx = 0; i = 0;
  while ((mv = MESH_Next_Vertex(mesh,&idx)))
    MEnt_Rem_AttVal(mv,vidatt);

  idx = 0; i = 0;
  while ((me = MESH_Next_Edge(mesh,&idx)))
    MEnt_Rem_AttVal(me,eidatt);

  idx = 0; i = 0;
  while ((mf = MESH_Next_Face(mesh,&idx)))
    MEnt_Rem_AttVal(mf,fidatt);

  idx = 0; i = 0;
  while ((mr = MESH_Next_Region(mesh,&idx)))
    MEnt_Rem_AttVal(mr,ridatt);
  
  MAttrib_Delete(vidatt);
  MAttrib_Delete(eidatt);
  MAttrib_Delete(fidatt);
  MAttrib_Delete(ridatt);




  fclose(fp);

  return 1;
}
Beispiel #14
0
  List_ptr MR_Vertices_FNR3R4(MRegion_ptr r) {
    int i, j, n, ne, nf, mkr, found, idx;
    int diradj0=0, diropp=0, fdir, fdir0, fdir1, allquad, alltri;
    int nquads, ntris, itri0, itri1, iquad0;
    MFace_ptr face=NULL, face0=NULL, fadj0=NULL, fopp=NULL;
    MFace_ptr quad0=NULL, tri0=NULL, tri1=NULL;
    MEdge_ptr edge, fedge00, upedge;
    MVertex_ptr vert, rv0, rvopp0=NULL;
    List_ptr rvertices, fverts, fedges0, adjfedges;
    MRegion_Adj_FN *adj;

    adj = (MRegion_Adj_FN *) r->adj;

    nf = List_Num_Entries(adj->rfaces);

    switch (r->mrtype) {

    case TET: 

      /* Add vertices of first face to list of region vertices */
      face0 = List_Entry(adj->rfaces,0); /* first face */
      fdir0 = MR_FaceDir_i(r,0);  /* Sense in which face is used in region */
      rvertices = MF_Vertices(face0,!fdir0,0);
      
      face = List_Entry(adj->rfaces,1);
      fverts = MF_Vertices(face,1,0);
      for (i = 0; i < 3; i++) { 
        vert = List_Entry(fverts,i);
        if (!List_Contains(rvertices,vert)) {
          List_Add(rvertices,vert);
          break;
        }
      }
      List_Delete(fverts);
      
      return rvertices;
      break;

    case PRISM:

      tri0 = NULL; itri0 = -1;
      tri1 = NULL; itri1 = -1;

      for (i = 0; i < nf; i++) {
	face = List_Entry(adj->rfaces,i);
	ne = MF_Num_Edges(face);
	if (ne == 3) {
	  if (!tri0) {
	    tri0 = face;
	    itri0 = i;
	  }
	  else {
	    tri1 = face;
	    itri1 = i;
	  }
	}
      }
      
      fdir0 = MR_FaceDir_i(r,itri0); /* Sense in which face is used in region */
      rvertices = MF_Vertices(tri0,!fdir0,0);
      
      /* find the vertical edge between vertex 0 of bottom triangle and
         top triangle */
      
      fdir1 = MR_FaceDir_i(r,itri1);
      fverts = MF_Vertices(tri1,fdir1,0);
      
      rv0 = List_Entry(rvertices,0); /* first vtx of region & bottom face */
      
      for (i = 0; i < 3; i++) {
        vert = List_Entry(fverts,i);
        
        if (MVs_CommonEdge(rv0,vert)) {
          List_Add(rvertices,vert);
          List_Add(rvertices,List_Entry(fverts,(i+1)%3));
          List_Add(rvertices,List_Entry(fverts,(i+2)%3));
          break;
        }
      }
      
      List_Delete(fverts);
      
      return rvertices;
      break;

    case PYRAMID:

      quad0 = NULL; iquad0 = -1;
      tri0 = NULL; itri0 = -1;

      for (i = 0; i < nf; i++) {
	face = List_Entry(adj->rfaces,i);
	ne = MF_Num_Edges(face);
	if (ne == 4) {
	  if (!quad0) {
	    quad0 = face;
	    iquad0 = i;
	  }          
	}
        else if (ne == 3) {
          if (!tri0) {
            tri0 = face;
            itri0 = i;
          }
        }
      }
      

      fdir0 = MR_FaceDir_i(r,iquad0);  /* Sense in which face is used in region */
      rvertices = MF_Vertices(quad0,!fdir0,0);
      
      fverts = MF_Vertices(tri0,1,0);
      
      for (i = 0; i < 3; i++) {
        vert = List_Entry(fverts,i);
        if (!List_Contains(rvertices,vert)) { /* found apex vtx of pyramid */
          List_Add(rvertices,vert);
          break;
        }
      }

      List_Delete(fverts);
	  
      return rvertices;
      break;

    case HEX:

      face0 = List_Entry(adj->rfaces,0); /* face 0 */
      fdir0 = MR_FaceDir_i(r,0); /* dir of face w.r.t. region */
	
      /* Add vertices of first face */
      rvertices = MF_Vertices(face0,!fdir0,0);
	
      /* vertex 0 of region and of face 0 */
      rv0 = List_Entry(rvertices,0);      
	
      /* Edges of face 0 */
      fedges0 = MF_Edges(face0,!fdir0,rv0);
	
      /* edge 0 of face 0 (wrt face dir pointing into the region) */
      fedge00 = List_Entry(fedges0,0); 
	
      /* Get the face adjacent to edge 0 of face 0 and also the
         opposite face, a face that has no edge common face 0 */
	
      fopp = NULL; fadj0 = NULL; 
      found = 0;
      for (i = 1; i < nf; i++) {
        face = List_Entry(adj->rfaces,i);
	  
        /* Check if face uses any edge of face 0 */
	  
        for (j = 0, found = 0; j < 4; j++) {
          edge = List_Entry(fedges0,j);
	    
          if (MF_UsesEntity(face,edge,1)) {
            if (edge == fedge00) {
              /* face uses edge 0 of face 0 (w.r.t. face dir pointing
                 into region) */
              fadj0 = face;
              diradj0 = MR_FaceDir_i(r,i);
            }
            found = 1;
            break;
          }
        }
        if (!found) {
          fopp = face;
          diropp = MR_FaceDir_i(r,i);
        }
        if (fopp && fadj0)
          break;
      }
	
      if (!fopp) {
        MSTK_Report("MR_Vertices_FNR3R4","Could not find opposite face",MSTK_ERROR);
        List_Delete(fedges0);
        List_Delete(rvertices);
        return (void *) NULL;
      }
	
      /* edges of face adjacent to edge 0 of face 0 */
      adjfedges = MF_Edges(fadj0,1,rv0);
	
      /* edge connecting rv0 and vertex on opposite face */
      upedge = diradj0 ? List_Entry(adjfedges,3): List_Entry(adjfedges,0);
	
#ifdef DEBUG
      if (!ME_UsesEntity(upedge,rv0,0))
        MSTK_Report("MR_Vertices_FNR3R4","Cannot find correct vertical edge",
                    MSTK_ERROR);
#endif
	
      if (ME_Vertex(upedge,0) == rv0)
        rvopp0 = ME_Vertex(upedge,1);
      else {
        rvopp0 = ME_Vertex(upedge,0);
      }
	
      List_Delete(fedges0);
      List_Delete(adjfedges);
	
      fverts = MF_Vertices(fopp,diropp,rvopp0);
	
      for (i = 0; i < 4; i++)
        List_Add(rvertices,List_Entry(fverts,i));
      List_Delete(fverts);
	
      return rvertices;
      break;

    default: 

      /* General Polyhedra */
      mkr = MSTK_GetMarker();
      
      /* Add vertices of first face */
      face = List_Entry(adj->rfaces,0); /* first face */
      fdir = MR_FaceDir_i(r,0);    /* Sense in which face is used in region */
      
      rvertices = MF_Vertices(face,!fdir,0); 
      List_Mark(rvertices,mkr);
      
      for (i = 1; i < nf-1; i++) {
        face = List_Entry(adj->rfaces,i);
        fverts = MF_Vertices(face,1,0);
        n = List_Num_Entries(fverts);
        for (j = 0; j < n; j++) {
          vert = List_Entry(fverts,j);
          if (!MEnt_IsMarked(vert,mkr)) {
            List_Add(rvertices,vert);
            MEnt_Mark(vert,mkr);
          }
        }
        List_Delete(fverts);
      }
      List_Unmark(rvertices,mkr);
      MSTK_FreeMarker(mkr);
      
      return rvertices;
    }

    return NULL;
  }
Beispiel #15
0
  int MESH_AssignGlobalIDs_Edge(Mesh_ptr submesh, MSTK_Comm comm) {
  int i, j, k, nbe, noe, nge, ne, mesh_info[10], global_id;
  MVertex_ptr mv;
  MEdge_ptr me;
  List_ptr boundary_edges;
  int *loc, edge_id[2], max_nbe, index_nbe, iloc, is_boundary;
  int *global_mesh_info, *list_edge, *recv_list_edge, *edge_ov_label, *id_on_ov_list;
  
  int rank, num;
  MPI_Comm_rank(comm,&rank);
  MPI_Comm_size(comm,&num);

  for (i = 0; i < 10; i++) mesh_info[i] = 0;
  ne = MESH_Num_Edges(submesh);
  mesh_info[2] = ne;

  /* 
     collect 'boundary' edges
     if endpoints are either GHOST or OVERLAP, then it is a boundary edge 
  */
  nbe = 0;  boundary_edges = List_New(10);
  for(i = 0; i < ne; i++) {
    is_boundary = 1;       
    me = MESH_Edge(submesh,i);
    for( k = 0; k < 2; k++) {
      mv = ME_Vertex(me,k);
      if(MV_PType(mv)!=PGHOST && MV_PType(mv)!=POVERLAP)
	is_boundary = 0;
    }
    if(is_boundary) {
      ME_Flag_OnParBoundary(me);
      List_Add(boundary_edges,me);
      nbe++;
    }
  }
  mesh_info[6] = nbe;

  List_Sort(boundary_edges,nbe,sizeof(MEdge_ptr),compareEdgeID);

  global_mesh_info = (int *)malloc(10*num*sizeof(int));
  MPI_Allgather(mesh_info,10,MPI_INT,global_mesh_info,10,MPI_INT,comm);

  max_nbe = 0;
  for(i = 0; i < num; i++)
    if(max_nbe < global_mesh_info[10*i+6])
      max_nbe = global_mesh_info[10*i+6];

  list_edge = (int *)malloc(max_nbe*2*sizeof(int));
  recv_list_edge = (int *)malloc(num*max_nbe*2*sizeof(int));

  /* indicate if a edge is overlapped */
  edge_ov_label = (int *)malloc(num*max_nbe*sizeof(int));
  for (i = 0; i < num*max_nbe; i++)
    edge_ov_label[i] = 0;
  id_on_ov_list = (int *)malloc(max_nbe*sizeof(int));
  /* pack edge information to send  */
  index_nbe = 0;
  for(i = 0; i < nbe; i++) {
    me = List_Entry(boundary_edges,i);
    list_edge[index_nbe] = MV_GlobalID(ME_Vertex(me,0));
    list_edge[index_nbe+1] = MV_GlobalID(ME_Vertex(me,1));
    index_nbe += 2;
  }

  MPI_Allgather(list_edge,2*max_nbe,MPI_INT,recv_list_edge,2*max_nbe,MPI_INT,comm);

  nge = 0;
  /* for processor other than 0 */
  if(rank > 0) {
    for(i = 0; i < nbe; i++) {
      me = List_Entry(boundary_edges,i);
      if(ME_GlobalID(me) > 0) continue;  /* if already assigned */
      edge_id[0] = MV_GlobalID(ME_Vertex(me,0));
      edge_id[1] = MV_GlobalID(ME_Vertex(me,1));
      for(j = 0; j < rank; j++) {
	loc = (int *)bsearch(&edge_id,
			     &recv_list_edge[2*max_nbe*j],
			     global_mesh_info[10*j+6],
			     2*sizeof(int),
			     compareEdgeINT);
	if(loc) {
	  iloc = (int)(loc - &recv_list_edge[2*max_nbe*j])/2;
	  ME_Set_PType(me,PGHOST);
	  ME_Set_MasterParID(me,j);
	  edge_ov_label[max_nbe*j+iloc] |= 1;
	  id_on_ov_list[i] = iloc;
	  nge++;
	  break;
	}
      }
    }
  }

 
  /* num of ghost verts */
  mesh_info[9] = nge;
  MPI_Allgather(mesh_info,10,MPI_INT,global_mesh_info,10,MPI_INT,comm);
  /* since this is a OR reduction, we can use MPI_IN_PLACE, send buffer same as recv buffer */
  MPI_Allreduce(MPI_IN_PLACE,edge_ov_label,num*max_nbe,MPI_INT,MPI_LOR,comm);    

  /* Assign global ID for non ghost edge */
  global_id = 1;
  for(i = 0; i < rank; i++) 
    global_id = global_id + global_mesh_info[10*i+2] - global_mesh_info[10*i+9];
  for(i = 0; i < ne; i++) {
    me = MESH_Edge(submesh,i);
    if (ME_PType(me) == PGHOST) continue;
    if (!ME_GlobalID(me)) ME_Set_GlobalID(me,global_id++);
    ME_Set_MasterParID(me,rank);
  }

  /* label OVERLAP edge */
  noe = 0;
  for(i = 0; i < nbe; i++) 
    if(edge_ov_label[rank*max_nbe+i]) {
      me = List_Entry(boundary_edges,i);
      ME_Set_PType(me,POVERLAP);
      noe++;
  }

  /* this time only global id are sent */
  for(i = 0; i < nbe; i++) {
    me = List_Entry(boundary_edges,i);
    list_edge[i] = ME_GlobalID(me);
  }

  MPI_Allgather(list_edge,max_nbe,MPI_INT,recv_list_edge,max_nbe,MPI_INT,comm);

  for(i = 0; i < nbe; i++) {
    me = List_Entry(boundary_edges,i);
    if(ME_PType(me)==PGHOST) {
      int gid = recv_list_edge[ME_MasterParID(me)*max_nbe+id_on_ov_list[i]];
#ifdef DEBUG
      if (ME_GlobalID(me) && ME_GlobalID(me) != gid)
	MSTK_Report("MESH_Assign_GlobalIDs_Edge",
		    "Ghost edge already has different global ID",
		    MSTK_WARN);
#endif
	ME_Set_GlobalID(me, gid);
    }
  }



  List_Delete(boundary_edges);
  free(global_mesh_info);
  free(edge_ov_label);
  free(id_on_ov_list);
  free(list_edge);
  free(recv_list_edge);
  return 1;
}
  int MESH_Send_NonVertexEntities_FN(Mesh_ptr mesh, int torank, MSTK_Comm comm,
                           int *numreq, int *maxreq, MPI_Request **requests,
                           int *numptrs2free, int *maxptrs2free,
                           void ***ptrs2free) {
    int i, j, nv, ne, nf, nr;
    int nevs, nfes, nrfs, nfe, nrv, nrf, dir;
    int maxnfe, maxnrf;
    int *mesh_info;
    int *list_edge=NULL, *list_face=NULL, *list_region=NULL;
    MVertex_ptr mv;
    MEdge_ptr me;
    MFace_ptr mf;
    MRegion_ptr mr;
    List_ptr mfedges, mrfaces, mrverts;
    RepType rtype;
    double coor[3];
    MPI_Request mpirequest;

    if (requests == NULL)
      MSTK_Report("MESH_Surf_SendMesh","MPI requests array is NULL",MSTK_FATAL);

    if (*maxreq == 0) {
      *maxreq = 25;
      *requests = (MPI_Request *) malloc(*maxreq*sizeof(MPI_Request));
      *numreq = 0;
    }
    else if (*maxreq < (*numreq) + 13) {
      *maxreq = 2*(*maxreq) + 11;
      *requests = (MPI_Request *) realloc(*requests,*maxreq*sizeof(MPI_Request));
    }
  

    ne = MESH_Num_Edges(mesh);
    nf = MESH_Num_Faces(mesh);
    nr = MESH_Num_Regions(mesh);

    /* some other known quantitites - 5 items per edge (2 for verts
       and 3 for extra data), maxnfe+4 items per face (1 for number of
       edges, maxnfe for edge indices, anad 3 for extra data),
       maxnrf+4 items per region (1 for number of faces, maxnrf for
       face indices and 3 for extra data */


    maxnfe = 0;
    for (i = 0; i < nf; i++) {
      mf = MESH_Face(mesh,i);
      nfe = MF_Num_Edges(mf);
      if (nfe > maxnfe)
        maxnfe = nfe;
    }

    maxnrf = 0;
    for (i = 0; i < nr; i++) {
      mr = MESH_Region(mesh,i);
      nrf = MR_Num_Faces(mr);
      if (nrf > maxnrf)
        maxnrf = nrf;
    }

    // The amount of extra info we are sending and their meaning is obviously
    // known on the receiving side too. So nevs, nfes and nrfs can be 
    // calculated without us sending it


    nevs = (2+3)*ne;    
    nfes = (1 + maxnfe + 3)*nf;
    nrfs = (1 + maxnrf + 3)*nr;
    
    /* Reserve nevs spots for each edge */

    list_edge = (int *) malloc(5*ne*sizeof(int));

    nevs = 0;

    /* Store the vertex ids, then the 3 auxilliary data fields */

    for(i = 0; i < ne; i++) {
      me = MESH_Edge(mesh,i);
      list_edge[nevs]   = MV_ID(ME_Vertex(me,0));
      list_edge[nevs+1] = MV_ID(ME_Vertex(me,1));
      list_edge[nevs+2] = (ME_GEntID(me)<<3) | (ME_GEntDim(me));
      list_edge[nevs+3] = (ME_MasterParID(me) <<3) | (ME_OnParBoundary(me)<<2) | (ME_PType(me));
      list_edge[nevs+4] = ME_GlobalID(me);
      nevs += 5;
    }

    /* send detailed edge info */

    MPI_Isend(list_edge,nevs,MPI_INT,torank,torank,comm,&mpirequest);
    (*requests)[*numreq] = mpirequest;
    (*numreq)++;
  

    /* Reserve nfes spots for each face */

    list_face = (int *) malloc(nfes*sizeof(int));

    nfes = 0;

    /* first store nfe, then the edge ids, then the 3 auxilliary data fields */

    for(i = 0; i < nf; i++) {
      mf = MESH_Face(mesh,i);
      mfedges = MF_Edges(mf,1,0);
      nfe = List_Num_Entries(mfedges);
      list_face[nfes] = nfe;
      for(j = 0; j < nfe; j++) {
        dir = MF_EdgeDir_i(mf,j) ? 1 : -1;
        list_face[nfes+j+1] = dir*ME_ID(List_Entry(mfedges,j));
      }
      list_face[nfes+nfe+1] = (MF_GEntID(mf)<<3) | (MF_GEntDim(mf));
      list_face[nfes+nfe+2] = (MF_MasterParID(mf)<<3) | (MF_OnParBoundary(mf)<<2) | (MF_PType(mf));
      list_face[nfes+nfe+3] = MF_GlobalID(mf);
      nfes += (nfe + 4);
      List_Delete(mfedges);
    }


    /* send detailed face info */

    MPI_Isend(list_face,nfes,MPI_INT,torank,torank,comm,&mpirequest);
    (*requests)[*numreq] = mpirequest;
    (*numreq)++;

    
    if (nr) {

      list_region = (int *) malloc(nrfs*sizeof(int));
      
      nrfs = 0;
      
      /* first store nrf, then the face ids, then the 3 auxilliary data fields */
      
      for(i = 0; i < nr; i++) {
        mr = MESH_Region(mesh,i);
        mrfaces = MR_Faces(mr);
        nrf = List_Num_Entries(mrfaces);
        list_region[nrfs] = nrf;
        for(j = 0; j < nrf; j++) {
          dir = MR_FaceDir_i(mr,j) == 1 ? 1 : -1;
          list_region[nrfs+j+1] = dir*MF_ID(List_Entry(mrfaces,j));
        }
        list_region[nrfs+nrf+1] = (MR_GEntID(mr)<<3) | (MR_GEntDim(mr));
        list_region[nrfs+nrf+2] = (MR_MasterParID(mr)<<3) | (MR_PType(mr)); /* MR_PType is 2 bits; 3 bit is 0 */
        list_region[nrfs+nrf+3] = MR_GlobalID(mr);
        nrfs += (nrf + 4);
        List_Delete(mrfaces);
      }
      
      /* send detailed region info */
      
      MPI_Isend(list_region,nrfs,MPI_INT,torank,torank,comm,&mpirequest);
      (*requests)[*numreq] = mpirequest;
      (*numreq)++;
      
    }
      

    /* collect allocated memory so it can be freed in a higher level
       routine after MPI_Waitall or MPI_Test has ensured that the send
       has been completed */

    if (ptrs2free == NULL) 
      MSTK_Report("MESH_Surf_SendMesh_FN","ptrs2free array is NULL",MSTK_FATAL);

    int nptrs = 3;

    if (*maxptrs2free == 0) {
      *maxptrs2free = 25;
      *ptrs2free = (void **) malloc(*maxptrs2free*sizeof(void *));
      *numptrs2free = 0;
    }
    else if (*maxptrs2free < (*numptrs2free) + nptrs) {
      *maxptrs2free = 2*(*maxptrs2free) + nptrs;
      *ptrs2free = (void **) realloc(*ptrs2free,(*maxptrs2free)*sizeof(void *));
    }

    if (ne)
      (*ptrs2free)[(*numptrs2free)++] = list_edge;
    if (nf)
      (*ptrs2free)[(*numptrs2free)++] = list_face;
    if (nr)
      (*ptrs2free)[(*numptrs2free)++] = list_region;

    return 1;
  }