int MESH_Renumber_EntityGlobalIDs(Mesh_ptr mesh, MType mtype, int method, int *preassigned_gids, MSTK_Comm comm) { int i; if (method != 0) { MSTK_Report("MESH_Renumber_EntityGlobalIDs", "Chosen renumbering scheme not implemented", MSTK_ERROR); return 0; } if (mtype == MALLTYPE) { MSTK_Report("MESH_Renumber_EntityGlobalIDs", "Cannot call this routine for MALLTYPE", MSTK_ERROR); return 0; } MAttrib_ptr tmpatt = MAttrib_New(mesh, "tmpatt_renumber", INT, mtype); int nproc, rank; MPI_Comm_size(comm, &nproc); MPI_Comm_rank(comm, &rank); int idx = 0, nowned = 0; MEntity_ptr ment; switch (mtype) { case MVERTEX: while ((ment = MESH_Next_Vertex(mesh, &idx))) if (MV_PType(ment) != PGHOST) nowned++; break; case MEDGE: while ((ment = MESH_Next_Edge(mesh, &idx))) if (ME_PType(ment) != PGHOST) nowned++; break; case MFACE: while ((ment = MESH_Next_Face(mesh, &idx))) if (MF_PType(ment) != PGHOST) nowned++; break; case MREGION: while ((ment = MESH_Next_Region(mesh, &idx))) if (MR_PType(ment) != PGHOST) nowned++; break; default: {} } /* Gather the number of entities on every processor */ int *nowned_all = NULL; if (rank == 0) nowned_all = (int *) calloc(nproc, sizeof(int)); MPI_Gather(&nowned, 1, MPI_INT, nowned_all, 1, MPI_INT, 0, comm); int *offset_all = NULL; if (rank == 0) { offset_all = (int *) malloc(nproc*sizeof(int)); offset_all[0] = 0; int p; for (p = 1; p < nproc; p++) offset_all[p] = offset_all[p-1] + nowned_all[p-1]; } int offset = 0; MPI_Scatter(offset_all, 1, MPI_INT, &offset, 1, MPI_INT, 0, comm); /* At this point if we had different methods for renumbering the * global set of entities, we would generate a Global ID map. For * now this is just a sequential map (method 0) */ int *new_index = (int *) malloc(nowned*sizeof(int)); if (method == 0) { for (i = 0; i < nowned; i++) new_index[i] = i+1; } /* Now assign global IDs to the entities */ int new_gid; idx = 0; i = 0; switch (mtype) { case MVERTEX: while ((ment = MESH_Next_Vertex(mesh, &idx))) if (MV_PType(ment) != PGHOST) { new_gid = offset + new_index[i]; MEnt_Set_AttVal(ment, tmpatt, new_gid, 0.0, NULL); i++; } break; case MEDGE: while ((ment = MESH_Next_Edge(mesh, &idx))) if (ME_PType(ment) != PGHOST) { new_gid = offset + new_index[i]; MEnt_Set_AttVal(ment, tmpatt, new_gid, 0.0, NULL); i++; } break; case MFACE: while ((ment = MESH_Next_Face(mesh, &idx))) if (MF_PType(ment) != PGHOST) { new_gid = offset + new_index[i]; MEnt_Set_AttVal(ment, tmpatt, new_gid, 0.0, NULL); i++; } break; case MREGION: while ((ment = MESH_Next_Region(mesh, &idx))) if (MR_PType(ment) != PGHOST) { new_gid = offset + new_index[i]; MEnt_Set_AttVal(ment, tmpatt, new_gid, 0.0, NULL); i++; } break; default: {} } /* Now exchange the attribute across processors */ MESH_Update1Attribute(mesh, tmpatt, comm); /* Now assign global IDs of the entities based on the values of * the gidatt attribute */ idx = 0; double rval; void *pval; switch (mtype) { case MVERTEX: while ((ment = MESH_Next_Vertex(mesh, &idx))) { MEnt_Get_AttVal(ment, tmpatt, &new_gid, &rval, &pval); MV_Set_GlobalID(ment, new_gid); } break; case MEDGE: while ((ment = MESH_Next_Edge(mesh, &idx))) { MEnt_Get_AttVal(ment, tmpatt, &new_gid, &rval, &pval); ME_Set_GlobalID(ment, new_gid); } break; case MFACE: while ((ment = MESH_Next_Face(mesh, &idx))) { MEnt_Get_AttVal(ment, tmpatt, &new_gid, &rval, &pval); MF_Set_GlobalID(ment, new_gid); } break; case MREGION: while ((ment = MESH_Next_Region(mesh, &idx))) { MEnt_Get_AttVal(ment, tmpatt, &new_gid, &rval, &pval); MR_Set_GlobalID(ment, new_gid); } break; default: {} } free(nowned_all); free(offset_all); MAttrib_Delete(tmpatt); return 1; }
int 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 */
int MESH_AssignGlobalIDs_Region(Mesh_ptr submesh, MSTK_Comm comm) { int i, j, k, nfv, nbf, nof, ngf, nf, nr, mesh_info[10], global_id; MVertex_ptr mv; MFace_ptr mf; MRegion_ptr mr; List_ptr boundary_faces, mfverts; int *loc, face_id[MAXPV2+3],index_nbf, max_nbf, iloc, is_boundary; int *global_mesh_info, *list_face, *recv_list_face, *face_ov_label, *id_on_ov_list; int rank, num; MPI_Comm_rank(comm,&rank); MPI_Comm_size(comm,&num); for (i = 0; i < 10; i++) mesh_info[i] = 0; nf = MESH_Num_Faces(submesh); nr = MESH_Num_Regions(submesh); mesh_info[3] = nf; mesh_info[4] = nr; /* collect 'boundary' faces if endpoints are either GHOST or OVERLAP, then it is a boundary face */ nbf = 0; boundary_faces = List_New(10); for(i = 0; i < nf; i++) { is_boundary = 1; mf = MESH_Face(submesh,i); mfverts = MF_Vertices(mf,1,0); nfv = List_Num_Entries(mfverts); for(j = 0; j < nfv; j++) { mv = List_Entry(mfverts,j); if(MV_PType(mv)!=PGHOST && MV_PType(mv)!=POVERLAP) is_boundary = 0; } if(is_boundary) { MF_Flag_OnParBoundary(mf); List_Add(boundary_faces,mf); nbf++; } List_Delete(mfverts); } /* printf("num of boundary faces %d, on rank %d\n", nbf,rank); */ mesh_info[6] = nbf; List_Sort(boundary_faces,nbf,sizeof(MFace_ptr),compareFaceID); global_mesh_info = (int *)malloc(10*num*sizeof(int)); MPI_Allgather(mesh_info,10,MPI_INT,global_mesh_info,10,MPI_INT,comm); max_nbf = 0; for(i = 0; i < num; i++) if(max_nbf < global_mesh_info[10*i+6]) max_nbf = global_mesh_info[10*i+6]; list_face = (int *)malloc(max_nbf*(MAXPV2+1)*sizeof(int)); recv_list_face = (int *)malloc(num*max_nbf*(MAXPV2+1)*sizeof(int)); /* indicate if a face is overlapped */ face_ov_label = (int *)malloc(num*max_nbf*sizeof(int)); for (i = 0; i < num*max_nbf; i++) face_ov_label[i] = 0; id_on_ov_list = (int *)malloc(max_nbf*sizeof(int)); /* pack face information to send */ index_nbf = 0; for(i = 0; i < nbf; i++) { mf = List_Entry(boundary_faces,i); mfverts = MF_Vertices(mf,1,0); nfv = List_Num_Entries(mfverts); list_face[index_nbf] = nfv; for(j = 0; j < nfv; j++) list_face[index_nbf+j+1] = MV_GlobalID(List_Entry(mfverts,j)); index_nbf += MAXPV2+1; List_Delete(mfverts); } MPI_Allgather(list_face,(MAXPV2+1)*max_nbf,MPI_INT,recv_list_face,(MAXPV2+1)*max_nbf,MPI_INT,comm); ngf = 0; /* for processor other than 0 */ if(rank > 0) { for(i = 0; i < nbf; i++) { mf = List_Entry(boundary_faces,i); if(MF_GlobalID(mf) > 0) continue; /* if already assigned */ mfverts = MF_Vertices(mf,1,0); nfv = List_Num_Entries(mfverts); face_id[0] = nfv; for(k = 0; k < nfv; k++) face_id[k+1] = MV_GlobalID(List_Entry(mfverts,k)); List_Delete(mfverts); for(j = 0; j < rank; j++) { loc = (int *)bsearch(&face_id, &recv_list_face[(MAXPV2+1)*max_nbf*j], global_mesh_info[10*j+6], (MAXPV2+1)*sizeof(int), compareFaceINT); if(loc) { iloc = (int)(loc - &recv_list_face[(MAXPV2+1)*max_nbf*j])/(MAXPV2+1); MF_Set_PType(mf,PGHOST); MF_Set_MasterParID(mf,j); face_ov_label[max_nbf*j+iloc] |= 1; id_on_ov_list[i] = iloc; ngf++; break; } } } } /* num of ghost verts */ mesh_info[9] = ngf; MPI_Allgather(mesh_info,10,MPI_INT,global_mesh_info,10,MPI_INT,comm); /* since this is a OR reduction, we can use MPI_IN_PLACE, send buffer same as recv buffer */ MPI_Allreduce(MPI_IN_PLACE,face_ov_label,num*max_nbf,MPI_INT,MPI_LOR,comm); /* Assign global ID for non ghost face */ global_id = 1; for(i = 0; i < rank; i++) global_id = global_id + global_mesh_info[10*i+3] - global_mesh_info[10*i+9]; for(i = 0; i < nf; i++) { mf = MESH_Face(submesh,i); if (MF_PType(mf) == PGHOST) continue; if (!MF_GlobalID(mf)) MF_Set_GlobalID(mf,global_id++); MF_Set_MasterParID(mf,rank); } /* label OVERLAP face */ nof = 0; for(i = 0; i < nbf; i++) if(face_ov_label[rank*max_nbf+i]) { mf = List_Entry(boundary_faces,i); MF_Set_PType(mf,POVERLAP); nof++; } /* printf("num of ghost faces %d, overlap faces %d on rank %d\n", ngf, nof, rank); */ /* this time only global id are sent */ for(i = 0; i < nbf; i++) { mf = List_Entry(boundary_faces,i); list_face[i] = MF_GlobalID(mf); } MPI_Allgather(list_face,max_nbf,MPI_INT,recv_list_face,max_nbf,MPI_INT,comm); for(i = 0; i < nbf; i++) { mf = List_Entry(boundary_faces,i); if(MF_PType(mf)==PGHOST) { int gid = recv_list_face[MF_MasterParID(mf)*max_nbf+id_on_ov_list[i]]; #ifdef DEBUG if (MF_GlobalID(mf) && MF_GlobalID(mf) != gid) MSTK_Report("MESH_AssignGlobalIDs_region", "Ghost face already has different global ID", MSTK_WARN); #endif MF_Set_GlobalID(mf, gid); } } /* assign region global id */ global_id = 1; for(i = 0; i < rank; i++) global_id = global_id + global_mesh_info[10*i+4]; for(i = 0; i < nr; i++) { mr = MESH_Region(submesh,i); MR_Set_PType(mr,PINTERIOR); if (!MR_GlobalID(mr)) MR_Set_GlobalID(mr,global_id++); MR_Set_MasterParID(mr,rank); } List_Delete(boundary_faces); free(global_mesh_info); free(face_ov_label); free(id_on_ov_list); free(list_face); free(recv_list_face); return 1; }
int MESH_ConcatSubMesh_Region(Mesh_ptr mesh, int num, Mesh_ptr *submeshes) { int nrf, nre, nrv, nfe, i, j, k, num_parbndry_verts, num_parbndry_edges, num_parbndry_faces, ival; MVertex_ptr mv, new_mv, sub_mv; MEdge_ptr me, new_me, sub_me; MFace_ptr mf, new_mf, sub_mf; MRegion_ptr new_mr, sub_mr; List_ptr mrfaces, mredges, mrverts, mfedges; int add_region, 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); List_ptr parbndry_faces = List_New(10); MFace_ptr *rfaces = (MFace_ptr *) malloc(MAXPF3*sizeof(MFace_ptr)); int *rfdirs = (int *) malloc(MAXPF3*sizeof(int)); 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 faces, edges and vertices on the partition boundary */ idx = 0; num_parbndry_faces = 0; while ((mf = MESH_Next_Face(mesh,&idx))) if (MF_PType(mf) != PINTERIOR) { List_Add(parbndry_faces,mf); num_parbndry_faces++; } idx = 0; num_parbndry_edges = 0; while ((me = MESH_Next_Edge(mesh,&idx))) if (ME_PType(me) != PINTERIOR) { List_Add(parbndry_edges,me); num_parbndry_edges++; } idx = 0; num_parbndry_verts = 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_faces,num_parbndry_faces,sizeof(MFace_ptr),compareGlobalID); 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)); int *parbndry_face_gids = (int *)malloc(num_parbndry_faces*sizeof(int)); /* store them in array for binary search */ for (i = 0; i < num_parbndry_faces; i++) { mf = List_Entry(parbndry_faces,i); parbndry_face_gids[i] = MF_GlobalID(mf); } 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, max_fnew = 0; for (i = 0; i < num; i++) { max_vnew += MESH_Num_Vertices(submeshes[i]); max_enew += MESH_Num_Edges(submeshes[i]); max_fnew += MESH_Num_Faces(submeshes[i]); } int num_new_verts = 0, num_new_edges = 0, num_new_faces = 0; int *new_vert_gids = (int *) malloc(max_vnew*sizeof(int)); int *new_edge_gids = (int *) malloc(max_enew*sizeof(int)); int *new_face_gids = (int *) malloc(max_fnew*sizeof(int)); List_ptr new_verts = List_New(max_vnew); List_ptr new_edges = List_New(max_enew); List_ptr new_faces = List_New(max_fnew); /* 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); MAttrib_ptr fidatt = MAttrib_New(submesh, "tempfid", POINTER, MFACE); idx = 0; while ((sub_mr = MESH_Next_Region(submesh, &idx))) { add_region = 0; /* Find matching vertices between submesh and main mesh */ mrverts = MR_Vertices(sub_mr); nrv = List_Num_Entries(mrverts); for (j = 0; j < nrv; j++) { sub_mv = List_Entry(mrverts,j); 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_region = 1; } else { /* Does the global ID of this vertex of the sub mesh region * match the global ID of a 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) { add_region = 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(mrverts); /* Find matching edges between submesh and main mesh */ mredges = MR_Edges(sub_mr); nre = List_Num_Entries(mredges); for (j = 0; j < nre; j++) { sub_me = List_Entry(mredges,j); /* Does the edge already have a counterpart in 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 region * match the global ID of a 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) { add_region = 1; 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); } } } List_Delete(mredges); /* Find matching faces between submesh and main mesh */ mrfaces = MR_Faces(sub_mr); nrf = List_Num_Entries(mrfaces); for (j = 0; j < nrf; j++) { sub_mf = List_Entry(mrfaces,j); MEnt_Get_AttVal(sub_mf, fidatt, &ival, &rval, &mf); if (!mf) { /* Does the global ID of this face of the sub mesh region * match the global ID of a boundary face in the main * mesh? */ global_id = MF_GlobalID(sub_mf); loc = (int *) bsearch(&global_id, parbndry_face_gids, num_parbndry_faces, sizeof(int), compareINT); if (loc) { iloc = loc - parbndry_face_gids; mf = List_Entry(parbndry_faces,iloc); /* here set the ghost edge property, only necessary when the input submeshes are not consistent */ if (MF_PType(mf) == PGHOST && MF_PType(sub_mf) != PGHOST) { MF_Set_GEntDim(mf,MF_GEntDim(sub_mf)); MF_Set_GEntID(mf,MF_GEntID(sub_mf)); } MEnt_Set_AttVal(sub_mf, fidatt, 0, 0.0, mf); } } } if (!add_region) { List_Delete(mrfaces); continue; } new_mr = MR_New(mesh); /* add region */ MR_Set_GEntDim(new_mr,MR_GEntDim(sub_mr)); MR_Set_GEntID(new_mr,MR_GEntID(sub_mr)); MR_Set_PType(new_mr,PGHOST); MR_Set_MasterParID(new_mr,MR_MasterParID(sub_mr)); MR_Set_GlobalID(new_mr,MR_GlobalID(sub_mr)); nrf = List_Num_Entries(mrfaces); int i2; for(i2 = 0; i2 < nrf; i2++) { sub_mf = List_Entry(mrfaces,i2); global_id = MF_GlobalID(sub_mf); rfdirs[i2] = MR_FaceDir_i(sub_mr,i2) == 1 ? 1 : 0; new_mf = NULL; MEnt_Get_AttVal(sub_mf, fidatt, &ival, &rval, &new_mf); if (!new_mf) { /* search in the ghost layer if another face with * this global ID has been added */ loc = (int *) bsearch(&global_id, new_face_gids, num_new_faces, sizeof(int), compareINT); if (loc) { iloc = loc - new_face_gids; new_mf = List_Entry(new_faces, iloc); MEnt_Set_AttVal(sub_mf, fidatt, 0, 0.0, new_mf); } } if (new_mf) { List_ptr mfverts = MF_Vertices(sub_mf,1,0); int fvgid0[2]; fvgid0[0] = MF_GlobalID(List_Entry(mfverts,0)); fvgid0[1] = MF_GlobalID(List_Entry(mfverts,1)); List_Delete(mfverts); mfverts = MF_Vertices(new_mf,1,0); int nfv = List_Num_Entries(mfverts); int fvgid1[MAXPV2]; for (j = 0; j < nfv; j++) fvgid1[j] = MF_GlobalID(List_Entry(mfverts,j)); List_Delete(mfverts); for (j = 0; j < nfv; j++) { if (fvgid1[j] == fvgid0[0]) { if (fvgid1[(j+nfv-1)%nfv] == fvgid0[1]) /* reverse dir */ rfdirs[i2] = !rfdirs[i2]; break; } } } else { /* add a new face to main mesh */ 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)); MEnt_Set_AttVal(sub_mf, fidatt, 0, 0.0, new_mf); List_Add(new_faces, new_mf); mfedges = MF_Edges(sub_mf,1,0); 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); /* add new edge and copy information */ 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 new vertex to main mesh */ new_mv = MV_New(mesh); /* add new vertex and copy information */ 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); } rfaces[i2] = new_mf; } MR_Set_Faces(new_mr,nrf,rfaces,rfdirs); /* set region-face */ List_Delete(mrfaces); } 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); idx = 0; while ((sub_mf = MESH_Next_Face(submesh, &idx))) MEnt_Rem_AttVal(sub_mf, fidatt); MAttrib_Delete(fidatt); /* Sort the added entity lists by GlobalID */ num_new_faces = List_Num_Entries(new_faces); List_Sort(new_faces, num_new_faces, sizeof(MFace_ptr), compareGlobalID); for (j = 0; j < num_new_faces; j++) new_face_gids[j] = MF_GlobalID(List_Entry(new_faces, j)); 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_faces); List_Delete(parbndry_edges); List_Delete(parbndry_verts); List_Delete(new_faces); List_Delete(new_edges); List_Delete(new_verts); free(parbndry_vert_gids); free(parbndry_edge_gids); free(parbndry_face_gids); free(new_face_gids); free(new_edge_gids); free(new_vert_gids); free(fedges); free(fedirs); free(rfaces); free(rfdirs); return 1; }
int MESH_Send_NonVertexEntities_FN(Mesh_ptr mesh, int torank, MSTK_Comm comm, int *numreq, int *maxreq, MPI_Request **requests, int *numptrs2free, int *maxptrs2free, void ***ptrs2free) { int i, j, nv, ne, nf, nr; int nevs, nfes, nrfs, nfe, nrv, nrf, dir; int maxnfe, maxnrf; int *mesh_info; int *list_edge=NULL, *list_face=NULL, *list_region=NULL; MVertex_ptr mv; MEdge_ptr me; MFace_ptr mf; MRegion_ptr mr; List_ptr mfedges, mrfaces, mrverts; RepType rtype; double coor[3]; MPI_Request mpirequest; if (requests == NULL) MSTK_Report("MESH_Surf_SendMesh","MPI requests array is NULL",MSTK_FATAL); if (*maxreq == 0) { *maxreq = 25; *requests = (MPI_Request *) malloc(*maxreq*sizeof(MPI_Request)); *numreq = 0; } else if (*maxreq < (*numreq) + 13) { *maxreq = 2*(*maxreq) + 11; *requests = (MPI_Request *) realloc(*requests,*maxreq*sizeof(MPI_Request)); } ne = MESH_Num_Edges(mesh); nf = MESH_Num_Faces(mesh); nr = MESH_Num_Regions(mesh); /* some other known quantitites - 5 items per edge (2 for verts and 3 for extra data), maxnfe+4 items per face (1 for number of edges, maxnfe for edge indices, anad 3 for extra data), maxnrf+4 items per region (1 for number of faces, maxnrf for face indices and 3 for extra data */ maxnfe = 0; for (i = 0; i < nf; i++) { mf = MESH_Face(mesh,i); nfe = MF_Num_Edges(mf); if (nfe > maxnfe) maxnfe = nfe; } maxnrf = 0; for (i = 0; i < nr; i++) { mr = MESH_Region(mesh,i); nrf = MR_Num_Faces(mr); if (nrf > maxnrf) maxnrf = nrf; } // The amount of extra info we are sending and their meaning is obviously // known on the receiving side too. So nevs, nfes and nrfs can be // calculated without us sending it nevs = (2+3)*ne; nfes = (1 + maxnfe + 3)*nf; nrfs = (1 + maxnrf + 3)*nr; /* Reserve nevs spots for each edge */ list_edge = (int *) malloc(5*ne*sizeof(int)); nevs = 0; /* Store the vertex ids, then the 3 auxilliary data fields */ for(i = 0; i < ne; i++) { me = MESH_Edge(mesh,i); list_edge[nevs] = MV_ID(ME_Vertex(me,0)); list_edge[nevs+1] = MV_ID(ME_Vertex(me,1)); list_edge[nevs+2] = (ME_GEntID(me)<<3) | (ME_GEntDim(me)); list_edge[nevs+3] = (ME_MasterParID(me) <<3) | (ME_OnParBoundary(me)<<2) | (ME_PType(me)); list_edge[nevs+4] = ME_GlobalID(me); nevs += 5; } /* send detailed edge info */ MPI_Isend(list_edge,nevs,MPI_INT,torank,torank,comm,&mpirequest); (*requests)[*numreq] = mpirequest; (*numreq)++; /* Reserve nfes spots for each face */ list_face = (int *) malloc(nfes*sizeof(int)); nfes = 0; /* first store nfe, then the edge ids, then the 3 auxilliary data fields */ for(i = 0; i < nf; i++) { mf = MESH_Face(mesh,i); mfedges = MF_Edges(mf,1,0); nfe = List_Num_Entries(mfedges); list_face[nfes] = nfe; for(j = 0; j < nfe; j++) { dir = MF_EdgeDir_i(mf,j) ? 1 : -1; list_face[nfes+j+1] = dir*ME_ID(List_Entry(mfedges,j)); } list_face[nfes+nfe+1] = (MF_GEntID(mf)<<3) | (MF_GEntDim(mf)); list_face[nfes+nfe+2] = (MF_MasterParID(mf)<<3) | (MF_OnParBoundary(mf)<<2) | (MF_PType(mf)); list_face[nfes+nfe+3] = MF_GlobalID(mf); nfes += (nfe + 4); List_Delete(mfedges); } /* send detailed face info */ MPI_Isend(list_face,nfes,MPI_INT,torank,torank,comm,&mpirequest); (*requests)[*numreq] = mpirequest; (*numreq)++; if (nr) { list_region = (int *) malloc(nrfs*sizeof(int)); nrfs = 0; /* first store nrf, then the face ids, then the 3 auxilliary data fields */ for(i = 0; i < nr; i++) { mr = MESH_Region(mesh,i); mrfaces = MR_Faces(mr); nrf = List_Num_Entries(mrfaces); list_region[nrfs] = nrf; for(j = 0; j < nrf; j++) { dir = MR_FaceDir_i(mr,j) == 1 ? 1 : -1; list_region[nrfs+j+1] = dir*MF_ID(List_Entry(mrfaces,j)); } list_region[nrfs+nrf+1] = (MR_GEntID(mr)<<3) | (MR_GEntDim(mr)); list_region[nrfs+nrf+2] = (MR_MasterParID(mr)<<3) | (MR_PType(mr)); /* MR_PType is 2 bits; 3 bit is 0 */ list_region[nrfs+nrf+3] = MR_GlobalID(mr); nrfs += (nrf + 4); List_Delete(mrfaces); } /* send detailed region info */ MPI_Isend(list_region,nrfs,MPI_INT,torank,torank,comm,&mpirequest); (*requests)[*numreq] = mpirequest; (*numreq)++; } /* collect allocated memory so it can be freed in a higher level routine after MPI_Waitall or MPI_Test has ensured that the send has been completed */ if (ptrs2free == NULL) MSTK_Report("MESH_Surf_SendMesh_FN","ptrs2free array is NULL",MSTK_FATAL); int nptrs = 3; if (*maxptrs2free == 0) { *maxptrs2free = 25; *ptrs2free = (void **) malloc(*maxptrs2free*sizeof(void *)); *numptrs2free = 0; } else if (*maxptrs2free < (*numptrs2free) + nptrs) { *maxptrs2free = 2*(*maxptrs2free) + nptrs; *ptrs2free = (void **) realloc(*ptrs2free,(*maxptrs2free)*sizeof(void *)); } if (ne) (*ptrs2free)[(*numptrs2free)++] = list_edge; if (nf) (*ptrs2free)[(*numptrs2free)++] = list_face; if (nr) (*ptrs2free)[(*numptrs2free)++] = list_region; return 1; }