/*@ DMNetworkLayoutSetUp - Sets up the bare layout (graph) for the network Collective on DM Input Parameters . DM - the dmnetwork object Notes: This routine should be called after the network sizes and edgelists have been provided. It creates the bare layout of the network and sets up the network to begin insertion of components. All the components should be registered before calling this routine. Level: intermediate .seealso: DMNetworkSetSizes, DMNetworkSetEdgeList @*/ PetscErrorCode DMNetworkLayoutSetUp(DM dm) { PetscErrorCode ierr; DM_Network *network = (DM_Network*) dm->data; PetscInt dim = 1; /* One dimensional network */ PetscInt numCorners=2; PetscInt spacedim=2; double *vertexcoords=NULL; PetscInt i; PetscInt ndata; PetscFunctionBegin; if (network->nNodes) { ierr = PetscMalloc1(numCorners*network->nNodes,&vertexcoords);CHKERRQ(ierr); } ierr = DMPlexCreateFromCellList(PetscObjectComm((PetscObject)dm),dim,network->nEdges,network->nNodes,numCorners,PETSC_FALSE,network->edges,spacedim,vertexcoords,&network->plex);CHKERRQ(ierr); if (network->nNodes) { ierr = PetscFree(vertexcoords);CHKERRQ(ierr); } ierr = DMPlexGetChart(network->plex,&network->pStart,&network->pEnd);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(network->plex,0,&network->eStart,&network->eEnd);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(network->plex,1,&network->vStart,&network->vEnd);CHKERRQ(ierr); ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DataSection);CHKERRQ(ierr); ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&network->DofSection);CHKERRQ(ierr); ierr = PetscSectionSetChart(network->DataSection,network->pStart,network->pEnd);CHKERRQ(ierr); ierr = PetscSectionSetChart(network->DofSection,network->pStart,network->pEnd);CHKERRQ(ierr); network->dataheadersize = sizeof(struct _p_DMNetworkComponentHeader)/sizeof(DMNetworkComponentGenericDataType); ierr = PetscMalloc1(network->pEnd-network->pStart,&network->header);CHKERRQ(ierr); for (i = network->pStart; i < network->pEnd; i++) { network->header[i].ndata = 0; ndata = network->header[i].ndata; ierr = PetscSectionAddDof(network->DataSection,i,network->dataheadersize);CHKERRQ(ierr); network->header[i].offset[ndata] = 0; } ierr = PetscMalloc1(network->pEnd-network->pStart,&network->cvalue);CHKERRQ(ierr); PetscFunctionReturn(0); }
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); }
PetscErrorCode DMCoarsen_Plex(DM dm, MPI_Comm comm, DM *dmCoarsened) { DM_Plex *mesh = (DM_Plex*) dm->data; #ifdef PETSC_HAVE_PRAGMATIC DM udm, coordDM; DMLabel bd; Mat A; Vec coordinates, mb, mx; PetscSection coordSection; const PetscScalar *coords; double *coarseCoords; IS bdIS; PetscReal *x, *y, *z, *eqns, *metric; PetscReal coarseRatio = PetscSqr(0.5); const PetscInt *faces; PetscInt *cells, *bdFaces, *bdFaceIds; PetscInt dim, numCorners, cStart, cEnd, numCells, numCoarseCells, c, vStart, vEnd, numVertices, numCoarseVertices, v, numBdFaces, f, maxConeSize, size, bdSize, coff; #endif PetscErrorCode ierr; PetscFunctionBegin; #ifdef PETSC_HAVE_PRAGMATIC if (!mesh->coarseMesh) { ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); ierr = DMGetCoordinateDM(dm, &coordDM);CHKERRQ(ierr); ierr = DMGetDefaultSection(coordDM, &coordSection);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMPlexUninterpolate(dm, &udm);CHKERRQ(ierr); ierr = DMPlexGetMaxSizes(udm, &maxConeSize, NULL);CHKERRQ(ierr); numCells = cEnd - cStart; numVertices = vEnd - vStart; ierr = PetscCalloc5(numVertices, &x, numVertices, &y, numVertices, &z, numVertices*PetscSqr(dim), &metric, numCells*maxConeSize, &cells);CHKERRQ(ierr); ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); for (v = vStart; v < vEnd; ++v) { PetscInt off; ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); x[v-vStart] = coords[off+0]; y[v-vStart] = coords[off+1]; if (dim > 2) z[v-vStart] = coords[off+2]; } ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); for (c = 0, coff = 0; c < numCells; ++c) { const PetscInt *cone; PetscInt coneSize, cl; ierr = DMPlexGetConeSize(udm, c, &coneSize);CHKERRQ(ierr); ierr = DMPlexGetCone(udm, c, &cone);CHKERRQ(ierr); for (cl = 0; cl < coneSize; ++cl) cells[coff++] = cone[cl] - vStart; } switch (dim) { case 2: pragmatic_2d_init(&numVertices, &numCells, cells, x, y); break; case 3: pragmatic_3d_init(&numVertices, &numCells, cells, x, y, z); break; default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No Pragmatic coarsening defined for dimension %d", dim); } /* Create boundary mesh */ ierr = DMLabelCreate("boundary", &bd);CHKERRQ(ierr); ierr = DMPlexMarkBoundaryFaces(dm, bd);CHKERRQ(ierr); ierr = DMLabelGetStratumIS(bd, 1, &bdIS);CHKERRQ(ierr); ierr = DMLabelGetStratumSize(bd, 1, &numBdFaces);CHKERRQ(ierr); ierr = ISGetIndices(bdIS, &faces);CHKERRQ(ierr); for (f = 0, bdSize = 0; f < numBdFaces; ++f) { PetscInt *closure = NULL; PetscInt closureSize, cl; ierr = DMPlexGetTransitiveClosure(dm, faces[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); for (cl = 0; cl < closureSize*2; cl += 2) { if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) ++bdSize; } ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); } ierr = PetscMalloc2(bdSize, &bdFaces, numBdFaces, &bdFaceIds);CHKERRQ(ierr); for (f = 0, bdSize = 0; f < numBdFaces; ++f) { PetscInt *closure = NULL; PetscInt closureSize, cl; ierr = DMPlexGetTransitiveClosure(dm, faces[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); for (cl = 0; cl < closureSize*2; cl += 2) { if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) bdFaces[bdSize++] = closure[cl] - vStart; } /* TODO Fix */ bdFaceIds[f] = 1; ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); } ierr = ISDestroy(&bdIS);CHKERRQ(ierr); ierr = DMLabelDestroy(&bd);CHKERRQ(ierr); pragmatic_set_boundary(&numBdFaces, bdFaces, bdFaceIds); /* Create metric */ size = (dim*(dim+1))/2; ierr = PetscMalloc1(PetscSqr(size), &eqns);CHKERRQ(ierr); ierr = MatCreateSeqDense(PETSC_COMM_SELF, size, size, eqns, &A);CHKERRQ(ierr); ierr = MatCreateVecs(A, &mx, &mb);CHKERRQ(ierr); ierr = VecSet(mb, 1.0);CHKERRQ(ierr); for (c = 0; c < numCells; ++c) { const PetscScalar *sol; PetscScalar *cellCoords = NULL; PetscReal e[3], vol; const PetscInt *cone; PetscInt coneSize, cl, i, j, d, r; ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, NULL, &cellCoords);CHKERRQ(ierr); /* Only works for simplices */ for (i = 0, r = 0; i < dim+1; ++i) { for (j = 0; j < i; ++j, ++r) { for (d = 0; d < dim; ++d) e[d] = cellCoords[i*dim+d] - cellCoords[j*dim+d]; /* FORTRAN ORDERING */ if (dim == 2) { eqns[0*size+r] = PetscSqr(e[0]); eqns[1*size+r] = 2.0*e[0]*e[1]; eqns[2*size+r] = PetscSqr(e[1]); } else { eqns[0*size+r] = PetscSqr(e[0]); eqns[1*size+r] = 2.0*e[0]*e[1]; eqns[2*size+r] = 2.0*e[0]*e[2]; eqns[3*size+r] = PetscSqr(e[1]); eqns[4*size+r] = 2.0*e[1]*e[2]; eqns[5*size+r] = PetscSqr(e[2]); } } } ierr = MatSetUnfactored(A);CHKERRQ(ierr); ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, NULL, &cellCoords);CHKERRQ(ierr); ierr = MatLUFactor(A, NULL, NULL, NULL);CHKERRQ(ierr); ierr = MatSolve(A, mb, mx);CHKERRQ(ierr); ierr = VecGetArrayRead(mx, &sol);CHKERRQ(ierr); ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol, NULL, NULL);CHKERRQ(ierr); ierr = DMPlexGetCone(udm, c, &cone);CHKERRQ(ierr); ierr = DMPlexGetConeSize(udm, c, &coneSize);CHKERRQ(ierr); for (cl = 0; cl < coneSize; ++cl) { const PetscInt v = cone[cl] - vStart; if (dim == 2) { metric[v*4+0] += vol*coarseRatio*sol[0]; metric[v*4+1] += vol*coarseRatio*sol[1]; metric[v*4+2] += vol*coarseRatio*sol[1]; metric[v*4+3] += vol*coarseRatio*sol[2]; } else { metric[v*9+0] += vol*coarseRatio*sol[0]; metric[v*9+1] += vol*coarseRatio*sol[1]; metric[v*9+3] += vol*coarseRatio*sol[1]; metric[v*9+2] += vol*coarseRatio*sol[2]; metric[v*9+6] += vol*coarseRatio*sol[2]; metric[v*9+4] += vol*coarseRatio*sol[3]; metric[v*9+5] += vol*coarseRatio*sol[4]; metric[v*9+7] += vol*coarseRatio*sol[4]; metric[v*9+8] += vol*coarseRatio*sol[5]; } } ierr = VecRestoreArrayRead(mx, &sol);CHKERRQ(ierr); } for (v = 0; v < numVertices; ++v) { const PetscInt *support; PetscInt supportSize, s; PetscReal vol, totVol = 0.0; ierr = DMPlexGetSupport(udm, v+vStart, &support);CHKERRQ(ierr); ierr = DMPlexGetSupportSize(udm, v+vStart, &supportSize);CHKERRQ(ierr); for (s = 0; s < supportSize; ++s) {ierr = DMPlexComputeCellGeometryFVM(dm, support[s], &vol, NULL, NULL);CHKERRQ(ierr); totVol += vol;} for (s = 0; s < PetscSqr(dim); ++s) metric[v*PetscSqr(dim)+s] /= totVol; } ierr = VecDestroy(&mx);CHKERRQ(ierr); ierr = VecDestroy(&mb);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = DMDestroy(&udm);CHKERRQ(ierr); ierr = PetscFree(eqns);CHKERRQ(ierr); pragmatic_set_metric(metric); pragmatic_adapt(); /* Read out mesh */ pragmatic_get_info(&numCoarseVertices, &numCoarseCells); ierr = PetscMalloc1(numCoarseVertices*dim, &coarseCoords);CHKERRQ(ierr); switch (dim) { case 2: pragmatic_get_coords_2d(x, y); numCorners = 3; for (v = 0; v < numCoarseVertices; ++v) {coarseCoords[v*2+0] = x[v]; coarseCoords[v*2+1] = y[v];} break; case 3: pragmatic_get_coords_3d(x, y, z); numCorners = 4; for (v = 0; v < numCoarseVertices; ++v) {coarseCoords[v*3+0] = x[v]; coarseCoords[v*3+1] = y[v]; coarseCoords[v*3+2] = z[v];} break; default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No Pragmatic coarsening defined for dimension %d", dim); } pragmatic_get_elements(cells); /* TODO Read out markers for boundary */ ierr = DMPlexCreateFromCellList(PetscObjectComm((PetscObject) dm), dim, numCoarseCells, numCoarseVertices, numCorners, PETSC_TRUE, cells, dim, coarseCoords, &mesh->coarseMesh);CHKERRQ(ierr); pragmatic_finalize(); ierr = PetscFree5(x, y, z, metric, cells);CHKERRQ(ierr); ierr = PetscFree2(bdFaces, bdFaceIds);CHKERRQ(ierr); ierr = PetscFree(coarseCoords);CHKERRQ(ierr); } #endif ierr = PetscObjectReference((PetscObject) mesh->coarseMesh);CHKERRQ(ierr); *dmCoarsened = mesh->coarseMesh; PetscFunctionReturn(0); }
PETSC_EXTERN void PETSC_STDCALL dmplexcreatefromcelllist_(MPI_Comm *comm, PetscInt *dim, PetscInt *numCells, PetscInt *numVertices, PetscInt *numCorners, PetscBool *interpolate, const int cells[], PetscInt *spaceDim, const double vertexCoords[], DM *dm, int *ierr) { *ierr = DMPlexCreateFromCellList(*comm, *dim, *numCells, *numVertices, *numCorners, *interpolate, cells, *spaceDim, vertexCoords, dm); }
// Read in a mesh from a file DM NewMesh(MPI_Comm comm, unsigned overlap) { FILE * input = fopen("CubedSphere.mesh","r"); // Read in vertex co-ordinates size_t dim = 3; size_t vertex_count; fscanf(input, " %zu ", &vertex_count); assert(vertex_count == 1572866); double * vertices = calloc(vertex_count*dim, sizeof(*vertices)); for (size_t vertex=0; vertex<vertex_count; ++vertex) { for (int d=0; d<dim; ++d) { int read = fscanf(input, " %lf ", &vertices[vertex*dim+d]); assert(read == 1); } } assert(vertices[0] == -1.00000000000000000); assert(vertices[3] == -0.99999529380957619); // Read in each face's vertex id size_t corners = 4; size_t face_count; fscanf(input, " %zu ", &face_count); assert(face_count == 1572864); int * faces = calloc(face_count*corners, sizeof(*faces)); for (size_t face=0; face<face_count; ++face) { for (int c=0; c<corners; ++c) { int read = fscanf(input, " %d ", &faces[corners*face+c]); assert(read == 1); // Vertex ids are 0-based in petsc --faces[corners*face+c]; } } assert(faces[0] == 1232838-1); assert(faces[4] == 1233870-1); fclose(input); int rank; MPI_Comm_rank(comm,&rank); DM mesh = NULL; if (rank == 0) { DMPlexCreateFromCellList(comm, // MPI Communicator 2, // Spatial dimension of graph face_count, // Number of faces vertex_count, // Number of vertices corners, // Number of vertices per face PETSC_FALSE, // Create edges faces, // Vertex IDs for each face dim, // Vertex dimension vertices, // Co-ordinates of each vertex &mesh); // Output } else { DMPlexCreateFromCellList(comm, 2, 0, 0, corners, PETSC_FALSE, NULL, dim, NULL, &mesh); } DM distmesh = NULL; DMPlexDistribute(mesh, NULL, overlap, &distmesh); if (distmesh) { mesh = distmesh; } free(faces); free(vertices); return mesh; }