#include #include #include #include #include #include #include typedef struct { PetscInt nf; VecScatter *scctx; } GLVisViewerCtx; static PetscErrorCode DestroyGLVisViewerCtx_Private(void *vctx) { GLVisViewerCtx *ctx = (GLVisViewerCtx*)vctx; PetscInt i; PetscErrorCode ierr; PetscFunctionBegin; for (i=0;inf;i++) { ierr = VecScatterDestroy(&ctx->scctx[i]);CHKERRQ(ierr); } ierr = PetscFree(ctx->scctx);CHKERRQ(ierr); ierr = PetscFree(vctx);CHKERRQ(ierr); PetscFunctionReturn(0); } static PetscErrorCode DMPlexSampleGLVisFields_Private(PetscObject oX, PetscInt nf, PetscObject oXfield[], void *vctx) { GLVisViewerCtx *ctx = (GLVisViewerCtx*)vctx; PetscInt f; PetscErrorCode ierr; PetscFunctionBegin; for (f=0;fscctx[f],(Vec)oX,(Vec)oXfield[f],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(ctx->scctx[f],(Vec)oX,(Vec)oXfield[f],INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); } PetscFunctionReturn(0); } /* for FEM, it works for H1 fields only and extracts dofs at cell vertices, discarding any other dof */ PetscErrorCode DMSetUpGLVisViewer_Plex(PetscObject odm, PetscViewer viewer) { DM dm = (DM)odm; Vec xlocal,xfield,*Ufield; PetscDS ds; IS globalNum,isfield; PetscBT vown; char **fieldname = NULL,**fec_type = NULL; const PetscInt *gNum; PetscInt *nlocal,*bs,*idxs,*dims; PetscInt f,maxfields,nfields,c,totc,totdofs,Nv,cum,i; PetscInt dim,cStart,cEnd,cEndInterior,vStart,vEnd; GLVisViewerCtx *ctx; PetscSection s; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(dm,0,&vStart,&vEnd);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); cEnd = cEndInterior < 0 ? cEnd : cEndInterior; ierr = DMPlexGetCellNumbering(dm,&globalNum);CHKERRQ(ierr); ierr = ISGetIndices(globalNum,&gNum);CHKERRQ(ierr); ierr = PetscBTCreate(vEnd-vStart,&vown);CHKERRQ(ierr); for (c = cStart, totc = 0; c < cEnd; c++) { if (gNum[c-cStart] >= 0) { PetscInt i,numPoints,*points = NULL; totc++; ierr = DMPlexGetTransitiveClosure(dm,c,PETSC_TRUE,&numPoints,&points);CHKERRQ(ierr); for (i=0;i= vStart) && (points[i] < vEnd)) { ierr = PetscBTSet(vown,points[i]-vStart);CHKERRQ(ierr); } } ierr = DMPlexRestoreTransitiveClosure(dm,c,PETSC_TRUE,&numPoints,&points);CHKERRQ(ierr); } } for (f=0,Nv=0;fscctx);CHKERRQ(ierr); ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); if (ds) { for (f=0;f 0) { ierr = PetscSNPrintf(fec,64,"FiniteElementCollection: H1_%dD_P1",dim);CHKERRQ(ierr); } else { H1 = PETSC_FALSE; ierr = PetscSNPrintf(fec,64,"FiniteElementCollection: L2_%dD_P%d",dim,order);CHKERRQ(ierr); } ierr = PetscStrallocpy(name,&fieldname[ctx->nf]);CHKERRQ(ierr); bs[ctx->nf] = Nc; dims[ctx->nf] = dim; if (H1) { nlocal[ctx->nf] = Nc * Nv; ierr = PetscStrallocpy(fec,&fec_type[ctx->nf]);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,Nv*Nc,&xfield);CHKERRQ(ierr); for (i=0,cum=0;inf] = Nc * totc; ierr = PetscStrallocpy(fec,&fec_type[ctx->nf]);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,Nc*totc,&xfield);CHKERRQ(ierr); for (i=0,cum=0;iscctx[ctx->nf]);CHKERRQ(ierr); ierr = VecDestroy(&xfield);CHKERRQ(ierr); ierr = ISDestroy(&isfield);CHKERRQ(ierr); ctx->nf++; } else if (id == PETSCFV_CLASSID) { PetscInt c; ierr = PetscFVGetNumComponents((PetscFV)disc,&Nc);CHKERRQ(ierr); ierr = PetscSNPrintf(fec,64,"FiniteElementCollection: L2_%dD_P0",dim);CHKERRQ(ierr); for (c = 0; c < Nc; c++) { char comp[256]; ierr = PetscSNPrintf(comp,256,"%s-Comp%d",name,c);CHKERRQ(ierr); ierr = PetscStrallocpy(comp,&fieldname[ctx->nf]);CHKERRQ(ierr); bs[ctx->nf] = 1; /* Does PetscFV support components with different block size? */ nlocal[ctx->nf] = totc; dims[ctx->nf] = dim; ierr = PetscStrallocpy(fec,&fec_type[ctx->nf]);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,totc,&xfield);CHKERRQ(ierr); for (i=0,cum=0;iscctx[ctx->nf]);CHKERRQ(ierr); ierr = VecDestroy(&xfield);CHKERRQ(ierr); ierr = ISDestroy(&isfield);CHKERRQ(ierr); ctx->nf++; } } else SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONG,"Unknown discretization type for field %D",f); } else SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Missing discretization for field %D",f); } } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Needs a DS attached to the DM"); ierr = PetscBTDestroy(&vown);CHKERRQ(ierr); ierr = VecDestroy(&xlocal);CHKERRQ(ierr); ierr = ISRestoreIndices(globalNum,&gNum);CHKERRQ(ierr); /* create work vectors */ for (f=0;fnf;f++) { ierr = VecCreateMPI(PetscObjectComm((PetscObject)dm),nlocal[f],PETSC_DECIDE,&Ufield[f]);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)Ufield[f],fieldname[f]);CHKERRQ(ierr); ierr = VecSetBlockSize(Ufield[f],bs[f]);CHKERRQ(ierr); ierr = VecSetDM(Ufield[f],dm);CHKERRQ(ierr); } /* customize the viewer */ ierr = PetscViewerGLVisSetFields(viewer,ctx->nf,(const char**)fec_type,dims,DMPlexSampleGLVisFields_Private,(PetscObject*)Ufield,ctx,DestroyGLVisViewerCtx_Private);CHKERRQ(ierr); for (f=0;fnf;f++) { ierr = PetscFree(fieldname[f]);CHKERRQ(ierr); ierr = PetscFree(fec_type[f]);CHKERRQ(ierr); ierr = VecDestroy(&Ufield[f]);CHKERRQ(ierr); } ierr = PetscFree7(fieldname,nlocal,bs,dims,fec_type,idxs,Ufield);CHKERRQ(ierr); PetscFunctionReturn(0); } typedef enum {MFEM_POINT=0,MFEM_SEGMENT,MFEM_TRIANGLE,MFEM_SQUARE,MFEM_TETRAHEDRON,MFEM_CUBE,MFEM_UNDEF} MFEM_cid; MFEM_cid mfem_table_cid[4][7] = { {MFEM_POINT,MFEM_UNDEF,MFEM_UNDEF ,MFEM_UNDEF ,MFEM_UNDEF ,MFEM_UNDEF, MFEM_UNDEF}, {MFEM_POINT,MFEM_UNDEF,MFEM_SEGMENT,MFEM_UNDEF ,MFEM_UNDEF ,MFEM_UNDEF, MFEM_UNDEF}, {MFEM_POINT,MFEM_UNDEF,MFEM_SEGMENT,MFEM_TRIANGLE,MFEM_SQUARE ,MFEM_UNDEF, MFEM_UNDEF}, {MFEM_POINT,MFEM_UNDEF,MFEM_SEGMENT,MFEM_UNDEF ,MFEM_TETRAHEDRON,MFEM_UNDEF, MFEM_CUBE } }; static PetscErrorCode DMPlexGetPointMFEMCellID_Internal(DM dm, DMLabel label, PetscInt p, PetscInt *mid, PetscInt *cid) { DMLabel dlabel; PetscInt depth,csize; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPlexGetDepthLabel(dm,&dlabel);CHKERRQ(ierr); ierr = DMLabelGetValue(dlabel,p,&depth);CHKERRQ(ierr); ierr = DMPlexGetConeSize(dm,p,&csize);CHKERRQ(ierr); if (label) { ierr = DMLabelGetValue(label,p,mid);CHKERRQ(ierr); } else *mid = 1; *cid = mfem_table_cid[depth][csize]; PetscFunctionReturn(0); } static PetscErrorCode DMPlexGetPointMFEMVertexIDs_Internal(DM dm, PetscInt p, PetscSection csec, PetscInt *nv, int vids[]) { PetscInt dim,sdim,dof = 0,off = 0,i,q,vStart,vEnd,numPoints,*points = NULL; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPlexGetDepthStratum(dm,0,&vStart,&vEnd);CHKERRQ(ierr); ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); sdim = dim; if (csec) { ierr = DMGetCoordinateDim(dm,&sdim);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csec,vStart,&off);CHKERRQ(ierr); off = off/sdim; ierr = PetscSectionGetDof(csec,p,&dof);CHKERRQ(ierr); } if (!dof) { ierr = DMPlexGetTransitiveClosure(dm,p,PETSC_TRUE,&numPoints,&points);CHKERRQ(ierr); for (i=0,q=0;i= vStart) && (points[i] < vEnd)) vids[q++] = points[i]-vStart+off; ierr = DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&numPoints,&points);CHKERRQ(ierr); } else { ierr = PetscSectionGetOffset(csec,p,&off);CHKERRQ(ierr); ierr = PetscSectionGetDof(csec,p,&dof);CHKERRQ(ierr); for (q=0;q 1) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Use single sequential viewers for parallel visualization"); ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr); ierr = DMPlexGetDepth(dm,&depth);CHKERRQ(ierr); if (depth >= 0 && dim != depth) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated"); /* get container: determines if a process visualizes is portion of the data or not */ ierr = PetscObjectQuery((PetscObject)viewer,"_glvis_info_container",(PetscObject*)&glvis_container);CHKERRQ(ierr); if (!glvis_container) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Missing GLVis container"); { PetscViewerGLVisInfo glvis_info; ierr = PetscContainerGetPointer(glvis_container,(void**)&glvis_info);CHKERRQ(ierr); enabled = glvis_info->enabled; fmt = glvis_info->fmt; } ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr); cEnd = cEndInterior < 0 ? cEnd : cEndInterior; ierr = DMPlexGetDepthStratum(dm,0,&vStart,&vEnd);CHKERRQ(ierr); ierr = DMGetPeriodicity(dm,&periodic,NULL,NULL,NULL);CHKERRQ(ierr); ierr = DMGetCoordinatesLocalized(dm,&localized);CHKERRQ(ierr); if (periodic && !localized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Coordinates need to be localized"); ierr = DMGetCoordinateSection(dm,&coordSection);CHKERRQ(ierr); ierr = DMGetCoordinateDim(dm,&sdim);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm,&coordinates);CHKERRQ(ierr); /* Users can attach a coordinate vector to the DM in case they have a higher-order mesh DMPlex does not currently support HO meshes, so there's no API for this */ ierr = PetscObjectQuery((PetscObject)dm,"_glvis_mesh_coords",(PetscObject*)&hovec);CHKERRQ(ierr); /* a couple of sections of the mesh specification are disabled - boundary: unless we want to visualize boundary attributes or we have a periodic mesh the boundary is not needed for proper mesh visualization - vertex_parents: used for non-conforming meshes only when we want to use MFEM as a discretization package and be able to derefine the mesh */ enable_boundary = periodic; enable_ncmesh = PETSC_FALSE; ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)dm),((PetscObject)dm)->prefix,"GLVis PetscViewer DMPlex Options","PetscViewer");CHKERRQ(ierr); ierr = PetscOptionsBool("-viewer_glvis_dm_plex_enable_boundary","Enable boundary section in mesh representation; useful for debugging purposes",NULL,enable_boundary,&enable_boundary,NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-viewer_glvis_dm_plex_enable_ncmesh","Enable vertex_parents section in mesh representation; useful for debugging purposes",NULL,enable_ncmesh,&enable_ncmesh,NULL);CHKERRQ(ierr); ierr = PetscOptionsEnd();CHKERRQ(ierr); /* Identify possible cells in the overlap */ gNum = NULL; novl = 0; ovl = PETSC_FALSE; pown = NULL; ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&commsize);CHKERRQ(ierr); if (commsize > 1) { ierr = DMPlexGetCellNumbering(dm,&globalNum);CHKERRQ(ierr); ierr = ISGetIndices(globalNum,&gNum);CHKERRQ(ierr); for (p=cStart; p= vStart && cellClosure[2*v] < vEnd) { vidxs = cellClosure + 2*v; break; } if (!vidxs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing vertices"); for (v=0;vPETSC_MACHINE_EPSILON) { ierr = DMLabelSetValue(perLabel,vidxs[2*v],2);CHKERRQ(ierr); } } } ierr = DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&cellClosureSize,&cellClosure);CHKERRQ(ierr); ierr = DMPlexVecRestoreClosure(dm,coordSection,coordinates,p,&csize,&vals);CHKERRQ(ierr); } } if (dim > 1) { PetscInt eEnd,eStart,eEndInterior; ierr = DMPlexGetHybridBounds(dm,NULL,NULL,&eEndInterior,NULL);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(dm,1,&eStart,&eEnd);CHKERRQ(ierr); eEnd = eEndInterior < 0 ? eEnd : eEndInterior; for (p=eStart;p 2) { for (p=fStart;p 1 && has_owned && has_ghost)); } else { isbf = (PetscBool)(supportSize == 1); } if (!isbf && perLabel) { const PetscInt *cone; PetscInt coneSize,i; ierr = DMPlexGetCone(dm,p,&cone);CHKERRQ(ierr); ierr = DMPlexGetConeSize(dm,p,&coneSize);CHKERRQ(ierr); isbf = PETSC_TRUE; for (i=0;i= vStart && pp < vEnd) { ierr = PetscBTSet(pown,pp-vStart);CHKERRQ(ierr); } } ierr = DMPlexRestoreTransitiveClosure(dm,p,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); } } if (globalNum) { ierr = ISRestoreIndices(globalNum,&gNum);CHKERRQ(ierr); } /* vertex_parents (Non-conforming meshes) */ parentSection = NULL; if (enable_ncmesh) { ierr = DMPlexGetTree(dm,&parentSection,NULL,NULL,NULL,NULL);CHKERRQ(ierr); } if (parentSection) { PetscInt vp,gvp; for (vp=0,p=vStart;p