static PetscErrorCode CreateSpectralPlanes(DM dm, PetscInt numPlanes, const PetscInt planeDir[], const PetscReal planeCoord[], AppCtx *user) { PetscSection coordSection; Vec coordinates; const PetscScalar *coords; PetscInt dim, p, vStart, vEnd, v; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); for (p = 0; p < numPlanes; ++p) { DMLabel label; char name[PETSC_MAX_PATH_LEN]; ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "spectral_plane_%D", p);CHKERRQ(ierr); ierr = DMCreateLabel(dm, name);CHKERRQ(ierr); ierr = DMGetLabel(dm, name, &label);CHKERRQ(ierr); ierr = DMLabelAddStratum(label, 1);CHKERRQ(ierr); for (v = vStart; v < vEnd; ++v) { PetscInt off; ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); if (PetscAbsReal(planeCoord[p] - PetscRealPart(coords[off+planeDir[p]])) < PETSC_SMALL) { ierr = DMLabelSetValue(label, v, 1);CHKERRQ(ierr); } } } ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode AddIdentityLabel(DM dm) { PetscInt pStart,pEnd,p; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMCreateLabel(dm, "identity");CHKERRQ(ierr); ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); for (p = pStart; p < pEnd; p++) {ierr = DMSetLabelValue(dm, "identity", p, p);CHKERRQ(ierr);} PetscFunctionReturn(0); }
static PetscErrorCode CreateBCLabel(DM dm, const char name[]) { DMLabel label; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = DMCreateLabel(dm, name); CHKERRQ(ierr); ierr = DMGetLabel(dm, name, &label); CHKERRQ(ierr); ierr = DMPlexMarkBoundaryFaces(dm, label); CHKERRQ(ierr); ierr = DMPlexLabelComplete(dm, label); CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **args) { Mat Amat; PetscErrorCode ierr; SNES snes; KSP ksp; MPI_Comm comm; PetscMPIInt npe,rank; PetscLogStage stage[7]; PetscBool test_nonzero_cols=PETSC_FALSE,use_nearnullspace=PETSC_TRUE; Vec xx,bb; PetscInt iter,i,N,dim=3,cells[3]={1,1,1},max_conv_its,local_sizes[7],run_type=1; DM dm,distdm,basedm; PetscBool flg; char convType[256]; PetscReal Lx,mdisp[10],err[10]; const char * const options[10] = {"-ex56_dm_refine 0", "-ex56_dm_refine 1", "-ex56_dm_refine 2", "-ex56_dm_refine 3", "-ex56_dm_refine 4", "-ex56_dm_refine 5", "-ex56_dm_refine 6", "-ex56_dm_refine 7", "-ex56_dm_refine 8", "-ex56_dm_refine 9"}; PetscFunctionBeginUser; ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr; comm = PETSC_COMM_WORLD; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &npe);CHKERRQ(ierr); /* options */ ierr = PetscOptionsBegin(comm,NULL,"3D bilinear Q1 elasticity options","");CHKERRQ(ierr); { i = 3; ierr = PetscOptionsIntArray("-cells", "Number of (flux tube) processor in each dimension", "ex56.c", cells, &i, NULL);CHKERRQ(ierr); Lx = 1.; /* or ne for rod */ max_conv_its = 3; ierr = PetscOptionsInt("-max_conv_its","Number of iterations in convergence study","",max_conv_its,&max_conv_its,NULL);CHKERRQ(ierr); if (max_conv_its<=0 || max_conv_its>7) SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_USER, "Bad number of iterations for convergence test (%D)",max_conv_its); ierr = PetscOptionsReal("-lx","Length of domain","",Lx,&Lx,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-alpha","material coefficient inside circle","",s_soft_alpha,&s_soft_alpha,NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-test_nonzero_cols","nonzero test","",test_nonzero_cols,&test_nonzero_cols,NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-use_mat_nearnullspace","MatNearNullSpace API test","",use_nearnullspace,&use_nearnullspace,NULL);CHKERRQ(ierr); ierr = PetscOptionsInt("-run_type","0: twisting load on cantalever, 1: 3rd order accurate convergence test","",run_type,&run_type,NULL);CHKERRQ(ierr); i = 3; ierr = PetscOptionsInt("-mat_block_size","","",i,&i,&flg);CHKERRQ(ierr); if (!flg || i!=3) SETERRQ2(PETSC_COMM_WORLD, PETSC_ERR_USER, "'-mat_block_size 3' must be set (%D) and = 3 (%D)",flg,flg? i : 3); } ierr = PetscOptionsEnd();CHKERRQ(ierr); ierr = PetscLogStageRegister("Mesh Setup", &stage[6]);CHKERRQ(ierr); ierr = PetscLogStageRegister("1st Setup", &stage[0]);CHKERRQ(ierr); ierr = PetscLogStageRegister("1st Solve", &stage[1]);CHKERRQ(ierr); /* create DM, Plex calls DMSetup */ ierr = PetscLogStagePush(stage[6]);CHKERRQ(ierr); ierr = DMPlexCreateHexBoxMesh(comm, dim, cells, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, &dm);CHKERRQ(ierr); { DMLabel label; IS is; ierr = DMCreateLabel(dm, "boundary");CHKERRQ(ierr); ierr = DMGetLabel(dm, "boundary", &label);CHKERRQ(ierr); ierr = DMPlexMarkBoundaryFaces(dm, label);CHKERRQ(ierr); if (run_type==0) { ierr = DMGetStratumIS(dm, "boundary", 1, &is);CHKERRQ(ierr); ierr = DMCreateLabel(dm,"Faces");CHKERRQ(ierr); if (is) { PetscInt d, f, Nf; const PetscInt *faces; PetscInt csize; PetscSection cs; Vec coordinates ; DM cdm; ierr = ISGetLocalSize(is, &Nf);CHKERRQ(ierr); ierr = ISGetIndices(is, &faces);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); ierr = DMGetDefaultSection(cdm, &cs);CHKERRQ(ierr); /* Check for each boundary face if any component of its centroid is either 0.0 or 1.0 */ for (f = 0; f < Nf; ++f) { PetscReal faceCoord; PetscInt b,v; PetscScalar *coords = NULL; PetscInt Nv; ierr = DMPlexVecGetClosure(cdm, cs, coordinates, faces[f], &csize, &coords);CHKERRQ(ierr); Nv = csize/dim; /* Calculate mean coordinate vector */ for (d = 0; d < dim; ++d) { faceCoord = 0.0; for (v = 0; v < Nv; ++v) faceCoord += PetscRealPart(coords[v*dim+d]); faceCoord /= Nv; for (b = 0; b < 2; ++b) { if (PetscAbs(faceCoord - b) < PETSC_SMALL) { /* domain have not been set yet, still [0,1]^3 */ ierr = DMSetLabelValue(dm, "Faces", faces[f], d*2+b+1);CHKERRQ(ierr); } } } ierr = DMPlexVecRestoreClosure(cdm, cs, coordinates, faces[f], &csize, &coords);CHKERRQ(ierr); } ierr = ISRestoreIndices(is, &faces);CHKERRQ(ierr); } ierr = ISDestroy(&is);CHKERRQ(ierr); ierr = DMGetLabel(dm, "Faces", &label);CHKERRQ(ierr); ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); } } { PetscInt dimEmbed, i; PetscInt nCoords; PetscScalar *coords,bounds[] = {0,Lx,-.5,.5,-.5,.5,}; /* x_min,x_max,y_min,y_max */ Vec coordinates; if (run_type==1) { for (i = 0; i < 2*dim; i++) bounds[i] = (i%2) ? 1 : 0; } ierr = DMGetCoordinatesLocal(dm,&coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateDim(dm,&dimEmbed);CHKERRQ(ierr); if (dimEmbed != dim) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"dimEmbed != dim %D",dimEmbed);CHKERRQ(ierr); ierr = VecGetLocalSize(coordinates,&nCoords);CHKERRQ(ierr); if (nCoords % dimEmbed) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Coordinate vector the wrong size");CHKERRQ(ierr); ierr = VecGetArray(coordinates,&coords);CHKERRQ(ierr); for (i = 0; i < nCoords; i += dimEmbed) { PetscInt j; PetscScalar *coord = &coords[i]; for (j = 0; j < dimEmbed; j++) { coord[j] = bounds[2 * j] + coord[j] * (bounds[2 * j + 1] - bounds[2 * j]); } } ierr = VecRestoreArray(coordinates,&coords);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(dm,coordinates);CHKERRQ(ierr); } /* convert to p4est, and distribute */ ierr = PetscOptionsBegin(comm, "", "Mesh conversion options", "DMPLEX");CHKERRQ(ierr); ierr = PetscOptionsFList("-dm_type","Convert DMPlex to another format (should not be Plex!)","ex56.c",DMList,DMPLEX,convType,256,&flg);CHKERRQ(ierr); ierr = PetscOptionsEnd(); if (flg) { DM newdm; ierr = DMConvert(dm,convType,&newdm);CHKERRQ(ierr); if (newdm) { const char *prefix; PetscBool isForest; ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject)newdm,prefix);CHKERRQ(ierr); ierr = DMIsForest(newdm,&isForest);CHKERRQ(ierr); if (isForest) { } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_USER, "Converted to non Forest?"); ierr = DMDestroy(&dm);CHKERRQ(ierr); dm = newdm; } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_USER, "Convert failed?"); } else { /* Plex Distribute mesh over processes */ ierr = DMPlexDistribute(dm, 0, NULL, &distdm);CHKERRQ(ierr); if (distdm) { const char *prefix; ierr = PetscObjectGetOptionsPrefix((PetscObject)dm,&prefix);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject)distdm,prefix);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); dm = distdm; } } ierr = PetscLogStagePop();CHKERRQ(ierr); basedm = dm; dm = NULL; for (iter=0 ; iter<max_conv_its ; iter++) { ierr = PetscLogStagePush(stage[6]);CHKERRQ(ierr); /* make new DM */ ierr = DMClone(basedm, &dm);CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) dm, "ex56_");CHKERRQ(ierr); ierr = PetscObjectSetName( (PetscObject)dm,"Mesh");CHKERRQ(ierr); ierr = PetscOptionsClearValue(NULL,"-ex56_dm_refine");CHKERRQ(ierr); ierr = PetscOptionsInsertString(NULL,options[iter]);CHKERRQ(ierr); ierr = DMSetFromOptions(dm);CHKERRQ(ierr); /* refinement done here in Plex, p4est */ /* snes */ ierr = SNESCreate(comm, &snes);CHKERRQ(ierr); ierr = SNESSetDM(snes, dm);CHKERRQ(ierr); /* fem */ { const PetscInt Ncomp = dim; const PetscInt components[] = {0,1,2}; const PetscInt Nfid = 1, Npid = 1; const PetscInt fid[] = {1}; /* The fixed faces (x=0) */ const PetscInt pid[] = {2}; /* The faces with loading (x=L_x) */ PetscFE fe; PetscDS prob; DM cdm = dm; ierr = PetscFECreateDefault(dm, dim, dim, PETSC_FALSE, NULL, PETSC_DECIDE, &fe);CHKERRQ(ierr); /* elasticity */ ierr = PetscObjectSetName((PetscObject) fe, "deformation");CHKERRQ(ierr); /* FEM prob */ ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); ierr = PetscDSSetDiscretization(prob, 0, (PetscObject) fe);CHKERRQ(ierr); /* setup problem */ if (run_type==1) { ierr = PetscDSSetJacobian(prob, 0, 0, NULL, NULL, NULL, g3_uu_3d);CHKERRQ(ierr); ierr = PetscDSSetResidual(prob, 0, f0_u_x4, f1_u_3d);CHKERRQ(ierr); } else { ierr = PetscDSSetJacobian(prob, 0, 0, NULL, NULL, NULL, g3_uu_3d_alpha);CHKERRQ(ierr); ierr = PetscDSSetResidual(prob, 0, f0_u, f1_u_3d_alpha);CHKERRQ(ierr); ierr = PetscDSSetBdResidual(prob, 0, f0_bd_u_3d, f1_bd_u);CHKERRQ(ierr); } /* bcs */ if (run_type==1) { PetscInt id = 1; ierr = DMAddBoundary(dm, DM_BC_ESSENTIAL, "wall", "boundary", 0, 0, NULL, (void (*)()) zero, 1, &id, NULL);CHKERRQ(ierr); } else { ierr = PetscDSAddBoundary(prob, DM_BC_ESSENTIAL, "fixed", "Faces", 0, Ncomp, components, (void (*)()) zero, Nfid, fid, NULL);CHKERRQ(ierr); ierr = PetscDSAddBoundary(prob, DM_BC_NATURAL, "traction", "Faces", 0, Ncomp, components, NULL, Npid, pid, NULL);CHKERRQ(ierr); } while (cdm) { ierr = DMSetDS(cdm,prob);CHKERRQ(ierr); ierr = DMGetCoarseDM(cdm, &cdm);CHKERRQ(ierr); } ierr = PetscFEDestroy(&fe);CHKERRQ(ierr); } /* vecs & mat */ ierr = DMCreateGlobalVector(dm,&xx);CHKERRQ(ierr); ierr = VecDuplicate(xx, &bb);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) bb, "b");CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) xx, "u");CHKERRQ(ierr); ierr = DMCreateMatrix(dm, &Amat);CHKERRQ(ierr); ierr = VecGetSize(bb,&N);CHKERRQ(ierr); local_sizes[iter] = N; ierr = PetscPrintf(PETSC_COMM_WORLD,"[%d]%s %d global equations, %d vertices\n",rank,PETSC_FUNCTION_NAME,N,N/dim);CHKERRQ(ierr); if (use_nearnullspace && N/dim > 1) { /* Set up the near null space (a.k.a. rigid body modes) that will be used by the multigrid preconditioner */ DM subdm; MatNullSpace nearNullSpace; PetscInt fields = 0; PetscObject deformation; ierr = DMCreateSubDM(dm, 1, &fields, NULL, &subdm);CHKERRQ(ierr); ierr = DMPlexCreateRigidBody(subdm, &nearNullSpace);CHKERRQ(ierr); ierr = DMGetField(dm, 0, &deformation);CHKERRQ(ierr); ierr = PetscObjectCompose(deformation, "nearnullspace", (PetscObject) nearNullSpace);CHKERRQ(ierr); ierr = DMDestroy(&subdm);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nearNullSpace);CHKERRQ(ierr); /* created by DM and destroyed by Mat */ } ierr = DMPlexSetSNESLocalFEM(dm,NULL,NULL,NULL);CHKERRQ(ierr); ierr = SNESSetJacobian(snes, Amat, Amat, NULL, NULL);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); ierr = DMSetUp(dm);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = PetscLogStagePush(stage[0]);CHKERRQ(ierr); /* ksp */ ierr = SNESGetKSP(snes, &ksp);CHKERRQ(ierr); ierr = KSPSetComputeSingularValues(ksp,PETSC_TRUE);CHKERRQ(ierr); /* test BCs */ ierr = VecZeroEntries(xx);CHKERRQ(ierr); if (test_nonzero_cols) { if (rank==0) ierr = VecSetValue(xx,0,1.0,INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(xx);CHKERRQ(ierr); ierr = VecAssemblyEnd(xx);CHKERRQ(ierr); } ierr = VecZeroEntries(bb);CHKERRQ(ierr); ierr = VecGetSize(bb,&i);CHKERRQ(ierr); local_sizes[iter] = i; ierr = PetscPrintf(PETSC_COMM_WORLD,"[%d]%s %d equations in vector, %d vertices\n",rank,PETSC_FUNCTION_NAME,i,i/dim);CHKERRQ(ierr); /* setup solver, dummy solve to really setup */ if (0) { ierr = KSPSetTolerances(ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,1);CHKERRQ(ierr); ierr = SNESSolve(snes, bb, xx);CHKERRQ(ierr); ierr = KSPSetTolerances(ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,50);CHKERRQ(ierr); ierr = VecZeroEntries(xx);CHKERRQ(ierr); } ierr = PetscLogStagePop();CHKERRQ(ierr); /* solve */ ierr = PetscLogStagePush(stage[1]);CHKERRQ(ierr); ierr = SNESSolve(snes, bb, xx);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = VecNorm(xx,NORM_INFINITY,&mdisp[iter]);CHKERRQ(ierr); ierr = DMViewFromOptions(dm, NULL, "-dm_view");CHKERRQ(ierr); { PetscViewer viewer = NULL; PetscViewerFormat fmt; ierr = PetscOptionsGetViewer(comm,"ex56_","-vec_view",&viewer,&fmt,&flg);CHKERRQ(ierr); if (flg) { ierr = PetscViewerPushFormat(viewer,fmt);CHKERRQ(ierr); ierr = VecView(xx,viewer);CHKERRQ(ierr); ierr = VecView(bb,viewer);CHKERRQ(ierr); ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); } ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } /* Free work space */ ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = VecDestroy(&xx);CHKERRQ(ierr); ierr = VecDestroy(&bb);CHKERRQ(ierr); ierr = MatDestroy(&Amat);CHKERRQ(ierr); } ierr = DMDestroy(&basedm);CHKERRQ(ierr); if (run_type==1) { err[0] = 59.975208 - mdisp[0]; /* error with what I think is the exact solution */ } else { err[0] = 171.038 - mdisp[0]; } for (iter=1 ; iter<max_conv_its ; iter++) { if (run_type==1) { err[iter] = 59.975208 - mdisp[iter]; } else { err[iter] = 171.038 - mdisp[iter]; } PetscPrintf(PETSC_COMM_WORLD,"[%d]%s %D) N=%12D, max displ=%9.7e, disp diff=%9.2e, error=%4.3e, rate=%3.2g\n", rank,PETSC_FUNCTION_NAME,iter,local_sizes[iter],mdisp[iter], mdisp[iter]-mdisp[iter-1],err[iter],log(err[iter-1]/err[iter])/log(2.)); } ierr = PetscFinalize(); return ierr; }
PETSC_EXTERN PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) { MPI_Comm comm; const PetscInt dim = 3; const char *labelName = "marker"; PLC *in, *out; DMLabel label; PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); ierr = MPIU_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMGetLabel(dm, labelName, &label);CHKERRQ(ierr); ierr = PLCCreate(&in);CHKERRQ(ierr); ierr = PLCCreate(&out);CHKERRQ(ierr); in->numberofpoints = vEnd - vStart; if (in->numberofpoints > 0) { PetscSection coordSection; Vec coordinates; PetscScalar *array; ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); for (v = vStart; v < vEnd; ++v) { const PetscInt idx = v - vStart; PetscInt off, d, m = -1; ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); for (d = 0; d < dim; ++d) { in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); } if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);} in->pointmarkerlist[idx] = (int) m; } ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); } ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); in->numberofcorners = 4; in->numberoftetrahedra = cEnd - cStart; in->tetrahedronvolumelist = maxVolumes; if (in->numberoftetrahedra > 0) { ierr = PetscMalloc1(in->numberoftetrahedra*in->numberofcorners, &in->tetrahedronlist);CHKERRQ(ierr); for (c = cStart; c < cEnd; ++c) { const PetscInt idx = c - cStart; PetscInt *closure = NULL; PetscInt closureSize; ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); for (v = 0; v < 4; ++v) { in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; } ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); } } if (!rank) { TetGenOpts t; ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); t.in = dm; /* Should go away */ t.refine = 1; t.varvolume = 1; t.quality = 1; t.edgesout = 1; t.zeroindex = 1; t.quiet = 1; t.verbose = verbose; /* Change this */ ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); } in->tetrahedronvolumelist = NULL; { DMLabel rlabel = NULL; const PetscInt numCorners = 4; const PetscInt numCells = out->numberoftetrahedra; const PetscInt numVertices = out->numberofpoints; double *meshCoords; int *cells = out->tetrahedronlist; PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; if (sizeof (PetscReal) == sizeof (double)) { meshCoords = (double *) out->pointlist; } else { PetscInt i; ierr = PetscMalloc1(3 * numVertices,&meshCoords);CHKERRQ(ierr); for (i = 0; i < 3 * numVertices; i++) { meshCoords[i] = (PetscReal) out->pointlist[i]; } } ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dmRefined);CHKERRQ(ierr); if (sizeof (PetscReal) != sizeof (double)) { ierr = PetscFree(meshCoords);CHKERRQ(ierr); } if (label) {ierr = DMCreateLabel(*dmRefined, labelName); ierr = DMGetLabel(*dmRefined, labelName, &rlabel);} /* Set labels */ for (v = 0; v < numVertices; ++v) { if (out->pointmarkerlist[v]) { if (rlabel) {ierr = DMLabelSetValue(rlabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);} } } if (interpolate) { PetscInt e, f; for (e = 0; e < out->numberofedges; e++) { if (out->edgemarkerlist[e]) { const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; const PetscInt *edges; PetscInt numEdges; ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); if (rlabel) {ierr = DMLabelSetValue(rlabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);} ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); } } for (f = 0; f < out->numberoftrifaces; f++) { if (out->trifacemarkerlist[f]) { const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; const PetscInt *faces; PetscInt numFaces; ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); if (rlabel) {ierr = DMLabelSetValue(rlabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);} ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); } } } ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); } ierr = PLCDestroy(&in);CHKERRQ(ierr); ierr = PLCDestroy(&out);CHKERRQ(ierr); PetscFunctionReturn(0); }
PETSC_EXTERN PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) { MPI_Comm comm; const PetscInt dim = 3; const char *labelName = "marker"; PLC *in, *out; DMLabel label; PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)boundary,&comm);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, NULL);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMGetLabel(boundary, labelName, &label);CHKERRQ(ierr); ierr = PLCCreate(&in);CHKERRQ(ierr); ierr = PLCCreate(&out);CHKERRQ(ierr); in->numberofpoints = vEnd - vStart; if (in->numberofpoints > 0) { PetscSection coordSection; Vec coordinates; PetscScalar *array; ierr = PetscMalloc1(in->numberofpoints*dim, &in->pointlist);CHKERRQ(ierr); ierr = PetscMalloc1(in->numberofpoints, &in->pointmarkerlist);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); ierr = DMGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); for (v = vStart; v < vEnd; ++v) { const PetscInt idx = v - vStart; PetscInt off, d, m = -1; ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); for (d = 0; d < dim; ++d) { in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); } if (label) {ierr = DMLabelGetValue(label, v, &m);CHKERRQ(ierr);} in->pointmarkerlist[idx] = (int) m; } ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); } ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); in->numberoffacets = fEnd - fStart; if (in->numberoffacets > 0) { ierr = PetscMalloc1(in->numberoffacets, &in->facetlist);CHKERRQ(ierr); ierr = PetscMalloc1(in->numberoffacets, &in->facetmarkerlist);CHKERRQ(ierr); for (f = fStart; f < fEnd; ++f) { const PetscInt idx = f - fStart; PetscInt *points = NULL, numPoints, p, numVertices = 0, v, m = -1; polygon *poly; in->facetlist[idx].numberofpolygons = 1; ierr = PetscMalloc1(in->facetlist[idx].numberofpolygons, &in->facetlist[idx].polygonlist);CHKERRQ(ierr); in->facetlist[idx].numberofholes = 0; in->facetlist[idx].holelist = NULL; ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); for (p = 0; p < numPoints*2; p += 2) { const PetscInt point = points[p]; if ((point >= vStart) && (point < vEnd)) points[numVertices++] = point; } poly = in->facetlist[idx].polygonlist; poly->numberofvertices = numVertices; ierr = PetscMalloc1(poly->numberofvertices, &poly->vertexlist);CHKERRQ(ierr); for (v = 0; v < numVertices; ++v) { const PetscInt vIdx = points[v] - vStart; poly->vertexlist[v] = vIdx; } if (label) {ierr = DMLabelGetValue(label, f, &m);CHKERRQ(ierr);} in->facetmarkerlist[idx] = (int) m; ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); } } if (!rank) { TetGenOpts t; ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); t.in = boundary; /* Should go away */ t.plc = 1; t.quality = 1; t.edgesout = 1; t.zeroindex = 1; t.quiet = 1; t.verbose = verbose; ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); } { DMLabel glabel = NULL; const PetscInt numCorners = 4; const PetscInt numCells = out->numberoftetrahedra; const PetscInt numVertices = out->numberofpoints; double *meshCoords; int *cells = out->tetrahedronlist; if (sizeof (PetscReal) == sizeof (double)) { meshCoords = (double *) out->pointlist; } else { PetscInt i; ierr = PetscMalloc1(3 * numVertices,&meshCoords);CHKERRQ(ierr); for (i = 0; i < 3 * numVertices; i++) { meshCoords[i] = (PetscReal) out->pointlist[i]; } } ierr = DMPlexInvertCells_Internal(dim, numCells, numCorners, cells);CHKERRQ(ierr); ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, dim, meshCoords, dm);CHKERRQ(ierr); if (sizeof (PetscReal) != sizeof (double)) { ierr = PetscFree(meshCoords);CHKERRQ(ierr); } if (label) {ierr = DMCreateLabel(*dm, labelName); ierr = DMGetLabel(*dm, labelName, &glabel);} /* Set labels */ for (v = 0; v < numVertices; ++v) { if (out->pointmarkerlist[v]) { if (glabel) {ierr = DMLabelSetValue(glabel, v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr);} } } if (interpolate) { PetscInt e; for (e = 0; e < out->numberofedges; e++) { if (out->edgemarkerlist[e]) { const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; const PetscInt *edges; PetscInt numEdges; ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); if (glabel) {ierr = DMLabelSetValue(glabel, edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr);} ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); } } for (f = 0; f < out->numberoftrifaces; f++) { if (out->trifacemarkerlist[f]) { const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; const PetscInt *faces; PetscInt numFaces; ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); if (glabel) {ierr = DMLabelSetValue(glabel, faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr);} ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); } } } ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); } ierr = PLCDestroy(&in);CHKERRQ(ierr); ierr = PLCDestroy(&out);CHKERRQ(ierr); PetscFunctionReturn(0); }