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; }
int MESH_Renumber_EntityGlobalIDs(Mesh_ptr mesh, MType mtype, int method, int *preassigned_gids, MSTK_Comm comm) { int i; if (method != 0) { MSTK_Report("MESH_Renumber_EntityGlobalIDs", "Chosen renumbering scheme not implemented", MSTK_ERROR); return 0; } if (mtype == MALLTYPE) { MSTK_Report("MESH_Renumber_EntityGlobalIDs", "Cannot call this routine for MALLTYPE", MSTK_ERROR); return 0; } MAttrib_ptr tmpatt = MAttrib_New(mesh, "tmpatt_renumber", INT, mtype); int nproc, rank; MPI_Comm_size(comm, &nproc); MPI_Comm_rank(comm, &rank); int idx = 0, nowned = 0; MEntity_ptr ment; switch (mtype) { case MVERTEX: while ((ment = MESH_Next_Vertex(mesh, &idx))) if (MV_PType(ment) != PGHOST) nowned++; break; case MEDGE: while ((ment = MESH_Next_Edge(mesh, &idx))) if (ME_PType(ment) != PGHOST) nowned++; break; case MFACE: while ((ment = MESH_Next_Face(mesh, &idx))) if (MF_PType(ment) != PGHOST) nowned++; break; case MREGION: while ((ment = MESH_Next_Region(mesh, &idx))) if (MR_PType(ment) != PGHOST) nowned++; break; default: {} } /* Gather the number of entities on every processor */ int *nowned_all = NULL; if (rank == 0) nowned_all = (int *) calloc(nproc, sizeof(int)); MPI_Gather(&nowned, 1, MPI_INT, nowned_all, 1, MPI_INT, 0, comm); int *offset_all = NULL; if (rank == 0) { offset_all = (int *) malloc(nproc*sizeof(int)); offset_all[0] = 0; int p; for (p = 1; p < nproc; p++) offset_all[p] = offset_all[p-1] + nowned_all[p-1]; } int offset = 0; MPI_Scatter(offset_all, 1, MPI_INT, &offset, 1, MPI_INT, 0, comm); /* At this point if we had different methods for renumbering the * global set of entities, we would generate a Global ID map. For * now this is just a sequential map (method 0) */ int *new_index = (int *) malloc(nowned*sizeof(int)); if (method == 0) { for (i = 0; i < nowned; i++) new_index[i] = i+1; } /* Now assign global IDs to the entities */ int new_gid; idx = 0; i = 0; switch (mtype) { case MVERTEX: while ((ment = MESH_Next_Vertex(mesh, &idx))) if (MV_PType(ment) != PGHOST) { new_gid = offset + new_index[i]; MEnt_Set_AttVal(ment, tmpatt, new_gid, 0.0, NULL); i++; } break; case MEDGE: while ((ment = MESH_Next_Edge(mesh, &idx))) if (ME_PType(ment) != PGHOST) { new_gid = offset + new_index[i]; MEnt_Set_AttVal(ment, tmpatt, new_gid, 0.0, NULL); i++; } break; case MFACE: while ((ment = MESH_Next_Face(mesh, &idx))) if (MF_PType(ment) != PGHOST) { new_gid = offset + new_index[i]; MEnt_Set_AttVal(ment, tmpatt, new_gid, 0.0, NULL); i++; } break; case MREGION: while ((ment = MESH_Next_Region(mesh, &idx))) if (MR_PType(ment) != PGHOST) { new_gid = offset + new_index[i]; MEnt_Set_AttVal(ment, tmpatt, new_gid, 0.0, NULL); i++; } break; default: {} } /* Now exchange the attribute across processors */ MESH_Update1Attribute(mesh, tmpatt, comm); /* Now assign global IDs of the entities based on the values of * the gidatt attribute */ idx = 0; double rval; void *pval; switch (mtype) { case MVERTEX: while ((ment = MESH_Next_Vertex(mesh, &idx))) { MEnt_Get_AttVal(ment, tmpatt, &new_gid, &rval, &pval); MV_Set_GlobalID(ment, new_gid); } break; case MEDGE: while ((ment = MESH_Next_Edge(mesh, &idx))) { MEnt_Get_AttVal(ment, tmpatt, &new_gid, &rval, &pval); ME_Set_GlobalID(ment, new_gid); } break; case MFACE: while ((ment = MESH_Next_Face(mesh, &idx))) { MEnt_Get_AttVal(ment, tmpatt, &new_gid, &rval, &pval); MF_Set_GlobalID(ment, new_gid); } break; case MREGION: while ((ment = MESH_Next_Region(mesh, &idx))) { MEnt_Get_AttVal(ment, tmpatt, &new_gid, &rval, &pval); MR_Set_GlobalID(ment, new_gid); } break; default: {} } free(nowned_all); free(offset_all); MAttrib_Delete(tmpatt); return 1; }
int main(int argc, char **argv) { int len, ok; int i, j, id, idx, ncells, file_found; int num_parts, imethod; int nproc, rank; Mesh_ptr mesh; char basename[256], meshname[256], gmvfilename[256], method[256]; if (argc == 1) { fprintf(stderr,"Usage: %s --num=num_parts --method=Metis/Zoltan (default=Metis) --file=name.mstk\n",argv[0]); exit(-1); } file_found = 0; num_parts = 4; strcpy(method,"Metis"); for (i = 1; i < argc; i++) { if (strncmp(argv[i],"--file=",7) == 0) { sscanf(argv[i]+7,"%s",meshname); file_found = 1; } else if (strncmp(argv[i],"--num=",6) == 0) sscanf(argv[i]+6,"%d",&num_parts); else if (strncmp(argv[i],"--method=",9) == 0) sscanf(argv[i]+9,"%s",method); else if (strncmp(argv[i],"--help",6) == 0) { fprintf(stderr,"Usage: %s --num=num_parts --method=Metis/Zoltan (default=Metis) --file=name.mstk\n",argv[0]); exit(-1); } } if (strncasecmp(method,"metis",5) == 0) imethod = 0; else if (strncasecmp(method,"zoltan",6) == 0) imethod = 1; else { fprintf(stderr,"vizpart: Partitioning method not recognized\n"); exit(-1); } if (!file_found) { fprintf(stderr,"Must specify input filename using --file argument\n"); exit(-1); } MPI_Init(&argc,&argv); MSTK_Init(); MSTK_Comm comm = MPI_COMM_WORLD; MPI_Comm_size(comm,&nproc); MPI_Comm_rank(comm,&rank); if (imethod == 1 && nproc != num_parts) { fprintf(stderr,"Zoltan based partitioner: Number of processors must equal requested number of partition\n"); exit(-1); } strcpy(basename,meshname); len = strlen(meshname); if (len > 5 && strncmp(&(meshname[len-5]),".mstk",5) == 0) basename[len-5] = '\0'; else strcat(meshname,".mstk"); mesh = MESH_New(UNKNOWN_REP); if (rank == 0) { ok = MESH_InitFromFile(mesh,meshname,comm); if (!ok) { fprintf(stderr,"Cannot file input file %s\n\n\n",meshname); exit(-1); } if ( (ncells = MESH_Num_Regions(mesh)) > 0) { printf("3D mesh with %d regions\n", ncells); } else if ( (ncells = MESH_Num_Faces(mesh)) > 0) printf("2D mesh with %d faces\n", ncells); else { fprintf(stderr,"Mesh is neither solid nor surface mesh. Exiting...\n"); exit(-1); } } Mesh_ptr *submeshes = (Mesh_ptr*) malloc(num_parts*sizeof(Mesh_ptr)); int *part; MESH_Get_Partitioning(mesh, imethod, &part, comm); if(rank == 0) { int del_inmesh = 0; MESH_Partition(mesh, num_parts, part, submeshes); idx = 0; if(MESH_Num_Regions(mesh)) { MAttrib_ptr region_part = MAttrib_New(mesh, "part", INT, MREGION); MRegion_ptr mr; while ((mr = MESH_Next_Region(mesh, &idx))) { id = MR_ID(mr); MEnt_Set_AttVal(mr,region_part,part[id-1],0,NULL); } } else { MAttrib_ptr face_part = MAttrib_New(mesh, "part", INT, MFACE); MFace_ptr mf; while ((mf = MESH_Next_Face(mesh, &idx))) { id = MF_ID(mf); MEnt_Set_AttVal(mf,face_part,part[idx-1],0,NULL); } } sprintf(gmvfilename,"%s_part.gmv",basename); MESH_ExportToGMV(mesh,gmvfilename,0,NULL,NULL,comm); for( i = 0; i < num_parts; i++) { sprintf(gmvfilename,"%s_part.%04d.%04d.gmv",basename,i,0); MESH_ExportToGMV(submeshes[i],gmvfilename,0,NULL,NULL,comm); } for (i = 0; i < num_parts; i++) MESH_Delete(submeshes[i]); } free(submeshes); MESH_Delete(mesh); free(part); MPI_Finalize(); return 1; }
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; }
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; }
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; }
void import_attributes(Mesh_ptr mesh, char *attfname) { FILE *fp; int i, j, idx, status, entid, natt, nent, celldim; char mesg[256]; MRegion_ptr mr; MFace_ptr mf; MVertex_ptr mv; char attname[256], typestr[256]; double attval; MAttrib_ptr att; fp = fopen(attfname,"r"); if (!fp) { sprintf(mesg,"Could not open attribute file %s",attfname); MSTK_Report(progname,mesg,MSTK_FATAL); } status = fscanf(fp,"%d",&natt); if (status == EOF) MSTK_Report(progname,"Attributes file ended prematurely",MSTK_FATAL); celldim = MESH_Num_Regions(mesh) ? 3 : 2; for (i = 0; i < natt; ++i) { status = fscanf(fp,"%s %s %d\n",attname,typestr,&nent); fprintf(stderr,"\nCreating %s attribute %s\n",typestr,attname); if (strcasecmp(typestr,"NODE") == 0) { att = MAttrib_New(mesh,attname,DOUBLE,MVERTEX); if (nent == -1) { /* data specified on the whole mesh */ idx = 0; while ((mv = MESH_Next_Vertex(mesh,&idx))) { status = fscanf(fp,"%lf",&attval); if (status == EOF) MSTK_Report(progname,"Attributes file ended prematurely",MSTK_FATAL); MEnt_Set_AttVal(mv,att,0,attval,NULL); } } else { for (j = 0; j < nent; ++j) { status = fscanf(fp,"%d %lf",&entid,&attval); if (status == EOF) MSTK_Report(progname,"Attributes file ended prematurely",MSTK_FATAL); mv = MESH_VertexFromID(mesh,entid); if (!mv) { sprintf(mesg,"Cannot find mesh element with ID = %-d",entid); MSTK_Report(progname,mesg,MSTK_FATAL); } MEnt_Set_AttVal(mv,att,0,attval,NULL); } } } else if (strcasecmp(typestr,"SIDESET") == 0) { MSTK_Report(progname,"SIDESET attribute import not implemented",MSTK_FATAL); } else if (strcasecmp(typestr,"CELL") == 0) { if (celldim == 3) { att = MAttrib_New(mesh,attname,DOUBLE,MREGION); if (nent == -1) { /* data specified on the whole mesh */ idx = 0; while ((mr = MESH_Next_Region(mesh,&idx))) { status = fscanf(fp,"%lf",&attval); if (status == EOF) MSTK_Report(progname,"Attributes file ended prematurely",MSTK_FATAL); MEnt_Set_AttVal(mr,att,0,attval,NULL); } } else { for (j = 0; j < nent; ++j) { status = fscanf(fp,"%d %lf",&entid,&attval); if (status == EOF) MSTK_Report(progname,"Attributes file ended prematurely",MSTK_FATAL); mr = MESH_RegionFromID(mesh,entid); if (!mr) { sprintf(mesg,"Cannot find mesh element with ID = %-d",entid); MSTK_Report(progname,mesg,MSTK_FATAL); } MEnt_Set_AttVal(mr,att,0,attval,NULL); } } } else { att = MAttrib_New(mesh,attname,DOUBLE,MFACE); if (nent == -1) { /* data specified on the whole mesh */ idx = 0; while ((mf = MESH_Next_Face(mesh,&idx))) { status = fscanf(fp,"%lf",&attval); if (status == EOF) MSTK_Report(progname,"Attributes file ended prematurely",MSTK_FATAL); MEnt_Set_AttVal(mf,att,0,attval,NULL); } } else { for (j = 0; j < nent; ++j) { status = fscanf(fp,"%d %lf",&entid,&attval); if (status == EOF) MSTK_Report(progname,"Attributes file ended prematurely",MSTK_FATAL); mf = MESH_FaceFromID(mesh,entid); if (!mf) { sprintf(mesg,"Cannot find mesh element with ID = %-d",entid); MSTK_Report(progname,mesg,MSTK_FATAL); } MEnt_Set_AttVal(mf,att,0,attval,NULL); } } } } else MSTK_Report(progname, "Unknown entity type for attribute: Valid types are NODE, CELL or SIDESET (case does not matter)", MSTK_FATAL); } }