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; }
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_CheckTopo(Mesh_ptr mesh) { int valid = 1; char mesg[256], funcname[32] = "MESH_CheckTopo"; int idx1, idx2, idx3, idx4; MVertex_ptr mv; MEdge_ptr me, ve, fe, re; MFace_ptr mf, vf, ef, rf; MRegion_ptr mr, vr, er, fr; int found, done; int dir; int i, j, k; int nfe; int vid, eid, fid, rid; int gvid, geid, gfid, grid; int gvdim, gedim, gfdim, grdim; int maxiter = 1000; List_ptr vedges, vfaces, vregions; List_ptr efaces; List_ptr fverts, fedges, fregs, fregs1; List_ptr rverts, redges, rfaces; /*****************************************************************/ /* Vertices */ /*****************************************************************/ /* Check that edges connected to vertices reference the vertices */ /* Also check that the classification of the vertex is consistent with respect to the edge */ int first_unknown_classfn = 1; idx1 = 0; while ((mv = MESH_Next_Vertex(mesh,&idx1))) { #ifdef MSTK_HAVE_MPI if (MV_PType(mv) == PGHOST) continue; #endif vid = MV_ID(mv); gvdim = MV_GEntDim(mv); gvid = MV_GEntID(mv); if (gvdim == 4 && first_unknown_classfn) { sprintf(mesg, "Vertex %-d - classification unknown\n", vid); MSTK_Report(funcname, mesg, MSTK_WARN); first_unknown_classfn = 0; } vedges = MV_Edges(mv); if (!vedges) { sprintf(mesg,"Vertex %-d does not have any connected edges\n",vid); MSTK_Report(funcname,mesg,MSTK_WARN); continue; } idx2 = 0; while ((ve = List_Next_Entry(vedges,&idx2))) { eid = ME_ID(ve); if (ME_Vertex(ve,0) != mv && ME_Vertex(ve,1) != mv) { sprintf(mesg,"Vertex %-d connected to edge %-d but edge does not use vertex",vid,eid); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } } if (gvdim == 1) { /* If vertex is classified on a model edge, then it should be connected to two and only two edges that are classified on the same model edge */ int ne = 0; idx2 = 0; while ((ve = List_Next_Entry(vedges,&idx2))) { gedim = ME_GEntDim(ve); geid = ME_GEntID(ve); if (gedim == 1 && geid == gvid) ne++; } if (ne != 2) { sprintf(mesg,"Vertex %-d classified on model edge %-d but it is not \n connected to two edges classified on this model edge",vid,gvid); MSTK_Report(funcname,mesg,MSTK_WARN); } } List_Delete(vedges); if (gvdim == 2) { MEdge_ptr e0, ecur, enxt; MFace_ptr fcur; int flipped = 0; /* If vertex is classified on a model face, then we should be able to find a ring of faces classified on that model face */ vfaces = MV_Faces(mv); found = 0; idx2 = 0; while ((vf = List_Next_Entry(vfaces,&idx2))) { if (MF_GEntDim(vf) == 2) { found = 1; break; } } List_Delete(vfaces); if (!found) { sprintf(mesg,"Vertex %-d classified on model face %-d but could not \n find connected face classified on this model face",vid,gvid); MSTK_Report(funcname,mesg,MSTK_WARN); valid = 0; } fcur = vf; fedges = MF_Edges(fcur,1,mv); nfe = List_Num_Entries(fedges); e0 = List_Entry(fedges,0); ecur = e0; enxt = List_Entry(fedges,nfe-1); List_Delete(fedges); done = 0; i = 0; while (!done) { ecur = enxt; efaces = ME_Faces(ecur); found = 0; idx3 = 0; while ((ef = List_Next_Entry(efaces,&idx3))) { if (ef != fcur && MF_GEntDim(ef) == 2 && MF_GEntID(ef) == gvid) { fcur = ef; found = 1; break; } } List_Delete(efaces); if (!found) { sprintf(mesg,"Could not find next boundary face connected to vertex %-d",vid); MSTK_Report(funcname,mesg,MSTK_WARN); valid = 0; break; } fedges = MF_Edges(fcur,1,mv); nfe = List_Num_Entries(fedges); if (List_Entry(fedges,0) == ecur) enxt = List_Entry(fedges,nfe-1); else if (List_Entry(fedges,nfe-1) == ecur) { enxt = List_Entry(fedges,0); flipped = 1; } else { sprintf(mesg,"Could not find next edge while traversing around vertex %-d on model face %-d",vid,gvid); MSTK_Report(funcname,mesg,MSTK_ERROR); } List_Delete(fedges); if (enxt == e0) done = 1; if (++i > maxiter) break; } if (!done) { sprintf(mesg,"Vertex %-d classified on model face %-d but could not find ring of faces classified on this model face",vid,gvid); MSTK_Report(funcname,mesg,MSTK_WARN); } if (done && flipped) { List_ptr fregs = MF_Regions(fcur); if (List_Num_Entries(fregs) < 2) { sprintf(mesg,"Inconsistent orientations of boundary faces around vertex %-d",vid); MSTK_Report(funcname,mesg,MSTK_WARN); } if (fregs) List_Delete(fregs); } } } /* while ((mv = MESH_Next_Vertex(mesh,&idx1))) */ /*****************************************************************/ /* Edges */ /*****************************************************************/ first_unknown_classfn = 1; idx1 = 0; while ((me = MESH_Next_Edge(mesh,&idx1))) { #ifdef MSTK_HAVE_MPI if (ME_PType(me) == PGHOST) continue; #endif eid = ME_ID(me); gedim = ME_GEntDim(me); geid = ME_GEntID(me); if (gedim == 4 && first_unknown_classfn) { sprintf(mesg, "Edge %-d - unknown classification", eid); MSTK_Report(funcname, mesg, MSTK_WARN); first_unknown_classfn = 0; } if (ME_Vertex(me,0) == ME_Vertex(me,1)) { sprintf(mesg,"Edge %-d has repeated vertices",eid); MSTK_Report(funcname,mesg,MSTK_ERROR); } for (i = 0; i < 2; i++) { MVertex_ptr ev = ME_Vertex(me,i); vid = MV_ID(ev); gvid = MV_GEntID(ev); gvdim = MV_GEntDim(ev); if (gvdim != 4 && gvdim != 4) { /* vertex and edge classifn is known */ if (gedim < gvdim) { sprintf(mesg,"Edge %-d classified on lower dimensional entity than connected vertex %-d",eid,vid); MSTK_Report(funcname,mesg,MSTK_WARN); valid = 0; } else if (gedim == gvdim && geid != gvid) { sprintf(mesg,"Edge %-d and its vertex %-d classified on different entities of the same dimension",eid,vid); MSTK_Report(funcname,mesg,MSTK_WARN); valid = 0; } } vedges = MV_Edges(ev); if (!List_Contains(vedges,me)) { sprintf(mesg,"Edge %-d sees vertex %-d but not vice versa",eid,vid); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } List_Delete(vedges); if (gedim == 2) { MFace_ptr ebf[2], fcur, fnxt; MRegion_ptr rcur; int nf, nfr; List_ptr eregs; /* Edge is classified on model face - it should be connected to two and only two faces also classified on this model face */ ebf[0] = ebf[1] = NULL; nf = 0; efaces = ME_Faces(me); idx2 = 0; while ((ef = List_Next_Entry(efaces,&idx2))) { fid = MF_ID(ef); if (MF_GEntDim(ef) == 2) { nf++; if (gedim == 2 && MF_GEntID(ef) != geid) { sprintf(mesg,"Face %-d connected to edge %-d classified on different model face",fid,eid); MSTK_Report(funcname,mesg,MSTK_WARN); valid = 0; } if (ebf[0] == NULL) ebf[0] = ef; else ebf[1] = ef; } } List_Delete(efaces); if (nf != 2) { sprintf(mesg,"Boundary edge %-d is not connected to exactly two\n faces classified on the boundary",eid); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } eregs = ME_Regions(me); if (!eregs) continue; else List_Delete(eregs); /* Can we go from f0 to f1 in one or two dirs? */ fcur = ebf[0]; fnxt = NULL; fregs = MF_Regions(fcur); if (!fregs) { fid = MF_ID(fcur); sprintf(mesg,"Edge %-d connected to regions but face %-d is not",eid,fid); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } nfr = List_Num_Entries(fregs); for (i = 0; i < nfr; i++) { rcur = List_Entry(fregs,i); rfaces = MR_Faces(rcur); idx3 = 0; found = 0; while ((rf = List_Next_Entry(rfaces,&idx3))) { if (rf != fcur && MF_UsesEntity(rf,me,1)) { found = 1; fnxt = rf; break; } } List_Delete(rfaces); if (!found) { rid = MR_ID(rcur); sprintf(mesg,"Could not find second face in region %-d using edge %-d",rid,eid); } done = 0; j = 0; while (!done) { fcur = fnxt; fid = MF_ID(fcur); if (fnxt == ebf[1]) { done = 1; break; } fregs1 = MF_Regions(fcur); idx3 = 0; while ((fr = List_Next_Entry(fregs1,&idx3))) { if (fr != rcur) { rcur = fr; found = 1; break; } } List_Delete(fregs1); if (!found) { sprintf(mesg,"Could not find next region around edge %-d",eid); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; break; } rfaces = MR_Faces(rcur); idx3 = 0; found = 0; while ((rf = List_Next_Entry(rfaces,&idx3))) { if (rf != fcur && MF_UsesEntity(rf,me,1)) { found = 1; fnxt = rf; break; } } List_Delete(rfaces); if (!found) { rid = MR_ID(rcur); sprintf(mesg,"Could not find second face in region %-d using edge %-d",rid,eid); } if (++j > maxiter) break; } /* while (!done) */ if (!done) { sprintf(mesg,"Could not traverse around edge %-d from face %-d to face %-d",eid,MF_ID(ebf[0]),MF_ID(ebf[1])); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } } /* for (i = 0; i < nfr; i++) */ List_Delete(fregs); } /* if (geid == 2) */ } /* for (i = 0; i < 2; i++) */ } /* while ((me = MESH_Next_Edge(mesh,&idx1))) */ /*****************************************************************/ /* Faces */ /*****************************************************************/ first_unknown_classfn = 1; idx1 = 0; while ((mf = MESH_Next_Face(mesh,&idx1))) { #ifdef MSTK_HAVE_MPI if (MF_PType(mf) == PGHOST) continue; #endif fid = MF_ID(mf); gfid = MF_GEntID(mf); gfdim = MF_GEntDim(mf); if (gfdim == 4 && first_unknown_classfn) { sprintf(mesg, "Face %-d - unknown classification", fid); MSTK_Report(funcname, mesg, MSTK_WARN); first_unknown_classfn = 0; } fedges = MF_Edges(mf,1,0); if (List_Num_Entries(fedges) < 3) { sprintf(mesg,"Face %-d has less than 3 edges",fid); MSTK_Report(funcname,mesg,MSTK_ERROR); } idx2 = 0; while ((fe = List_Next_Entry(fedges,&idx2))) { eid = ME_ID(fe); geid = ME_GEntID(fe); gedim = ME_GEntDim(fe); if (gedim != 4 && gfdim != 4) { /* Edge, Face classfn is known */ if (gfdim < gedim) { sprintf(mesg,"Face %-d classified on lower order entity than edge %-d",fid,ME_ID(fe)); MSTK_Report(funcname,mesg,MSTK_WARN); valid = 0; } else if (gedim == gfdim && geid != gfid) { sprintf(mesg,"Face %-d and edge %-d classified on different\n entities of the same dimension",fid,eid); MSTK_Report(funcname,mesg,MSTK_WARN); } } efaces = ME_Faces(fe); if (!List_Contains(efaces,mf)) { sprintf(mesg,"Face %-d refers to edge %-d but not vice versa",fid,ME_ID(fe)); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } List_Delete(efaces); } List_Delete(fedges); fregs = MF_Regions(mf); if (gfdim == 3) { if (!fregs || List_Num_Entries(fregs) != 2) { sprintf(mesg,"Interior face %-d does not have two connected regions",fid); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } } if (fregs) { if (List_Num_Entries(fregs) == 2) { if (MR_FaceDir(List_Entry(fregs,0),mf) == MR_FaceDir(List_Entry(fregs,1),mf)) { sprintf(mesg,"Both regions using face %-d in the same sense",fid); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } } List_Delete(fregs); } } /* while ((mf = MESH_Next_Face(mesh,&idx1))) */ /*****************************************************************/ /* Regions */ /*****************************************************************/ idx1 = 0; while ((mr = MESH_Next_Region(mesh,&idx1))) { #ifdef MSTK_HAVE_MPI if (MR_PType(mr) == PGHOST) continue; #endif rid = MR_ID(mr); grid = MR_GEntID(mr); rfaces = MR_Faces(mr); int nrf = List_Num_Entries(rfaces); if (nrf < 4) { sprintf(mesg,"Region %-d has less than 4 faces",rid); MSTK_Report(funcname,mesg,MSTK_ERROR); } /* Check that face to region and region to face links are consistent with each other */ int *rfdirs = (int *) malloc(nrf*sizeof(int)); i = 0; idx2 = 0; while ((rf = List_Next_Entry(rfaces,&idx2))) { rfdirs[i] = MR_FaceDir_i(mr,i); if (mr != MF_Region(rf,!rfdirs[i])) { sprintf(mesg,"Region %-d to face %-d dir inconsistent with \n face to region dir",rid,MF_ID(rf)); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } i++; } /* Check that faces of a region have consistent orientation in the region with respect to each other */ for (i = 0; i < nrf; i++) { MFace_ptr rf, rf2; rf = List_Entry(rfaces,i); fedges = MF_Edges(rf,1,0); nfe = List_Num_Entries(fedges); for (j = 0; j < nfe; j++) { fe = List_Entry(fedges,j); int fedir = MF_EdgeDir_i(rf,j); /* Find adjacent face in the region */ found = 0; for (k = 0; k < nrf; k++) { rf2 = List_Entry(rfaces,k); if (rf != rf2 && MF_UsesEntity(rf2,fe,MEDGE)) { found = 1; break; } } if (!found) { sprintf(mesg,"Cannot find another face in region %-d sharing edge %-d (ID = %-d) of face with ID = %-d",MR_ID(mr),j,ME_ID(fe),MF_ID(rf)); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } int fedir_adj = MF_EdgeDir(rf2,fe); /* If the two faces use the edge in opposite directions then the region should use the faces in the same direction and vice versa */ if (((fedir_adj == fedir) && (rfdirs[i] == rfdirs[k])) || ((fedir_adj != fedir) && (rfdirs[i] != rfdirs[k]))) { sprintf(mesg,"Region %-d faces are inconsistently oriented",MR_ID(mr)); MSTK_Report(funcname,mesg,MSTK_ERROR); valid = 0; } } List_Delete(fedges); } List_Delete(rfaces); free(rfdirs); } return valid; } /* int MESH_CheckTopo */
MVertex_ptr ME_Split_SimplexMesh(MEdge_ptr esplit, double *splitxyz) { int i, j, k, rfdir, ntets=0, ntris=0, *fdim, *fid, *rid=NULL, found; MVertex_ptr vsplit, ev[2], (*tetverts)[4]=NULL, (*triverts)[3]=NULL, fv; MVertex_ptr fvarr[3], rvarr[4]; MFace_ptr f; MRegion_ptr r; List_ptr etets, rfaces, etris, fverts; Mesh_ptr mesh = ME_Mesh(esplit); ev[0] = ME_Vertex(esplit,0); ev[1] = ME_Vertex(esplit,1); etets = ME_Regions(esplit); if (etets) { ntets = List_Num_Entries(etets); tetverts = (MVertex_ptr (*)[4]) malloc(ntets*sizeof(MVertex_ptr [4])); rid = (int *) malloc(ntets*sizeof(int)); } for (i = 0; i < ntets; i++) { r = List_Entry(etets,i); rfaces = MR_Faces(r); /* Find a tet face that uses ev[0] but not ev[1] */ found = 0; for (j = 0; !found && j < 4; j++) { f = List_Entry(rfaces,j); fverts = MF_Vertices(f,1,0); if (List_Contains(fverts,ev[0]) && !List_Contains(fverts,ev[1])) { found = 1; /* Get the two vertices (a,b) of this face excluding ev[0] in such an order that ev[0],a,b,ev[1] will form a valid tet. This requires checking whether the face points into or out of this tet (look at rfdir) */ rfdir = MR_FaceDir_i(r,j); for (k = 0; k < 3; k++) { fv = List_Entry(fverts,k); if (fv == ev[0]) { tetverts[i][0] = ev[0]; tetverts[i][1] = rfdir ? List_Entry(fverts,(k+2)%3) : List_Entry(fverts,(k+1)%3); tetverts[i][2] = rfdir ? List_Entry(fverts,(k+1)%3) : List_Entry(fverts,(k+2)%3); tetverts[i][3] = ev[1]; } } } List_Delete(fverts); if (found) break; } List_Delete(rfaces); } /* Now that we finished collecting info about the connected tets we can delete them */ if (etets) { for (i = 0; i < ntets; i++) MR_Delete(List_Entry(etets,i),0); List_Delete(etets); } /* Now get the triangular face connected to the edge. For each triangular face, record the vertex opposite to edge esplit and delete the triangular face */ etris = ME_Faces(esplit); if (etris) { ntris = List_Num_Entries(etris); triverts = (MVertex_ptr (*)[3]) malloc(ntris*sizeof(MVertex_ptr[3])); fdim = (int *) malloc(ntris*sizeof(int)); fid = (int *) malloc(ntris*sizeof(int)); } for (i = 0; i < ntris; i++) { f = List_Entry(etris,i); fverts = MF_Vertices(f,1,0); for (j = 0; j < 3; j++) { fv = List_Entry(fverts,j); if (fv != ev[0] && fv != ev[1]) { triverts[i][0] = fv; triverts[i][1] = List_Entry(fverts,(j+1)%3); triverts[i][2] = List_Entry(fverts,(j+2)%3); fdim[i] = MF_GEntDim(f); fid[i] = MF_GEntID(f); break; } } List_Delete(fverts); MF_Delete(f,0); } if (etris) List_Delete(etris); /* Now split the edge itself */ vsplit = ME_Split(esplit, splitxyz); /* Now for each tri face that we deleted, create two tri faces that incorporate the split vertex, one of the split edge vertices and opposite vertex */ for (i = 0; i < ntris; i++) { /* First triangle */ fvarr[0] = triverts[i][0]; fvarr[1] = triverts[i][1]; fvarr[2] = vsplit; f = MF_New(mesh); MF_Set_Vertices(f,3,fvarr); MF_Set_GEntDim(f,fdim[i]); MF_Set_GEntID(f,fid[i]); /* Second triangle */ fvarr[0] = triverts[i][0]; fvarr[1] = vsplit; fvarr[2] = triverts[i][2]; f = MF_New(mesh); MF_Set_Vertices(f,3,fvarr); MF_Set_GEntDim(f,fdim[i]); MF_Set_GEntID(f,fid[i]); } if (ntris) { free(triverts); free(fdim); free(fid); } /* Now for each tet that we deleted, create two tets (these will use the split faces that are already created */ for (i = 0; i < ntets; i++) { rvarr[0] = vsplit; rvarr[1] = tetverts[i][2]; rvarr[2] = tetverts[i][1]; rvarr[3] = tetverts[i][0]; r = MR_New(mesh); MR_Set_Vertices(r,4,rvarr,0,NULL); MR_Set_GEntID(r,rid[i]); rvarr[0] = vsplit; rvarr[1] = tetverts[i][1]; rvarr[2] = tetverts[i][2]; rvarr[3] = tetverts[i][3]; r = MR_New(mesh); MR_Set_Vertices(r,4,rvarr,0,NULL); MR_Set_GEntID(r,rid[i]); } if (ntets) { free(tetverts); free(rid); } return vsplit; }
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; }
MVertex_ptr MF_Split(MFace_ptr fsplit, double *splitxyz) { Mesh_ptr mesh; MVertex_ptr vsplit, fv[3]; MEdge_ptr enew, *fedges0, *fedges1, fe; MFace_ptr fnew[MAXPV2]; MRegion_ptr fr; int gid, gdim, i, j, idx, nnew; int nfv, fnewdir[MAXPV2], rfdir; List_ptr fregs, fverts; gdim = MF_GEntDim(fsplit); gid = MF_GEntID(fsplit); /* Collect information */ mesh = MF_Mesh(fsplit); /* Regions connected to face */ fregs = MF_Regions(fsplit); /* Vertices of face */ fverts = MF_Vertices(fsplit,1,0); nfv = List_Num_Entries(fverts); /* Create the splitting vertex */ vsplit = MV_New(mesh); MV_Set_Coords(vsplit,splitxyz); MV_Set_GEntDim(vsplit,gdim); MV_Set_GEntID(vsplit,gid); /* Create the 'nfe' faces */ for (i = 0; i < nfv; i++) { fv[0] = vsplit; fv[1] = List_Entry(fverts,i); fv[2] = List_Entry(fverts,(i+1)%nfv); fnew[i] = MF_New(mesh); MF_Set_GEntDim(fnew[i],gdim); MF_Set_GEntID(fnew[i],gid); MF_Set_Vertices(fnew[i],3,fv); } List_Delete(fverts); nnew = nfv; if (fregs) { for (i = 0; i < List_Num_Entries(fregs); i++) { fr = List_Entry(fregs,i); rfdir = MR_FaceDir(fr,fsplit); for (j = 0; j < nnew; j++) fnewdir[j] = rfdir; MR_Replace_Faces(fr,1,&fsplit,nnew,fnew,fnewdir); } List_Delete(fregs); } MF_Delete(fsplit,0); return vsplit; }
MRegion_ptr MRs_Join(MRegion_ptr r1, MRegion_ptr r2, MFace_ptr f) { int i, j, nrf1, nrf2, gdim, gid, *rfdir2; MFace_ptr *rf2, fcmn=f; Mesh_ptr mesh; List_ptr rfaces2; mesh = MF_Mesh(r1); gid = MF_GEntID(r1); if (mesh != MF_Mesh(r2)) { MSTK_Report("MRs_Join","Regions not from same mesh",MSTK_ERROR); return 0; } else if (gid != MR_GEntID(r2)) { MSTK_Report("MRs_Join","Regions not from same geometric entity",MSTK_ERROR); return 0; } rfaces2 = MR_Faces(r2); nrf2 = List_Num_Entries(rfaces2); if (fcmn) { if (!MR_UsesEntity(r1,fcmn,MFACE)) { MSTK_Report("MRs_Join","Cannot find common face in region",MSTK_ERROR); return 0; } } else { /* find the common face */ List_ptr rfaces1 = MR_Faces(r1); int idx = 0; MFace_ptr rf; while ((rf = List_Next_Entry(rfaces2,&idx))) { if (List_Contains(rfaces1,rf)) { fcmn = rf; break; } } List_Delete(rfaces1); } rf2 = (MFace_ptr) malloc(nrf2*sizeof(MFace_ptr)); rfdir2 = (int *) malloc(nrf2*sizeof(int)); int found; for (i = 0, j = 0, found = 0; i < nrf2; i++) { MFace_ptr rface = List_Entry(rfaces2,i); if (rface == fcmn) found = 1; else { rf2[j] = rface; rfdir2[j] = MR_FaceDir_i(r2,i); j++; } } List_Delete(rfaces2); if (!found) { MSTK_Report("MRs_Join","Cannot find common face in region",MSTK_ERROR); return 0; } MR_Delete(r2,0); MR_Replace_Faces(r1,1,&fcmn,nrf2-1,rf2,rfdir2); MF_Delete(fcmn,0); free(rf2); free(rfdir2); return r1; }
MVertex_ptr MF_Split_SimplexMesh(MFace_ptr fsplit, double *splitxyz) { int i, j, k, rfdir=1, ntets=0, ntris=0, *rid=NULL, fgdim, fgid, found; MVertex_ptr vsplit, ev[2], (*tetverts)[4]=NULL, triverts[3], fv; MVertex_ptr fvarr[3], rvarr[4]; MFace_ptr f; MRegion_ptr r; List_ptr fedges, ftets, rfaces, fverts; Mesh_ptr mesh = MF_Mesh(fsplit); /* point is not on the boundary of the face */ ftets = MF_Regions(fsplit); if (ftets) { ntets = List_Num_Entries(ftets); tetverts = (MVertex_ptr (*)[4]) malloc(ntets*sizeof(MVertex_ptr [4])); rid = (int *) malloc(ntets*sizeof(int)); } for (i = 0; i < ntets; i++) { r = List_Entry(ftets,i); rfaces = MR_Faces(r); /* Find the face to be split and get the first three vertices in a suitable order from it. Also, find another face and get a vertex that is not in the face to be split. This vertex forms the fourth vertex of the tet */ for (j = 0; j < 4; j++) { f = List_Entry(rfaces,j); if (f == fsplit) { rfdir = MR_FaceDir_i(r,j); fverts = MF_Vertices(f,!rfdir,0); for (k = 0; k < 3; k++) { tetverts[i][0] = List_Entry(fverts,0); tetverts[i][1] = List_Entry(fverts,1); tetverts[i][2] = List_Entry(fverts,2); } List_Delete(fverts); break; } } found = 0; for (j = 0; j < 4; j++) { f = List_Entry(rfaces,j); if (f != fsplit) { fverts = MF_Vertices(f,!rfdir,0); for (k = 0; k < 3; k++) { fv = List_Entry(fverts,k); if (!MF_UsesEntity(fsplit,fv,MVERTEX)) { tetverts[i][3] = fv; found = 1; break; } } List_Delete(fverts); } if (found) break; } List_Delete(rfaces); } /* Now that we finished collecting info about the connected tets we can delete them */ if (ftets) { for (i = 0; i < ntets; i++) MR_Delete(List_Entry(ftets,i),0); List_Delete(ftets); } /* Delete the face itself */ fverts = MF_Vertices(fsplit,1,0); for (i = 0; i < 3; i++) triverts[i] = List_Entry(fverts,i); List_Delete(fverts); fgdim = MF_GEntDim(fsplit); fgid = MF_GEntID(fsplit); /* Split the face */ vsplit = MF_Split(fsplit, splitxyz); /* Create three tets for each tet that was deleted */ for (i = 0; i < ntets; i++) { for (j = 0; j < 3; j++) { r = MR_New(mesh); rvarr[0] = vsplit; rvarr[1] = tetverts[i][j]; rvarr[2] = tetverts[i][(j+1)%3]; rvarr[3] = tetverts[i][3]; MR_Set_Vertices(r, 4, rvarr, 0, NULL); MR_Set_GEntID(r,rid[i]); } } if (ntets) { free(tetverts); free(rid); } return vsplit; }
int MESH_Send_NonVertexEntities_FN(Mesh_ptr mesh, int torank, MSTK_Comm comm, int *numreq, int *maxreq, MPI_Request **requests, int *numptrs2free, int *maxptrs2free, void ***ptrs2free) { int i, j, nv, ne, nf, nr; int nevs, nfes, nrfs, nfe, nrv, nrf, dir; int maxnfe, maxnrf; int *mesh_info; int *list_edge=NULL, *list_face=NULL, *list_region=NULL; MVertex_ptr mv; MEdge_ptr me; MFace_ptr mf; MRegion_ptr mr; List_ptr mfedges, mrfaces, mrverts; RepType rtype; double coor[3]; MPI_Request mpirequest; if (requests == NULL) MSTK_Report("MESH_Surf_SendMesh","MPI requests array is NULL",MSTK_FATAL); if (*maxreq == 0) { *maxreq = 25; *requests = (MPI_Request *) malloc(*maxreq*sizeof(MPI_Request)); *numreq = 0; } else if (*maxreq < (*numreq) + 13) { *maxreq = 2*(*maxreq) + 11; *requests = (MPI_Request *) realloc(*requests,*maxreq*sizeof(MPI_Request)); } ne = MESH_Num_Edges(mesh); nf = MESH_Num_Faces(mesh); nr = MESH_Num_Regions(mesh); /* some other known quantitites - 5 items per edge (2 for verts and 3 for extra data), maxnfe+4 items per face (1 for number of edges, maxnfe for edge indices, anad 3 for extra data), maxnrf+4 items per region (1 for number of faces, maxnrf for face indices and 3 for extra data */ maxnfe = 0; for (i = 0; i < nf; i++) { mf = MESH_Face(mesh,i); nfe = MF_Num_Edges(mf); if (nfe > maxnfe) maxnfe = nfe; } maxnrf = 0; for (i = 0; i < nr; i++) { mr = MESH_Region(mesh,i); nrf = MR_Num_Faces(mr); if (nrf > maxnrf) maxnrf = nrf; } // The amount of extra info we are sending and their meaning is obviously // known on the receiving side too. So nevs, nfes and nrfs can be // calculated without us sending it nevs = (2+3)*ne; nfes = (1 + maxnfe + 3)*nf; nrfs = (1 + maxnrf + 3)*nr; /* Reserve nevs spots for each edge */ list_edge = (int *) malloc(5*ne*sizeof(int)); nevs = 0; /* Store the vertex ids, then the 3 auxilliary data fields */ for(i = 0; i < ne; i++) { me = MESH_Edge(mesh,i); list_edge[nevs] = MV_ID(ME_Vertex(me,0)); list_edge[nevs+1] = MV_ID(ME_Vertex(me,1)); list_edge[nevs+2] = (ME_GEntID(me)<<3) | (ME_GEntDim(me)); list_edge[nevs+3] = (ME_MasterParID(me) <<3) | (ME_OnParBoundary(me)<<2) | (ME_PType(me)); list_edge[nevs+4] = ME_GlobalID(me); nevs += 5; } /* send detailed edge info */ MPI_Isend(list_edge,nevs,MPI_INT,torank,torank,comm,&mpirequest); (*requests)[*numreq] = mpirequest; (*numreq)++; /* Reserve nfes spots for each face */ list_face = (int *) malloc(nfes*sizeof(int)); nfes = 0; /* first store nfe, then the edge ids, then the 3 auxilliary data fields */ for(i = 0; i < nf; i++) { mf = MESH_Face(mesh,i); mfedges = MF_Edges(mf,1,0); nfe = List_Num_Entries(mfedges); list_face[nfes] = nfe; for(j = 0; j < nfe; j++) { dir = MF_EdgeDir_i(mf,j) ? 1 : -1; list_face[nfes+j+1] = dir*ME_ID(List_Entry(mfedges,j)); } list_face[nfes+nfe+1] = (MF_GEntID(mf)<<3) | (MF_GEntDim(mf)); list_face[nfes+nfe+2] = (MF_MasterParID(mf)<<3) | (MF_OnParBoundary(mf)<<2) | (MF_PType(mf)); list_face[nfes+nfe+3] = MF_GlobalID(mf); nfes += (nfe + 4); List_Delete(mfedges); } /* send detailed face info */ MPI_Isend(list_face,nfes,MPI_INT,torank,torank,comm,&mpirequest); (*requests)[*numreq] = mpirequest; (*numreq)++; if (nr) { list_region = (int *) malloc(nrfs*sizeof(int)); nrfs = 0; /* first store nrf, then the face ids, then the 3 auxilliary data fields */ for(i = 0; i < nr; i++) { mr = MESH_Region(mesh,i); mrfaces = MR_Faces(mr); nrf = List_Num_Entries(mrfaces); list_region[nrfs] = nrf; for(j = 0; j < nrf; j++) { dir = MR_FaceDir_i(mr,j) == 1 ? 1 : -1; list_region[nrfs+j+1] = dir*MF_ID(List_Entry(mrfaces,j)); } list_region[nrfs+nrf+1] = (MR_GEntID(mr)<<3) | (MR_GEntDim(mr)); list_region[nrfs+nrf+2] = (MR_MasterParID(mr)<<3) | (MR_PType(mr)); /* MR_PType is 2 bits; 3 bit is 0 */ list_region[nrfs+nrf+3] = MR_GlobalID(mr); nrfs += (nrf + 4); List_Delete(mrfaces); } /* send detailed region info */ MPI_Isend(list_region,nrfs,MPI_INT,torank,torank,comm,&mpirequest); (*requests)[*numreq] = mpirequest; (*numreq)++; } /* collect allocated memory so it can be freed in a higher level routine after MPI_Waitall or MPI_Test has ensured that the send has been completed */ if (ptrs2free == NULL) MSTK_Report("MESH_Surf_SendMesh_FN","ptrs2free array is NULL",MSTK_FATAL); int nptrs = 3; if (*maxptrs2free == 0) { *maxptrs2free = 25; *ptrs2free = (void **) malloc(*maxptrs2free*sizeof(void *)); *numptrs2free = 0; } else if (*maxptrs2free < (*numptrs2free) + nptrs) { *maxptrs2free = 2*(*maxptrs2free) + nptrs; *ptrs2free = (void **) realloc(*ptrs2free,(*maxptrs2free)*sizeof(void *)); } if (ne) (*ptrs2free)[(*numptrs2free)++] = list_edge; if (nf) (*ptrs2free)[(*numptrs2free)++] = list_face; if (nr) (*ptrs2free)[(*numptrs2free)++] = list_region; return 1; }