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; }
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; }