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; } }
MVertex_ptr MVs_Merge_R1R2(MVertex_ptr v1, MVertex_ptr v2, int topoflag) { int i, idx, gdim, gid; MFace_ptr face; MRegion_ptr region; Mesh_ptr mesh; List_ptr vfaces2, vregions2; mesh = MV_Mesh(v1); gid = MV_GEntID(v1); gdim = MV_GEntDim(v1); if (mesh != MF_Mesh(v2)) { MSTK_Report("MVs_Join","Vertices not from same mesh",MSTK_ERROR); return 0; } else if (topoflag) { /* make sure geometric model topology is not violated */ if (gid != MV_GEntID(v2) || gdim != MV_GEntDim(v2)) { MSTK_Report("MFs_Join","Faces not from same geometric entity",MSTK_ERROR); return 0; } } vfaces2 = MV_Faces(v2); if (vfaces2) { idx = 0; while ((face = List_Next_Entry(vfaces2,&idx))) MF_Replace_Vertex(face,v2,v1); List_Delete(vfaces2); } vregions2 = MV_Regions(v2); if (vregions2) { idx = 0; while ((region = List_Next_Entry(vregions2,&idx))) MR_Replace_Vertex(region,v2,v1); List_Delete(vregions2); } MV_Delete(v2,0); return v1; }
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); }
/* test if a vertex is on partition boundary, for volume mesh a vertex is on boundary if one of its incident faces has less than 2 neighboring regions */ static int vertex_on_boundary3D(MVertex_ptr mv) { int i, nrf, ok = 0; MFace_ptr mf; List_ptr vfaces = MV_Faces(mv); nrf = List_Num_Entries(vfaces); for(i = 0; (i < nrf) && !ok; i++) { List_ptr fregs; mf = List_Entry(vfaces,i); fregs = MF_Regions(mf); if(List_Num_Entries(fregs) <= 1) ok = 1; List_Delete(fregs); } List_Delete(vfaces); return ok; }
List_ptr ME_Regions_F1(MEdge_ptr e) { MEdge_Adj_F1 *adj; int i, j, nr, nf; List_ptr eregs; MFace_ptr eface; MRegion_ptr freg; adj = (MEdge_Adj_F1 *) e->adj; nf = List_Num_Entries(adj->efaces); eregs = List_New(nf); nr = 0; for (i = 0; i < nf; i++) { eface = List_Entry(adj->efaces,i); for (j = 0; j < 2; j++) { freg = MF_Region(eface,j); if (freg) { int inlist; inlist = List_Contains(eregs,freg); if (!inlist) { List_Add(eregs,freg); nr++; } } } } if (nr) return eregs; else { List_Delete(eregs); return 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; }
/* test if a vertex is on partition boundary, for surface mesh a vertex is on boundary if one of its incident edges has less than 2 neighboring faces */ static int vertex_on_boundary2D(MVertex_ptr mv) { int i, nve, ok = 0; MEdge_ptr me; List_ptr vedges = MV_Edges(mv); nve = List_Num_Entries(vedges); for(i = 0; (i < nve) &!ok; i++) { List_ptr efaces; me = List_Entry(vedges,i); efaces = ME_Faces(me); if(List_Num_Entries(efaces) <= 1) ok = 1; List_Delete(efaces); } List_Delete(vedges); return ok; }
void Axle_Delete(int carnum, int i) { PTCar car = Car_Get(carnum); if (car == NULL) { return; } List_Delete(car->axles, i); }
void PStack_Free_Page(PStack *pstack) { while (!List_Is_Empty(&(pstack->page_list))) { PStack_Page *last_page = PStack_Page_Fetch(pstack->page_list.prev); last_page->hwm = 0; delete[] last_page->page; List_Delete(&(pstack->page_list), &(last_page->list_head)); delete last_page; } }
void Utilities_String_Split(void* State) { CpArray* DestArray = (CpArray*)State_Pop(State); char* Delims = State_PopString(State); char* Target = State_PopString(State); List* Values = Split(Target, Delims); Utilities_ListToArray(Values, DestArray); List_Delete(Values); };
void MF_Destroy_For_MESH_Delete_R1(MFace_ptr f) { MFace_Adj_R1 *adj; adj = (MFace_Adj_R1 *) f->adj; if (adj) { if (adj->fvertices) List_Delete(adj->fvertices); free(adj); } }
void ME_Destroy_For_MESH_Delete_F1(MEdge_ptr e) { MEdge_Adj_F1 *adj; adj = (MEdge_Adj_F1 *) e->adj; if (adj) { if (adj->efaces) List_Delete(adj->efaces); free(adj); } }
void ME_RegionIDs_F1(MEdge_ptr e, int *ner, int *eregionids) { int i; List_ptr eregs = ME_Regions_F1(e); *ner = 0; if (eregs) { *ner = List_Num_Entries(eregs); for (i = 0; i < *ner; i++) eregionids[i] = MEnt_ID(List_Entry(eregs,i)); List_Delete(eregs); } }
void PStack_List_Delete_PStack(unsigned int id) { PStack *pstack = PStack_List_Search(id); if (0 != pstack) { PStack_Free_Page(pstack); List_Delete(&PStack_List, &(pstack->list_head)); delete pstack; } else { return; } }
//------------------------------------------------------------------- void FunctionTable_End(void) { if(g_Initialized) { List_Delete(g_FunctionList); g_Initialized = 0; } else { DEBUG_msg("Trying to End FunctionTable without having Init it!"); ASSERT("Trying to End FunctionTable without having Init it!" != NULL); } }
int ME_Num_Faces_R1R2(MEdge_ptr e) { int nf; List_ptr efaces = ME_Faces(e); if (efaces) { nf = List_Num_Entries(efaces); List_Delete(efaces); } else nf = 0; return nf; }
MVertex_ptr MVs_Merge_R3R4(MVertex_ptr v1, MVertex_ptr v2, int topoflag) { int idx, gdim, gid, nsets; MFace_ptr face; Mesh_ptr mesh; List_ptr vfaces2; MSet_ptr mset; mesh = MV_Mesh(v1); gid = MV_GEntID(v1); gdim = MV_GEntDim(v1); if (mesh != MF_Mesh(v2)) { MSTK_Report("MVs_Join","Vertices not from same mesh",MSTK_ERROR); return 0; } else if (topoflag) { /* Make sure model topology is not violated */ if (gid != MV_GEntID(v2) || gdim != MV_GEntDim(v2)) { MSTK_Report("MFs_Join","Faces not from same geometric entity",MSTK_ERROR); return 0; } } vfaces2 = MV_Faces(v2); if (vfaces2) { idx = 0; while ((face = List_Next_Entry(vfaces2,&idx))) MF_Replace_Vertex(face,v2,v1); List_Delete(vfaces2); } nsets = MESH_Num_MSets(mesh); if(nsets) { idx = 0; while ((mset = (MSet_ptr) MESH_Next_MSet(mesh,&idx))) { if (MSet_Contains(mset, v2)) { if(MSet_Contains(mset, v1)) MSet_Rem(mset, v2); else MSet_Replace(mset, v2, v1); } } } MV_Delete(v2,1); return v1; }
int main() { int element = 255; unsigned int key = 127; list_t lst; List_Init(&lst); List_Insert(&lst, (void*)&element, key); List_Delete(&lst, key); void *val = List_Lookup(&lst, key); if (!val) return 0; else return -1; }
int ME_Num_Faces_R3R4(MEdge_ptr e) { List_ptr efaces; int nf; #ifdef DEBUG MSTK_Report("ME_Num_Faces", "Inefficient to call this routine with this representation", MSTK_MESG); #endif efaces = ME_Faces(e); nf = efaces ? List_Num_Entries(efaces) : 0; if (efaces) List_Delete(efaces); return nf; }
void MF_Delete_R1(MFace_ptr f, int keep) { MFace_Adj_R1 *adj; adj = (MFace_Adj_R1 *) f->adj; if (adj) { if (adj->fvertices) List_Delete(adj->fvertices); free(adj); } if (!keep) { MEnt_Set_DelFlag((MEntity_ptr) f); } if (keep) MSTK_Report("MF_Delete_R1","Deletion of faces is permanent in this representation",MSTK_ERROR); }
int ME_Num_Regions_F1(MEdge_ptr e) { List_ptr eregs; int nr; #ifdef DEBUG MSTK_Report("ME_Num_Regions", "Inefficient to call this routine with this representation", MSTK_MESG); #endif eregs = ME_Regions_F1(e); nr = eregs ? List_Num_Entries(eregs) : 0; if (eregs) List_Delete(eregs); return nr; }
void ME_Delete_F1(MEdge_ptr e, int keep) { MEdge_Adj_F1 *adj; if (MEnt_Dim((MEntity_ptr) e) != MDELETED) { /* if edge hasnt been temporarily deleted */ if (e->vertex[0]) MV_Rem_Edge(e->vertex[0],e); if (e->vertex[1]) MV_Rem_Edge(e->vertex[1],e); } if (!keep) { adj = (MEdge_Adj_F1 *) e->adj; if (adj) { if (adj->efaces) List_Delete(adj->efaces); free(adj); } } }
/*构建一个新的链表*/ list_t* List_CreateNew(unsigned int size) { list_t *pList = 0; do{ pList = (list_t*)malloc(sizeof(list_t)); if(0==pList) break; memset(pList,0,sizeof(list_t)); pList->nodeSize = size; pList->nodeCount = 0; pList->pHead = 0; pList->pTail = 0; return pList; }while(0); List_Delete(pList); return 0; }
int main() { Node * head_ptr; head_ptr = List_User_Init(); List_Traversal(head_ptr); List_Insert(head_ptr,7); List_Insertn(head_ptr,2,7); List_Traversal(head_ptr); List_DeleteNode(head_ptr); List_DeleteNthNode(head_ptr,3); List_Traversal(head_ptr); head_ptr = remove_if_basic(head_ptr,fun1); remove_if(&head_ptr,fun2); List_Traversal(head_ptr); List_Delete(head_ptr); }
int MR_Num_Edges(MRegion_ptr r) { List_ptr redges; int nre; redges = MR_Edges(r); nre = List_Num_Entries(redges); List_Delete(redges); #ifdef DEBUG { RepType RTYPE = MEnt_RepType((MEntity_ptr) r); if (RTYPE != R1 || RTYPE != R2) MSTK_Report("MR_Num_Vertices", "Inefficient to use this routine for this representation", MSTK_WARN); } #endif return nre; }
void MF_Set_Vertices_R2(MFace_ptr f, int n, MVertex_ptr *v) { MFace_Adj_R2 *adj; int i; adj = (MFace_Adj_R2 *) f->adj; if (adj->fvertices) List_Delete(adj->fvertices); adj->fvertices = List_New(n); for (i = 0; i < n; i++) { #ifdef DEBUG if (MF_Mesh(f) != MV_Mesh(v[i])) MSTK_Report("MF_Set_Vertices_R2", "Face and Vertex are not from the same mesh", MSTK_FATAL); #endif List_Add(adj->fvertices,v[i]); } }
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; }
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; }
List_ptr ME_Faces_R1R2(MEdge_ptr e) { int idx, idx1, idx2, found; MFace_ptr face, lstface; MRegion_ptr reg; List_ptr rfaces, vfaces1, efaces, vregs0, vregs1, cmnregs=NULL; efaces = List_New(0); vregs0 = MV_Regions(e->vertex[0]); vregs1 = MV_Regions(e->vertex[1]); if (vregs0 || vregs1) { if (vregs0 && vregs1) { cmnregs = List_New(0); idx = 0; while ((reg = List_Next_Entry(vregs0,&idx))) { if (List_Contains(vregs1,reg)) List_Add(cmnregs,reg); } } if (vregs0) List_Delete(vregs0); if (vregs1) List_Delete(vregs1); if (!List_Num_Entries(cmnregs)) { List_Delete(cmnregs); return NULL; } idx = 0; while ((reg = List_Next_Entry(cmnregs,&idx))) { rfaces = MR_Faces(reg); idx1 = 0; while ((face = List_Next_Entry(rfaces,&idx1))) { if (MF_UsesEntity(face,(MEntity_ptr) e,MEDGE)) { idx2 = 0; found = 0; while ((lstface = List_Next_Entry(efaces,&idx2))) { if (MFs_AreSame(face,lstface)) { found = 1; break; } } if (!found) List_Add(efaces,face); } } List_Delete(rfaces); } List_Delete(cmnregs); } else { /* Must be only faces are connected to edge */ vfaces1 = MV_Faces(e->vertex[0]); if (vfaces1) { idx = 0; while ((face = List_Next_Entry(vfaces1,&idx))) { if (MF_UsesEntity(face,e->vertex[1],MVERTEX)) List_Add(efaces,face); } } } if (List_Num_Entries(efaces)) return efaces; else { List_Delete(efaces); return NULL; } }
int MESH_BuildFaceClassfn(Mesh_ptr mesh, int use_geometry) { int i, j, k, idx, idx2, fnd, gfid, gfid2, gdim; int ngfaces, ngfalloc, grid0, grid1; int max_gface_id, processedmk, submk; int nfe, nef, nbf, nfr, nsub, *gfids, (*gfregids)[2]; double PI=3.141592, ang, COSSHARPANG; MEdge_ptr edge; MFace_ptr face, subface, adjface; MRegion_ptr freg0, freg1; List_ptr fregs, fedges, efaces, ebfaces, gffaces, subfaces; COSSHARPANG = cos(9*PI/12); /* 135 degrees */ /* Verify that mesh faces on the boundary have classification information; if not, assign all faces to the same model faces */ ngfaces = 0; ngfalloc = 10; gfids = (int *) malloc(ngfalloc*sizeof(int)); gfregids = (int (*)[2]) malloc(ngfalloc*sizeof(int [2])); /* Take stock of existing model face information */ max_gface_id = 0; idx = 0; while ((face = MESH_Next_Face(mesh,&idx))) { gdim = MF_GEntDim(face); if (gdim != 2) continue; gfid = MF_GEntID(face); if (gfid) { /* Has this model face been encountered? If not, add it to list of model faces */ for (i = 0, fnd = 0; i < ngfaces; i++) if (gfids[i] == gfid) { fnd = 1; break; } if (!fnd) { if (gfid > max_gface_id) max_gface_id = gfid; if (ngfalloc == ngfaces) { ngfalloc *= 2; gfids = (int *) realloc(gfids,ngfalloc*sizeof(int)); gfregids = (int (*)[2])realloc(gfregids,ngfalloc*sizeof(int [2])); } gfids[ngfaces] = gfid; gfregids[ngfaces][0] = gfregids[ngfaces][1] = 0; fregs = MF_Regions(face); if (fregs) { nfr = List_Num_Entries(fregs); freg0 = List_Entry(fregs,0); gfregids[ngfaces][0] = MR_GEntID(freg0); /* NOTE 1 (see EOF) */ if (nfr == 2) { freg1 = List_Entry(fregs,1); gfregids[ngfaces][1] = MR_GEntID(freg1); } List_Delete(fregs); } ngfaces++; } } } /* Build new model face information based on adjacent model region info */ idx = 0; while ((face = MESH_Next_Face(mesh,&idx))) { gdim = MF_GEntDim(face); gfid = MF_GEntID(face); /* Face has no classification? Assign classification info */ /* Face classified as interior face? Verify */ freg0 = freg1 = NULL; grid0 = grid1 = 0; fregs = MF_Regions(face); if (fregs) { nfr = List_Num_Entries(fregs); freg0 = List_Entry(fregs,0); grid0 = MR_GEntID(freg0); if (nfr == 2) { freg1 = List_Entry(fregs,1); grid1 = MR_GEntID(freg1); } List_Delete(fregs); } else nfr = 0; if (nfr == 2 && (grid0 == grid1)) { /* Interior face */ MF_Set_GEntDim(face,3); MF_Set_GEntID(face,grid0); } else { /* Boundary face */ if (gdim > 2 || (gdim == 2 && gfid <= 0)) { MF_Set_GEntDim(face,2); /* Check if this type of face with these adjacent regions has been encountered before; if it has, we just use the existing model face id */ for (i = 0, fnd = 0; i < ngfaces; i++) if ((gfregids[i][0] == grid0 && gfregids[i][1] == grid1) || (gfregids[i][0] == grid1 && gfregids[i][1] == grid0)) { fnd = 1; break; } if (fnd) MF_Set_GEntID(face,gfids[i]); else { max_gface_id++; MF_Set_GEntID(face,max_gface_id); if (ngfalloc == ngfaces) { ngfalloc *= 2; gfids = (int *) realloc(gfids,ngfalloc*sizeof(int)); gfregids = (int (*)[2]) realloc(gfregids,ngfalloc*sizeof(int [2])); } gfids[ngfaces] = max_gface_id; gfregids[ngfaces][0] = grid0; gfregids[ngfaces][1] = grid1; ngfaces++; } } } } if (use_geometry == 1) { /* Now assign model face IDs based on whether a sharp set of edges enclose a set of faces */ for (i = 0; i < ngfaces; i++) { /* Find all mesh faces with this model face id */ gffaces = List_New(10); idx = 0; while ((face = MESH_Next_Face(mesh,&idx))) { if (MF_GEntDim(face) == 2 && MF_GEntID(face) == gfids[i]) List_Add(gffaces,face); } /* Process faces of this list and subdivide them into subfaces */ /* The way we do that is 1) we put an unprocessed face from the original list in a subface list 2) we then add its neighboring faces to subface list if they are of the same color (same model face id) and do not have a sharp edge separating them from the current face 3) we then process the next face in the subface list 4) we are done if we cannot find any more neighbors of faces in the subface list to add to the subface list 5) we then repeat steps 1 through 4 until we are left with no more faces to process from the original list */ processedmk = MSTK_GetMarker(); nsub = 0; idx = 0; while ((face = List_Next_Entry(gffaces,&idx))) { if (MEnt_IsMarked(face,processedmk)) continue; /* Found a face in gffaces that has not been processed */ MEnt_Mark(face,processedmk); submk = MSTK_GetMarker(); subfaces = List_New(10); List_Add(subfaces,face); MEnt_Mark(face,submk); idx2 = 0; while ((subface = List_Next_Entry(subfaces,&idx2))) { gfid = MF_GEntID(subface); fedges = MF_Edges(subface,1,0); nfe = List_Num_Entries(fedges); for (j = 0; j < nfe; j++) { edge = List_Entry(fedges,j); efaces = ME_Faces(edge); nef = List_Num_Entries(efaces); ebfaces = List_New(nef); /* list of boundary faces cnctd 2 edge */ for (k = 0; k < nef; k++) { adjface = List_Entry(efaces,k); if (MF_GEntDim(adjface) == 2) List_Add(ebfaces,adjface); } List_Delete(efaces); nbf = List_Num_Entries(ebfaces); if (nbf == 2) { /* we might be on a model face or on a model edge */ adjface = List_Entry(ebfaces,0); if (adjface == subface) adjface = List_Entry(ebfaces,1); gfid2 = MF_GEntID(adjface); if (gfid == gfid2) { /* The two faces are of the same ID. If the angle between them is not sharp they can be classified as being on the same subface */ ang = MFs_DihedralAngle(subface,adjface,edge); if (ang <= COSSHARPANG) { /* Add face2 to subface list unless its already there */ if (!MEnt_IsMarked(adjface,submk)) { List_Add(subfaces,adjface); MEnt_Mark(adjface,submk); } } else { /* The two faces make a very sharp angle. We will consider the edge b/w them to be a model edge */ /* Tag the edge as being on a model edge (we don't know the model edge ID as yet) and continue */ ME_Set_GEntDim(edge,1); ME_Set_GEntID(edge,0); } } else { /* we reached a model edge */ /* Tag the edge as being on a model edge (we don't know the model edge ID as yet) and continue */ ME_Set_GEntDim(edge,1); ME_Set_GEntID(edge,0); } } else { /* we reached a a model edge */ /* Tag the edge as being on a model edge (we don't know the model edge ID as yet) and continue */ ME_Set_GEntDim(edge,1); ME_Set_GEntID(edge,0); } List_Delete(ebfaces); } /* Finished processing all neighbors of the face */ List_Delete(fedges); } /* Now we have a list of faces which we believe constitutes a model face by itself. If this is the first subface (which means it could also be the entire model face originally considered), leave the model face tag as it is. If not, assign the faces in the subface a new model face ID */ if (nsub != 0) { max_gface_id++; idx2 = 0; while ((subface = List_Next_Entry(subfaces,&idx2))) MF_Set_GEntID(subface,max_gface_id); } nsub++; /* Done with this subface */ idx2 = 0; while ((subface = List_Next_Entry(subfaces,&idx2))) { MEnt_Mark(subface,processedmk); MEnt_Unmark(subface,submk); } MSTK_FreeMarker(submk); List_Delete(subfaces); } List_Unmark(gffaces,processedmk); MSTK_FreeMarker(processedmk); List_Delete(gffaces); } } /* if use_geometry == 1 */ free(gfids); free(gfregids); return 1; }