10bbe5d31Sbarral #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 20bbe5d31Sbarral #ifdef PETSC_HAVE_PRAGMATIC 30bbe5d31Sbarral #include <pragmatic/cpragmatic.h> 40bbe5d31Sbarral #endif 50bbe5d31Sbarral 60bbe5d31Sbarral 70bbe5d31Sbarral 80bbe5d31Sbarral #undef __FUNCT__ 952b40ca0Sbarral #define __FUNCT__ "DMPlexAdapt" 10*0f7e110dSbarral /*@ 11*0f7e110dSbarral DMPlexAdapt - Generates a mesh adapted to the specified metric field using the pragmatic library. 12*0f7e110dSbarral 13*0f7e110dSbarral Input Parameters: 14*0f7e110dSbarral + dm - The DM object 15*0f7e110dSbarral . metric - The metric to which the mesh is adapted, defined vertex-wise. 16*0f7e110dSbarral - bdyLabelName - Label name for boundary tags. These will be preserved in the output mesh. bdyLabelName should be different from "boundary". 17*0f7e110dSbarral 18*0f7e110dSbarral Output Parameter: 19*0f7e110dSbarral . dmAdapted - Pointer to the DM object containing the adapted mesh 20*0f7e110dSbarral 21*0f7e110dSbarral Level: advanced 22*0f7e110dSbarral 23*0f7e110dSbarral .seealso: DMCoarsen(), DMRefine() 24*0f7e110dSbarral @*/ 256b1afcafSbarral PetscErrorCode DMPlexAdapt(DM dm, Vec metric, const char bdyLabelName[], DM *dmAdapted) 260bbe5d31Sbarral { 270bbe5d31Sbarral #ifdef PETSC_HAVE_PRAGMATIC 280bbe5d31Sbarral DM udm, coordDM; 296b1afcafSbarral DMLabel bd, bdTags, bdTagsAdp; 300bbe5d31Sbarral Vec coordinates; 310bbe5d31Sbarral PetscSection coordSection; 320bbe5d31Sbarral IS bdIS; 33*0f7e110dSbarral double *coordsAdp; 34*0f7e110dSbarral const PetscScalar *coords; 356b1afcafSbarral PetscReal *x, *y, *z, *xAdp, *yAdp, *zAdp; 36*0f7e110dSbarral const PetscScalar *metricArray; 37*0f7e110dSbarral PetscReal *met; 380bbe5d31Sbarral const PetscInt *faces; 396b1afcafSbarral PetscInt *cells, *cellsAdp, *bdFaces, *bdFaceIds; 40*0f7e110dSbarral PetscInt *boundaryTags; 416b1afcafSbarral PetscInt dim, numCornersAdp, cStart, cEnd, numCells, numCellsAdp, c; 426b1afcafSbarral PetscInt vStart, vEnd, numVertices, numVerticesAdp, v; 436b1afcafSbarral PetscInt numBdFaces, f, maxConeSize, bdSize, coff; 44*0f7e110dSbarral PetscInt *cell, iVer, cellOff, i, j, idx, facet; 45*0f7e110dSbarral PetscInt perm[4], isInFacetClosure[4]; // 4 = max number of facets for an element in 2D & 3D. Only for simplicial meshes 462499d69cSbarral PetscBool flag, hasBdyFacet; 470bbe5d31Sbarral #endif 480bbe5d31Sbarral PetscErrorCode ierr; 490bbe5d31Sbarral MPI_Comm comm; 500bbe5d31Sbarral 510bbe5d31Sbarral PetscFunctionBegin; 520bbe5d31Sbarral ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 530bbe5d31Sbarral #ifdef PETSC_HAVE_PRAGMATIC 540bbe5d31Sbarral ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 550bbe5d31Sbarral ierr = DMGetCoordinateDM(dm, &coordDM);CHKERRQ(ierr); 560bbe5d31Sbarral ierr = DMGetDefaultSection(coordDM, &coordSection);CHKERRQ(ierr); 570bbe5d31Sbarral ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 580bbe5d31Sbarral ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 590bbe5d31Sbarral ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 600bbe5d31Sbarral ierr = DMPlexUninterpolate(dm, &udm);CHKERRQ(ierr); 610bbe5d31Sbarral ierr = DMPlexGetMaxSizes(udm, &maxConeSize, NULL);CHKERRQ(ierr); 620bbe5d31Sbarral numCells = cEnd - cStart; 630bbe5d31Sbarral numVertices = vEnd - vStart; 640bbe5d31Sbarral ierr = PetscCalloc5(numVertices, &x, numVertices, &y, numVertices, &z, numCells*maxConeSize, &cells, dim*dim*numVertices, &met);CHKERRQ(ierr); 650bbe5d31Sbarral ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 660bbe5d31Sbarral ierr = VecGetArrayRead(metric, &metricArray);CHKERRQ(ierr); 670bbe5d31Sbarral for (v = vStart; v < vEnd; ++v) { 680bbe5d31Sbarral PetscInt off; 690bbe5d31Sbarral 700bbe5d31Sbarral ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 710bbe5d31Sbarral x[v-vStart] = coords[off+0]; 720bbe5d31Sbarral y[v-vStart] = coords[off+1]; 730bbe5d31Sbarral if (dim > 2) z[v-vStart] = coords[off+2]; 740bbe5d31Sbarral ierr = PetscMemcpy(&met[dim*dim*(v-vStart)], &metricArray[dim*off], dim*dim*sizeof(PetscScalar));CHKERRQ(ierr); 750bbe5d31Sbarral } 760bbe5d31Sbarral ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 770bbe5d31Sbarral ierr = VecRestoreArrayRead(metric, &metricArray);CHKERRQ(ierr); 780bbe5d31Sbarral for (c = 0, coff = 0; c < numCells; ++c) { 790bbe5d31Sbarral const PetscInt *cone; 800bbe5d31Sbarral PetscInt coneSize, cl; 810bbe5d31Sbarral 820bbe5d31Sbarral ierr = DMPlexGetConeSize(udm, c, &coneSize);CHKERRQ(ierr); 830bbe5d31Sbarral ierr = DMPlexGetCone(udm, c, &cone);CHKERRQ(ierr); 840bbe5d31Sbarral for (cl = 0; cl < coneSize; ++cl) cells[coff++] = cone[cl] - vStart; 850bbe5d31Sbarral } 860bbe5d31Sbarral switch (dim) { 870bbe5d31Sbarral case 2: 880bbe5d31Sbarral pragmatic_2d_init(&numVertices, &numCells, cells, x, y); 890bbe5d31Sbarral break; 900bbe5d31Sbarral case 3: 910bbe5d31Sbarral pragmatic_3d_init(&numVertices, &numCells, cells, x, y, z); 920bbe5d31Sbarral break; 930bbe5d31Sbarral default: 940bbe5d31Sbarral SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No Pragmatic adaptation defined for dimension %d", dim); 950bbe5d31Sbarral } 960bbe5d31Sbarral /* Create boundary mesh */ 974190e864Sbarral if (bdyLabelName) { 986b1afcafSbarral ierr = PetscStrcmp(bdyLabelName, "boundary", &flag);CHKERRQ(ierr); 996b1afcafSbarral if (flag) { 1006b1afcafSbarral SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "\"%s\" cannot be used as label for boundary facets", bdyLabelName); 1014190e864Sbarral } 1026b1afcafSbarral ierr = DMGetLabel(dm, bdyLabelName, &bdTags);CHKERRQ(ierr); 1036b1afcafSbarral } 104*0f7e110dSbarral /* TODO To avoid marking bdy facets again if bdyLabelName exists, could/should we loop over bdyLabelName stratas ? */ 1050bbe5d31Sbarral ierr = DMLabelCreate("boundary", &bd);CHKERRQ(ierr); 1060bbe5d31Sbarral ierr = DMPlexMarkBoundaryFaces(dm, bd);CHKERRQ(ierr); 1070bbe5d31Sbarral ierr = DMLabelGetStratumIS(bd, 1, &bdIS);CHKERRQ(ierr); 1080bbe5d31Sbarral ierr = DMLabelGetStratumSize(bd, 1, &numBdFaces);CHKERRQ(ierr); 1090bbe5d31Sbarral ierr = ISGetIndices(bdIS, &faces);CHKERRQ(ierr); 1106b1afcafSbarral /* TODO why not assume that we are considering simplicial meshes, in which case bdSize = dim*numBdFaces ? */ 1110bbe5d31Sbarral for (f = 0, bdSize = 0; f < numBdFaces; ++f) { 1120bbe5d31Sbarral PetscInt *closure = NULL; 1130bbe5d31Sbarral PetscInt closureSize, cl; 1140bbe5d31Sbarral 1150bbe5d31Sbarral ierr = DMPlexGetTransitiveClosure(dm, faces[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1160bbe5d31Sbarral for (cl = 0; cl < closureSize*2; cl += 2) { 1170bbe5d31Sbarral if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) ++bdSize; 1180bbe5d31Sbarral } 1190bbe5d31Sbarral ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1200bbe5d31Sbarral } 1210bbe5d31Sbarral ierr = PetscMalloc2(bdSize, &bdFaces, numBdFaces, &bdFaceIds);CHKERRQ(ierr); 1220bbe5d31Sbarral for (f = 0, bdSize = 0; f < numBdFaces; ++f) { 1230bbe5d31Sbarral PetscInt *closure = NULL; 1240bbe5d31Sbarral PetscInt closureSize, cl; 1250bbe5d31Sbarral 1260bbe5d31Sbarral ierr = DMPlexGetTransitiveClosure(dm, faces[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1270bbe5d31Sbarral for (cl = 0; cl < closureSize*2; cl += 2) { 1280bbe5d31Sbarral if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) bdFaces[bdSize++] = closure[cl] - vStart; 1290bbe5d31Sbarral } 1306b1afcafSbarral if (bdyLabelName) { 1316b1afcafSbarral ierr = DMLabelGetValue(bdTags, faces[f], &bdFaceIds[f]);CHKERRQ(ierr); 1326b1afcafSbarral } else { 1330bbe5d31Sbarral bdFaceIds[f] = 1; 1346b1afcafSbarral } 1350bbe5d31Sbarral ierr = DMPlexRestoreTransitiveClosure(dm, f, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 1360bbe5d31Sbarral } 1370bbe5d31Sbarral ierr = ISDestroy(&bdIS);CHKERRQ(ierr); 1380bbe5d31Sbarral ierr = DMLabelDestroy(&bd);CHKERRQ(ierr); 1390bbe5d31Sbarral pragmatic_set_boundary(&numBdFaces, bdFaces, bdFaceIds); 1400bbe5d31Sbarral pragmatic_set_metric(met); 1410bbe5d31Sbarral pragmatic_adapt(); 1426b1afcafSbarral ierr = PetscFree5(x, y, z, cells, met);CHKERRQ(ierr); 1436b1afcafSbarral ierr = PetscFree2(bdFaces, bdFaceIds);CHKERRQ(ierr); 1446b1afcafSbarral ierr = PetscFree(coords);CHKERRQ(ierr); 1450bbe5d31Sbarral /* Read out mesh */ 1466b1afcafSbarral pragmatic_get_info(&numVerticesAdp, &numCellsAdp); 1476b1afcafSbarral ierr = PetscMalloc1(numVerticesAdp*dim, &coordsAdp);CHKERRQ(ierr); 1480bbe5d31Sbarral switch (dim) { 1490bbe5d31Sbarral case 2: 1506b1afcafSbarral ierr = PetscMalloc2(numVerticesAdp, &xAdp, numVerticesAdp, &yAdp);CHKERRQ(ierr); 1516b1afcafSbarral zAdp = NULL; 1526b1afcafSbarral pragmatic_get_coords_2d(xAdp, yAdp); 1536b1afcafSbarral numCornersAdp = 3; 1546b1afcafSbarral for (v = 0; v < numVerticesAdp; ++v) {coordsAdp[v*2+0] = xAdp[v]; coordsAdp[v*2+1] = yAdp[v];} 1550bbe5d31Sbarral break; 1560bbe5d31Sbarral case 3: 1576b1afcafSbarral ierr = PetscMalloc3(numVerticesAdp, &xAdp, numVerticesAdp, &yAdp, numVerticesAdp, &zAdp);CHKERRQ(ierr); 1586b1afcafSbarral pragmatic_get_coords_3d(xAdp, yAdp, zAdp); 1596b1afcafSbarral numCornersAdp = 4; 1606b1afcafSbarral for (v = 0; v < numVerticesAdp; ++v) {coordsAdp[v*3+0] = xAdp[v]; coordsAdp[v*3+1] = yAdp[v]; coordsAdp[v*3+2] = zAdp[v];} 1610bbe5d31Sbarral break; 1620bbe5d31Sbarral default: 1636b1afcafSbarral SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "No Pragmatic adaptation defined for dimension %d", dim); 1640bbe5d31Sbarral } 1656b1afcafSbarral ierr = PetscMalloc1(numCellsAdp*(dim+1), &cellsAdp);CHKERRQ(ierr); // only for simplicial meshes 1666b1afcafSbarral pragmatic_get_elements(cellsAdp); 1676b1afcafSbarral ierr = DMPlexCreate(comm, dmAdapted);CHKERRQ(ierr); 1686b1afcafSbarral ierr = DMPlexCreateFromCellList(PetscObjectComm((PetscObject) dm), dim, numCellsAdp, numVerticesAdp, numCornersAdp, PETSC_TRUE, cellsAdp, dim, coordsAdp, dmAdapted);CHKERRQ(ierr); 169f7caa48eSbarral /* Read out boundary tags */ 170f7caa48eSbarral pragmatic_get_boundaryTags(&boundaryTags); 171f7caa48eSbarral if (!bdyLabelName) bdyLabelName = "boundary"; 1726b1afcafSbarral ierr = DMCreateLabel(*dmAdapted, bdyLabelName);CHKERRQ(ierr); 1736b1afcafSbarral ierr = DMGetLabel(*dmAdapted, bdyLabelName, &bdTagsAdp);CHKERRQ(ierr); 1746b1afcafSbarral ierr = DMPlexGetHeightStratum(*dmAdapted, 0, &cStart, &cEnd);CHKERRQ(ierr); 1756b1afcafSbarral ierr = DMPlexGetDepthStratum(*dmAdapted, 0, &vStart, &vEnd);CHKERRQ(ierr); 176f7caa48eSbarral for (c = cStart; c < cEnd; ++c) { 177f7caa48eSbarral PetscInt *cellClosure = NULL; 178f7caa48eSbarral PetscInt cellClosureSize, cl; 179f7caa48eSbarral PetscInt *facetClosure = NULL; 180f7caa48eSbarral PetscInt facetClosureSize, cl2; 181f7caa48eSbarral const PetscInt *facetList; 182f7caa48eSbarral PetscInt facetListSize, f; 183f7caa48eSbarral 184*0f7e110dSbarral cellOff = (c-cStart)*(dim+1); // gives the offset corresponding to the cell in pragmatic boundary arrays. Only for simplicial meshes 1852499d69cSbarral hasBdyFacet = 0; 186*0f7e110dSbarral for (i = 0; i < dim+1; ++i) { // only for simplicial meshes 1872499d69cSbarral if (boundaryTags[cellOff+i]) { 1882499d69cSbarral hasBdyFacet = 1; 1892499d69cSbarral break; 1902499d69cSbarral } 1912499d69cSbarral } 192*0f7e110dSbarral if (!hasBdyFacet) continue; // The cell has no boundary edge/facet => no boundary tagging 1932499d69cSbarral 194*0f7e110dSbarral cell = &cellsAdp[cellOff]; // pointing to the current cell in the cellsAdp table 1956b1afcafSbarral ierr = DMPlexGetTransitiveClosure(*dmAdapted, c, PETSC_TRUE, &cellClosureSize, &cellClosure);CHKERRQ(ierr); 1966b1afcafSbarral /* first, encode the permutation of the vertices indices betwenn the cell closure and pragmatic ordering */ 197fc167ce7Sbarral j = 0; 198f7caa48eSbarral for (cl = 0; cl < cellClosureSize*2; cl += 2) { 199f7caa48eSbarral if ((cellClosure[cl] < vStart) || (cellClosure[cl] >= vEnd)) continue; 200f7caa48eSbarral iVer = cellClosure[cl] - vStart; 201*0f7e110dSbarral for (i = 0; i < dim+1; ++i) { // only for simplicial meshes 202f7caa48eSbarral if (iVer == cell[i]) { 203fc167ce7Sbarral perm[j] = i; // the cl-th element of the closure is the i-th vertex of the cell 204f7caa48eSbarral break; 205f7caa48eSbarral } 206f7caa48eSbarral } 207fc167ce7Sbarral j++; 208f7caa48eSbarral } 2096b1afcafSbarral ierr = DMPlexGetCone(*dmAdapted, c, &facetList);CHKERRQ(ierr); // list of edges/facets of the cell 2106b1afcafSbarral ierr = DMPlexGetConeSize(*dmAdapted, c, &facetListSize);CHKERRQ(ierr); 211*0f7e110dSbarral /* then, for each edge/facet of the cell, find the opposite vertex (ie the one in the closure of the cell and not in the closure of the facet/edge) */ 212f7caa48eSbarral for (f = 0; f < facetListSize; ++f){ 213f7caa48eSbarral facet = facetList[f]; 2146b1afcafSbarral ierr = DMPlexGetTransitiveClosure(*dmAdapted, facet, PETSC_TRUE, &facetClosureSize, &facetClosure);CHKERRQ(ierr); 2156b1afcafSbarral /* loop over the vertices of the cell closure, and check if each vertex belongs to the edge/facet closure */ 216*0f7e110dSbarral /* TODO should we use bitmaps to mark vertices instead of a static array ? */ 217f7caa48eSbarral PetscMemzero(isInFacetClosure, sizeof(isInFacetClosure)); 218fc167ce7Sbarral j = 0; 219f7caa48eSbarral for (cl = 0; cl < cellClosureSize*2; cl += 2) { 220*0f7e110dSbarral if ((cellClosure[cl] < vStart) || (cellClosure[cl] >= vEnd)) continue; 221f7caa48eSbarral for (cl2 = 0; cl2 < facetClosureSize*2; cl2 += 2){ 222f7caa48eSbarral if ((facetClosure[cl2] < vStart) || (facetClosure[cl2] >= vEnd)) continue; 223f7caa48eSbarral if (cellClosure[cl] == facetClosure[cl2]) { 224fc167ce7Sbarral isInFacetClosure[j] = 1; 225f7caa48eSbarral } 226f7caa48eSbarral } 227fc167ce7Sbarral j++; 228f7caa48eSbarral } 2296b1afcafSbarral /* the vertex that was not marked is the vertex opposite to the edge/facet, ie the one giving the edge/facet boundary tag in pragmatic */ 230fc167ce7Sbarral j = 0; 231f7caa48eSbarral for (cl = 0; cl < cellClosureSize*2; cl += 2) { 232fc167ce7Sbarral if ((cellClosure[cl] < vStart) || (cellClosure[cl] >= vEnd)) continue; 233fc167ce7Sbarral if (!isInFacetClosure[j]) { 234fc167ce7Sbarral idx = cellOff + perm[j]; 2356b1afcafSbarral if (boundaryTags[idx]) { 2366b1afcafSbarral ierr = DMLabelSetValue(bdTagsAdp, facet, boundaryTags[idx]);CHKERRQ(ierr); 2376b1afcafSbarral } 238f7caa48eSbarral break; 239f7caa48eSbarral } 240fc167ce7Sbarral j++; 241f7caa48eSbarral } 2426b1afcafSbarral ierr = DMPlexRestoreTransitiveClosure(*dmAdapted, facet, PETSC_TRUE, &facetClosureSize, &facetClosure);CHKERRQ(ierr); 243f7caa48eSbarral } 2446b1afcafSbarral ierr = DMPlexRestoreTransitiveClosure(*dmAdapted, c, PETSC_TRUE, &cellClosureSize, &cellClosure);CHKERRQ(ierr); 245f7caa48eSbarral } 2460bbe5d31Sbarral pragmatic_finalize(); 2476b1afcafSbarral ierr = PetscFree5(xAdp, yAdp, zAdp, cellsAdp, coordsAdp);CHKERRQ(ierr); 2480bbe5d31Sbarral #endif 2490bbe5d31Sbarral PetscFunctionReturn(0); 2500bbe5d31Sbarral } 251