PetscErrorCode DMPlexCreateHexBoxMesh(MPI_Comm comm, PetscInt dim, const PetscInt cells[], DM *dm) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(dm, 4); ierr = DMCreate(comm, dm);CHKERRQ(ierr); PetscValidLogicalCollectiveInt(*dm,dim,2); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); switch (dim) { case 2: { PetscReal lower[2] = {0.0, 0.0}; PetscReal upper[2] = {1.0, 1.0}; ierr = DMPlexCreateSquareMesh(*dm, lower, upper, cells);CHKERRQ(ierr); break; } #if 0 case 3: { PetscReal lower[3] = {0.0, 0.0, 0.0}; PetscReal upper[3] = {1.0, 1.0, 1.0}; ierr = DMPlexCreateCubeMesh(boundary, lower, upper, cells);CHKERRQ(ierr); break; } #endif default: SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim); } PetscFunctionReturn(0); }
EXTERN_C_END #undef __FUNCT__ #define __FUNCT__ "DMCartesianCreate" /*@ DMCartesianCreate - Creates a DMCartesian object. Collective on MPI_Comm Input Parameter: . comm - The communicator for the DMCartesian object Output Parameter: . mesh - The DMCartesian object Level: beginner .keywords: DMCartesian, create @*/ PetscErrorCode DMCartesianCreate(MPI_Comm comm, DM *mesh) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(mesh,2); ierr = DMCreate(comm, mesh); CHKERRQ(ierr); ierr = DMSetType(*mesh, DMCARTESIAN); CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc, char **argv) { PetscErrorCode ierr; DM dm, rdm; PetscViewer vwr; PetscBool flg; char datafile[PETSC_MAX_PATH_LEN]; MPI_Comm comm; ierr = PetscInitialize(&argc, &argv, NULL, help); if (ierr) return ierr; comm = PETSC_COMM_WORLD; ierr = PetscViewerCreate(comm, &vwr);CHKERRQ(ierr); ierr = PetscViewerSetType(vwr, PETSCVIEWERHDF5);CHKERRQ(ierr); ierr = PetscViewerFileSetMode(vwr, FILE_MODE_READ);CHKERRQ(ierr); ierr = PetscOptionsGetString(NULL, NULL, "-f", datafile, PETSC_MAX_PATH_LEN, &flg);CHKERRQ(ierr); if (!flg) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Must provide meshfile"); ierr = PetscViewerFileSetName(vwr, datafile);CHKERRQ(ierr); ierr = DMCreate(comm, &dm);CHKERRQ(ierr); ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); ierr = DMLoad(dm, vwr);CHKERRQ(ierr); ierr = PetscViewerDestroy(&vwr);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)dm, "BaryDM");CHKERRQ(ierr); ierr = DMViewFromOptions(dm, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMPlexSetRefinementUniform(dm, PETSC_TRUE);CHKERRQ(ierr); ierr = DMRefine(dm, comm, &rdm);CHKERRQ(ierr); ierr = DMDestroy(&dm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)rdm, "RefinedDM");CHKERRQ(ierr); ierr = DMViewFromOptions(rdm, NULL, "-refined_dm_view");CHKERRQ(ierr); ierr = DMDestroy(&rdm);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
PetscErrorCode CreateHex_3D(MPI_Comm comm, DM *newdm) { DM dm; PetscInt numPoints[2] = {12, 2}; PetscInt coneSize[14] = {8, 8, 0,0,0,0,0,0,0,0,0,0,0,0}; PetscInt cones[16] = {2,5,4,3,6,7,8,9, 3,4,11,10,7,12,13,8}; PetscInt coneOrientations[16] = {0,0,0,0,0,0,0,0, 0,0, 0, 0,0, 0, 0,0}; PetscScalar vertexCoords[36] = {-0.5,0.0,0.0, 0.0,0.0,0.0, 0.0,1.0,0.0, -0.5,1.0,0.0, -0.5,0.0,1.0, 0.0,0.0,1.0, 0.0,1.0,1.0, -0.5,1.0,1.0, 0.5,0.0,0.0, 0.5,1.0,0.0, 0.5,0.0,1.0, 0.5,1.0,1.0}; PetscInt markerPoints[24] = {2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1,10,1,11,1,12,1,13,1}; PetscInt dim = 3, depth = 1, p; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMCreate(comm, &dm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) dm, "hexahedral");CHKERRQ(ierr); ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(dm, dim);CHKERRQ(ierr); ierr = DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for(p = 0; p < 12; ++p) { ierr = DMPlexSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr); } *newdm = dm; PetscFunctionReturn(0); }
/*@C DMPlexInterpolate - Take in a cell-vertex mesh and return one with all intermediate faces, edges, etc. Collective on DM Input Parameters: + dm - The DMPlex object with only cells and vertices - dmInt - If NULL a new DM is created, otherwise the interpolated DM is put into the given DM Output Parameter: . dmInt - The complete DMPlex object Level: intermediate .keywords: mesh .seealso: DMPlexUninterpolate(), DMPlexCreateFromCellList() @*/ PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) { DM idm, odm = dm; PetscInt depth, dim, d; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscLogEventBegin(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); if (dim <= 1) { ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); idm = dm; } for (d = 1; d < dim; ++d) { /* Create interpolated mesh */ if ((d == dim-1) && *dmInt) {idm = *dmInt;} else {ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr);} ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); if (depth > 0) {ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr);} if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);} odm = idm; } *dmInt = idm; ierr = PetscLogEventEnd(DMPLEX_Interpolate,dm,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
EXTERN_C_END #undef __FUNCT__ #define __FUNCT__ "DMComplexCreate" /*@ DMComplexCreate - Creates a DMComplex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. Collective on MPI_Comm Input Parameter: . comm - The communicator for the DMComplex object Output Parameter: . mesh - The DMComplex object Level: beginner .keywords: DMComplex, create @*/ PetscErrorCode DMComplexCreate(MPI_Comm comm, DM *mesh) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(mesh,2); ierr = DMCreate(comm, mesh);CHKERRQ(ierr); ierr = DMSetType(*mesh, DMCOMPLEX);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMPatchCreateGrid(MPI_Comm comm, PetscInt dim, MatStencil patchSize, MatStencil commSize, MatStencil gridSize, DM *dm) { DM_Patch *mesh; DM da; PetscInt dof = 1, width = 1; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPatchCreate(comm, dm);CHKERRQ(ierr); mesh = (DM_Patch*) (*dm)->data; if (dim < 2) { gridSize.j = 1; patchSize.j = 1; } if (dim < 3) { gridSize.k = 1; patchSize.k = 1; } ierr = DMCreate(comm, &da); ierr = DMSetType(da, DMDA); ierr = DMSetDimension(da, dim);CHKERRQ(ierr); ierr = DMDASetSizes(da, gridSize.i, gridSize.j, gridSize.k);CHKERRQ(ierr); ierr = DMDASetBoundaryType(da, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE);CHKERRQ(ierr); ierr = DMDASetDof(da, dof);CHKERRQ(ierr); ierr = DMDASetStencilType(da, DMDA_STENCIL_BOX);CHKERRQ(ierr); ierr = DMDASetStencilWidth(da, width);CHKERRQ(ierr); mesh->dmCoarse = da; ierr = DMPatchSetPatchSize(*dm, patchSize);CHKERRQ(ierr); ierr = DMPatchSetCommSize(*dm, commSize);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) { PetscInt dim = user->dim; PetscBool refinementUniform = user->refinementUniform; PetscBool cellSimplex = user->cellSimplex; const char *partitioner = "chaco"; PetscMPIInt rank; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); switch(dim) { case 2: if (cellSimplex) { ierr = CreateSimplexHybrid_2D(comm, *dm);CHKERRQ(ierr); } else { SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make hybrid meshes for quadrilaterals"); } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make hybrid meshes for dimension %d", dim); } { DM refinedMesh = PETSC_NULL; DM distributedMesh = PETSC_NULL; /* Distribute mesh over processes */ ierr = DMPlexDistribute(*dm, partitioner, 0, &distributedMesh);CHKERRQ(ierr); if (distributedMesh) { PetscInt cMax = PETSC_DETERMINE, fMax = PETSC_DETERMINE; /* Do not know how to preserve this after distribution */ if (rank) { cMax = 1; fMax = 11; } ierr = DMPlexSetHybridBounds(distributedMesh, cMax, PETSC_DETERMINE, fMax, PETSC_DETERMINE);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = distributedMesh; } if (refinementUniform) { ierr = DMPlexSetRefinementUniform(*dm, refinementUniform);CHKERRQ(ierr); ierr = DMRefine(*dm, comm, &refinedMesh);CHKERRQ(ierr); if (refinedMesh) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = refinedMesh; } } } ierr = PetscObjectSetName((PetscObject) *dm, "Hybrid Mesh");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); user->dm = *dm; PetscFunctionReturn(0); }
/*@ DMDACreate - Creates a DMDA object. Collective on MPI_Comm Input Parameter: . comm - The communicator for the DMDA object Output Parameter: . da - The DMDA object Level: advanced Developers Note: Since there exists DMDACreate1/2/3d() should this routine even exist? .keywords: DMDA, create .seealso: DMDASetSizes(), DMDADuplicate(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d() @*/ PetscErrorCode DMDACreate(MPI_Comm comm, DM *da) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(da,2); ierr = DMCreate(comm,da);CHKERRQ(ierr); ierr = DMSetType(*da,DMDA);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMShellCreate - Creates a shell DM object, used to manage user-defined problem data Collective on MPI_Comm Input Parameter: . comm - the processors that will share the global vector Output Parameters: . shell - the shell DM Level: advanced .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateLocalVector() @*/ PetscErrorCode DMShellCreate(MPI_Comm comm,DM *dm) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(dm,2); ierr = DMCreate(comm,dm);CHKERRQ(ierr); ierr = DMSetType(*dm,DMSHELL);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMPatchCreate - Creates a DMPatch object, which is a collections of DMs called patches. Collective on MPI_Comm Input Parameter: . comm - The communicator for the DMPatch object Output Parameter: . mesh - The DMPatch object Level: beginner .keywords: DMPatch, create @*/ PetscErrorCode DMPatchCreate(MPI_Comm comm, DM *mesh) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(mesh,2); ierr = DMCreate(comm, mesh);CHKERRQ(ierr); ierr = DMSetType(*mesh, DMPATCH);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMCreateSubDM_DA(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) { DM_DA *da = (DM_DA*) dm->data; PetscSection section; PetscErrorCode ierr; PetscFunctionBegin; if (subdm) { PetscSF sf; Vec coords; void *ctx; /* Cannot use DMClone since the dof stuff is mixed in. Ugh ierr = DMClone(dm, subdm);CHKERRQ(ierr); */ ierr = DMCreate(PetscObjectComm((PetscObject)dm), subdm);CHKERRQ(ierr); ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); ierr = DMSetPointSF(*subdm, sf);CHKERRQ(ierr); ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); ierr = DMSetApplicationContext(*subdm, ctx);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); if (coords) { ierr = DMSetCoordinatesLocal(*subdm, coords);CHKERRQ(ierr); } else { ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); if (coords) {ierr = DMSetCoordinates(*subdm, coords);CHKERRQ(ierr);} } ierr = DMSetType(*subdm, DMDA);CHKERRQ(ierr); ierr = DMSetDimension(*subdm, dm->dim);CHKERRQ(ierr); ierr = DMDASetSizes(*subdm, da->M, da->N, da->P);CHKERRQ(ierr); ierr = DMDASetNumProcs(*subdm, da->m, da->n, da->p);CHKERRQ(ierr); ierr = DMDASetBoundaryType(*subdm, da->bx, da->by, da->bz);CHKERRQ(ierr); ierr = DMDASetDof(*subdm, numFields);CHKERRQ(ierr); ierr = DMDASetStencilType(*subdm, da->stencil_type);CHKERRQ(ierr); ierr = DMDASetStencilWidth(*subdm, da->s);CHKERRQ(ierr); ierr = DMDASetOwnershipRanges(*subdm, da->lx, da->ly, da->lz);CHKERRQ(ierr); } ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); if (section) { ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr); } else { if (is) { PetscInt *indices, cnt = 0, dof = da->w, i, j; ierr = PetscMalloc1(da->Nlocal*numFields/dof, &indices);CHKERRQ(ierr); for (i = da->base/dof; i < (da->base+da->Nlocal)/dof; ++i) { for (j = 0; j < numFields; ++j) { indices[cnt++] = dof*i + fields[j]; } } if (cnt != da->Nlocal*numFields/dof) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count %d does not equal expected value %d", cnt, da->Nlocal*numFields/dof); ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cnt, indices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
/*@C DMADDACreate - Creates and ADDA object that translate between coordinates in a geometric grid of arbitrary dimension and data in a PETSc vector distributed on several processors. Collective on MPI_Comm Input Parameters: + comm - MPI communicator . dim - the dimension of the grid . nodes - array with d entries that give the number of nodes in each dimension . procs - array with d entries that give the number of processors in each dimension (or NULL if to be determined automatically) . dof - number of degrees of freedom per node - periodic - array with d entries that, i-th entry is set to true iff dimension i is periodic Output Parameters: . adda - pointer to ADDA data structure that is created Level: intermediate @*/ PetscErrorCode DMADDACreate(MPI_Comm comm, PetscInt dim, PetscInt *nodes,PetscInt *procs,PetscInt dof, PetscBool *periodic,DM *dm_p) { PetscErrorCode ierr; PetscFunctionBegin; ierr = DMCreate(comm,dm_p);CHKERRQ(ierr); ierr = DMSetType(*dm_p,DMADDA);CHKERRQ(ierr); ierr = DMADDASetParameters(*dm_p,dim,nodes,procs,dof,periodic);CHKERRQ(ierr); ierr = DMSetUp(*dm_p);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMRedundantCreate - Creates a DM object, used to manage data for dense globally coupled variables Collective on MPI_Comm Input Parameter: + comm - the processors that will share the global vector . rank - rank to own the redundant values - N - total number of degrees of freedom Output Parameters: . red - the redundant DM Level: advanced .seealso DMDestroy(), DMCreateGlobalVector(), DMCreateMatrix(), DMCompositeAddDM(), DMREDUNDANT, DMSetType(), DMRedundantSetSize(), DMRedundantGetSize() @*/ PetscErrorCode DMRedundantCreate(MPI_Comm comm,PetscInt rank,PetscInt N,DM *dm) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(dm,2); ierr = DMCreate(comm,dm);CHKERRQ(ierr); ierr = DMSetType(*dm,DMREDUNDANT);CHKERRQ(ierr); ierr = DMRedundantSetSize(*dm,rank,N);CHKERRQ(ierr); ierr = DMSetUp(*dm);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMPlexUninterpolate - Take in a mesh with all intermediate faces, edges, etc. and return a cell-vertex mesh Collective on DM Input Parameter: . dm - The complete DMPlex object Output Parameter: . dmUnint - The DMPlex object with only cells and vertices Level: intermediate .keywords: mesh .seealso: DMPlexInterpolate(), DMPlexCreateFromCellList() @*/ PetscErrorCode DMPlexUninterpolate(DM dm, DM *dmUnint) { DM udm; PetscInt dim, vStart, vEnd, cStart, cEnd, c, maxConeSize = 0, *cone; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); if (dim <= 1) { ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); *dmUnint = dm; PetscFunctionReturn(0); } ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMCreate(PetscObjectComm((PetscObject) dm), &udm);CHKERRQ(ierr); ierr = DMSetType(udm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(udm, dim);CHKERRQ(ierr); ierr = DMPlexSetChart(udm, cStart, vEnd);CHKERRQ(ierr); for (c = cStart; c < cEnd; ++c) { PetscInt *closure = NULL, closureSize, cl, coneSize = 0; ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); for (cl = 0; cl < closureSize*2; cl += 2) { const PetscInt p = closure[cl]; if ((p >= vStart) && (p < vEnd)) ++coneSize; } ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); ierr = DMPlexSetConeSize(udm, c, coneSize);CHKERRQ(ierr); maxConeSize = PetscMax(maxConeSize, coneSize); } ierr = DMSetUp(udm);CHKERRQ(ierr); ierr = PetscMalloc1(maxConeSize, &cone);CHKERRQ(ierr); for (c = cStart; c < cEnd; ++c) { PetscInt *closure = NULL, closureSize, cl, coneSize = 0; ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); for (cl = 0; cl < closureSize*2; cl += 2) { const PetscInt p = closure[cl]; if ((p >= vStart) && (p < vEnd)) cone[coneSize++] = p; } ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); ierr = DMPlexSetCone(udm, c, cone);CHKERRQ(ierr); } ierr = PetscFree(cone);CHKERRQ(ierr); ierr = DMPlexSymmetrize(udm);CHKERRQ(ierr); ierr = DMPlexStratify(udm);CHKERRQ(ierr); *dmUnint = udm; PetscFunctionReturn(0); }
PetscErrorCode DMLibMeshCreateDomainDecompositionDM(DM dm, PetscInt dnumber, PetscInt* dsizes, char*** dblocklists, DM* ddm) { PetscErrorCode ierr; PetscBool islibmesh; PetscFunctionBegin; PetscValidHeaderSpecific(dm,DM_CLASSID,1); ierr = PetscObjectTypeCompare((PetscObject)dm, DMLIBMESH,&islibmesh); if(!islibmesh) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Got DM oftype %s, not of type %s", ((PetscObject)dm)->type_name, DMLIBMESH); if(dnumber < 0) SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative number %D of decomposition parts", dnumber); PetscValidPointer(ddm,5); DM_libMesh *dlm = (DM_libMesh *)(dm->data); ierr = DMCreate(((PetscObject)dm)->comm, ddm); CHKERRQ(ierr); ierr = DMSetType(*ddm, DMLIBMESH); CHKERRQ(ierr); DM_libMesh *ddlm = (DM_libMesh *)((*ddm)->data); ddlm->sys = dlm->sys; ddlm->varids = dlm->varids; ddlm->varnames = dlm->varnames; ddlm->blockids = dlm->blockids; ddlm->blocknames = dlm->blocknames; ddlm->decomposition = new(std::vector<std::set<unsigned int> >); ddlm->decomposition_type = DMLIBMESH_DOMAIN_DECOMPOSITION; if(dnumber) { for(PetscInt d = 0; d < dnumber; ++d) { if(dsizes[d] < 0) SETERRQ2(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Negative size %D of decomposition part %D", dsizes[d],d); ddlm->decomposition->push_back(std::set<unsigned int>()); for(PetscInt b = 0; b < dsizes[d]; ++b) { std::string bname(dblocklists[d][b]); std::map<std::string, unsigned int>::const_iterator bit = dlm->blockids->find(bname); if(bit == dlm->blockids->end()) SETERRQ3(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONG, "Block %D on the %D-th list with name %s is not owned by this DM", b, d, dblocklists[d][b]); unsigned int bid = bit->second; (*ddlm->decomposition)[d].insert(bid); } } } else { /* Empty splits indicate default: split all blocks with one per split. */ PetscInt d = 0; for(std::map<std::string, unsigned int>::const_iterator bit = ddlm->blockids->begin(); bit != ddlm->blockids->end(); ++bit) { ddlm->decomposition->push_back(std::set<unsigned int>()); unsigned int bid = bit->second; std::string bname = bit->first; (*ddlm->decomposition)[d].insert(bid); ++d; } } ierr = DMLibMeshSetUpName_Private(*ddm); CHKERRQ(ierr); ierr = DMSetFromOptions(*ddm); CHKERRQ(ierr); ierr = DMSetUp(*ddm); CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMMeshCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool interpolate, DM *dm) { PetscBool flg; PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(dm, 4); ierr = PetscOptionsBool("-dm_mesh_new_impl", "Use the new C unstructured mesh implementation", "DMView", PETSC_FALSE, &flg, PETSC_NULL);CHKERRQ(ierr); if (flg) { DM boundary; if (interpolate) {SETERRQ(comm, PETSC_ERR_SUP, "Interpolation (creation of faces and edges) is not yet supported.");} ierr = DMCreate(comm, &boundary);CHKERRQ(ierr); PetscValidLogicalCollectiveInt(boundary,dim,2); ierr = DMSetType(boundary, DMMESH);CHKERRQ(ierr); ierr = DMMeshSetDimension(boundary, dim-1);CHKERRQ(ierr); switch(dim) { case 2: { PetscReal lower[2] = {0.0, 0.0}; PetscReal upper[2] = {1.0, 1.0}; PetscInt edges[2] = {2, 2}; ierr = DMMeshCreateSquareBoundary(boundary, lower, upper, edges);CHKERRQ(ierr); break; } case 3: { PetscReal lower[3] = {0.0, 0.0, 0.0}; PetscReal upper[3] = {1.0, 1.0, 1.0}; PetscInt faces[3] = {1, 1, 1}; ierr = DMMeshCreateCubeBoundary(boundary, lower, upper, faces);CHKERRQ(ierr); break; } default: SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim); } ierr = DMMeshGenerate(boundary, interpolate, dm);CHKERRQ(ierr); ierr = DMDestroy(&boundary);CHKERRQ(ierr); } else { PetscInt debug = 0; try { ierr = ALE::DMBuilder::createBoxMesh(comm, dim, false, interpolate, debug, dm);CHKERRQ(ierr); } catch(ALE::Exception e) { SETERRQ1(comm, PETSC_ERR_PLIB, "Unable to create mesh: %s", e.message()); } } PetscFunctionReturn(0); }
EXTERN_C_END #undef __FUNCT__ #define __FUNCT__ "DMSlicedCreate" /*@C DMSlicedCreate - Creates a DM object, used to manage data for a unstructured problem Collective on MPI_Comm Input Parameter: + comm - the processors that will share the global vector . bs - the block size . nlocal - number of vector entries on this process . Nghosts - number of ghost points needed on this process . ghosts - global indices of all ghost points for this process . d_nnz - matrix preallocation information representing coupling within this process - o_nnz - matrix preallocation information representing coupling between this process and other processes Output Parameters: . slice - the slice object Notes: This DM does not support DMCreateLocalVector(), DMGlobalToLocalBegin(), and DMGlobalToLocalEnd() instead one directly uses VecGhostGetLocalForm() and VecGhostRestoreLocalForm() to access the local representation and VecGhostUpdateBegin() and VecGhostUpdateEnd() to update the ghost points. One can use DMGlobalToLocalBegin(), and DMGlobalToLocalEnd() instead of VecGhostUpdateBegin() and VecGhostUpdateEnd(). Level: advanced .seealso DMDestroy(), DMCreateGlobalVector(), DMSetType(), DMSLICED, DMSlicedSetGhosts(), DMSlicedSetPreallocation(), VecGhostUpdateBegin(), VecGhostUpdateEnd(), VecGhostGetLocalForm(), VecGhostRestoreLocalForm() @*/ PetscErrorCode DMSlicedCreate(MPI_Comm comm,PetscInt bs,PetscInt nlocal,PetscInt Nghosts,const PetscInt ghosts[], const PetscInt d_nnz[],const PetscInt o_nnz[],DM *dm) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(dm,2); ierr = DMCreate(comm,dm);CHKERRQ(ierr); ierr = DMSetType(*dm,DMSLICED);CHKERRQ(ierr); ierr = DMSlicedSetGhosts(*dm,bs,nlocal,Nghosts,ghosts);CHKERRQ(ierr); if (d_nnz) { ierr = DMSlicedSetPreallocation(*dm,0, d_nnz,0,o_nnz);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode DMClone_DA(DM dm, DM *newdm) { DM_DA *da = (DM_DA *) dm->data; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMSetType(*newdm, DMDA);CHKERRQ(ierr); ierr = DMSetDimension(*newdm, dm->dim);CHKERRQ(ierr); ierr = DMDASetSizes(*newdm, da->M, da->N, da->P);CHKERRQ(ierr); ierr = DMDASetNumProcs(*newdm, da->m, da->n, da->p);CHKERRQ(ierr); ierr = DMDASetBoundaryType(*newdm, da->bx, da->by, da->bz);CHKERRQ(ierr); ierr = DMDASetDof(*newdm, da->w);CHKERRQ(ierr); ierr = DMDASetStencilType(*newdm, da->stencil_type);CHKERRQ(ierr); ierr = DMDASetStencilWidth(*newdm, da->s);CHKERRQ(ierr); ierr = DMDASetOwnershipRanges(*newdm, da->lx, da->ly, da->lz);CHKERRQ(ierr); ierr = DMSetUp(*newdm);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMPlexCreateFromCellList - This takes as input common mesh generator output, a list of the vertices for each cell, and produces a DM Input Parameters: + comm - The communicator . dim - The topological dimension of the mesh . numCells - The number of cells . numVertices - The number of vertices . numCorners - The number of vertices for each cell . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically . cells - An array of numCells*numCorners numbers, the vertices for each cell . spaceDim - The spatial dimension used for coordinates - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex Output Parameter: . dm - The DM Note: Two triangles sharing a face $ $ 2 $ / | \ $ / | \ $ / | \ $ 0 0 | 1 3 $ \ | / $ \ | / $ \ | / $ 1 would have input $ numCells = 2, numVertices = 4 $ cells = [0 1 2 1 3 2] $ which would result in the DMPlex $ $ 4 $ / | \ $ / | \ $ / | \ $ 2 0 | 1 5 $ \ | / $ \ | / $ \ | / $ 3 Level: beginner .seealso: DMPlexCreate() @*/ PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], PetscInt spaceDim, const double vertexCoords[], DM *dm) { PetscErrorCode ierr; PetscFunctionBegin; ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); if (interpolate) { DM idm; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } ierr = DMPlexBuildCoordinates_Private(*dm, spaceDim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMPlexInterpolate(DM dm, DM *dmInt) { DM idm, odm = dm; PetscInt dim, d; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); for (d = 1; d < dim; ++d) { /* Create interpolated mesh */ ierr = DMCreate(PetscObjectComm((PetscObject)dm), &idm);CHKERRQ(ierr); ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); ierr = DMPlexInterpolateFaces_Internal(odm, 1, idm);CHKERRQ(ierr); if (odm != dm) {ierr = DMDestroy(&odm);CHKERRQ(ierr);} odm = idm; } *dmInt = idm; PetscFunctionReturn(0); }
/*@ DMMeshCreateMeshFromAdjacency - Create an unstrctured mesh from a list of the vertices for each cell, and the coordinates for each vertex. Collective on comm Input Parameters: + comm - An MPI communicator . dim - The dimension of the cells, e.g. triangles have dimension 2 . numCells - The number of cells in the mesh . numCorners - The number of vertices in each cell . cellVertices - An array of the vertices for each cell, numbered 0 to numVertices-1 . spatialDim - The dimension for coordinates, e.g. for a triangle in 3D this would be 3 . numVertices - The number of mesh vertices . coordinates - An array of the coordinates for each vertex - interpolate - Flag to create faces and edges Output Parameter: . dm - The DMMesh object Level: beginner .seealso DMMESH, DMMeshCreateMeshFromAdjacencyHybrid(), DMMeshCreateBoxMesh() @*/ PetscErrorCode DMMeshCreateMeshFromAdjacency(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numCorners, PetscInt cellVertices[], PetscInt spatialDim, PetscInt numVertices, const PetscReal coordinates[], PetscBool interpolate, DM *dm) { PetscInt *cone; PetscInt *coneO; PetscInt debug = 0; PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(cellVertices, 5); /* PetscValidLogicalCollectiveBool(comm,interpolate,6); */ PetscValidPointer(dm, 7); if (interpolate) {SETERRQ(comm, PETSC_ERR_SUP, "Interpolation (creation of faces and edges) is not yet supported.");} ierr = PetscOptionsGetInt(PETSC_NULL, "-dm_mesh_debug", &debug, PETSC_NULL);CHKERRQ(ierr); Obj<PETSC_MESH_TYPE> mesh = new PETSC_MESH_TYPE(comm, dim, debug); Obj<PETSC_MESH_TYPE::sieve_type> sieve = new PETSC_MESH_TYPE::sieve_type(comm, 0, numCells+numVertices, debug); mesh->setSieve(sieve); for(PetscInt c = 0; c < numCells; ++c) { sieve->setConeSize(c, numCorners); } sieve->symmetrizeSizes(numCells, numCorners, cellVertices, numCells); sieve->allocate(); ierr = PetscMalloc2(numCorners,PetscInt,&cone,numCorners,PetscInt,&coneO);CHKERRQ(ierr); for(PetscInt v = 0; v < numCorners; ++v) { coneO[v] = 1; } for(PetscInt c = 0; c < numCells; ++c) { for(PetscInt v = 0; v < numCorners; ++v) { cone[v] = cellVertices[c*numCorners+v]+numCells; } sieve->setCone(cone, c); sieve->setConeOrientation(coneO, c); } ierr = PetscFree2(cone,coneO);CHKERRQ(ierr); sieve->symmetrize(); mesh->stratify(); ALE::SieveBuilder<PETSC_MESH_TYPE>::buildCoordinates(mesh, spatialDim, coordinates, numCells); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMMESH);CHKERRQ(ierr); ierr = DMMeshSetMesh(*dm, mesh);CHKERRQ(ierr); PetscFunctionReturn(0); }
EXTERN_C_END #undef __FUNCT__ #define __FUNCT__ "DMADDACreate" /*@C DMADDACreate - Creates and ADDA object that translate between coordinates in a geometric grid of arbitrary dimension and data in a PETSc vector distributed on several processors. Collective on MPI_Comm Input Parameters: + comm - MPI communicator . dim - the dimension of the grid . nodes - array with d entries that give the number of nodes in each dimension . procs - array with d entries that give the number of processors in each dimension (or PETSC_NULL if to be determined automatically) . dof - number of degrees of freedom per node - periodic - array with d entries that, i-th entry is set to true iff dimension i is periodic Output Parameters: . adda - pointer to ADDA data structure that is created Level: intermediate @*/ PetscErrorCode DMADDACreate(MPI_Comm comm, PetscInt dim, PetscInt *nodes,PetscInt *procs,PetscInt dof, PetscBool *periodic,DM *dm_p) { PetscErrorCode ierr; PetscFunctionBegin; ierr = DMCreate(comm,dm_p);CHKERRQ(ierr); ierr = DMSetType(*dm_p,DMADDA);CHKERRQ(ierr); ierr = DMADDASetParameters(*dm_p,dim,nodes,procs,dof,periodic);CHKERRQ(ierr); ierr = DMSetUp(*dm_p);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box). Collective on MPI_Comm Input Parameters: + comm - The communicator for the DM object . dim - The spatial dimension - interpolate - Flag to create intermediate mesh pieces (edges, faces) Output Parameter: . dm - The DM object Level: beginner .keywords: DM, create .seealso: DMSetType(), DMCreate() @*/ PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool interpolate, DM *dm) { DM boundary; PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(dm, 4); ierr = DMCreate(comm, &boundary);CHKERRQ(ierr); PetscValidLogicalCollectiveInt(boundary,dim,2); ierr = DMSetType(boundary, DMPLEX);CHKERRQ(ierr); ierr = DMPlexSetDimension(boundary, dim-1);CHKERRQ(ierr); switch (dim) { case 2: { PetscReal lower[2] = {0.0, 0.0}; PetscReal upper[2] = {1.0, 1.0}; PetscInt edges[2] = {2, 2}; ierr = DMPlexCreateSquareBoundary(boundary, lower, upper, edges);CHKERRQ(ierr); break; } case 3: { PetscReal lower[3] = {0.0, 0.0, 0.0}; PetscReal upper[3] = {1.0, 1.0, 1.0}; PetscInt faces[3] = {1, 1, 1}; ierr = DMPlexCreateCubeBoundary(boundary, lower, upper, faces);CHKERRQ(ierr); break; } default: SETERRQ1(comm, PETSC_ERR_SUP, "Dimension not supported: %d", dim); } ierr = DMPlexGenerate(boundary, NULL, interpolate, dm);CHKERRQ(ierr); ierr = DMDestroy(&boundary);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@C DMStagCreate1d - Create an object to manage data living on the faces, edges, and vertices of a parallelized regular 1D grid. Collective Input Parameters: + comm - MPI communicator . bndx - boundary type: DM_BOUNDARY_NONE, DM_BOUNDARY_PERIODIC, or DM_BOUNDARY_GHOSTED . M - global number of grid points . dof0 - number of degrees of freedom per vertex/point/node/0-cell . dof1 - number of degrees of freedom per element/edge/1-cell . stencilType - ghost/halo region type: DMSTAG_STENCIL_BOX or DMSTAG_STENCIL_NONE . stencilWidth - width, in elements, of halo/ghost region - lx - array of local sizes, of length equal to the comm size, summing to M Output Parameter: . dm - the new DMStag object Options Database Keys: + -dm_view - calls DMViewFromOptions() a the conclusion of DMSetUp() . -stag_grid_x <nx> - number of elements in the x direction . -stag_ghost_stencil_width - width of ghost region, in elements - -stag_boundary_type_x <none,ghosted,periodic> - DMBoundaryType value Notes: You must call DMSetUp() after this call before using the DM. If you wish to use the options database (see the keys above) to change values in the DMStag, you must call DMSetFromOptions() after this function but before DMSetUp(). Level: beginner .seealso: DMSTAG, DMStagCreate2d(), DMStagCreate3d(), DMDestroy(), DMView(), DMCreateGlobalVector(), DMCreateLocalVector(), DMLocalToGlobalBegin() @*/ PETSC_EXTERN PetscErrorCode DMStagCreate1d(MPI_Comm comm,DMBoundaryType bndx,PetscInt M,PetscInt dof0,PetscInt dof1,DMStagStencilType stencilType,PetscInt stencilWidth,const PetscInt lx[],DM* dm) { PetscErrorCode ierr; DM_Stag *stag; PetscMPIInt size; PetscFunctionBegin; ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = DMCreate(comm,dm);CHKERRQ(ierr); ierr = DMSetDimension(*dm,1);CHKERRQ(ierr); /* Must precede DMSetType */ ierr = DMSetType(*dm,DMSTAG);CHKERRQ(ierr); stag = (DM_Stag*)(*dm)->data; /* Global sizes and flags (derived quantities set in DMSetUp_Stag) */ stag->boundaryType[0] = bndx; stag->N[0] = M; stag->nRanks[0] = size; stag->stencilType = stencilType; stag->stencilWidth = stencilWidth; ierr = DMStagSetDOF(*dm,dof0,dof1,0,0);CHKERRQ(ierr); ierr = DMStagSetOwnershipRanges(*dm,lx,NULL,NULL);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode CreateSimplex_2D(MPI_Comm comm, DM *newdm) { DM dm; PetscInt numPoints[2] = {4, 2}; PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; PetscInt markerPoints[8] = {2, 1, 3, 1, 4, 1, 5, 1}; PetscInt dim = 2, depth = 1, p; PetscErrorCode ierr; PetscFunctionBegin; ierr = DMCreate(comm, &dm);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) dm, "triangular");CHKERRQ(ierr); ierr = DMSetType(dm, DMPLEX);CHKERRQ(ierr); ierr = DMSetDimension(dm, dim);CHKERRQ(ierr); ierr = DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords);CHKERRQ(ierr); for (p = 0; p < 4; ++p) { ierr = DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr); } *newdm = dm; PetscFunctionReturn(0); }
/*@ DMPlexPermute - Reorder the mesh according to the input permutation Collective on DM Input Parameter: + dm - The DMPlex object - perm - The point permutation, perm[old point number] = new point number Output Parameter: . pdm - The permuted DM Level: intermediate .keywords: mesh .seealso: MatPermute() @*/ PetscErrorCode DMPlexPermute(DM dm, IS perm, DM *pdm) { DM_Plex *plex = (DM_Plex *) dm->data, *plexNew; PetscSection section, sectionNew; PetscInt dim; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidHeaderSpecific(perm, IS_CLASSID, 2); PetscValidPointer(pdm, 3); ierr = DMCreate(PetscObjectComm((PetscObject) dm), pdm);CHKERRQ(ierr); ierr = DMSetType(*pdm, DMPLEX);CHKERRQ(ierr); ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); ierr = DMSetDimension(*pdm, dim);CHKERRQ(ierr); ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); if (section) { ierr = PetscSectionPermute(section, perm, §ionNew);CHKERRQ(ierr); ierr = DMSetDefaultSection(*pdm, sectionNew);CHKERRQ(ierr); ierr = PetscSectionDestroy(§ionNew);CHKERRQ(ierr); } plexNew = (DM_Plex *) (*pdm)->data; /* Ignore ltogmap, ltogmapb */ /* Ignore sf, defaultSF */ /* Ignore globalVertexNumbers, globalCellNumbers */ /* Remap coordinates */ { DM cdm, cdmNew; PetscSection csection, csectionNew; Vec coordinates, coordinatesNew; PetscScalar *coords, *coordsNew; const PetscInt *pperm; PetscInt pStart, pEnd, p; const char *name; ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); ierr = DMGetDefaultSection(cdm, &csection);CHKERRQ(ierr); ierr = PetscSectionPermute(csection, perm, &csectionNew);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); ierr = VecDuplicate(coordinates, &coordinatesNew);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject)coordinates,&name);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject)coordinatesNew,name);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); ierr = PetscSectionGetChart(csectionNew, &pStart, &pEnd);CHKERRQ(ierr); ierr = ISGetIndices(perm, &pperm);CHKERRQ(ierr); for (p = pStart; p < pEnd; ++p) { PetscInt dof, off, offNew, d; ierr = PetscSectionGetDof(csectionNew, p, &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csection, p, &off);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csectionNew, pperm[p], &offNew);CHKERRQ(ierr); for (d = 0; d < dof; ++d) coordsNew[offNew+d] = coords[off+d]; } ierr = ISRestoreIndices(perm, &pperm);CHKERRQ(ierr); ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); ierr = DMGetCoordinateDM(*pdm, &cdmNew);CHKERRQ(ierr); ierr = DMSetDefaultSection(cdmNew, csectionNew);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(*pdm, coordinatesNew);CHKERRQ(ierr); ierr = PetscSectionDestroy(&csectionNew);CHKERRQ(ierr); ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); } /* Reorder labels */ { PetscInt numLabels, l; DMLabel label, labelNew; ierr = DMGetNumLabels(dm, &numLabels);CHKERRQ(ierr); for (l = numLabels-1; l >= 0; --l) { ierr = DMGetLabelByNum(dm, l, &label);CHKERRQ(ierr); ierr = DMLabelPermute(label, perm, &labelNew);CHKERRQ(ierr); ierr = DMAddLabel(*pdm, labelNew);CHKERRQ(ierr); } if (plex->subpointMap) {ierr = DMLabelPermute(plex->subpointMap, perm, &plexNew->subpointMap);CHKERRQ(ierr);} } /* Reorder topology */ { const PetscInt *pperm; PetscInt maxConeSize, maxSupportSize, n, pStart, pEnd, p; ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); plexNew->maxConeSize = maxConeSize; plexNew->maxSupportSize = maxSupportSize; ierr = PetscSectionDestroy(&plexNew->coneSection);CHKERRQ(ierr); ierr = PetscSectionPermute(plex->coneSection, perm, &plexNew->coneSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(plexNew->coneSection, &n);CHKERRQ(ierr); ierr = PetscMalloc1(n, &plexNew->cones);CHKERRQ(ierr); ierr = PetscMalloc1(n, &plexNew->coneOrientations);CHKERRQ(ierr); ierr = ISGetIndices(perm, &pperm);CHKERRQ(ierr); ierr = PetscSectionGetChart(plex->coneSection, &pStart, &pEnd);CHKERRQ(ierr); for (p = pStart; p < pEnd; ++p) { PetscInt dof, off, offNew, d; ierr = PetscSectionGetDof(plexNew->coneSection, pperm[p], &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(plex->coneSection, p, &off);CHKERRQ(ierr); ierr = PetscSectionGetOffset(plexNew->coneSection, pperm[p], &offNew);CHKERRQ(ierr); for (d = 0; d < dof; ++d) { plexNew->cones[offNew+d] = pperm[plex->cones[off+d]]; plexNew->coneOrientations[offNew+d] = plex->coneOrientations[off+d]; } } ierr = PetscSectionDestroy(&plexNew->supportSection);CHKERRQ(ierr); ierr = PetscSectionPermute(plex->supportSection, perm, &plexNew->supportSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(plexNew->supportSection, &n);CHKERRQ(ierr); ierr = PetscMalloc1(n, &plexNew->supports);CHKERRQ(ierr); ierr = PetscSectionGetChart(plex->supportSection, &pStart, &pEnd);CHKERRQ(ierr); for (p = pStart; p < pEnd; ++p) { PetscInt dof, off, offNew, d; ierr = PetscSectionGetDof(plexNew->supportSection, pperm[p], &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(plex->supportSection, p, &off);CHKERRQ(ierr); ierr = PetscSectionGetOffset(plexNew->supportSection, pperm[p], &offNew);CHKERRQ(ierr); for (d = 0; d < dof; ++d) { plexNew->supports[offNew+d] = pperm[plex->supports[off+d]]; } } ierr = ISRestoreIndices(perm, &pperm);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ DMPlexCreateGmsh - Create a DMPlex mesh from a Gmsh file. Collective on comm Input Parameters: + comm - The MPI communicator . viewer - The Viewer associated with a Gmsh file - interpolate - Create faces and edges in the mesh Output Parameter: . dm - The DM object representing the mesh Note: http://www.geuz.org/gmsh/doc/texinfo/#MSH-ASCII-file-format Level: beginner .keywords: mesh,Gmsh .seealso: DMPLEX, DMCreate() @*/ PetscErrorCode DMPlexCreateGmsh(MPI_Comm comm, PetscViewer viewer, PetscBool interpolate, DM *dm) { FILE *fd; PetscSection coordSection; Vec coordinates; PetscScalar *coords, *coordsIn = NULL; PetscInt dim = 0, coordSize, c, v, d; int numVertices = 0, numCells = 0, snum; long fpos = 0; PetscMPIInt num_proc, rank; char line[PETSC_MAX_PATH_LEN]; PetscBool match; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); if (!rank) { PetscBool match; int fileType, dataSize; ierr = PetscViewerASCIIGetPointer(viewer, &fd);CHKERRQ(ierr); /* Read header */ fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$MeshFormat\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); snum = fscanf(fd, "2.2 %d %d\n", &fileType, &dataSize);CHKERRQ(snum != 2); if (fileType) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File type %d is not a valid Gmsh ASCII file", fileType); if (dataSize != sizeof(double)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data size %d is not valid for a Gmsh file", dataSize); fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$EndMeshFormat\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); /* Read vertices */ fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$Nodes\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); snum = fscanf(fd, "%d\n", &numVertices);CHKERRQ(snum != 1); ierr = PetscMalloc(numVertices*3 * sizeof(PetscScalar), &coordsIn);CHKERRQ(ierr); for (v = 0; v < numVertices; ++v) { double x, y, z; int i; snum = fscanf(fd, "%d %lg %lg %lg\n", &i, &x, &y, &z);CHKERRQ(snum != 4); coordsIn[v*3+0] = x; coordsIn[v*3+1] = y; coordsIn[v*3+2] = z; if (i != v+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid node number %d should be %d", i, v+1); } fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$EndNodes\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); /* Read cells */ fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$Elements\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); snum = fscanf(fd, "%d\n", &numCells);CHKERRQ(snum != 1); } ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); if (!rank) { fpos = ftell(fd); for (c = 0; c < numCells; ++c) { PetscInt numCorners, t; int cone[8], i, cellType, numTags, tag; snum = fscanf(fd, "%d %d %d", &i, &cellType, &numTags);CHKERRQ(snum != 3); if (numTags) for (t = 0; t < numTags; ++t) {snum = fscanf(fd, "%d", &tag);CHKERRQ(snum != 1);} switch (cellType) { case 1: /* 2-node line */ dim = 1; numCorners = 2; snum = fscanf(fd, "%d %d\n", &cone[0], &cone[1]);CHKERRQ(snum != numCorners); break; case 2: /* 3-node triangle */ dim = 2; numCorners = 3; snum = fscanf(fd, "%d %d %d\n", &cone[0], &cone[1], &cone[2]);CHKERRQ(snum != numCorners); break; case 3: /* 4-node quadrangle */ dim = 2; numCorners = 4; snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != numCorners); break; case 4: /* 4-node tetrahedron */ dim = 3; numCorners = 4; snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != numCorners); break; case 5: /* 8-node hexahedron */ dim = 3; numCorners = 8; snum = fscanf(fd, "%d %d %d %d %d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3], &cone[4], &cone[5], &cone[6], &cone[7]);CHKERRQ(snum != numCorners); break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported Gmsh element type %d", cellType); } ierr = DMPlexSetConeSize(*dm, c, numCorners);CHKERRQ(ierr); if (i != c+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell number %d should be %d", i, c+1); } } ierr = DMSetUp(*dm);CHKERRQ(ierr); if (!rank) { ierr = fseek(fd, fpos, SEEK_SET);CHKERRQ(ierr); for (c = 0; c < numCells; ++c) { PetscInt pcone[8], numCorners, corner, t; int cone[8], i, cellType, numTags, tag; snum = fscanf(fd, "%d %d %d", &i, &cellType, &numTags);CHKERRQ(snum != 3); if (numTags) for (t = 0; t < numTags; ++t) {snum = fscanf(fd, "%d", &tag);CHKERRQ(snum != 1);} switch (cellType) { case 1: /* 2-node line */ dim = 1; numCorners = 2; snum = fscanf(fd, "%d %d\n", &cone[0], &cone[1]);CHKERRQ(snum != numCorners); break; case 2: /* 3-node triangle */ dim = 2; numCorners = 3; snum = fscanf(fd, "%d %d %d\n", &cone[0], &cone[1], &cone[2]);CHKERRQ(snum != numCorners); break; case 3: /* 4-node quadrangle */ dim = 2; numCorners = 4; snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != numCorners); break; case 4: /* 4-node tetrahedron */ dim = 3; numCorners = 4; snum = fscanf(fd, "%d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3]);CHKERRQ(snum != numCorners); ierr = DMPlexInvertCell(dim, numCorners, cone);CHKERRQ(ierr); break; case 5: /* 8-node hexahedron */ dim = 3; numCorners = 8; snum = fscanf(fd, "%d %d %d %d %d %d %d %d\n", &cone[0], &cone[1], &cone[2], &cone[3], &cone[4], &cone[5], &cone[6], &cone[7]);CHKERRQ(snum != numCorners); ierr = DMPlexInvertCell(dim, numCorners, cone);CHKERRQ(ierr); break; default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unsupported Gmsh element type %d", cellType); } for (corner = 0; corner < numCorners; ++corner) pcone[corner] = cone[corner] + numCells-1; ierr = DMPlexSetCone(*dm, c, pcone);CHKERRQ(ierr); if (i != c+1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid cell number %d should be %d", i, c+1); } fgets(line, PETSC_MAX_PATH_LEN, fd); ierr = PetscStrncmp(line, "$EndElements\n", PETSC_MAX_PATH_LEN, &match);CHKERRQ(ierr); if (!match) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "File is not a valid Gmsh file"); } ierr = MPI_Bcast(&dim, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); ierr = DMPlexStratify(*dm);CHKERRQ(ierr); if (interpolate) { DM idm; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } /* Read coordinates */ ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); for (v = numCells; v < numCells+numVertices; ++v) { ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); ierr = VecCreate(comm, &coordinates);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); ierr = VecSetType(coordinates, VECSTANDARD);CHKERRQ(ierr); ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); if (!rank) { for (v = 0; v < numVertices; ++v) { for (d = 0; d < dim; ++d) { coords[v*dim+d] = coordsIn[v*3+d]; } } } ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); ierr = PetscFree(coordsIn);CHKERRQ(ierr); ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); ierr = VecDestroy(&coordinates);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMCoarsen_AKKT(DM dm, MPI_Comm comm, DM *cdm) { PetscErrorCode ierr; DM_AKKT* kkt = (DM_AKKT*)(dm->data); Mat Acc; /* coarse-level KKT matrix */ Mat P0f0c, P1f1c; /* Primal and dual block prolongator */ DM dmc[2] = {PETSC_NULL, PETSC_NULL}; /* Coarse subDMs defining the block prolongators and the coarsened decomposition. */ PetscInt M0,N0,M1,N1; /* Sizes of P0f0c and P1f1c. */ PetscInt start0,end0,start1,end1; /* Ownership ranges for P0f0c and P1f1c. */ static Mat mats[4] = {PETSC_NULL, PETSC_NULL, PETSC_NULL, PETSC_NULL}; /* Used to construct MatNest out of pieces. */ IS isc[2]; /* Used to construct MatNest out of pieces and to define the coarsened decomposition. */ PetscFunctionBegin; if(!cdm) PetscFunctionReturn(0); if(kkt->cdm) { ierr = PetscObjectReference((PetscObject)(kkt->cdm)); CHKERRQ(ierr); *cdm = kkt->cdm; PetscFunctionReturn(0); } /* Coarsen the 00 block with the attached DM and obtain the primal prolongator. */ if(kkt->dmf[0]) { ierr = DMCoarsen(kkt->dmf[0], comm, dmc+0); CHKERRQ(ierr); ierr = DMCreateInterpolation(dmc[0], kkt->dmf[0], &P0f0c, PETSC_NULL); CHKERRQ(ierr); } else SETERRQ(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Could not coarsen the primal block: primal subDM not set."); /* Should P0f0c be transposed to act as a prolongator (i.e., to map from coarse to fine). */ ierr = MatGetSize(P0f0c, &M0, &N0); CHKERRQ(ierr); if(M0 == N0) SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE,"Primal prolongator is square with size %D: cannot distinguish coarse from fine",M0); if(M0 < N0) kkt->transposeP = PETSC_TRUE; else kkt->transposeP = PETSC_FALSE; /* See if the 11 block can be coarsened with an attached DM. If so, we are done. Otherwise, use GAMG to coarsen 11. */ if(kkt->dmf[1]) { ierr = DMCoarsen(kkt->dmf[1], comm, &dmc[1]); CHKERRQ(ierr); ierr = DMCreateInterpolation(dmc[1], kkt->dmf[1], &P1f1c, PETSC_NULL); CHKERRQ(ierr); } else { ierr = DMCoarsen_AKKT_GAMG11(dm, P0f0c, &P1f1c); CHKERRQ(ierr); } /* Determine whether P1f1c should be transposed in order to act as a prolongator (i.e., to map from coarse to fine). */ ierr = MatGetSize(P1f1c, &M1, &N1); CHKERRQ(ierr); if(M1 == N1) SETERRQ1(((PetscObject)dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Dual prlongator is square with size %D: cannot distinguish coarse from fine", M1); if((M1 < N1 && !kkt->transposeP) || (M1 >= N1 && kkt->transposeP)) { Mat P1f1ct; ierr = MatTranspose(P1f1c, MAT_INITIAL_MATRIX, &P1f1ct); CHKERRQ(ierr); ierr = MatDestroy(&P1f1c); CHKERRQ(ierr); P1f1c = P1f1ct; } /* MatNest P0f0c, P1f1c together into Pfc. */ mats[0] = P0f0c; mats[3] = P1f1c; ierr = MatGetOwnershipRange(P0f0c, &start0, &end0); CHKERRQ(ierr); ierr = MatGetOwnershipRange(P1f1c, &start1, &end1); CHKERRQ(ierr); ierr = ISCreateStride(((PetscObject)dm)->comm, end0-start0,start0,1,isc+0); CHKERRQ(ierr); ierr = ISCreateStride(((PetscObject)dm)->comm, end1-start1,start1,1,isc+1); CHKERRQ(ierr); if(kkt->transposeP) { ierr = MatCreateNest(((PetscObject)dm)->comm,2,isc,2,kkt->isf,mats,&(kkt->Pfc)); CHKERRQ(ierr); } else { ierr = MatCreateNest(((PetscObject)dm)->comm,2,kkt->isf,2,isc,mats,&(kkt->Pfc)); CHKERRQ(ierr); } ierr = MatDestroy(&P0f0c); CHKERRQ(ierr); ierr = MatDestroy(&P1f1c); CHKERRQ(ierr); /* Coarsening the underlying matrix and primal-dual decomposition. */ /* We do not coarsen the underlying DM because (a) Its coarsening may be incompatible with the specialized KKT-aware coarsening of the blocks defined here. (b) Even if the coarsening the decomposition is compatible with the decomposition of the coarsening, we can pick the former without loss of generality. (c) Even if (b) is true, the embeddings (IS) of the coarsened subDMs are potentially different now from what they would be in the coarsened DM; thus, embeddings would have to be supplied manually anyhow. (d) In the typical situation we should only use the primal subDM for coarsening -- the whole point of DMAKKT is that the dual block coarsening should be derived from the primal block coarsening for compatibility. If we are given both subDMs, DMAKKT essentially becomes a version of DMComposite, in which case the composition of the coarsened decomposition is by definition the coarsening of the whole system DM. */ /* Create the coarser DM. */ ierr = DMCreate(((PetscObject)dm)->comm, &(kkt->cdm)); CHKERRQ(ierr); ierr = DMSetType(kkt->cdm, DMAKKT); CHKERRQ(ierr); /* Coarsen the underlying matrix. */ ierr = MatPtAP(kkt->Aff, kkt->Pfc, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &Acc); CHKERRQ(ierr); ierr = DMAKKTSetMatrix(dm, Acc); CHKERRQ(ierr); /* Set the coarsened decomposition. */ ierr = DMAKKTSetFieldDecomposition(kkt->cdm, 2, (const char**)kkt->names, isc, dmc); CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) { PetscInt dim = user->dim; PetscBool cellHybrid = user->cellHybrid; PetscBool cellSimplex = user->cellSimplex; PetscMPIInt rank, size; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); ierr = DMCreate(comm, dm);CHKERRQ(ierr); ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); switch (dim) { case 1: if (cellHybrid) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make hybrid meshes for dimension %d", dim); ierr = CreateSimplex_1D(comm, dm);CHKERRQ(ierr); break; case 2: if (cellSimplex) { if (cellHybrid) { ierr = CreateSimplexHybrid_2D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateSimplex_2D(comm, dm);CHKERRQ(ierr); } } else { if (cellHybrid) { ierr = CreateTensorProductHybrid_2D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateTensorProduct_2D(comm, user->testNum, dm);CHKERRQ(ierr); } } break; case 3: if (cellSimplex) { if (cellHybrid) { ierr = CreateSimplexHybrid_3D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateSimplex_3D(comm, user->testNum, dm);CHKERRQ(ierr); } } else { if (cellHybrid) { ierr = CreateTensorProductHybrid_3D(comm, user->testNum, dm);CHKERRQ(ierr); } else { ierr = CreateTensorProduct_3D(comm, user->testNum, dm);CHKERRQ(ierr); } } break; default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %d", dim); } if (user->testPartition && size > 1) { PetscPartitioner part; PetscInt *sizes = NULL; PetscInt *points = NULL; if (!rank) { if (dim == 2 && cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt triSizes_p2[2] = {1, 1}; PetscInt triPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, triSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, triPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular mesh on 2 procs", user->testNum); } } else if (dim == 2 && cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt triSizes_p2[2] = {1, 2}; PetscInt triPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, triSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, triPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular hybrid mesh on 2 procs", user->testNum); } } else if (dim == 2 && !cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt quadSizes_p2[2] = {1, 1}; PetscInt quadPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, quadSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, quadPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for quadrilateral mesh on 2 procs", user->testNum); } } else if (dim == 2 && !cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt quadSizes_p2[2] = {1, 2}; PetscInt quadPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, quadSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, quadPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for quadrilateral hybrid mesh on 2 procs", user->testNum); } } else if (dim == 3 && cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt tetSizes_p2[2] = {1, 1}; PetscInt tetPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt tetSizes_p2[2] = {1, 1}; PetscInt tetPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for tetrahedral mesh on 2 procs", user->testNum); } } else if (dim == 3 && cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt tetSizes_p2[2] = {1, 2}; PetscInt tetPoints_p2[3] = {0, 1, 2}; ierr = PetscMalloc2(2, &sizes, 3, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 3 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt tetSizes_p2[2] = {3, 4}; PetscInt tetPoints_p2[7] = {0, 3, 5, 1, 2, 4, 6}; ierr = PetscMalloc2(2, &sizes, 7, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, tetSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, tetPoints_p2, 7 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for tetrahedral hybrid mesh on 2 procs", user->testNum); } } else if (dim == 3 && !cellSimplex && !cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt hexSizes_p2[2] = {1, 1}; PetscInt hexPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for hexahedral mesh on 2 procs", user->testNum); } } else if (dim == 3 && !cellSimplex && cellHybrid && size == 2) { switch (user->testNum) { case 0: { PetscInt hexSizes_p2[2] = {1, 1}; PetscInt hexPoints_p2[2] = {0, 1}; ierr = PetscMalloc2(2, &sizes, 2, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr);break;} case 1: { PetscInt hexSizes_p2[2] = {5, 4}; PetscInt hexPoints_p2[9] = {3, 4, 5, 7, 8, 0, 1, 2, 6}; ierr = PetscMalloc2(2, &sizes, 9, &points);CHKERRQ(ierr); ierr = PetscMemcpy(sizes, hexSizes_p2, 2 * sizeof(PetscInt));CHKERRQ(ierr); ierr = PetscMemcpy(points, hexPoints_p2, 9 * sizeof(PetscInt));CHKERRQ(ierr);break;} default: SETERRQ1(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for hexahedral hybrid mesh on 2 procs", user->testNum); } } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test partition"); } ierr = DMPlexGetPartitioner(*dm, &part);CHKERRQ(ierr); ierr = PetscPartitionerSetType(part, PETSCPARTITIONERSHELL);CHKERRQ(ierr); ierr = PetscPartitionerShellSetPartition(part, size, sizes, points);CHKERRQ(ierr); ierr = PetscFree2(sizes, points);CHKERRQ(ierr); } else { PetscPartitioner part; ierr = DMPlexGetPartitioner(*dm,&part);CHKERRQ(ierr); ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); } { DM pdm = NULL; ierr = DMPlexDistribute(*dm, 0, NULL, &pdm);CHKERRQ(ierr); if (pdm) { ierr = DMViewFromOptions(pdm, NULL, "-dm_view");CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = pdm; } } ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); if (user->simplex2tensor) { DM rdm = NULL; ierr = DMPlexSetRefinementUniform(*dm, PETSC_TRUE);CHKERRQ(ierr); ierr = DMPlexRefineSimplexToTensor(*dm, &rdm);CHKERRQ(ierr); if (rdm) { ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = rdm; } user->cellSimplex = PETSC_FALSE; } if (user->uninterpolate || user->reinterpolate) { DM udm = NULL; ierr = DMPlexUninterpolate(*dm, &udm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, udm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = udm; } if (user->reinterpolate) { DM idm = NULL; ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); ierr = DMPlexCopyCoordinates(*dm, idm);CHKERRQ(ierr); ierr = DMDestroy(dm);CHKERRQ(ierr); *dm = idm; } ierr = PetscObjectSetName((PetscObject) *dm, "Hybrid Mesh");CHKERRQ(ierr); ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); ierr = PetscObjectSetOptionsPrefix((PetscObject) *dm, "hyb_");CHKERRQ(ierr); ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); PetscFunctionReturn(0); }