10bbe5d31Sbarral #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 20bbe5d31Sbarral #ifdef PETSC_HAVE_PRAGMATIC 30bbe5d31Sbarral #include <pragmatic/cpragmatic.h> 40bbe5d31Sbarral #endif 50bbe5d31Sbarral 6*f7bcbcbbSMatthew G. Knepley #undef __FUNCT__ 7*f7bcbcbbSMatthew G. Knepley #define __FUNCT__ "DMPlexRemesh_Internal" 8*f7bcbcbbSMatthew G. Knepley /* 9*f7bcbcbbSMatthew G. Knepley DMPlexRemesh_Internal - Generates a new mesh conforming to a metric field. 100bbe5d31Sbarral 11*f7bcbcbbSMatthew G. Knepley Input Parameters: 12*f7bcbcbbSMatthew G. Knepley + dm - The DM object 13*f7bcbcbbSMatthew G. Knepley . vertexMetric - The metric to which the mesh is adapted, defined vertex-wise. 14*f7bcbcbbSMatthew G. Knepley - bdLabelName - Label name for boundary tags which are preserved in dmNew, or NULL. Should not be "_boundary_". 15*f7bcbcbbSMatthew G. Knepley 16*f7bcbcbbSMatthew G. Knepley Output Parameter: 17*f7bcbcbbSMatthew G. Knepley . dmNew - the new DM 18*f7bcbcbbSMatthew G. Knepley 19*f7bcbcbbSMatthew G. Knepley Level: advanced 20*f7bcbcbbSMatthew G. Knepley 21*f7bcbcbbSMatthew G. Knepley .seealso: DMCoarsen(), DMRefine() 22*f7bcbcbbSMatthew G. Knepley */ 23*f7bcbcbbSMatthew G. Knepley PetscErrorCode DMPlexRemesh_Internal(DM dm, Vec vertexMetric, const char bdLabelName[], DM *dmNew) 24*f7bcbcbbSMatthew G. Knepley { 25*f7bcbcbbSMatthew G. Knepley const char *bdName = "_boundary_"; 26*f7bcbcbbSMatthew G. Knepley DM udm, cdm; 27*f7bcbcbbSMatthew G. Knepley DMLabel bdLabel = NULL, bdLabelFull, bdLabelNew; 28*f7bcbcbbSMatthew G. Knepley IS bdIS; 29*f7bcbcbbSMatthew G. Knepley PetscSection coordSection; 30*f7bcbcbbSMatthew G. Knepley Vec coordinates; 31*f7bcbcbbSMatthew G. Knepley const PetscScalar *coords, *met; 32*f7bcbcbbSMatthew G. Knepley PetscScalar *coordsNew; 33*f7bcbcbbSMatthew G. Knepley const PetscInt *bdFacesFull; 34*f7bcbcbbSMatthew G. Knepley PetscInt *bdFaces, *bdFaceIds, *bdTags; 35*f7bcbcbbSMatthew G. Knepley PetscReal *x, *y, *z, *metric; 36*f7bcbcbbSMatthew G. Knepley PetscReal *xNew[3] = {NULL, NULL, NULL}; 37*f7bcbcbbSMatthew G. Knepley PetscInt *cells, *cellsNew; 38*f7bcbcbbSMatthew G. Knepley PetscInt dim, d, cStart, cEnd, numCells, numCellsNew, c, coff, vStart, vEnd, numVertices, numVerticesNew, v; 39*f7bcbcbbSMatthew G. Knepley PetscInt off, maxConeSize, numCornersNew, numBdFaces, fStart, fEnd, f, bdSize; 40*f7bcbcbbSMatthew G. Knepley PetscBool flg; 41*f7bcbcbbSMatthew G. Knepley PetscErrorCode ierr; 42*f7bcbcbbSMatthew G. Knepley 43*f7bcbcbbSMatthew G. Knepley PetscFunctionBegin; 44*f7bcbcbbSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 45*f7bcbcbbSMatthew G. Knepley PetscValidHeaderSpecific(vertexMetric, VEC_CLASSID, 2); 46*f7bcbcbbSMatthew G. Knepley PetscValidCharPointer(bdLabelName, 3); 47*f7bcbcbbSMatthew G. Knepley PetscValidPointer(dmNew, 4); 48*f7bcbcbbSMatthew G. Knepley if (bdLabelName) { 49*f7bcbcbbSMatthew G. Knepley size_t len; 50*f7bcbcbbSMatthew G. Knepley 51*f7bcbcbbSMatthew G. Knepley ierr = PetscStrcmp(bdLabelName, bdName, &flg);CHKERRQ(ierr); 52*f7bcbcbbSMatthew G. Knepley if (flg) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "\"%s\" cannot be used as label for boundary facets", bdLabelName); 53*f7bcbcbbSMatthew G. Knepley ierr = PetscStrlen(bdLabelName, &len);CHKERRQ(ierr); 54*f7bcbcbbSMatthew G. Knepley if (len) { 55*f7bcbcbbSMatthew G. Knepley ierr = DMGetLabel(dm, bdLabelName, &bdLabel);CHKERRQ(ierr); 56*f7bcbcbbSMatthew G. Knepley if (!bdLabel) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Label \"%s\" does not exist in DM", bdLabelName); 57*f7bcbcbbSMatthew G. Knepley } 58*f7bcbcbbSMatthew G. Knepley } 59*f7bcbcbbSMatthew G. Knepley /* Get mesh information */ 60*f7bcbcbbSMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 61*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 62*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 63*f7bcbcbbSMatthew G. Knepley ierr = DMPlexUninterpolate(dm, &udm);CHKERRQ(ierr); 64*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetMaxSizes(udm, &maxConeSize, NULL);CHKERRQ(ierr); 65*f7bcbcbbSMatthew G. Knepley numCells = cEnd - cStart; 66*f7bcbcbbSMatthew G. Knepley numVertices = vEnd - vStart; 67*f7bcbcbbSMatthew G. Knepley ierr = PetscCalloc5(numVertices, &x, numVertices, &y, numVertices, &z, numVertices*PetscSqr(dim), &metric, numCells*maxConeSize, &cells);CHKERRQ(ierr); 68*f7bcbcbbSMatthew G. Knepley for (c = 0, coff = 0; c < numCells; ++c) { 69*f7bcbcbbSMatthew G. Knepley const PetscInt *cone; 70*f7bcbcbbSMatthew G. Knepley PetscInt coneSize, cl; 71*f7bcbcbbSMatthew G. Knepley 72*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetConeSize(udm, c, &coneSize);CHKERRQ(ierr); 73*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetCone(udm, c, &cone);CHKERRQ(ierr); 74*f7bcbcbbSMatthew G. Knepley for (cl = 0; cl < coneSize; ++cl) cells[coff++] = cone[cl] - vStart; 75*f7bcbcbbSMatthew G. Knepley } 76*f7bcbcbbSMatthew G. Knepley ierr = DMDestroy(&udm);CHKERRQ(ierr); 77*f7bcbcbbSMatthew G. Knepley ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 78*f7bcbcbbSMatthew G. Knepley ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 79*f7bcbcbbSMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 80*f7bcbcbbSMatthew G. Knepley ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 81*f7bcbcbbSMatthew G. Knepley for (v = vStart; v < vEnd; ++v) { 82*f7bcbcbbSMatthew G. Knepley ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 83*f7bcbcbbSMatthew G. Knepley x[v-vStart] = coords[off+0]; 84*f7bcbcbbSMatthew G. Knepley if (dim > 1) y[v-vStart] = coords[off+1]; 85*f7bcbcbbSMatthew G. Knepley if (dim > 2) z[v-vStart] = coords[off+2]; 86*f7bcbcbbSMatthew G. Knepley } 87*f7bcbcbbSMatthew G. Knepley ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 88*f7bcbcbbSMatthew G. Knepley /* Get boundary mesh */ 89*f7bcbcbbSMatthew G. Knepley ierr = DMLabelCreate(bdName, &bdLabelFull);CHKERRQ(ierr); 90*f7bcbcbbSMatthew G. Knepley ierr = DMPlexMarkBoundaryFaces(dm, bdLabelFull);CHKERRQ(ierr); 91*f7bcbcbbSMatthew G. Knepley ierr = DMLabelGetStratumIS(bdLabelFull, 1, &bdIS);CHKERRQ(ierr); 92*f7bcbcbbSMatthew G. Knepley ierr = DMLabelGetStratumSize(bdLabelFull, 1, &numBdFaces);CHKERRQ(ierr); 93*f7bcbcbbSMatthew G. Knepley ierr = ISGetIndices(bdIS, &bdFacesFull);CHKERRQ(ierr); 94*f7bcbcbbSMatthew G. Knepley for (f = 0, bdSize = 0; f < numBdFaces; ++f) { 95*f7bcbcbbSMatthew G. Knepley PetscInt *closure = NULL; 96*f7bcbcbbSMatthew G. Knepley PetscInt closureSize, cl; 97*f7bcbcbbSMatthew G. Knepley 98*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 99*f7bcbcbbSMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 100*f7bcbcbbSMatthew G. Knepley if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) ++bdSize; 101*f7bcbcbbSMatthew G. Knepley } 102*f7bcbcbbSMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 103*f7bcbcbbSMatthew G. Knepley } 104*f7bcbcbbSMatthew G. Knepley ierr = PetscMalloc2(bdSize, &bdFaces, numBdFaces, &bdFaceIds);CHKERRQ(ierr); 105*f7bcbcbbSMatthew G. Knepley for (f = 0, bdSize = 0; f < numBdFaces; ++f) { 106*f7bcbcbbSMatthew G. Knepley PetscInt *closure = NULL; 107*f7bcbcbbSMatthew G. Knepley PetscInt closureSize, cl; 108*f7bcbcbbSMatthew G. Knepley 109*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 110*f7bcbcbbSMatthew G. Knepley for (cl = 0; cl < closureSize*2; cl += 2) { 111*f7bcbcbbSMatthew G. Knepley if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) bdFaces[bdSize++] = closure[cl] - vStart; 112*f7bcbcbbSMatthew G. Knepley } 113*f7bcbcbbSMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 114*f7bcbcbbSMatthew G. Knepley if (bdLabel) {ierr = DMLabelGetValue(bdLabel, bdFacesFull[f], &bdFaceIds[f]);CHKERRQ(ierr);} 115*f7bcbcbbSMatthew G. Knepley else {bdFaceIds[f] = 1;} 116*f7bcbcbbSMatthew G. Knepley } 117*f7bcbcbbSMatthew G. Knepley ierr = ISDestroy(&bdIS);CHKERRQ(ierr); 118*f7bcbcbbSMatthew G. Knepley ierr = DMLabelDestroy(&bdLabelFull);CHKERRQ(ierr); 119*f7bcbcbbSMatthew G. Knepley /* Get metric */ 120*f7bcbcbbSMatthew G. Knepley ierr = VecGetArrayRead(vertexMetric, &met);CHKERRQ(ierr); 121*f7bcbcbbSMatthew G. Knepley for (v = 0; v < (vEnd-vStart)*PetscSqr(dim); ++v) metric[v] = met[v]; 122*f7bcbcbbSMatthew G. Knepley ierr = VecRestoreArrayRead(vertexMetric, &met);CHKERRQ(ierr); 123*f7bcbcbbSMatthew G. Knepley /* Create new mesh */ 124*f7bcbcbbSMatthew G. Knepley #ifdef PETSC_HAVE_PRAGMATIC 125*f7bcbcbbSMatthew G. Knepley switch (dim) { 126*f7bcbcbbSMatthew G. Knepley case 2: 127*f7bcbcbbSMatthew G. Knepley pragmatic_2d_init(&numVertices, &numCells, cells, x, y);break; 128*f7bcbcbbSMatthew G. Knepley case 3: 129*f7bcbcbbSMatthew G. Knepley pragmatic_3d_init(&numVertices, &numCells, cells, x, y, z);break; 130*f7bcbcbbSMatthew G. Knepley default: SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No Pragmatic adaptation defined for dimension %d", dim); 131*f7bcbcbbSMatthew G. Knepley } 132*f7bcbcbbSMatthew G. Knepley pragmatic_set_boundary(&numBdFaces, bdFaces, bdFaceIds); 133*f7bcbcbbSMatthew G. Knepley pragmatic_set_metric(metric); 134*f7bcbcbbSMatthew G. Knepley pragmatic_adapt(); 135*f7bcbcbbSMatthew G. Knepley /* Read out mesh */ 136*f7bcbcbbSMatthew G. Knepley pragmatic_get_info(&numVerticesNew, &numCellsNew); 137*f7bcbcbbSMatthew G. Knepley ierr = PetscMalloc1(numVerticesNew*dim, &coordsNew);CHKERRQ(ierr); 138*f7bcbcbbSMatthew G. Knepley switch (dim) { 139*f7bcbcbbSMatthew G. Knepley case 2: 140*f7bcbcbbSMatthew G. Knepley numCornersNew = 3; 141*f7bcbcbbSMatthew G. Knepley ierr = PetscMalloc2(numVerticesNew, &xNew[0], numVerticesNew, &xNew[1]);CHKERRQ(ierr); 142*f7bcbcbbSMatthew G. Knepley pragmatic_get_coords_2d(xNew[0], xNew[1]); 143*f7bcbcbbSMatthew G. Knepley break; 144*f7bcbcbbSMatthew G. Knepley case 3: 145*f7bcbcbbSMatthew G. Knepley numCornersNew = 4; 146*f7bcbcbbSMatthew G. Knepley ierr = PetscMalloc3(numVerticesNew, &xNew[0], numVerticesNew, &xNew[1], numVerticesNew, &xNew[2]);CHKERRQ(ierr); 147*f7bcbcbbSMatthew G. Knepley pragmatic_get_coords_3d(xNew[0], xNew[1], xNew[2]); 148*f7bcbcbbSMatthew G. Knepley break; 149*f7bcbcbbSMatthew G. Knepley default: 150*f7bcbcbbSMatthew G. Knepley SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No Pragmatic adaptation defined for dimension %d", dim); 151*f7bcbcbbSMatthew G. Knepley } 152*f7bcbcbbSMatthew G. Knepley for (v = 0; v < numVerticesNew; ++v) {for (d = 0; d < dim; ++d) coordsNew[v*dim+d] = xNew[d][v];} 153*f7bcbcbbSMatthew G. Knepley ierr = PetscMalloc1(numCellsNew*(dim+1), &cellsNew);CHKERRQ(ierr); 154*f7bcbcbbSMatthew G. Knepley pragmatic_get_elements(cellsNew); 155*f7bcbcbbSMatthew G. Knepley ierr = DMPlexCreateFromCellList(PetscObjectComm((PetscObject) dm), dim, numCellsNew, numVerticesNew, numCornersNew, PETSC_TRUE, cellsNew, dim, coordsNew, dmNew);CHKERRQ(ierr); 156*f7bcbcbbSMatthew G. Knepley /* Read out boundary label */ 157*f7bcbcbbSMatthew G. Knepley pragmatic_get_boundaryTags(&bdTags); 158*f7bcbcbbSMatthew G. Knepley ierr = DMCreateLabel(*dmNew, bdLabel ? bdLabelName : bdName);CHKERRQ(ierr); 159*f7bcbcbbSMatthew G. Knepley ierr = DMGetLabel(*dmNew, bdLabel ? bdLabelName : bdName, &bdLabelNew);CHKERRQ(ierr); 160*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(*dmNew, 0, &cStart, &cEnd);CHKERRQ(ierr); 161*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetHeightStratum(*dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 162*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetDepthStratum(*dmNew, 0, &vStart, &vEnd);CHKERRQ(ierr); 163*f7bcbcbbSMatthew G. Knepley for (c = cStart; c < cEnd; ++c) { 164*f7bcbcbbSMatthew G. Knepley /* Only for simplicial meshes */ 165*f7bcbcbbSMatthew G. Knepley coff = (c-cStart)*(dim+1); 166*f7bcbcbbSMatthew G. Knepley for (d = 0; d < dim+1; ++d) { 167*f7bcbcbbSMatthew G. Knepley if (bdTags[coff+d]) { 168*f7bcbcbbSMatthew G. Knepley const PetscInt *faces; 169*f7bcbcbbSMatthew G. Knepley PetscInt numFaces, vertices[3], p; 170*f7bcbcbbSMatthew G. Knepley 171*f7bcbcbbSMatthew G. Knepley /* Mark face opposite to this vertex */ 172*f7bcbcbbSMatthew G. Knepley for (p = 0, v = 0; p < dim+1; ++p) if (p != d) {vertices[v] = cellsNew[coff+p] + vStart; ++v;} 173*f7bcbcbbSMatthew G. Knepley ierr = DMPlexGetFullJoin(*dmNew, dim, vertices, &numFaces, &faces);CHKERRQ(ierr); 174*f7bcbcbbSMatthew G. Knepley if (numFaces != 1) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cannot find boundary face in new cell %D for vertex %D(%D) with tag %D", c, cellsNew[coff+d], d, bdTags[coff+d]); 175*f7bcbcbbSMatthew G. Knepley if (faces[0] < fStart || faces[0] >= fEnd) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Boundary point %D in new cell %D for vertex %D(%D) with tag %D is not a face", faces[0], c, cellsNew[coff+d], d, bdTags[coff+d]); 176*f7bcbcbbSMatthew G. Knepley ierr = DMLabelSetValue(bdLabelNew, faces[0], bdTags[coff+d]);CHKERRQ(ierr); 177*f7bcbcbbSMatthew G. Knepley ierr = DMPlexRestoreJoin(*dmNew, dim, vertices, &numFaces, &faces);CHKERRQ(ierr); 178*f7bcbcbbSMatthew G. Knepley } 179*f7bcbcbbSMatthew G. Knepley } 180*f7bcbcbbSMatthew G. Knepley } 181*f7bcbcbbSMatthew G. Knepley /* Cleanup */ 182*f7bcbcbbSMatthew G. Knepley switch (dim) { 183*f7bcbcbbSMatthew G. Knepley case 2: ierr = PetscFree2(xNew[0], xNew[1]);CHKERRQ(ierr);break; 184*f7bcbcbbSMatthew G. Knepley case 3: ierr = PetscFree3(xNew[0], xNew[1], xNew[2]);CHKERRQ(ierr);break; 185*f7bcbcbbSMatthew G. Knepley } 186*f7bcbcbbSMatthew G. Knepley ierr = PetscFree(cellsNew);CHKERRQ(ierr); 187*f7bcbcbbSMatthew G. Knepley ierr = PetscFree5(x, y, z, metric, cells);CHKERRQ(ierr); 188*f7bcbcbbSMatthew G. Knepley ierr = PetscFree2(bdFaces, bdFaceIds);CHKERRQ(ierr); 189*f7bcbcbbSMatthew G. Knepley ierr = PetscFree(coordsNew);CHKERRQ(ierr); 190*f7bcbcbbSMatthew G. Knepley pragmatic_finalize(); 191*f7bcbcbbSMatthew G. Knepley #else 192*f7bcbcbbSMatthew G. Knepley SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Remeshing needs external package support.\nPlease reconfigure with --download-pragmatic."); 193*f7bcbcbbSMatthew G. Knepley #endif 194*f7bcbcbbSMatthew G. Knepley PetscFunctionReturn(0); 195*f7bcbcbbSMatthew G. Knepley } 1960bbe5d31Sbarral 1970bbe5d31Sbarral #undef __FUNCT__ 19852b40ca0Sbarral #define __FUNCT__ "DMPlexAdapt" 1990f7e110dSbarral /*@ 2000f7e110dSbarral DMPlexAdapt - Generates a mesh adapted to the specified metric field using the pragmatic library. 2010f7e110dSbarral 2020f7e110dSbarral Input Parameters: 2030f7e110dSbarral + dm - The DM object 2040f7e110dSbarral . metric - The metric to which the mesh is adapted, defined vertex-wise. 205379fadc5Sbarral - bdyLabelName - Label name for boundary tags. These will be preserved in the output mesh. bdyLabelName should be "" (empty string) if there is no such label, and should be different from "boundary". 2060f7e110dSbarral 2070f7e110dSbarral Output Parameter: 208*f7bcbcbbSMatthew G. Knepley . dmAdapt - Pointer to the DM object containing the adapted mesh 2090f7e110dSbarral 2100f7e110dSbarral Level: advanced 2110f7e110dSbarral 2120f7e110dSbarral .seealso: DMCoarsen(), DMRefine() 2130f7e110dSbarral @*/ 214*f7bcbcbbSMatthew G. Knepley PetscErrorCode DMPlexAdapt(DM dm, Vec metric, const char bdLabelName[], DM *dmAdapt) 2150bbe5d31Sbarral { 2160bbe5d31Sbarral PetscErrorCode ierr; 2170bbe5d31Sbarral 2180bbe5d31Sbarral PetscFunctionBegin; 219*f7bcbcbbSMatthew G. Knepley ierr = DMPlexRemesh_Internal(dm, metric, bdLabelName, dmAdapt);CHKERRQ(ierr); 2200bbe5d31Sbarral PetscFunctionReturn(0); 2210bbe5d31Sbarral } 222