1*2bc0b47dSJoe Wallwork #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2*2bc0b47dSJoe Wallwork #include <parmmg/libparmmg.h> 3*2bc0b47dSJoe Wallwork 4*2bc0b47dSJoe Wallwork PETSC_EXTERN PetscErrorCode DMAdaptMetric_ParMmg_Plex(DM dm, Vec vertexMetric, DMLabel bdLabel, DM *dmNew) 5*2bc0b47dSJoe Wallwork { 6*2bc0b47dSJoe Wallwork MPI_Comm comm, tmpComm; 7*2bc0b47dSJoe Wallwork const char *bdName = "_boundary_"; 8*2bc0b47dSJoe Wallwork DM udm, cdm; 9*2bc0b47dSJoe Wallwork DMLabel bdLabelFull; 10*2bc0b47dSJoe Wallwork const char *bdLabelName; 11*2bc0b47dSJoe Wallwork IS bdIS, globalVertexNum; 12*2bc0b47dSJoe Wallwork PetscSection coordSection; 13*2bc0b47dSJoe Wallwork Vec coordinates; 14*2bc0b47dSJoe Wallwork PetscSF sf; 15*2bc0b47dSJoe Wallwork const PetscScalar *coords, *met; 16*2bc0b47dSJoe Wallwork const PetscInt *bdFacesFull; 17*2bc0b47dSJoe Wallwork PetscInt *bdFaces, *bdFaceIds; 18*2bc0b47dSJoe Wallwork PetscReal *vertices, *metric, *verticesNew; 19*2bc0b47dSJoe Wallwork PetscInt *cells; 20*2bc0b47dSJoe Wallwork const PetscInt *gV, *ioffset, *irootloc, *roffset, *rmine, *rremote; 21*2bc0b47dSJoe Wallwork PetscInt *numVerInterfaces, *ngbRanks, *verNgbRank, *interfaces_lv, *interfaces_gv, *intOffset; 22*2bc0b47dSJoe Wallwork PetscInt niranks, nrranks, numNgbRanks, numVerNgbRanksTotal, count, sliceSize; 23*2bc0b47dSJoe Wallwork PetscInt *verTags, *cellTags; 24*2bc0b47dSJoe Wallwork PetscInt dim, Neq, cStart, cEnd, numCells, coff, vStart, vEnd, numVertices; 25*2bc0b47dSJoe Wallwork PetscInt maxConeSize, numBdFaces, bdSize, fStart, fEnd; 26*2bc0b47dSJoe Wallwork PetscBool flg, noInsert, noSwap, noMove; 27*2bc0b47dSJoe Wallwork DMLabel bdLabelNew; 28*2bc0b47dSJoe Wallwork PetscReal *verticesNewLoc, gradationFactor; 29*2bc0b47dSJoe Wallwork PetscInt *verTagsNew, *cellsNew, *cellTagsNew, *corners; 30*2bc0b47dSJoe Wallwork PetscInt *requiredCells, *requiredVer, *facesNew, *faceTagsNew, *ridges, *requiredFaces; 31*2bc0b47dSJoe Wallwork PetscInt *gv_new, *owners, *verticesNewSorted; 32*2bc0b47dSJoe Wallwork PetscInt numCellsNew, numVerticesNew, numCornersNew, numFacesNew, numVerticesNewLoc; 33*2bc0b47dSJoe Wallwork PetscInt i, j, k, p, r, n, v, c, f, off, lv, gv; 34*2bc0b47dSJoe Wallwork PetscInt verbosity, numIter; 35*2bc0b47dSJoe Wallwork const PetscMPIInt *iranks, *rranks; 36*2bc0b47dSJoe Wallwork PetscMPIInt numProcs, rank; 37*2bc0b47dSJoe Wallwork PMMG_pParMesh parmesh = NULL; 38*2bc0b47dSJoe Wallwork PetscErrorCode ierr; 39*2bc0b47dSJoe Wallwork 40*2bc0b47dSJoe Wallwork PetscFunctionBegin; 41*2bc0b47dSJoe Wallwork ierr = PetscObjectGetComm((PetscObject) dm, &comm);CHKERRQ(ierr); 42*2bc0b47dSJoe Wallwork ierr = MPI_Comm_size(comm, &numProcs);CHKERRMPI(ierr); 43*2bc0b47dSJoe Wallwork ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 44*2bc0b47dSJoe Wallwork ierr = MPI_Comm_dup(comm, &tmpComm);CHKERRMPI(ierr); 45*2bc0b47dSJoe Wallwork if (bdLabel) { 46*2bc0b47dSJoe Wallwork ierr = PetscObjectGetName((PetscObject) bdLabel, &bdLabelName);CHKERRQ(ierr); 47*2bc0b47dSJoe Wallwork ierr = PetscStrcmp(bdLabelName, bdName, &flg);CHKERRQ(ierr); 48*2bc0b47dSJoe Wallwork if (flg) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "\"%s\" cannot be used as label for boundary facets", bdLabelName); 49*2bc0b47dSJoe Wallwork } 50*2bc0b47dSJoe Wallwork 51*2bc0b47dSJoe Wallwork /* Get mesh information */ 52*2bc0b47dSJoe Wallwork ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 53*2bc0b47dSJoe Wallwork if (dim != 3) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "ParMmg only works in 3D.\n"); 54*2bc0b47dSJoe Wallwork Neq = (dim*(dim+1))/2; 55*2bc0b47dSJoe Wallwork ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 56*2bc0b47dSJoe Wallwork ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 57*2bc0b47dSJoe Wallwork ierr = DMPlexUninterpolate(dm, &udm);CHKERRQ(ierr); 58*2bc0b47dSJoe Wallwork ierr = DMPlexGetMaxSizes(udm, &maxConeSize, NULL);CHKERRQ(ierr); 59*2bc0b47dSJoe Wallwork numCells = cEnd - cStart; 60*2bc0b47dSJoe Wallwork numVertices = vEnd - vStart; 61*2bc0b47dSJoe Wallwork 62*2bc0b47dSJoe Wallwork /* Get cell offsets */ 63*2bc0b47dSJoe Wallwork ierr = PetscMalloc1(numCells*maxConeSize, &cells);CHKERRQ(ierr); 64*2bc0b47dSJoe Wallwork for (c = 0, coff = 0; c < numCells; ++c) { 65*2bc0b47dSJoe Wallwork const PetscInt *cone; 66*2bc0b47dSJoe Wallwork PetscInt coneSize, cl; 67*2bc0b47dSJoe Wallwork 68*2bc0b47dSJoe Wallwork ierr = DMPlexGetConeSize(udm, c, &coneSize);CHKERRQ(ierr); 69*2bc0b47dSJoe Wallwork ierr = DMPlexGetCone(udm, c, &cone);CHKERRQ(ierr); 70*2bc0b47dSJoe Wallwork for (cl = 0; cl < coneSize; ++cl) cells[coff++] = cone[cl] - vStart+1; 71*2bc0b47dSJoe Wallwork } 72*2bc0b47dSJoe Wallwork 73*2bc0b47dSJoe Wallwork /* Get vertex coordinate array */ 74*2bc0b47dSJoe Wallwork ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 75*2bc0b47dSJoe Wallwork ierr = DMGetLocalSection(cdm, &coordSection);CHKERRQ(ierr); 76*2bc0b47dSJoe Wallwork ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 77*2bc0b47dSJoe Wallwork ierr = VecGetArrayRead(coordinates, &coords);CHKERRQ(ierr); 78*2bc0b47dSJoe Wallwork ierr = PetscMalloc2(numVertices*Neq, &metric, dim*numVertices, &vertices);CHKERRQ(ierr); 79*2bc0b47dSJoe Wallwork for (v = 0; v < vEnd-vStart; ++v) { 80*2bc0b47dSJoe Wallwork ierr = PetscSectionGetOffset(coordSection, v+vStart, &off);CHKERRQ(ierr); 81*2bc0b47dSJoe Wallwork for (i = 0; i < dim; ++i) vertices[dim*v+i] = PetscRealPart(coords[off+i]); 82*2bc0b47dSJoe Wallwork } 83*2bc0b47dSJoe Wallwork ierr = VecRestoreArrayRead(coordinates, &coords);CHKERRQ(ierr); 84*2bc0b47dSJoe Wallwork 85*2bc0b47dSJoe Wallwork /* Get boundary mesh */ 86*2bc0b47dSJoe Wallwork ierr = DMLabelCreate(PETSC_COMM_SELF, bdName, &bdLabelFull);CHKERRQ(ierr); 87*2bc0b47dSJoe Wallwork ierr = DMPlexMarkBoundaryFaces(dm, 1, bdLabelFull);CHKERRQ(ierr); 88*2bc0b47dSJoe Wallwork ierr = DMLabelGetStratumIS(bdLabelFull, 1, &bdIS);CHKERRQ(ierr); 89*2bc0b47dSJoe Wallwork ierr = DMLabelGetStratumSize(bdLabelFull, 1, &numBdFaces);CHKERRQ(ierr); 90*2bc0b47dSJoe Wallwork ierr = ISGetIndices(bdIS, &bdFacesFull);CHKERRQ(ierr); 91*2bc0b47dSJoe Wallwork for (f = 0, bdSize = 0; f < numBdFaces; ++f) { 92*2bc0b47dSJoe Wallwork PetscInt *closure = NULL; 93*2bc0b47dSJoe Wallwork PetscInt closureSize, cl; 94*2bc0b47dSJoe Wallwork 95*2bc0b47dSJoe Wallwork ierr = DMPlexGetTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 96*2bc0b47dSJoe Wallwork for (cl = 0; cl < closureSize*2; cl += 2) { 97*2bc0b47dSJoe Wallwork if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) ++bdSize; 98*2bc0b47dSJoe Wallwork } 99*2bc0b47dSJoe Wallwork ierr = DMPlexRestoreTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 100*2bc0b47dSJoe Wallwork } 101*2bc0b47dSJoe Wallwork ierr = PetscMalloc2(bdSize, &bdFaces, numBdFaces, &bdFaceIds);CHKERRQ(ierr); 102*2bc0b47dSJoe Wallwork for (f = 0, bdSize = 0; f < numBdFaces; ++f) { 103*2bc0b47dSJoe Wallwork PetscInt *closure = NULL; 104*2bc0b47dSJoe Wallwork PetscInt closureSize, cl; 105*2bc0b47dSJoe Wallwork 106*2bc0b47dSJoe Wallwork ierr = DMPlexGetTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 107*2bc0b47dSJoe Wallwork for (cl = 0; cl < closureSize*2; cl += 2) { 108*2bc0b47dSJoe Wallwork if ((closure[cl] >= vStart) && (closure[cl] < vEnd)) bdFaces[bdSize++] = closure[cl] - vStart+1; 109*2bc0b47dSJoe Wallwork } 110*2bc0b47dSJoe Wallwork ierr = DMPlexRestoreTransitiveClosure(dm, bdFacesFull[f], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 111*2bc0b47dSJoe Wallwork if (bdLabel) {ierr = DMLabelGetValue(bdLabel, bdFacesFull[f], &bdFaceIds[f]);CHKERRQ(ierr);} 112*2bc0b47dSJoe Wallwork else {bdFaceIds[f] = 1;} 113*2bc0b47dSJoe Wallwork } 114*2bc0b47dSJoe Wallwork ierr = ISDestroy(&bdIS);CHKERRQ(ierr); 115*2bc0b47dSJoe Wallwork ierr = DMLabelDestroy(&bdLabelFull);CHKERRQ(ierr); 116*2bc0b47dSJoe Wallwork 117*2bc0b47dSJoe Wallwork /* Get metric */ 118*2bc0b47dSJoe Wallwork ierr = VecViewFromOptions(vertexMetric, NULL, "-adapt_metric_view");CHKERRQ(ierr); 119*2bc0b47dSJoe Wallwork ierr = VecGetArrayRead(vertexMetric, &met);CHKERRQ(ierr); 120*2bc0b47dSJoe Wallwork for (v = 0; v < (vEnd-vStart); ++v) { 121*2bc0b47dSJoe Wallwork for (i = 0, k = 0; i < dim; ++i) { 122*2bc0b47dSJoe Wallwork for (j = i; j < dim; ++j) { 123*2bc0b47dSJoe Wallwork metric[Neq*v+k] = PetscRealPart(met[dim*dim*v+dim*i+j]); 124*2bc0b47dSJoe Wallwork k++; 125*2bc0b47dSJoe Wallwork } 126*2bc0b47dSJoe Wallwork } 127*2bc0b47dSJoe Wallwork } 128*2bc0b47dSJoe Wallwork ierr = VecRestoreArrayRead(vertexMetric, &met);CHKERRQ(ierr); 129*2bc0b47dSJoe Wallwork 130*2bc0b47dSJoe Wallwork /* Build ParMMG communicators: the list of vertices between two partitions */ 131*2bc0b47dSJoe Wallwork niranks = nrranks = 0; 132*2bc0b47dSJoe Wallwork numNgbRanks = 0; 133*2bc0b47dSJoe Wallwork if (numProcs > 1) { 134*2bc0b47dSJoe Wallwork ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 135*2bc0b47dSJoe Wallwork ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 136*2bc0b47dSJoe Wallwork ierr = PetscSFGetLeafRanks(sf, &niranks, &iranks, &ioffset, &irootloc);CHKERRQ(ierr); 137*2bc0b47dSJoe Wallwork ierr = PetscSFGetRootRanks(sf, &nrranks, &rranks, &roffset, &rmine, &rremote);CHKERRQ(ierr); 138*2bc0b47dSJoe Wallwork ierr = PetscCalloc1(numProcs, &numVerInterfaces);CHKERRQ(ierr); 139*2bc0b47dSJoe Wallwork 140*2bc0b47dSJoe Wallwork /* Counting */ 141*2bc0b47dSJoe Wallwork for (r = 0; r < niranks; ++r) { 142*2bc0b47dSJoe Wallwork for (i=ioffset[r], count=0; i<ioffset[r+1]; ++i) { 143*2bc0b47dSJoe Wallwork if (irootloc[i] >= vStart && irootloc[i] < vEnd) count++; 144*2bc0b47dSJoe Wallwork } 145*2bc0b47dSJoe Wallwork numVerInterfaces[iranks[r]] += count; 146*2bc0b47dSJoe Wallwork } 147*2bc0b47dSJoe Wallwork for (r = 0; r < nrranks; ++r) { 148*2bc0b47dSJoe Wallwork for (i=roffset[r], count=0; i<roffset[r+1]; ++i) { 149*2bc0b47dSJoe Wallwork if (rmine[i] >= vStart && rmine[i] < vEnd) count++; 150*2bc0b47dSJoe Wallwork } 151*2bc0b47dSJoe Wallwork numVerInterfaces[rranks[r]] += count; 152*2bc0b47dSJoe Wallwork } 153*2bc0b47dSJoe Wallwork for (p = 0; p < numProcs; ++p) { 154*2bc0b47dSJoe Wallwork if (numVerInterfaces[p]) numNgbRanks++; 155*2bc0b47dSJoe Wallwork } 156*2bc0b47dSJoe Wallwork ierr = PetscMalloc2(numNgbRanks, &ngbRanks, numNgbRanks, &verNgbRank);CHKERRQ(ierr); 157*2bc0b47dSJoe Wallwork for (p = 0, n = 0; p < numProcs; ++p) { 158*2bc0b47dSJoe Wallwork if (numVerInterfaces[p]) { 159*2bc0b47dSJoe Wallwork ngbRanks[n] = p; 160*2bc0b47dSJoe Wallwork verNgbRank[n] = numVerInterfaces[p]; 161*2bc0b47dSJoe Wallwork n++; 162*2bc0b47dSJoe Wallwork } 163*2bc0b47dSJoe Wallwork } 164*2bc0b47dSJoe Wallwork numVerNgbRanksTotal = 0; 165*2bc0b47dSJoe Wallwork for (p = 0; p < numNgbRanks; ++p) numVerNgbRanksTotal += verNgbRank[p]; 166*2bc0b47dSJoe Wallwork 167*2bc0b47dSJoe Wallwork /* For each neighbor, fill in interface arrays */ 168*2bc0b47dSJoe Wallwork ierr = PetscMalloc3(numVerNgbRanksTotal, &interfaces_lv, numVerNgbRanksTotal, &interfaces_gv, numNgbRanks+1, &intOffset);CHKERRQ(ierr); 169*2bc0b47dSJoe Wallwork intOffset[0] = 0; 170*2bc0b47dSJoe Wallwork for (p = 0, r = 0, i = 0; p < numNgbRanks; ++p) { 171*2bc0b47dSJoe Wallwork intOffset[p+1] = intOffset[p]; 172*2bc0b47dSJoe Wallwork if (iranks && iranks[i] == ngbRanks[p]) { 173*2bc0b47dSJoe Wallwork 174*2bc0b47dSJoe Wallwork /* Add the right slice of irootloc at the right place */ 175*2bc0b47dSJoe Wallwork sliceSize = ioffset[i+1]-ioffset[i]; 176*2bc0b47dSJoe Wallwork for (j = 0, count = 0; j < sliceSize; ++j) { 177*2bc0b47dSJoe Wallwork if (ioffset[i]+j >= ioffset[niranks]) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Offset out of range"); 178*2bc0b47dSJoe Wallwork v = irootloc[ioffset[i]+j]; 179*2bc0b47dSJoe Wallwork if (v >= vStart && v < vEnd) { 180*2bc0b47dSJoe Wallwork if (intOffset[p+1]+count >= numVerNgbRanksTotal) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Offset out of range"); 181*2bc0b47dSJoe Wallwork interfaces_lv[intOffset[p+1]+count] = v-vStart; 182*2bc0b47dSJoe Wallwork count++; 183*2bc0b47dSJoe Wallwork } 184*2bc0b47dSJoe Wallwork } 185*2bc0b47dSJoe Wallwork intOffset[p+1] += count; 186*2bc0b47dSJoe Wallwork i++; 187*2bc0b47dSJoe Wallwork } 188*2bc0b47dSJoe Wallwork if (rranks && rranks[r] == ngbRanks[p]) { 189*2bc0b47dSJoe Wallwork 190*2bc0b47dSJoe Wallwork /* Add the right slice of rmine at the right place */ 191*2bc0b47dSJoe Wallwork sliceSize = roffset[r+1]-roffset[r]; 192*2bc0b47dSJoe Wallwork for (j = 0, count = 0; j < sliceSize; ++j) { 193*2bc0b47dSJoe Wallwork if (roffset[r]+j >= roffset[nrranks]) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Offset out of range"); 194*2bc0b47dSJoe Wallwork v = rmine[roffset[r]+j]; 195*2bc0b47dSJoe Wallwork if (v >= vStart && v < vEnd) { 196*2bc0b47dSJoe Wallwork if (intOffset[p+1]+count >= numVerNgbRanksTotal) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Offset out of range"); 197*2bc0b47dSJoe Wallwork interfaces_lv[intOffset[p+1]+count] = v-vStart; 198*2bc0b47dSJoe Wallwork count++; 199*2bc0b47dSJoe Wallwork } 200*2bc0b47dSJoe Wallwork } 201*2bc0b47dSJoe Wallwork intOffset[p+1] += count; 202*2bc0b47dSJoe Wallwork r++; 203*2bc0b47dSJoe Wallwork } 204*2bc0b47dSJoe Wallwork if (intOffset[p+1] != intOffset[p] + verNgbRank[p]) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Unequal offsets"); 205*2bc0b47dSJoe Wallwork } 206*2bc0b47dSJoe Wallwork ierr = DMPlexGetVertexNumbering(udm, &globalVertexNum);CHKERRQ(ierr); 207*2bc0b47dSJoe Wallwork ierr = ISGetIndices(globalVertexNum, &gV);CHKERRQ(ierr); 208*2bc0b47dSJoe Wallwork for (i = 0; i < numVerNgbRanksTotal; ++i) { 209*2bc0b47dSJoe Wallwork v = gV[interfaces_lv[i]]; 210*2bc0b47dSJoe Wallwork interfaces_gv[i] = v < 0 ? -v-1 : v; 211*2bc0b47dSJoe Wallwork interfaces_lv[i] += 1; 212*2bc0b47dSJoe Wallwork interfaces_gv[i] += 1; 213*2bc0b47dSJoe Wallwork } 214*2bc0b47dSJoe Wallwork ierr = ISRestoreIndices(globalVertexNum, &gV);CHKERRQ(ierr); 215*2bc0b47dSJoe Wallwork ierr = PetscFree(numVerInterfaces);CHKERRQ(ierr); 216*2bc0b47dSJoe Wallwork } 217*2bc0b47dSJoe Wallwork ierr = DMDestroy(&udm);CHKERRQ(ierr); 218*2bc0b47dSJoe Wallwork 219*2bc0b47dSJoe Wallwork /* Send the data to ParMmg and remesh */ 220*2bc0b47dSJoe Wallwork ierr = DMPlexMetricNoInsertion(dm, &noInsert);CHKERRQ(ierr); 221*2bc0b47dSJoe Wallwork ierr = DMPlexMetricNoSwapping(dm, &noSwap);CHKERRQ(ierr); 222*2bc0b47dSJoe Wallwork ierr = DMPlexMetricNoMovement(dm, &noMove);CHKERRQ(ierr); 223*2bc0b47dSJoe Wallwork ierr = DMPlexMetricGetVerbosity(dm, &verbosity);CHKERRQ(ierr); 224*2bc0b47dSJoe Wallwork ierr = DMPlexMetricGetNumIterations(dm, &numIter);CHKERRQ(ierr); 225*2bc0b47dSJoe Wallwork ierr = DMPlexMetricGetGradationFactor(dm, &gradationFactor);CHKERRQ(ierr); 226*2bc0b47dSJoe Wallwork ierr = PetscCalloc2(numVertices, &verTags, numCells, &cellTags);CHKERRQ(ierr); 227*2bc0b47dSJoe Wallwork ierr = PMMG_Init_parMesh(PMMG_ARG_start, PMMG_ARG_ppParMesh, &parmesh, PMMG_ARG_pMesh, PMMG_ARG_pMet, PMMG_ARG_dim, 3, PMMG_ARG_MPIComm, tmpComm, PMMG_ARG_end); 228*2bc0b47dSJoe Wallwork ierr = PMMG_Set_meshSize(parmesh, numVertices, numCells, 0, numBdFaces, 0, 0); 229*2bc0b47dSJoe Wallwork ierr = PMMG_Set_iparameter(parmesh, PMMG_IPARAM_APImode, PMMG_APIDISTRIB_nodes); 230*2bc0b47dSJoe Wallwork ierr = PMMG_Set_iparameter(parmesh, PMMG_IPARAM_noinsert, noInsert); 231*2bc0b47dSJoe Wallwork ierr = PMMG_Set_iparameter(parmesh, PMMG_IPARAM_noswap, noSwap); 232*2bc0b47dSJoe Wallwork ierr = PMMG_Set_iparameter(parmesh, PMMG_IPARAM_nomove, noMove); 233*2bc0b47dSJoe Wallwork ierr = PMMG_Set_iparameter(parmesh, PMMG_IPARAM_verbose, verbosity); 234*2bc0b47dSJoe Wallwork ierr = PMMG_Set_iparameter(parmesh, PMMG_IPARAM_globalNum, 1); 235*2bc0b47dSJoe Wallwork ierr = PMMG_Set_iparameter(parmesh, PMMG_IPARAM_niter, numIter); 236*2bc0b47dSJoe Wallwork ierr = PMMG_Set_dparameter(parmesh, PMMG_DPARAM_hgrad, gradationFactor); 237*2bc0b47dSJoe Wallwork ierr = PMMG_Set_vertices(parmesh, vertices, verTags); 238*2bc0b47dSJoe Wallwork for (i=0; i<numCells; i++) ierr = PMMG_Set_tetrahedron(parmesh, cells[4*i+0], cells[4*i+1], cells[4*i+2], cells[4*i+3], 0, i+1); 239*2bc0b47dSJoe Wallwork ierr = PMMG_Set_triangles(parmesh, bdFaces, bdFaceIds); 240*2bc0b47dSJoe Wallwork ierr = PMMG_Set_metSize(parmesh, MMG5_Vertex, numVertices, MMG5_Tensor); 241*2bc0b47dSJoe Wallwork for (i=0; i<numVertices; i++) { 242*2bc0b47dSJoe Wallwork PMMG_Set_tensorMet(parmesh, metric[6*i], metric[6*i+1], metric[6*i+2], metric[6*i+3], metric[6*i+4], metric[6*i+5], i+1); 243*2bc0b47dSJoe Wallwork } 244*2bc0b47dSJoe Wallwork ierr = PMMG_Set_numberOfNodeCommunicators(parmesh, numNgbRanks); 245*2bc0b47dSJoe Wallwork for (c = 0; c < numNgbRanks; ++c) { 246*2bc0b47dSJoe Wallwork ierr = PMMG_Set_ithNodeCommunicatorSize(parmesh, c, ngbRanks[c], intOffset[c+1]-intOffset[c]); 247*2bc0b47dSJoe Wallwork ierr = PMMG_Set_ithNodeCommunicator_nodes(parmesh, c, &interfaces_lv[intOffset[c]], &interfaces_gv[intOffset[c]], 1); 248*2bc0b47dSJoe Wallwork } 249*2bc0b47dSJoe Wallwork ierr = PMMG_parmmglib_distributed(parmesh); 250*2bc0b47dSJoe Wallwork ierr = PetscFree(cells);CHKERRQ(ierr); 251*2bc0b47dSJoe Wallwork ierr = PetscFree2(metric, vertices);CHKERRQ(ierr); 252*2bc0b47dSJoe Wallwork ierr = PetscFree2(bdFaces, bdFaceIds);CHKERRQ(ierr); 253*2bc0b47dSJoe Wallwork ierr = PetscFree2(verTags, cellTags);CHKERRQ(ierr); 254*2bc0b47dSJoe Wallwork if (numProcs > 1) { 255*2bc0b47dSJoe Wallwork ierr = PetscFree2(ngbRanks, verNgbRank);CHKERRQ(ierr); 256*2bc0b47dSJoe Wallwork ierr = PetscFree3(interfaces_lv, interfaces_gv, intOffset);CHKERRQ(ierr); 257*2bc0b47dSJoe Wallwork } 258*2bc0b47dSJoe Wallwork 259*2bc0b47dSJoe Wallwork /* Retrieve mesh from Mmg and create new Plex */ 260*2bc0b47dSJoe Wallwork numCornersNew = 4; 261*2bc0b47dSJoe Wallwork ierr = PMMG_Get_meshSize(parmesh, &numVerticesNew, &numCellsNew, 0, &numFacesNew, 0, 0); 262*2bc0b47dSJoe Wallwork ierr = PetscMalloc4(dim*numVerticesNew, &verticesNew, numVerticesNew, &verTagsNew, numVerticesNew, &corners, numVerticesNew, &requiredVer);CHKERRQ(ierr); 263*2bc0b47dSJoe Wallwork ierr = PetscMalloc3((dim+1)*numCellsNew, &cellsNew, numCellsNew, &cellTagsNew, numCellsNew, &requiredCells);CHKERRQ(ierr); 264*2bc0b47dSJoe Wallwork ierr = PetscMalloc4(dim*numFacesNew, &facesNew, numFacesNew, &faceTagsNew, numFacesNew, &ridges, numFacesNew, &requiredFaces);CHKERRQ(ierr); 265*2bc0b47dSJoe Wallwork ierr = PMMG_Get_vertices(parmesh, verticesNew, verTagsNew, corners, requiredVer); 266*2bc0b47dSJoe Wallwork ierr = PMMG_Get_tetrahedra(parmesh, cellsNew, cellTagsNew, requiredCells); 267*2bc0b47dSJoe Wallwork ierr = PMMG_Get_triangles(parmesh, facesNew, faceTagsNew, requiredFaces); 268*2bc0b47dSJoe Wallwork ierr = PetscMalloc2(numVerticesNew, &owners, numVerticesNew, &gv_new); 269*2bc0b47dSJoe Wallwork ierr = PMMG_Set_iparameter(parmesh, PMMG_IPARAM_globalNum, 1); 270*2bc0b47dSJoe Wallwork ierr = PMMG_Get_verticesGloNum(parmesh, gv_new, owners); 271*2bc0b47dSJoe Wallwork for (i = 0; i < dim*numFacesNew; ++i) facesNew[i] -= 1; 272*2bc0b47dSJoe Wallwork for (i = 0; i < (dim+1)*numCellsNew; ++i) { 273*2bc0b47dSJoe Wallwork cellsNew[i] = gv_new[cellsNew[i]-1]-1; 274*2bc0b47dSJoe Wallwork } 275*2bc0b47dSJoe Wallwork numVerticesNewLoc = 0; 276*2bc0b47dSJoe Wallwork for (i = 0; i < numVerticesNew; ++i) { 277*2bc0b47dSJoe Wallwork if (owners[i] == rank) numVerticesNewLoc++; 278*2bc0b47dSJoe Wallwork } 279*2bc0b47dSJoe Wallwork ierr = PetscMalloc2(numVerticesNewLoc*dim, &verticesNewLoc, numVerticesNew, &verticesNewSorted);CHKERRQ(ierr); 280*2bc0b47dSJoe Wallwork for (i = 0, c = 0; i < numVerticesNew; i++) { 281*2bc0b47dSJoe Wallwork if (owners[i] == rank) { 282*2bc0b47dSJoe Wallwork for (j=0; j<dim; ++j) verticesNewLoc[dim*c+j] = verticesNew[dim*i+j]; 283*2bc0b47dSJoe Wallwork c++; 284*2bc0b47dSJoe Wallwork } 285*2bc0b47dSJoe Wallwork } 286*2bc0b47dSJoe Wallwork ierr = DMPlexCreateFromCellListParallelPetsc(comm, dim, numCellsNew, numVerticesNewLoc, PETSC_DECIDE, numCornersNew, PETSC_TRUE, cellsNew, dim, verticesNewLoc, NULL, &verticesNewSorted, dmNew);CHKERRQ(ierr); 287*2bc0b47dSJoe Wallwork ierr = PMMG_Free_all(PMMG_ARG_start, PMMG_ARG_ppParMesh, &parmesh, PMMG_ARG_end); 288*2bc0b47dSJoe Wallwork 289*2bc0b47dSJoe Wallwork /* Rebuild boundary label*/ 290*2bc0b47dSJoe Wallwork ierr = DMPlexGetHeightStratum(*dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 291*2bc0b47dSJoe Wallwork ierr = DMPlexGetHeightStratum(*dmNew, 0, &cStart, &cEnd);CHKERRQ(ierr); 292*2bc0b47dSJoe Wallwork ierr = DMPlexGetDepthStratum(*dmNew, 0, &vStart, &vEnd);CHKERRQ(ierr); 293*2bc0b47dSJoe Wallwork ierr = DMCreateLabel(*dmNew, bdLabel ? bdLabelName : bdName);CHKERRQ(ierr); 294*2bc0b47dSJoe Wallwork ierr = DMGetLabel(*dmNew, bdLabel ? bdLabelName : bdName, &bdLabelNew);CHKERRQ(ierr); 295*2bc0b47dSJoe Wallwork for (i = 0; i < numFacesNew; i++) { 296*2bc0b47dSJoe Wallwork PetscInt numCoveredPoints, numFaces = 0, facePoints[3]; 297*2bc0b47dSJoe Wallwork const PetscInt *coveredPoints = NULL; 298*2bc0b47dSJoe Wallwork 299*2bc0b47dSJoe Wallwork for (j = 0; j < dim; ++j) { 300*2bc0b47dSJoe Wallwork lv = facesNew[i*dim+j]; 301*2bc0b47dSJoe Wallwork gv = gv_new[lv]-1; 302*2bc0b47dSJoe Wallwork ierr = PetscFindInt(gv, numVerticesNew, verticesNewSorted, &lv);CHKERRQ(ierr); 303*2bc0b47dSJoe Wallwork facePoints[j] = lv+vStart; 304*2bc0b47dSJoe Wallwork } 305*2bc0b47dSJoe Wallwork ierr = DMPlexGetFullJoin(*dmNew, dim, facePoints, &numCoveredPoints, &coveredPoints);CHKERRQ(ierr); 306*2bc0b47dSJoe Wallwork for (j = 0; j < numCoveredPoints; ++j) { 307*2bc0b47dSJoe Wallwork if (coveredPoints[j] >= fStart && coveredPoints[j] < fEnd) { 308*2bc0b47dSJoe Wallwork numFaces++; 309*2bc0b47dSJoe Wallwork f = j; 310*2bc0b47dSJoe Wallwork } 311*2bc0b47dSJoe Wallwork } 312*2bc0b47dSJoe Wallwork if (numFaces != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "%d vertices cannot define more than 1 facet (%d)", dim, numFaces); 313*2bc0b47dSJoe Wallwork ierr = DMLabelSetValue(bdLabelNew, coveredPoints[f], faceTagsNew[i]);CHKERRQ(ierr); 314*2bc0b47dSJoe Wallwork ierr = DMPlexRestoreJoin(*dmNew, dim, facePoints, &numCoveredPoints, &coveredPoints);CHKERRQ(ierr); 315*2bc0b47dSJoe Wallwork } 316*2bc0b47dSJoe Wallwork 317*2bc0b47dSJoe Wallwork /* Clean up */ 318*2bc0b47dSJoe Wallwork ierr = PetscFree4(verticesNew, verTagsNew, corners, requiredVer);CHKERRQ(ierr); 319*2bc0b47dSJoe Wallwork ierr = PetscFree3(cellsNew, cellTagsNew, requiredCells);CHKERRQ(ierr); 320*2bc0b47dSJoe Wallwork ierr = PetscFree4(facesNew, faceTagsNew, ridges, requiredFaces);CHKERRQ(ierr); 321*2bc0b47dSJoe Wallwork ierr = PetscFree2(owners, gv_new);CHKERRQ(ierr); 322*2bc0b47dSJoe Wallwork ierr = PetscFree2(verticesNewLoc, verticesNewSorted);CHKERRQ(ierr); 323*2bc0b47dSJoe Wallwork PetscFunctionReturn(0); 324*2bc0b47dSJoe Wallwork } 325