1*552f7358SJed Brown #include <petsc-private/pleximpl.h> /*I "petscdmplex.h" I*/ 2*552f7358SJed Brown #include <../src/sys/utils/hash.h> 3*552f7358SJed Brown 4*552f7358SJed Brown /* Logging support */ 5*552f7358SJed Brown PetscLogEvent DMPLEX_Distribute, DMPLEX_Stratify; 6*552f7358SJed Brown 7*552f7358SJed Brown extern PetscErrorCode VecView_Seq(Vec, PetscViewer); 8*552f7358SJed Brown extern PetscErrorCode VecView_MPI(Vec, PetscViewer); 9*552f7358SJed Brown 10*552f7358SJed Brown #undef __FUNCT__ 11*552f7358SJed Brown #define __FUNCT__ "VecView_Plex_Local" 12*552f7358SJed Brown PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 13*552f7358SJed Brown { 14*552f7358SJed Brown DM dm; 15*552f7358SJed Brown PetscBool isvtk; 16*552f7358SJed Brown PetscErrorCode ierr; 17*552f7358SJed Brown 18*552f7358SJed Brown PetscFunctionBegin; 19*552f7358SJed Brown ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 20*552f7358SJed Brown if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 21*552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 22*552f7358SJed Brown if (isvtk) { 23*552f7358SJed Brown PetscViewerVTKFieldType ft = PETSC_VTK_POINT_FIELD; 24*552f7358SJed Brown PetscSection section; 25*552f7358SJed Brown PetscInt dim, pStart, pEnd, cStart, fStart, vStart, cdof = 0, fdof = 0, vdof = 0; 26*552f7358SJed Brown 27*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 28*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 29*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 30*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 1, &fStart, PETSC_NULL);CHKERRQ(ierr); 31*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, PETSC_NULL);CHKERRQ(ierr); 32*552f7358SJed Brown ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 33*552f7358SJed Brown /* Assumes that numer of dofs per point of each stratum is constant, natural for VTK */ 34*552f7358SJed Brown if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 35*552f7358SJed Brown if ((fStart >= pStart) && (fStart < pEnd)) {ierr = PetscSectionGetDof(section, fStart, &fdof);CHKERRQ(ierr);} 36*552f7358SJed Brown if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 37*552f7358SJed Brown if (cdof && fdof && vdof) { /* Actually Q2 or some such, but visualize as Q1 */ 38*552f7358SJed Brown ft = (cdof == dim) ? PETSC_VTK_POINT_VECTOR_FIELD : PETSC_VTK_POINT_FIELD; 39*552f7358SJed Brown } else if (cdof && vdof) { 40*552f7358SJed Brown SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"No support for viewing mixed space with dofs at both vertices and cells"); 41*552f7358SJed Brown } else if (cdof) { 42*552f7358SJed Brown /* TODO: This assumption should be removed when there is a way of identifying whether a space is conceptually a 43*552f7358SJed Brown * vector or just happens to have the same number of dofs as the dimension. */ 44*552f7358SJed Brown if (cdof == dim) { 45*552f7358SJed Brown ft = PETSC_VTK_CELL_VECTOR_FIELD; 46*552f7358SJed Brown } else { 47*552f7358SJed Brown ft = PETSC_VTK_CELL_FIELD; 48*552f7358SJed Brown } 49*552f7358SJed Brown } else if (vdof) { 50*552f7358SJed Brown if (vdof == dim) { 51*552f7358SJed Brown ft = PETSC_VTK_POINT_VECTOR_FIELD; 52*552f7358SJed Brown } else { 53*552f7358SJed Brown ft = PETSC_VTK_POINT_FIELD; 54*552f7358SJed Brown } 55*552f7358SJed Brown } else SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 56*552f7358SJed Brown 57*552f7358SJed Brown ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 58*552f7358SJed Brown ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 59*552f7358SJed Brown ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 60*552f7358SJed Brown } else { 61*552f7358SJed Brown PetscBool isseq; 62*552f7358SJed Brown 63*552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 64*552f7358SJed Brown if (isseq) { 65*552f7358SJed Brown ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 66*552f7358SJed Brown } else { 67*552f7358SJed Brown ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 68*552f7358SJed Brown } 69*552f7358SJed Brown } 70*552f7358SJed Brown PetscFunctionReturn(0); 71*552f7358SJed Brown } 72*552f7358SJed Brown 73*552f7358SJed Brown #undef __FUNCT__ 74*552f7358SJed Brown #define __FUNCT__ "VecView_Plex" 75*552f7358SJed Brown PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 76*552f7358SJed Brown { 77*552f7358SJed Brown DM dm; 78*552f7358SJed Brown PetscBool isvtk; 79*552f7358SJed Brown PetscErrorCode ierr; 80*552f7358SJed Brown 81*552f7358SJed Brown PetscFunctionBegin; 82*552f7358SJed Brown ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 83*552f7358SJed Brown if (!dm) SETERRQ(((PetscObject) v)->comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 84*552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 85*552f7358SJed Brown if (isvtk) { 86*552f7358SJed Brown Vec locv; 87*552f7358SJed Brown const char *name; 88*552f7358SJed Brown 89*552f7358SJed Brown ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 90*552f7358SJed Brown ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 91*552f7358SJed Brown ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 92*552f7358SJed Brown ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 93*552f7358SJed Brown ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 94*552f7358SJed Brown ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 95*552f7358SJed Brown ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 96*552f7358SJed Brown } else { 97*552f7358SJed Brown PetscBool isseq; 98*552f7358SJed Brown 99*552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 100*552f7358SJed Brown if (isseq) { 101*552f7358SJed Brown ierr = VecView_Seq(v, viewer);CHKERRQ(ierr); 102*552f7358SJed Brown } else { 103*552f7358SJed Brown ierr = VecView_MPI(v, viewer);CHKERRQ(ierr); 104*552f7358SJed Brown } 105*552f7358SJed Brown } 106*552f7358SJed Brown PetscFunctionReturn(0); 107*552f7358SJed Brown } 108*552f7358SJed Brown 109*552f7358SJed Brown #undef __FUNCT__ 110*552f7358SJed Brown #define __FUNCT__ "DMPlexView_Ascii" 111*552f7358SJed Brown PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 112*552f7358SJed Brown { 113*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 114*552f7358SJed Brown DM cdm; 115*552f7358SJed Brown DMLabel markers; 116*552f7358SJed Brown PetscSection coordSection; 117*552f7358SJed Brown Vec coordinates; 118*552f7358SJed Brown PetscViewerFormat format; 119*552f7358SJed Brown PetscErrorCode ierr; 120*552f7358SJed Brown 121*552f7358SJed Brown PetscFunctionBegin; 122*552f7358SJed Brown ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 123*552f7358SJed Brown ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 124*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 125*552f7358SJed Brown ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 126*552f7358SJed Brown if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 127*552f7358SJed Brown const char *name; 128*552f7358SJed Brown PetscInt maxConeSize, maxSupportSize; 129*552f7358SJed Brown PetscInt pStart, pEnd, p; 130*552f7358SJed Brown PetscMPIInt rank, size; 131*552f7358SJed Brown 132*552f7358SJed Brown ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 133*552f7358SJed Brown ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 134*552f7358SJed Brown ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 135*552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 136*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 137*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 138*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 139*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 140*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 141*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 142*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 143*552f7358SJed Brown PetscInt dof, off, s; 144*552f7358SJed Brown 145*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 146*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 147*552f7358SJed Brown for (s = off; s < off+dof; ++s) { 148*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 149*552f7358SJed Brown } 150*552f7358SJed Brown } 151*552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 152*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 153*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 154*552f7358SJed Brown PetscInt dof, off, c; 155*552f7358SJed Brown 156*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 157*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 158*552f7358SJed Brown for (c = off; c < off+dof; ++c) { 159*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%D]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 160*552f7358SJed Brown } 161*552f7358SJed Brown } 162*552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 163*552f7358SJed Brown ierr = PetscSectionGetChart(coordSection, &pStart, PETSC_NULL);CHKERRQ(ierr); 164*552f7358SJed Brown if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 165*552f7358SJed Brown ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 166*552f7358SJed Brown if (markers) { 167*552f7358SJed Brown ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 168*552f7358SJed Brown } 169*552f7358SJed Brown if (size > 1) { 170*552f7358SJed Brown PetscSF sf; 171*552f7358SJed Brown 172*552f7358SJed Brown ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 173*552f7358SJed Brown ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 174*552f7358SJed Brown } 175*552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 176*552f7358SJed Brown } else if (format == PETSC_VIEWER_ASCII_LATEX) { 177*552f7358SJed Brown const char *name; 178*552f7358SJed Brown const char *colors[3] = {"red", "blue", "green"}; 179*552f7358SJed Brown const int numColors = 3; 180*552f7358SJed Brown PetscReal scale = 2.0; 181*552f7358SJed Brown PetscScalar *coords; 182*552f7358SJed Brown PetscInt depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 183*552f7358SJed Brown PetscMPIInt rank, size; 184*552f7358SJed Brown 185*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 186*552f7358SJed Brown ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 187*552f7358SJed Brown ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 188*552f7358SJed Brown ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 189*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 190*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\\documentclass{article}\n\n\ 191*552f7358SJed Brown \\usepackage{tikz}\n\ 192*552f7358SJed Brown \\usepackage{pgflibraryshapes}\n\ 193*552f7358SJed Brown \\usetikzlibrary{backgrounds}\n\ 194*552f7358SJed Brown \\usetikzlibrary{arrows}\n\ 195*552f7358SJed Brown \\newenvironment{changemargin}[2]{%%\n\ 196*552f7358SJed Brown \\begin{list}{}{%%\n\ 197*552f7358SJed Brown \\setlength{\\topsep}{0pt}%%\n\ 198*552f7358SJed Brown \\setlength{\\leftmargin}{#1}%%\n\ 199*552f7358SJed Brown \\setlength{\\rightmargin}{#2}%%\n\ 200*552f7358SJed Brown \\setlength{\\listparindent}{\\parindent}%%\n\ 201*552f7358SJed Brown \\setlength{\\itemindent}{\\parindent}%%\n\ 202*552f7358SJed Brown \\setlength{\\parsep}{\\parskip}%%\n\ 203*552f7358SJed Brown }%%\n\ 204*552f7358SJed Brown \\item[]}{\\end{list}}\n\n\ 205*552f7358SJed Brown \\begin{document}\n\ 206*552f7358SJed Brown \\section{%s}\n\ 207*552f7358SJed Brown \\begin{changemargin}{-1cm}{0cm}\n\ 208*552f7358SJed Brown \\begin{center}\n\ 209*552f7358SJed Brown \\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", name, 8.0/scale);CHKERRQ(ierr); 210*552f7358SJed Brown /* Plot vertices */ 211*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 212*552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 213*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 214*552f7358SJed Brown for(v = vStart; v < vEnd; ++v) { 215*552f7358SJed Brown PetscInt off, dof, d; 216*552f7358SJed Brown 217*552f7358SJed Brown ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 218*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 219*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 220*552f7358SJed Brown for (d = 0; d < dof; ++d) { 221*552f7358SJed Brown if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 222*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*PetscRealPart(coords[off+d]));CHKERRQ(ierr); 223*552f7358SJed Brown } 224*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", v, rank, colors[rank%numColors], v);CHKERRQ(ierr); 225*552f7358SJed Brown } 226*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 227*552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 228*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 229*552f7358SJed Brown /* Plot edges */ 230*552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 231*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 232*552f7358SJed Brown if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 233*552f7358SJed Brown for(e = eStart; e < eEnd; ++e) { 234*552f7358SJed Brown const PetscInt *cone; 235*552f7358SJed Brown PetscInt coneSize, offA, offB, dof, d; 236*552f7358SJed Brown 237*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 238*552f7358SJed Brown if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 239*552f7358SJed Brown ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 240*552f7358SJed Brown ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 241*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 242*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 243*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 244*552f7358SJed Brown for (d = 0; d < dof; ++d) { 245*552f7358SJed Brown if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 246*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%G", scale*0.5*PetscRealPart(coords[offA+d]+coords[offB+d]));CHKERRQ(ierr); 247*552f7358SJed Brown } 248*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%D) [draw,shape=circle,color=%s] {%D} --\n", e, rank, colors[rank%numColors], e);CHKERRQ(ierr); 249*552f7358SJed Brown } 250*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 251*552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 252*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 253*552f7358SJed Brown /* Plot cells */ 254*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 255*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 256*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 257*552f7358SJed Brown PetscInt closureSize, firstPoint = -1; 258*552f7358SJed Brown 259*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 260*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 261*552f7358SJed Brown for (p = 0; p < closureSize*2; p += 2) { 262*552f7358SJed Brown const PetscInt point = closure[p]; 263*552f7358SJed Brown 264*552f7358SJed Brown if ((point < vStart) || (point >= vEnd)) continue; 265*552f7358SJed Brown if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 266*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%D)", point, rank);CHKERRQ(ierr); 267*552f7358SJed Brown if (firstPoint < 0) firstPoint = point; 268*552f7358SJed Brown } 269*552f7358SJed Brown /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 270*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%D);\n", firstPoint, rank);CHKERRQ(ierr); 271*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 272*552f7358SJed Brown } 273*552f7358SJed Brown ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 274*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n\\end{center}\n");CHKERRQ(ierr); 275*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "Mesh for process ");CHKERRQ(ierr); 276*552f7358SJed Brown for(p = 0; p < size; ++p) { 277*552f7358SJed Brown if (p > 0 && p == size-1) { 278*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 279*552f7358SJed Brown } else if (p > 0) { 280*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 281*552f7358SJed Brown } 282*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 283*552f7358SJed Brown } 284*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, ".\n");CHKERRQ(ierr); 285*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\\end{changemargin}\n\ 286*552f7358SJed Brown \\end{document}\n", name);CHKERRQ(ierr); 287*552f7358SJed Brown } else { 288*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 289*552f7358SJed Brown PetscInt *sizes; 290*552f7358SJed Brown PetscInt locDepth, depth, dim, d; 291*552f7358SJed Brown PetscInt pStart, pEnd, p; 292*552f7358SJed Brown PetscMPIInt size; 293*552f7358SJed Brown 294*552f7358SJed Brown ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 295*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 296*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr); 297*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 298*552f7358SJed Brown ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 299*552f7358SJed Brown ierr = PetscMalloc(size * sizeof(PetscInt), &sizes);CHKERRQ(ierr); 300*552f7358SJed Brown if (depth == 1) { 301*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 302*552f7358SJed Brown pEnd = pEnd - pStart; 303*552f7358SJed Brown ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 304*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 305*552f7358SJed Brown for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 306*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 307*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 308*552f7358SJed Brown pEnd = pEnd - pStart; 309*552f7358SJed Brown ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 310*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 311*552f7358SJed Brown for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 312*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 313*552f7358SJed Brown } else { 314*552f7358SJed Brown for (d = 0; d <= dim; d++) { 315*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 316*552f7358SJed Brown pEnd = pEnd - pStart; 317*552f7358SJed Brown ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 318*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 319*552f7358SJed Brown for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 320*552f7358SJed Brown ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 321*552f7358SJed Brown } 322*552f7358SJed Brown } 323*552f7358SJed Brown ierr = PetscFree(sizes);CHKERRQ(ierr); 324*552f7358SJed Brown } 325*552f7358SJed Brown PetscFunctionReturn(0); 326*552f7358SJed Brown } 327*552f7358SJed Brown 328*552f7358SJed Brown #undef __FUNCT__ 329*552f7358SJed Brown #define __FUNCT__ "DMView_Plex" 330*552f7358SJed Brown PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 331*552f7358SJed Brown { 332*552f7358SJed Brown PetscBool iascii, isbinary; 333*552f7358SJed Brown PetscErrorCode ierr; 334*552f7358SJed Brown 335*552f7358SJed Brown PetscFunctionBegin; 336*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 337*552f7358SJed Brown PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 338*552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 339*552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 340*552f7358SJed Brown if (iascii) { 341*552f7358SJed Brown ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 342*552f7358SJed Brown #if 0 343*552f7358SJed Brown } else if (isbinary) { 344*552f7358SJed Brown ierr = DMPlexView_Binary(dm, viewer);CHKERRQ(ierr); 345*552f7358SJed Brown #endif 346*552f7358SJed Brown } else SETERRQ1(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Viewer type %s not supported by this mesh object", ((PetscObject)viewer)->type_name); 347*552f7358SJed Brown PetscFunctionReturn(0); 348*552f7358SJed Brown } 349*552f7358SJed Brown 350*552f7358SJed Brown #undef __FUNCT__ 351*552f7358SJed Brown #define __FUNCT__ "DMDestroy_Plex" 352*552f7358SJed Brown PetscErrorCode DMDestroy_Plex(DM dm) 353*552f7358SJed Brown { 354*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 355*552f7358SJed Brown DMLabel next = mesh->labels; 356*552f7358SJed Brown PetscErrorCode ierr; 357*552f7358SJed Brown 358*552f7358SJed Brown PetscFunctionBegin; 359*552f7358SJed Brown if (--mesh->refct > 0) {PetscFunctionReturn(0);} 360*552f7358SJed Brown ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 361*552f7358SJed Brown ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 362*552f7358SJed Brown ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 363*552f7358SJed Brown ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 364*552f7358SJed Brown ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 365*552f7358SJed Brown ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 366*552f7358SJed Brown while(next) { 367*552f7358SJed Brown DMLabel tmp = next->next; 368*552f7358SJed Brown 369*552f7358SJed Brown ierr = DMLabelDestroy(&next);CHKERRQ(ierr); 370*552f7358SJed Brown next = tmp; 371*552f7358SJed Brown } 372*552f7358SJed Brown ierr = ISDestroy(&mesh->subpointMap);CHKERRQ(ierr); 373*552f7358SJed Brown ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 374*552f7358SJed Brown ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 375*552f7358SJed Brown /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 376*552f7358SJed Brown ierr = PetscFree(mesh);CHKERRQ(ierr); 377*552f7358SJed Brown PetscFunctionReturn(0); 378*552f7358SJed Brown } 379*552f7358SJed Brown 380*552f7358SJed Brown #undef __FUNCT__ 381*552f7358SJed Brown #define __FUNCT__ "DMPlexGetAdjacencySingleLevel_Private" 382*552f7358SJed Brown PetscErrorCode DMPlexGetAdjacencySingleLevel_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 383*552f7358SJed Brown { 384*552f7358SJed Brown const PetscInt *support = PETSC_NULL; 385*552f7358SJed Brown PetscInt numAdj = 0, maxAdjSize = *adjSize, supportSize, s; 386*552f7358SJed Brown PetscErrorCode ierr; 387*552f7358SJed Brown 388*552f7358SJed Brown PetscFunctionBegin; 389*552f7358SJed Brown if (useClosure) { 390*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &supportSize);CHKERRQ(ierr); 391*552f7358SJed Brown ierr = DMPlexGetCone(dm, p, &support);CHKERRQ(ierr); 392*552f7358SJed Brown for (s = 0; s < supportSize; ++s) { 393*552f7358SJed Brown const PetscInt *cone = PETSC_NULL; 394*552f7358SJed Brown PetscInt coneSize, c, q; 395*552f7358SJed Brown 396*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, support[s], &coneSize);CHKERRQ(ierr); 397*552f7358SJed Brown ierr = DMPlexGetSupport(dm, support[s], &cone);CHKERRQ(ierr); 398*552f7358SJed Brown for (c = 0; c < coneSize; ++c) { 399*552f7358SJed Brown for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 400*552f7358SJed Brown if (cone[c] == adj[q]) break; 401*552f7358SJed Brown } 402*552f7358SJed Brown if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 403*552f7358SJed Brown } 404*552f7358SJed Brown } 405*552f7358SJed Brown } else { 406*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 407*552f7358SJed Brown ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 408*552f7358SJed Brown for (s = 0; s < supportSize; ++s) { 409*552f7358SJed Brown const PetscInt *cone = PETSC_NULL; 410*552f7358SJed Brown PetscInt coneSize, c, q; 411*552f7358SJed Brown 412*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 413*552f7358SJed Brown ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 414*552f7358SJed Brown for (c = 0; c < coneSize; ++c) { 415*552f7358SJed Brown for (q = 0; q < numAdj || (adj[numAdj++] = cone[c],0); ++q) { 416*552f7358SJed Brown if (cone[c] == adj[q]) break; 417*552f7358SJed Brown } 418*552f7358SJed Brown if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 419*552f7358SJed Brown } 420*552f7358SJed Brown } 421*552f7358SJed Brown } 422*552f7358SJed Brown *adjSize = numAdj; 423*552f7358SJed Brown PetscFunctionReturn(0); 424*552f7358SJed Brown } 425*552f7358SJed Brown 426*552f7358SJed Brown #undef __FUNCT__ 427*552f7358SJed Brown #define __FUNCT__ "DMPlexGetAdjacency_Private" 428*552f7358SJed Brown PetscErrorCode DMPlexGetAdjacency_Private(DM dm, PetscInt p, PetscBool useClosure, const PetscInt *tmpClosure, PetscInt *adjSize, PetscInt adj[]) 429*552f7358SJed Brown { 430*552f7358SJed Brown const PetscInt *star = tmpClosure; 431*552f7358SJed Brown PetscInt numAdj = 0, maxAdjSize = *adjSize, starSize, s; 432*552f7358SJed Brown PetscErrorCode ierr; 433*552f7358SJed Brown 434*552f7358SJed Brown PetscFunctionBegin; 435*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, p, useClosure, &starSize, (PetscInt **) &star);CHKERRQ(ierr); 436*552f7358SJed Brown for (s = 2; s < starSize*2; s += 2) { 437*552f7358SJed Brown const PetscInt *closure = PETSC_NULL; 438*552f7358SJed Brown PetscInt closureSize, c, q; 439*552f7358SJed Brown 440*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 441*552f7358SJed Brown for (c = 0; c < closureSize*2; c += 2) { 442*552f7358SJed Brown for (q = 0; q < numAdj || (adj[numAdj++] = closure[c],0); ++q) { 443*552f7358SJed Brown if (closure[c] == adj[q]) break; 444*552f7358SJed Brown } 445*552f7358SJed Brown if (numAdj > maxAdjSize) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid mesh exceeded adjacency allocation (%D)", maxAdjSize); 446*552f7358SJed Brown } 447*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, star[s], (PetscBool)!useClosure, &closureSize, (PetscInt **) &closure);CHKERRQ(ierr); 448*552f7358SJed Brown } 449*552f7358SJed Brown *adjSize = numAdj; 450*552f7358SJed Brown PetscFunctionReturn(0); 451*552f7358SJed Brown } 452*552f7358SJed Brown 453*552f7358SJed Brown #undef __FUNCT__ 454*552f7358SJed Brown #define __FUNCT__ "DMPlexSetPreallocationCenterDimension" 455*552f7358SJed Brown PetscErrorCode DMPlexSetPreallocationCenterDimension(DM dm, PetscInt preallocCenterDim) 456*552f7358SJed Brown { 457*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 458*552f7358SJed Brown 459*552f7358SJed Brown PetscFunctionBegin; 460*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 461*552f7358SJed Brown mesh->preallocCenterDim = preallocCenterDim; 462*552f7358SJed Brown PetscFunctionReturn(0); 463*552f7358SJed Brown } 464*552f7358SJed Brown 465*552f7358SJed Brown #undef __FUNCT__ 466*552f7358SJed Brown #define __FUNCT__ "DMPlexPreallocateOperator" 467*552f7358SJed Brown PetscErrorCode DMPlexPreallocateOperator(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 468*552f7358SJed Brown { 469*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 470*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 471*552f7358SJed Brown PetscSF sf, sfDof, sfAdj; 472*552f7358SJed Brown PetscSection leafSectionAdj, rootSectionAdj, sectionAdj; 473*552f7358SJed Brown PetscInt nleaves, l, p; 474*552f7358SJed Brown const PetscInt *leaves; 475*552f7358SJed Brown const PetscSFNode *remotes; 476*552f7358SJed Brown PetscInt dim, pStart, pEnd, numDof, globalOffStart, globalOffEnd, numCols; 477*552f7358SJed Brown PetscInt *tmpClosure, *tmpAdj, *adj, *rootAdj, *cols, *remoteOffsets; 478*552f7358SJed Brown PetscInt depth, maxConeSize, maxSupportSize, maxClosureSize, maxAdjSize, adjSize; 479*552f7358SJed Brown PetscLayout rLayout; 480*552f7358SJed Brown PetscInt locRows, rStart, rEnd, r; 481*552f7358SJed Brown PetscMPIInt size; 482*552f7358SJed Brown PetscBool useClosure, debug = PETSC_FALSE; 483*552f7358SJed Brown PetscErrorCode ierr; 484*552f7358SJed Brown 485*552f7358SJed Brown PetscFunctionBegin; 486*552f7358SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL, "-dm_view_preallocation", &debug, PETSC_NULL);CHKERRQ(ierr); 487*552f7358SJed Brown ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 488*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 489*552f7358SJed Brown ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 490*552f7358SJed Brown /* Create dof SF based on point SF */ 491*552f7358SJed Brown if (debug) { 492*552f7358SJed Brown ierr = PetscPrintf(comm, "Input Section for Preallocation:\n");CHKERRQ(ierr); 493*552f7358SJed Brown ierr = PetscSectionView(section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 494*552f7358SJed Brown ierr = PetscPrintf(comm, "Input Global Section for Preallocation:\n");CHKERRQ(ierr); 495*552f7358SJed Brown ierr = PetscSectionView(sectionGlobal, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 496*552f7358SJed Brown ierr = PetscPrintf(comm, "Input SF for Preallocation:\n");CHKERRQ(ierr); 497*552f7358SJed Brown ierr = PetscSFView(sf, PETSC_NULL);CHKERRQ(ierr); 498*552f7358SJed Brown } 499*552f7358SJed Brown ierr = PetscSFCreateRemoteOffsets(sf, section, section, &remoteOffsets);CHKERRQ(ierr); 500*552f7358SJed Brown ierr = PetscSFCreateSectionSF(sf, section, remoteOffsets, section, &sfDof);CHKERRQ(ierr); 501*552f7358SJed Brown if (debug) { 502*552f7358SJed Brown ierr = PetscPrintf(comm, "Dof SF for Preallocation:\n");CHKERRQ(ierr); 503*552f7358SJed Brown ierr = PetscSFView(sfDof, PETSC_NULL);CHKERRQ(ierr); 504*552f7358SJed Brown } 505*552f7358SJed Brown /* Create section for dof adjacency (dof ==> # adj dof) */ 506*552f7358SJed Brown /* FEM: Two points p and q are adjacent if q \in closure(star(p)), preallocCenterDim = dim */ 507*552f7358SJed Brown /* FVM: Two points p and q are adjacent if q \in star(cone(p)), preallocCenterDim = dim-1 */ 508*552f7358SJed Brown /* FVM++: Two points p and q are adjacent if q \in star(closure(p)), preallocCenterDim = 0 */ 509*552f7358SJed Brown if (mesh->preallocCenterDim == dim) { 510*552f7358SJed Brown useClosure = PETSC_FALSE; 511*552f7358SJed Brown } else if (mesh->preallocCenterDim == 0) { 512*552f7358SJed Brown useClosure = PETSC_TRUE; 513*552f7358SJed Brown } else SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Do not support preallocation with center points of dimension %d", mesh->preallocCenterDim); 514*552f7358SJed Brown 515*552f7358SJed Brown ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 516*552f7358SJed Brown ierr = PetscSectionGetStorageSize(section, &numDof);CHKERRQ(ierr); 517*552f7358SJed Brown ierr = PetscSectionCreate(comm, &leafSectionAdj);CHKERRQ(ierr); 518*552f7358SJed Brown ierr = PetscSectionSetChart(leafSectionAdj, 0, numDof);CHKERRQ(ierr); 519*552f7358SJed Brown ierr = PetscSectionCreate(comm, &rootSectionAdj);CHKERRQ(ierr); 520*552f7358SJed Brown ierr = PetscSectionSetChart(rootSectionAdj, 0, numDof);CHKERRQ(ierr); 521*552f7358SJed Brown /* Fill in the ghost dofs on the interface */ 522*552f7358SJed Brown ierr = PetscSFGetGraph(sf, PETSC_NULL, &nleaves, &leaves, &remotes);CHKERRQ(ierr); 523*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 524*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 525*552f7358SJed Brown maxClosureSize = (PetscInt) (2*PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1)); 526*552f7358SJed Brown maxAdjSize = (PetscInt) (pow((PetscReal) mesh->maxConeSize, depth)*pow((PetscReal) mesh->maxSupportSize, depth)+1); 527*552f7358SJed Brown ierr = PetscMalloc2(maxClosureSize,PetscInt,&tmpClosure,maxAdjSize,PetscInt,&tmpAdj);CHKERRQ(ierr); 528*552f7358SJed Brown 529*552f7358SJed Brown /* 530*552f7358SJed Brown ** The bootstrapping process involves six rounds with similar structure of visiting neighbors of each point. 531*552f7358SJed Brown 1. Visit unowned points on interface, count adjacencies placing in leafSectionAdj 532*552f7358SJed Brown Reduce those counts to rootSectionAdj (now redundantly counting some interface points) 533*552f7358SJed Brown 2. Visit owned points on interface, count adjacencies placing in rootSectionAdj 534*552f7358SJed Brown Create sfAdj connecting rootSectionAdj and leafSectionAdj 535*552f7358SJed Brown 3. Visit unowned points on interface, write adjacencies to adj 536*552f7358SJed Brown Gather adj to rootAdj (note that there is redundancy in rootAdj when multiple procs find the same adjacencies) 537*552f7358SJed Brown 4. Visit owned points on interface, write adjacencies to rootAdj 538*552f7358SJed Brown Remove redundancy in rootAdj 539*552f7358SJed Brown ** The last two traversals use transitive closure 540*552f7358SJed Brown 5. Visit all owned points in the subdomain, count dofs for each point (sectionAdj) 541*552f7358SJed Brown Allocate memory addressed by sectionAdj (cols) 542*552f7358SJed Brown 6. Visit all owned points in the subdomain, insert dof adjacencies into cols 543*552f7358SJed Brown ** Knowing all the column adjacencies, check ownership and sum into dnz and onz 544*552f7358SJed Brown */ 545*552f7358SJed Brown 546*552f7358SJed Brown for (l = 0; l < nleaves; ++l) { 547*552f7358SJed Brown PetscInt dof, off, d, q; 548*552f7358SJed Brown PetscInt p = leaves[l], numAdj = maxAdjSize; 549*552f7358SJed Brown 550*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 551*552f7358SJed Brown ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 552*552f7358SJed Brown ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 553*552f7358SJed Brown for (q = 0; q < numAdj; ++q) { 554*552f7358SJed Brown PetscInt ndof, ncdof; 555*552f7358SJed Brown 556*552f7358SJed Brown ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 557*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 558*552f7358SJed Brown for (d = off; d < off+dof; ++d) { 559*552f7358SJed Brown ierr = PetscSectionAddDof(leafSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 560*552f7358SJed Brown } 561*552f7358SJed Brown } 562*552f7358SJed Brown } 563*552f7358SJed Brown ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 564*552f7358SJed Brown if (debug) { 565*552f7358SJed Brown ierr = PetscPrintf(comm, "Adjacency Section for Preallocation on Leaves:\n");CHKERRQ(ierr); 566*552f7358SJed Brown ierr = PetscSectionView(leafSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 567*552f7358SJed Brown } 568*552f7358SJed Brown /* Get maximum remote adjacency sizes for owned dofs on interface (roots) */ 569*552f7358SJed Brown if (size > 1) { 570*552f7358SJed Brown ierr = PetscSFReduceBegin(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 571*552f7358SJed Brown ierr = PetscSFReduceEnd(sfDof, MPIU_INT, leafSectionAdj->atlasDof, rootSectionAdj->atlasDof, MPI_SUM);CHKERRQ(ierr); 572*552f7358SJed Brown } 573*552f7358SJed Brown if (debug) { 574*552f7358SJed Brown ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots:\n");CHKERRQ(ierr); 575*552f7358SJed Brown ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 576*552f7358SJed Brown } 577*552f7358SJed Brown /* Add in local adjacency sizes for owned dofs on interface (roots) */ 578*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 579*552f7358SJed Brown PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 580*552f7358SJed Brown 581*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 582*552f7358SJed Brown ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 583*552f7358SJed Brown if (!dof) continue; 584*552f7358SJed Brown ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 585*552f7358SJed Brown if (adof <= 0) continue; 586*552f7358SJed Brown ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 587*552f7358SJed Brown for (q = 0; q < numAdj; ++q) { 588*552f7358SJed Brown PetscInt ndof, ncdof; 589*552f7358SJed Brown 590*552f7358SJed Brown ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 591*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 592*552f7358SJed Brown for (d = off; d < off+dof; ++d) { 593*552f7358SJed Brown ierr = PetscSectionAddDof(rootSectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 594*552f7358SJed Brown } 595*552f7358SJed Brown } 596*552f7358SJed Brown } 597*552f7358SJed Brown ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 598*552f7358SJed Brown if (debug) { 599*552f7358SJed Brown ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after local additions:\n");CHKERRQ(ierr); 600*552f7358SJed Brown ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 601*552f7358SJed Brown } 602*552f7358SJed Brown /* Create adj SF based on dof SF */ 603*552f7358SJed Brown ierr = PetscSFCreateRemoteOffsets(sfDof, rootSectionAdj, leafSectionAdj, &remoteOffsets);CHKERRQ(ierr); 604*552f7358SJed Brown ierr = PetscSFCreateSectionSF(sfDof, rootSectionAdj, remoteOffsets, leafSectionAdj, &sfAdj);CHKERRQ(ierr); 605*552f7358SJed Brown if (debug) { 606*552f7358SJed Brown ierr = PetscPrintf(comm, "Adjacency SF for Preallocation:\n");CHKERRQ(ierr); 607*552f7358SJed Brown ierr = PetscSFView(sfAdj, PETSC_NULL);CHKERRQ(ierr); 608*552f7358SJed Brown } 609*552f7358SJed Brown ierr = PetscSFDestroy(&sfDof);CHKERRQ(ierr); 610*552f7358SJed Brown /* Create leaf adjacency */ 611*552f7358SJed Brown ierr = PetscSectionSetUp(leafSectionAdj);CHKERRQ(ierr); 612*552f7358SJed Brown ierr = PetscSectionGetStorageSize(leafSectionAdj, &adjSize);CHKERRQ(ierr); 613*552f7358SJed Brown ierr = PetscMalloc(adjSize * sizeof(PetscInt), &adj);CHKERRQ(ierr); 614*552f7358SJed Brown ierr = PetscMemzero(adj, adjSize * sizeof(PetscInt));CHKERRQ(ierr); 615*552f7358SJed Brown for (l = 0; l < nleaves; ++l) { 616*552f7358SJed Brown PetscInt dof, off, d, q; 617*552f7358SJed Brown PetscInt p = leaves[l], numAdj = maxAdjSize; 618*552f7358SJed Brown 619*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 620*552f7358SJed Brown ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 621*552f7358SJed Brown ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 622*552f7358SJed Brown for (d = off; d < off+dof; ++d) { 623*552f7358SJed Brown PetscInt aoff, i = 0; 624*552f7358SJed Brown 625*552f7358SJed Brown ierr = PetscSectionGetOffset(leafSectionAdj, d, &aoff);CHKERRQ(ierr); 626*552f7358SJed Brown for (q = 0; q < numAdj; ++q) { 627*552f7358SJed Brown PetscInt ndof, ncdof, ngoff, nd; 628*552f7358SJed Brown 629*552f7358SJed Brown ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 630*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 631*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 632*552f7358SJed Brown for (nd = 0; nd < ndof-ncdof; ++nd) { 633*552f7358SJed Brown adj[aoff+i] = (ngoff < 0 ? -(ngoff+1) : ngoff) + nd; 634*552f7358SJed Brown ++i; 635*552f7358SJed Brown } 636*552f7358SJed Brown } 637*552f7358SJed Brown } 638*552f7358SJed Brown } 639*552f7358SJed Brown /* Debugging */ 640*552f7358SJed Brown if (debug) { 641*552f7358SJed Brown IS tmp; 642*552f7358SJed Brown ierr = PetscPrintf(comm, "Leaf adjacency indices\n");CHKERRQ(ierr); 643*552f7358SJed Brown ierr = ISCreateGeneral(comm, adjSize, adj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 644*552f7358SJed Brown ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 645*552f7358SJed Brown } 646*552f7358SJed Brown /* Gather adjacenct indices to root */ 647*552f7358SJed Brown ierr = PetscSectionGetStorageSize(rootSectionAdj, &adjSize);CHKERRQ(ierr); 648*552f7358SJed Brown ierr = PetscMalloc(adjSize * sizeof(PetscInt), &rootAdj);CHKERRQ(ierr); 649*552f7358SJed Brown for (r = 0; r < adjSize; ++r) { 650*552f7358SJed Brown rootAdj[r] = -1; 651*552f7358SJed Brown } 652*552f7358SJed Brown if (size > 1) { 653*552f7358SJed Brown ierr = PetscSFGatherBegin(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 654*552f7358SJed Brown ierr = PetscSFGatherEnd(sfAdj, MPIU_INT, adj, rootAdj);CHKERRQ(ierr); 655*552f7358SJed Brown } 656*552f7358SJed Brown ierr = PetscSFDestroy(&sfAdj);CHKERRQ(ierr); 657*552f7358SJed Brown ierr = PetscFree(adj);CHKERRQ(ierr); 658*552f7358SJed Brown /* Debugging */ 659*552f7358SJed Brown if (debug) { 660*552f7358SJed Brown IS tmp; 661*552f7358SJed Brown ierr = PetscPrintf(comm, "Root adjacency indices after gather\n");CHKERRQ(ierr); 662*552f7358SJed Brown ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 663*552f7358SJed Brown ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 664*552f7358SJed Brown } 665*552f7358SJed Brown /* Add in local adjacency indices for owned dofs on interface (roots) */ 666*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 667*552f7358SJed Brown PetscInt numAdj = maxAdjSize, adof, dof, off, d, q; 668*552f7358SJed Brown 669*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 670*552f7358SJed Brown ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 671*552f7358SJed Brown if (!dof) continue; 672*552f7358SJed Brown ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 673*552f7358SJed Brown if (adof <= 0) continue; 674*552f7358SJed Brown ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 675*552f7358SJed Brown for (d = off; d < off+dof; ++d) { 676*552f7358SJed Brown PetscInt adof, aoff, i; 677*552f7358SJed Brown 678*552f7358SJed Brown ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 679*552f7358SJed Brown ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 680*552f7358SJed Brown i = adof-1; 681*552f7358SJed Brown for (q = 0; q < numAdj; ++q) { 682*552f7358SJed Brown PetscInt ndof, ncdof, ngoff, nd; 683*552f7358SJed Brown 684*552f7358SJed Brown ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 685*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 686*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 687*552f7358SJed Brown for (nd = 0; nd < ndof-ncdof; ++nd) { 688*552f7358SJed Brown rootAdj[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 689*552f7358SJed Brown --i; 690*552f7358SJed Brown } 691*552f7358SJed Brown } 692*552f7358SJed Brown } 693*552f7358SJed Brown } 694*552f7358SJed Brown /* Debugging */ 695*552f7358SJed Brown if (debug) { 696*552f7358SJed Brown IS tmp; 697*552f7358SJed Brown ierr = PetscPrintf(comm, "Root adjacency indices\n");CHKERRQ(ierr); 698*552f7358SJed Brown ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 699*552f7358SJed Brown ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 700*552f7358SJed Brown } 701*552f7358SJed Brown /* Compress indices */ 702*552f7358SJed Brown ierr = PetscSectionSetUp(rootSectionAdj);CHKERRQ(ierr); 703*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 704*552f7358SJed Brown PetscInt dof, cdof, off, d; 705*552f7358SJed Brown PetscInt adof, aoff; 706*552f7358SJed Brown 707*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 708*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 709*552f7358SJed Brown ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 710*552f7358SJed Brown if (!dof) continue; 711*552f7358SJed Brown ierr = PetscSectionGetDof(rootSectionAdj, off, &adof);CHKERRQ(ierr); 712*552f7358SJed Brown if (adof <= 0) continue; 713*552f7358SJed Brown for (d = off; d < off+dof-cdof; ++d) { 714*552f7358SJed Brown ierr = PetscSectionGetDof(rootSectionAdj, d, &adof);CHKERRQ(ierr); 715*552f7358SJed Brown ierr = PetscSectionGetOffset(rootSectionAdj, d, &aoff);CHKERRQ(ierr); 716*552f7358SJed Brown ierr = PetscSortRemoveDupsInt(&adof, &rootAdj[aoff]);CHKERRQ(ierr); 717*552f7358SJed Brown ierr = PetscSectionSetDof(rootSectionAdj, d, adof);CHKERRQ(ierr); 718*552f7358SJed Brown } 719*552f7358SJed Brown } 720*552f7358SJed Brown /* Debugging */ 721*552f7358SJed Brown if (debug) { 722*552f7358SJed Brown IS tmp; 723*552f7358SJed Brown ierr = PetscPrintf(comm, "Adjancency Section for Preallocation on Roots after compression:\n");CHKERRQ(ierr); 724*552f7358SJed Brown ierr = PetscSectionView(rootSectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 725*552f7358SJed Brown ierr = PetscPrintf(comm, "Root adjacency indices after compression\n");CHKERRQ(ierr); 726*552f7358SJed Brown ierr = ISCreateGeneral(comm, adjSize, rootAdj, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 727*552f7358SJed Brown ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 728*552f7358SJed Brown } 729*552f7358SJed Brown /* Build adjacency section: Maps global indices to sets of adjacent global indices */ 730*552f7358SJed Brown ierr = PetscSectionGetOffsetRange(sectionGlobal, &globalOffStart, &globalOffEnd);CHKERRQ(ierr); 731*552f7358SJed Brown ierr = PetscSectionCreate(comm, §ionAdj);CHKERRQ(ierr); 732*552f7358SJed Brown ierr = PetscSectionSetChart(sectionAdj, globalOffStart, globalOffEnd);CHKERRQ(ierr); 733*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 734*552f7358SJed Brown PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 735*552f7358SJed Brown PetscBool found = PETSC_TRUE; 736*552f7358SJed Brown 737*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 738*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 739*552f7358SJed Brown ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 740*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 741*552f7358SJed Brown for (d = 0; d < dof-cdof; ++d) { 742*552f7358SJed Brown PetscInt ldof, rdof; 743*552f7358SJed Brown 744*552f7358SJed Brown ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 745*552f7358SJed Brown ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 746*552f7358SJed Brown if (ldof > 0) { 747*552f7358SJed Brown /* We do not own this point */ 748*552f7358SJed Brown } else if (rdof > 0) { 749*552f7358SJed Brown ierr = PetscSectionSetDof(sectionAdj, goff+d, rdof);CHKERRQ(ierr); 750*552f7358SJed Brown } else { 751*552f7358SJed Brown found = PETSC_FALSE; 752*552f7358SJed Brown } 753*552f7358SJed Brown } 754*552f7358SJed Brown if (found) continue; 755*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 756*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 757*552f7358SJed Brown ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 758*552f7358SJed Brown for (q = 0; q < numAdj; ++q) { 759*552f7358SJed Brown PetscInt ndof, ncdof, noff; 760*552f7358SJed Brown 761*552f7358SJed Brown /* Adjacent points may not be in the section chart */ 762*552f7358SJed Brown if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 763*552f7358SJed Brown ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 764*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 765*552f7358SJed Brown ierr = PetscSectionGetOffset(section, tmpAdj[q], &noff);CHKERRQ(ierr); 766*552f7358SJed Brown for (d = goff; d < goff+dof-cdof; ++d) { 767*552f7358SJed Brown ierr = PetscSectionAddDof(sectionAdj, d, ndof-ncdof);CHKERRQ(ierr); 768*552f7358SJed Brown } 769*552f7358SJed Brown } 770*552f7358SJed Brown } 771*552f7358SJed Brown ierr = PetscSectionSetUp(sectionAdj);CHKERRQ(ierr); 772*552f7358SJed Brown if (debug) { 773*552f7358SJed Brown ierr = PetscPrintf(comm, "Adjacency Section for Preallocation:\n");CHKERRQ(ierr); 774*552f7358SJed Brown ierr = PetscSectionView(sectionAdj, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 775*552f7358SJed Brown } 776*552f7358SJed Brown /* Get adjacent indices */ 777*552f7358SJed Brown ierr = PetscSectionGetStorageSize(sectionAdj, &numCols);CHKERRQ(ierr); 778*552f7358SJed Brown ierr = PetscMalloc(numCols * sizeof(PetscInt), &cols);CHKERRQ(ierr); 779*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 780*552f7358SJed Brown PetscInt numAdj = maxAdjSize, dof, cdof, off, goff, d, q; 781*552f7358SJed Brown PetscBool found = PETSC_TRUE; 782*552f7358SJed Brown 783*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 784*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 785*552f7358SJed Brown ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 786*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 787*552f7358SJed Brown for (d = 0; d < dof-cdof; ++d) { 788*552f7358SJed Brown PetscInt ldof, rdof; 789*552f7358SJed Brown 790*552f7358SJed Brown ierr = PetscSectionGetDof(leafSectionAdj, off+d, &ldof);CHKERRQ(ierr); 791*552f7358SJed Brown ierr = PetscSectionGetDof(rootSectionAdj, off+d, &rdof);CHKERRQ(ierr); 792*552f7358SJed Brown if (ldof > 0) { 793*552f7358SJed Brown /* We do not own this point */ 794*552f7358SJed Brown } else if (rdof > 0) { 795*552f7358SJed Brown PetscInt aoff, roff; 796*552f7358SJed Brown 797*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionAdj, goff+d, &aoff);CHKERRQ(ierr); 798*552f7358SJed Brown ierr = PetscSectionGetOffset(rootSectionAdj, off+d, &roff);CHKERRQ(ierr); 799*552f7358SJed Brown ierr = PetscMemcpy(&cols[aoff], &rootAdj[roff], rdof * sizeof(PetscInt));CHKERRQ(ierr); 800*552f7358SJed Brown } else { 801*552f7358SJed Brown found = PETSC_FALSE; 802*552f7358SJed Brown } 803*552f7358SJed Brown } 804*552f7358SJed Brown if (found) continue; 805*552f7358SJed Brown ierr = DMPlexGetAdjacency_Private(dm, p, useClosure, tmpClosure, &numAdj, tmpAdj);CHKERRQ(ierr); 806*552f7358SJed Brown for (d = goff; d < goff+dof-cdof; ++d) { 807*552f7358SJed Brown PetscInt adof, aoff, i = 0; 808*552f7358SJed Brown 809*552f7358SJed Brown ierr = PetscSectionGetDof(sectionAdj, d, &adof);CHKERRQ(ierr); 810*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionAdj, d, &aoff);CHKERRQ(ierr); 811*552f7358SJed Brown for (q = 0; q < numAdj; ++q) { 812*552f7358SJed Brown PetscInt ndof, ncdof, ngoff, nd; 813*552f7358SJed Brown const PetscInt *ncind; 814*552f7358SJed Brown 815*552f7358SJed Brown /* Adjacent points may not be in the section chart */ 816*552f7358SJed Brown if ((tmpAdj[q] < pStart) || (tmpAdj[q] >= pEnd)) continue; 817*552f7358SJed Brown ierr = PetscSectionGetDof(section, tmpAdj[q], &ndof);CHKERRQ(ierr); 818*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, tmpAdj[q], &ncdof);CHKERRQ(ierr); 819*552f7358SJed Brown ierr = PetscSectionGetConstraintIndices(section, tmpAdj[q], &ncind);CHKERRQ(ierr); 820*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionGlobal, tmpAdj[q], &ngoff);CHKERRQ(ierr); 821*552f7358SJed Brown for (nd = 0; nd < ndof-ncdof; ++nd, ++i) { 822*552f7358SJed Brown cols[aoff+i] = ngoff < 0 ? -(ngoff+1)+nd: ngoff+nd; 823*552f7358SJed Brown } 824*552f7358SJed Brown } 825*552f7358SJed Brown if (i != adof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of entries %D != %D for dof %D (point %D)", i, adof, d, p); 826*552f7358SJed Brown } 827*552f7358SJed Brown } 828*552f7358SJed Brown ierr = PetscSectionDestroy(&leafSectionAdj);CHKERRQ(ierr); 829*552f7358SJed Brown ierr = PetscSectionDestroy(&rootSectionAdj);CHKERRQ(ierr); 830*552f7358SJed Brown ierr = PetscFree(rootAdj);CHKERRQ(ierr); 831*552f7358SJed Brown ierr = PetscFree2(tmpClosure, tmpAdj);CHKERRQ(ierr); 832*552f7358SJed Brown /* Debugging */ 833*552f7358SJed Brown if (debug) { 834*552f7358SJed Brown IS tmp; 835*552f7358SJed Brown ierr = PetscPrintf(comm, "Column indices\n");CHKERRQ(ierr); 836*552f7358SJed Brown ierr = ISCreateGeneral(comm, numCols, cols, PETSC_USE_POINTER, &tmp);CHKERRQ(ierr); 837*552f7358SJed Brown ierr = ISView(tmp, PETSC_NULL);CHKERRQ(ierr); 838*552f7358SJed Brown } 839*552f7358SJed Brown /* Create allocation vectors from adjacency graph */ 840*552f7358SJed Brown ierr = MatGetLocalSize(A, &locRows, PETSC_NULL);CHKERRQ(ierr); 841*552f7358SJed Brown ierr = PetscLayoutCreate(((PetscObject) A)->comm, &rLayout);CHKERRQ(ierr); 842*552f7358SJed Brown ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 843*552f7358SJed Brown ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 844*552f7358SJed Brown ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 845*552f7358SJed Brown ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 846*552f7358SJed Brown ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 847*552f7358SJed Brown /* Only loop over blocks of rows */ 848*552f7358SJed Brown if (rStart%bs || rEnd%bs) SETERRQ3(((PetscObject) A)->comm, PETSC_ERR_ARG_WRONG, "Invalid layout [%d, %d) for matrix, must be divisible by block size %d", rStart, rEnd, bs); 849*552f7358SJed Brown for (r = rStart/bs; r < rEnd/bs; ++r) { 850*552f7358SJed Brown const PetscInt row = r*bs; 851*552f7358SJed Brown PetscInt numCols, cStart, c; 852*552f7358SJed Brown 853*552f7358SJed Brown ierr = PetscSectionGetDof(sectionAdj, row, &numCols);CHKERRQ(ierr); 854*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionAdj, row, &cStart);CHKERRQ(ierr); 855*552f7358SJed Brown for (c = cStart; c < cStart+numCols; ++c) { 856*552f7358SJed Brown if ((cols[c] >= rStart*bs) && (cols[c] < rEnd*bs)) { 857*552f7358SJed Brown ++dnz[r-rStart]; 858*552f7358SJed Brown if (cols[c] >= row) {++dnzu[r-rStart];} 859*552f7358SJed Brown } else { 860*552f7358SJed Brown ++onz[r-rStart]; 861*552f7358SJed Brown if (cols[c] >= row) {++onzu[r-rStart];} 862*552f7358SJed Brown } 863*552f7358SJed Brown } 864*552f7358SJed Brown } 865*552f7358SJed Brown if (bs > 1) { 866*552f7358SJed Brown for (r = 0; r < locRows/bs; ++r) { 867*552f7358SJed Brown dnz[r] /= bs; 868*552f7358SJed Brown onz[r] /= bs; 869*552f7358SJed Brown dnzu[r] /= bs; 870*552f7358SJed Brown onzu[r] /= bs; 871*552f7358SJed Brown } 872*552f7358SJed Brown } 873*552f7358SJed Brown /* Set matrix pattern */ 874*552f7358SJed Brown ierr = MatXAIJSetPreallocation(A, bs, dnz, onz, dnzu, onzu);CHKERRQ(ierr); 875*552f7358SJed Brown ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 876*552f7358SJed Brown /* Fill matrix with zeros */ 877*552f7358SJed Brown if (fillMatrix) { 878*552f7358SJed Brown PetscScalar *values; 879*552f7358SJed Brown PetscInt maxRowLen = 0; 880*552f7358SJed Brown 881*552f7358SJed Brown for (r = rStart; r < rEnd; ++r) { 882*552f7358SJed Brown PetscInt len; 883*552f7358SJed Brown 884*552f7358SJed Brown ierr = PetscSectionGetDof(sectionAdj, r, &len);CHKERRQ(ierr); 885*552f7358SJed Brown maxRowLen = PetscMax(maxRowLen, len); 886*552f7358SJed Brown } 887*552f7358SJed Brown ierr = PetscMalloc(maxRowLen * sizeof(PetscScalar), &values);CHKERRQ(ierr); 888*552f7358SJed Brown ierr = PetscMemzero(values, maxRowLen * sizeof(PetscScalar));CHKERRQ(ierr); 889*552f7358SJed Brown for (r = rStart; r < rEnd; ++r) { 890*552f7358SJed Brown PetscInt numCols, cStart; 891*552f7358SJed Brown 892*552f7358SJed Brown ierr = PetscSectionGetDof(sectionAdj, r, &numCols);CHKERRQ(ierr); 893*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionAdj, r, &cStart);CHKERRQ(ierr); 894*552f7358SJed Brown ierr = MatSetValues(A, 1, &r, numCols, &cols[cStart], values, INSERT_VALUES);CHKERRQ(ierr); 895*552f7358SJed Brown } 896*552f7358SJed Brown ierr = PetscFree(values);CHKERRQ(ierr); 897*552f7358SJed Brown ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 898*552f7358SJed Brown ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 899*552f7358SJed Brown } 900*552f7358SJed Brown ierr = PetscSectionDestroy(§ionAdj);CHKERRQ(ierr); 901*552f7358SJed Brown ierr = PetscFree(cols);CHKERRQ(ierr); 902*552f7358SJed Brown PetscFunctionReturn(0); 903*552f7358SJed Brown } 904*552f7358SJed Brown 905*552f7358SJed Brown #if 0 906*552f7358SJed Brown #undef __FUNCT__ 907*552f7358SJed Brown #define __FUNCT__ "DMPlexPreallocateOperator_2" 908*552f7358SJed Brown PetscErrorCode DMPlexPreallocateOperator_2(DM dm, PetscInt bs, PetscSection section, PetscSection sectionGlobal, PetscInt dnz[], PetscInt onz[], PetscInt dnzu[], PetscInt onzu[], Mat A, PetscBool fillMatrix) 909*552f7358SJed Brown { 910*552f7358SJed Brown PetscErrorCode ierr; 911*552f7358SJed Brown PetscInt c,cStart,cEnd,pStart,pEnd; 912*552f7358SJed Brown PetscInt *tmpClosure,*tmpAdj,*visits; 913*552f7358SJed Brown 914*552f7358SJed Brown PetscFunctionBegin; 915*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 916*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 917*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 918*552f7358SJed Brown maxClosureSize = 2*PetscMax(pow(mesh->maxConeSize, depth)+1, pow(mesh->maxSupportSize, depth)+1); 919*552f7358SJed Brown ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 920*552f7358SJed Brown npoints = pEnd - pStart; 921*552f7358SJed Brown ierr = PetscMalloc3(maxClosureSize,PetscInt,&tmpClosure,npoints,PetscInt,&lvisits,npoints,PetscInt,&visits);CHKERRQ(ierr); 922*552f7358SJed Brown ierr = PetscMemzero(lvisits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 923*552f7358SJed Brown ierr = PetscMemzero(visits,(pEnd-pStart)*sizeof(PetscInt));CHKERRQ(ierr); 924*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 925*552f7358SJed Brown for (c=cStart; c<cEnd; c++) { 926*552f7358SJed Brown PetscInt *support = tmpClosure; 927*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_FALSE, &supportSize, (PetscInt**)&support);CHKERRQ(ierr); 928*552f7358SJed Brown for (p=0; p<supportSize; p++) { 929*552f7358SJed Brown lvisits[support[p]]++; 930*552f7358SJed Brown } 931*552f7358SJed Brown } 932*552f7358SJed Brown ierr = PetscSFReduceBegin(sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 933*552f7358SJed Brown ierr = PetscSFReduceEnd (sf,MPIU_INT,lvisits,visits,MPI_SUM);CHKERRQ(ierr); 934*552f7358SJed Brown ierr = PetscSFBcastBegin(sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 935*552f7358SJed Brown ierr = PetscSFBcastEnd (sf,MPIU_INT,visits,lvisits);CHKERRQ(ierr); 936*552f7358SJed Brown 937*552f7358SJed Brown ierr = PetscSFGetRanks();CHKERRQ(ierr); 938*552f7358SJed Brown 939*552f7358SJed Brown 940*552f7358SJed Brown ierr = PetscMalloc2(maxClosureSize*maxClosureSize,PetscInt,&cellmat,npoints,PetscInt,&owner);CHKERRQ(ierr); 941*552f7358SJed Brown for (c=cStart; c<cEnd; c++) { 942*552f7358SJed Brown ierr = PetscMemzero(cellmat,maxClosureSize*maxClosureSize*sizeof(PetscInt));CHKERRQ(ierr); 943*552f7358SJed Brown /* 944*552f7358SJed Brown Depth-first walk of transitive closure. 945*552f7358SJed Brown At each leaf frame f of transitive closure that we see, add 1/visits[f] to each pair (p,q) not marked as done in cellmat. 946*552f7358SJed Brown This contribution is added to dnz if owning ranks of p and q match, to onz otherwise. 947*552f7358SJed Brown */ 948*552f7358SJed Brown } 949*552f7358SJed Brown 950*552f7358SJed Brown ierr = PetscSFReduceBegin(sf,MPIU_INT,ldnz,dnz,MPI_SUM);CHKERRQ(ierr); 951*552f7358SJed Brown ierr = PetscSFReduceEnd (sf,MPIU_INT,lonz,onz,MPI_SUM);CHKERRQ(ierr); 952*552f7358SJed Brown PetscFunctionReturn(0); 953*552f7358SJed Brown } 954*552f7358SJed Brown #endif 955*552f7358SJed Brown 956*552f7358SJed Brown #undef __FUNCT__ 957*552f7358SJed Brown #define __FUNCT__ "DMCreateMatrix_Plex" 958*552f7358SJed Brown PetscErrorCode DMCreateMatrix_Plex(DM dm, MatType mtype, Mat *J) 959*552f7358SJed Brown { 960*552f7358SJed Brown PetscSection section, sectionGlobal; 961*552f7358SJed Brown PetscInt bs = -1; 962*552f7358SJed Brown PetscInt localSize; 963*552f7358SJed Brown PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock, isSymmetric; 964*552f7358SJed Brown PetscErrorCode ierr; 965*552f7358SJed Brown 966*552f7358SJed Brown PetscFunctionBegin; 967*552f7358SJed Brown #ifndef PETSC_USE_DYNAMIC_LIBRARIES 968*552f7358SJed Brown ierr = MatInitializePackage(PETSC_NULL);CHKERRQ(ierr); 969*552f7358SJed Brown #endif 970*552f7358SJed Brown if (!mtype) mtype = MATAIJ; 971*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 972*552f7358SJed Brown ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 973*552f7358SJed Brown /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 974*552f7358SJed Brown ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 975*552f7358SJed Brown ierr = MatCreate(((PetscObject) dm)->comm, J);CHKERRQ(ierr); 976*552f7358SJed Brown ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 977*552f7358SJed Brown ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 978*552f7358SJed Brown ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 979*552f7358SJed Brown ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 980*552f7358SJed Brown ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 981*552f7358SJed Brown ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 982*552f7358SJed Brown ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 983*552f7358SJed Brown ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 984*552f7358SJed Brown ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 985*552f7358SJed Brown ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 986*552f7358SJed Brown /* Check for symmetric storage */ 987*552f7358SJed Brown isSymmetric = (PetscBool) (isSymBlock || isSymSeqBlock || isSymMPIBlock); 988*552f7358SJed Brown if (isSymmetric) { 989*552f7358SJed Brown ierr = MatSetOption(*J, MAT_IGNORE_LOWER_TRIANGULAR, PETSC_TRUE);CHKERRQ(ierr); 990*552f7358SJed Brown } 991*552f7358SJed Brown if (!isShell) { 992*552f7358SJed Brown PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 993*552f7358SJed Brown PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal; 994*552f7358SJed Brown 995*552f7358SJed Brown if (bs < 0) { 996*552f7358SJed Brown if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 997*552f7358SJed Brown PetscInt pStart, pEnd, p, dof; 998*552f7358SJed Brown 999*552f7358SJed Brown ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1000*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 1001*552f7358SJed Brown ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 1002*552f7358SJed Brown if (dof) { 1003*552f7358SJed Brown bs = dof; 1004*552f7358SJed Brown break; 1005*552f7358SJed Brown } 1006*552f7358SJed Brown } 1007*552f7358SJed Brown } else { 1008*552f7358SJed Brown bs = 1; 1009*552f7358SJed Brown } 1010*552f7358SJed Brown /* Must have same blocksize on all procs (some might have no points) */ 1011*552f7358SJed Brown bsLocal = bs; 1012*552f7358SJed Brown ierr = MPI_Allreduce(&bsLocal, &bs, 1, MPIU_INT, MPI_MAX, ((PetscObject) dm)->comm);CHKERRQ(ierr); 1013*552f7358SJed Brown } 1014*552f7358SJed Brown ierr = PetscMalloc4(localSize/bs, PetscInt, &dnz, localSize/bs, PetscInt, &onz, localSize/bs, PetscInt, &dnzu, localSize/bs, PetscInt, &onzu);CHKERRQ(ierr); 1015*552f7358SJed Brown ierr = PetscMemzero(dnz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1016*552f7358SJed Brown ierr = PetscMemzero(onz, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1017*552f7358SJed Brown ierr = PetscMemzero(dnzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1018*552f7358SJed Brown ierr = PetscMemzero(onzu, localSize/bs * sizeof(PetscInt));CHKERRQ(ierr); 1019*552f7358SJed Brown ierr = DMPlexPreallocateOperator(dm, bs, section, sectionGlobal, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 1020*552f7358SJed Brown ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 1021*552f7358SJed Brown } 1022*552f7358SJed Brown PetscFunctionReturn(0); 1023*552f7358SJed Brown } 1024*552f7358SJed Brown 1025*552f7358SJed Brown #undef __FUNCT__ 1026*552f7358SJed Brown #define __FUNCT__ "DMPlexGetDimension" 1027*552f7358SJed Brown /*@ 1028*552f7358SJed Brown DMPlexGetDimension - Return the topological mesh dimension 1029*552f7358SJed Brown 1030*552f7358SJed Brown Not collective 1031*552f7358SJed Brown 1032*552f7358SJed Brown Input Parameter: 1033*552f7358SJed Brown . mesh - The DMPlex 1034*552f7358SJed Brown 1035*552f7358SJed Brown Output Parameter: 1036*552f7358SJed Brown . dim - The topological mesh dimension 1037*552f7358SJed Brown 1038*552f7358SJed Brown Level: beginner 1039*552f7358SJed Brown 1040*552f7358SJed Brown .seealso: DMPlexCreate() 1041*552f7358SJed Brown @*/ 1042*552f7358SJed Brown PetscErrorCode DMPlexGetDimension(DM dm, PetscInt *dim) 1043*552f7358SJed Brown { 1044*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1045*552f7358SJed Brown 1046*552f7358SJed Brown PetscFunctionBegin; 1047*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1048*552f7358SJed Brown PetscValidPointer(dim, 2); 1049*552f7358SJed Brown *dim = mesh->dim; 1050*552f7358SJed Brown PetscFunctionReturn(0); 1051*552f7358SJed Brown } 1052*552f7358SJed Brown 1053*552f7358SJed Brown #undef __FUNCT__ 1054*552f7358SJed Brown #define __FUNCT__ "DMPlexSetDimension" 1055*552f7358SJed Brown /*@ 1056*552f7358SJed Brown DMPlexSetDimension - Set the topological mesh dimension 1057*552f7358SJed Brown 1058*552f7358SJed Brown Collective on mesh 1059*552f7358SJed Brown 1060*552f7358SJed Brown Input Parameters: 1061*552f7358SJed Brown + mesh - The DMPlex 1062*552f7358SJed Brown - dim - The topological mesh dimension 1063*552f7358SJed Brown 1064*552f7358SJed Brown Level: beginner 1065*552f7358SJed Brown 1066*552f7358SJed Brown .seealso: DMPlexCreate() 1067*552f7358SJed Brown @*/ 1068*552f7358SJed Brown PetscErrorCode DMPlexSetDimension(DM dm, PetscInt dim) 1069*552f7358SJed Brown { 1070*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1071*552f7358SJed Brown 1072*552f7358SJed Brown PetscFunctionBegin; 1073*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1074*552f7358SJed Brown PetscValidLogicalCollectiveInt(dm, dim, 2); 1075*552f7358SJed Brown mesh->dim = dim; 1076*552f7358SJed Brown mesh->preallocCenterDim = dim; 1077*552f7358SJed Brown PetscFunctionReturn(0); 1078*552f7358SJed Brown } 1079*552f7358SJed Brown 1080*552f7358SJed Brown #undef __FUNCT__ 1081*552f7358SJed Brown #define __FUNCT__ "DMPlexGetChart" 1082*552f7358SJed Brown /*@ 1083*552f7358SJed Brown DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 1084*552f7358SJed Brown 1085*552f7358SJed Brown Not collective 1086*552f7358SJed Brown 1087*552f7358SJed Brown Input Parameter: 1088*552f7358SJed Brown . mesh - The DMPlex 1089*552f7358SJed Brown 1090*552f7358SJed Brown Output Parameters: 1091*552f7358SJed Brown + pStart - The first mesh point 1092*552f7358SJed Brown - pEnd - The upper bound for mesh points 1093*552f7358SJed Brown 1094*552f7358SJed Brown Level: beginner 1095*552f7358SJed Brown 1096*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart() 1097*552f7358SJed Brown @*/ 1098*552f7358SJed Brown PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 1099*552f7358SJed Brown { 1100*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1101*552f7358SJed Brown PetscErrorCode ierr; 1102*552f7358SJed Brown 1103*552f7358SJed Brown PetscFunctionBegin; 1104*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1105*552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1106*552f7358SJed Brown PetscFunctionReturn(0); 1107*552f7358SJed Brown } 1108*552f7358SJed Brown 1109*552f7358SJed Brown #undef __FUNCT__ 1110*552f7358SJed Brown #define __FUNCT__ "DMPlexSetChart" 1111*552f7358SJed Brown /*@ 1112*552f7358SJed Brown DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 1113*552f7358SJed Brown 1114*552f7358SJed Brown Not collective 1115*552f7358SJed Brown 1116*552f7358SJed Brown Input Parameters: 1117*552f7358SJed Brown + mesh - The DMPlex 1118*552f7358SJed Brown . pStart - The first mesh point 1119*552f7358SJed Brown - pEnd - The upper bound for mesh points 1120*552f7358SJed Brown 1121*552f7358SJed Brown Output Parameters: 1122*552f7358SJed Brown 1123*552f7358SJed Brown Level: beginner 1124*552f7358SJed Brown 1125*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetChart() 1126*552f7358SJed Brown @*/ 1127*552f7358SJed Brown PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 1128*552f7358SJed Brown { 1129*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1130*552f7358SJed Brown PetscErrorCode ierr; 1131*552f7358SJed Brown 1132*552f7358SJed Brown PetscFunctionBegin; 1133*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1134*552f7358SJed Brown ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 1135*552f7358SJed Brown ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 1136*552f7358SJed Brown PetscFunctionReturn(0); 1137*552f7358SJed Brown } 1138*552f7358SJed Brown 1139*552f7358SJed Brown #undef __FUNCT__ 1140*552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeSize" 1141*552f7358SJed Brown /*@ 1142*552f7358SJed Brown DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 1143*552f7358SJed Brown 1144*552f7358SJed Brown Not collective 1145*552f7358SJed Brown 1146*552f7358SJed Brown Input Parameters: 1147*552f7358SJed Brown + mesh - The DMPlex 1148*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1149*552f7358SJed Brown 1150*552f7358SJed Brown Output Parameter: 1151*552f7358SJed Brown . size - The cone size for point p 1152*552f7358SJed Brown 1153*552f7358SJed Brown Level: beginner 1154*552f7358SJed Brown 1155*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1156*552f7358SJed Brown @*/ 1157*552f7358SJed Brown PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 1158*552f7358SJed Brown { 1159*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1160*552f7358SJed Brown PetscErrorCode ierr; 1161*552f7358SJed Brown 1162*552f7358SJed Brown PetscFunctionBegin; 1163*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1164*552f7358SJed Brown PetscValidPointer(size, 3); 1165*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1166*552f7358SJed Brown PetscFunctionReturn(0); 1167*552f7358SJed Brown } 1168*552f7358SJed Brown 1169*552f7358SJed Brown #undef __FUNCT__ 1170*552f7358SJed Brown #define __FUNCT__ "DMPlexSetConeSize" 1171*552f7358SJed Brown /*@ 1172*552f7358SJed Brown DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 1173*552f7358SJed Brown 1174*552f7358SJed Brown Not collective 1175*552f7358SJed Brown 1176*552f7358SJed Brown Input Parameters: 1177*552f7358SJed Brown + mesh - The DMPlex 1178*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1179*552f7358SJed Brown - size - The cone size for point p 1180*552f7358SJed Brown 1181*552f7358SJed Brown Output Parameter: 1182*552f7358SJed Brown 1183*552f7358SJed Brown Note: 1184*552f7358SJed Brown This should be called after DMPlexSetChart(). 1185*552f7358SJed Brown 1186*552f7358SJed Brown Level: beginner 1187*552f7358SJed Brown 1188*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 1189*552f7358SJed Brown @*/ 1190*552f7358SJed Brown PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 1191*552f7358SJed Brown { 1192*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1193*552f7358SJed Brown PetscErrorCode ierr; 1194*552f7358SJed Brown 1195*552f7358SJed Brown PetscFunctionBegin; 1196*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1197*552f7358SJed Brown ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1198*552f7358SJed Brown mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 1199*552f7358SJed Brown PetscFunctionReturn(0); 1200*552f7358SJed Brown } 1201*552f7358SJed Brown 1202*552f7358SJed Brown #undef __FUNCT__ 1203*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCone" 1204*552f7358SJed Brown /*@C 1205*552f7358SJed Brown DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1206*552f7358SJed Brown 1207*552f7358SJed Brown Not collective 1208*552f7358SJed Brown 1209*552f7358SJed Brown Input Parameters: 1210*552f7358SJed Brown + mesh - The DMPlex 1211*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1212*552f7358SJed Brown 1213*552f7358SJed Brown Output Parameter: 1214*552f7358SJed Brown . cone - An array of points which are on the in-edges for point p 1215*552f7358SJed Brown 1216*552f7358SJed Brown Level: beginner 1217*552f7358SJed Brown 1218*552f7358SJed Brown Note: 1219*552f7358SJed Brown This routine is not available in Fortran. 1220*552f7358SJed Brown 1221*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1222*552f7358SJed Brown @*/ 1223*552f7358SJed Brown PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1224*552f7358SJed Brown { 1225*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1226*552f7358SJed Brown PetscInt off; 1227*552f7358SJed Brown PetscErrorCode ierr; 1228*552f7358SJed Brown 1229*552f7358SJed Brown PetscFunctionBegin; 1230*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1231*552f7358SJed Brown PetscValidPointer(cone, 3); 1232*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1233*552f7358SJed Brown *cone = &mesh->cones[off]; 1234*552f7358SJed Brown PetscFunctionReturn(0); 1235*552f7358SJed Brown } 1236*552f7358SJed Brown 1237*552f7358SJed Brown #undef __FUNCT__ 1238*552f7358SJed Brown #define __FUNCT__ "DMPlexSetCone" 1239*552f7358SJed Brown /*@ 1240*552f7358SJed Brown DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1241*552f7358SJed Brown 1242*552f7358SJed Brown Not collective 1243*552f7358SJed Brown 1244*552f7358SJed Brown Input Parameters: 1245*552f7358SJed Brown + mesh - The DMPlex 1246*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1247*552f7358SJed Brown - cone - An array of points which are on the in-edges for point p 1248*552f7358SJed Brown 1249*552f7358SJed Brown Output Parameter: 1250*552f7358SJed Brown 1251*552f7358SJed Brown Note: 1252*552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1253*552f7358SJed Brown 1254*552f7358SJed Brown Level: beginner 1255*552f7358SJed Brown 1256*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1257*552f7358SJed Brown @*/ 1258*552f7358SJed Brown PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1259*552f7358SJed Brown { 1260*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1261*552f7358SJed Brown PetscInt pStart, pEnd; 1262*552f7358SJed Brown PetscInt dof, off, c; 1263*552f7358SJed Brown PetscErrorCode ierr; 1264*552f7358SJed Brown 1265*552f7358SJed Brown PetscFunctionBegin; 1266*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1267*552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1268*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1269*552f7358SJed Brown if (dof) PetscValidPointer(cone, 3); 1270*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1271*552f7358SJed Brown if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1272*552f7358SJed Brown for (c = 0; c < dof; ++c) { 1273*552f7358SJed Brown if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1274*552f7358SJed Brown mesh->cones[off+c] = cone[c]; 1275*552f7358SJed Brown } 1276*552f7358SJed Brown PetscFunctionReturn(0); 1277*552f7358SJed Brown } 1278*552f7358SJed Brown 1279*552f7358SJed Brown #undef __FUNCT__ 1280*552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeOrientation" 1281*552f7358SJed Brown /*@C 1282*552f7358SJed Brown DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1283*552f7358SJed Brown 1284*552f7358SJed Brown Not collective 1285*552f7358SJed Brown 1286*552f7358SJed Brown Input Parameters: 1287*552f7358SJed Brown + mesh - The DMPlex 1288*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1289*552f7358SJed Brown 1290*552f7358SJed Brown Output Parameter: 1291*552f7358SJed Brown . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1292*552f7358SJed Brown integer giving the prescription for cone traversal. If it is negative, the cone is 1293*552f7358SJed Brown traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1294*552f7358SJed Brown the index of the cone point on which to start. 1295*552f7358SJed Brown 1296*552f7358SJed Brown Level: beginner 1297*552f7358SJed Brown 1298*552f7358SJed Brown Note: 1299*552f7358SJed Brown This routine is not available in Fortran. 1300*552f7358SJed Brown 1301*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1302*552f7358SJed Brown @*/ 1303*552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1304*552f7358SJed Brown { 1305*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1306*552f7358SJed Brown PetscInt off; 1307*552f7358SJed Brown PetscErrorCode ierr; 1308*552f7358SJed Brown 1309*552f7358SJed Brown PetscFunctionBegin; 1310*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1311*552f7358SJed Brown #if defined(PETSC_USE_DEBUG) 1312*552f7358SJed Brown { 1313*552f7358SJed Brown PetscInt dof; 1314*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1315*552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 1316*552f7358SJed Brown } 1317*552f7358SJed Brown #endif 1318*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1319*552f7358SJed Brown *coneOrientation = &mesh->coneOrientations[off]; 1320*552f7358SJed Brown PetscFunctionReturn(0); 1321*552f7358SJed Brown } 1322*552f7358SJed Brown 1323*552f7358SJed Brown #undef __FUNCT__ 1324*552f7358SJed Brown #define __FUNCT__ "DMPlexSetConeOrientation" 1325*552f7358SJed Brown /*@ 1326*552f7358SJed Brown DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1327*552f7358SJed Brown 1328*552f7358SJed Brown Not collective 1329*552f7358SJed Brown 1330*552f7358SJed Brown Input Parameters: 1331*552f7358SJed Brown + mesh - The DMPlex 1332*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1333*552f7358SJed Brown - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1334*552f7358SJed Brown integer giving the prescription for cone traversal. If it is negative, the cone is 1335*552f7358SJed Brown traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1336*552f7358SJed Brown the index of the cone point on which to start. 1337*552f7358SJed Brown 1338*552f7358SJed Brown Output Parameter: 1339*552f7358SJed Brown 1340*552f7358SJed Brown Note: 1341*552f7358SJed Brown This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1342*552f7358SJed Brown 1343*552f7358SJed Brown Level: beginner 1344*552f7358SJed Brown 1345*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1346*552f7358SJed Brown @*/ 1347*552f7358SJed Brown PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1348*552f7358SJed Brown { 1349*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1350*552f7358SJed Brown PetscInt pStart, pEnd; 1351*552f7358SJed Brown PetscInt dof, off, c; 1352*552f7358SJed Brown PetscErrorCode ierr; 1353*552f7358SJed Brown 1354*552f7358SJed Brown PetscFunctionBegin; 1355*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1356*552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1357*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1358*552f7358SJed Brown if (dof) PetscValidPointer(coneOrientation, 3); 1359*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1360*552f7358SJed Brown if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1361*552f7358SJed Brown for (c = 0; c < dof; ++c) { 1362*552f7358SJed Brown PetscInt cdof, o = coneOrientation[c]; 1363*552f7358SJed Brown 1364*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1365*552f7358SJed Brown if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1366*552f7358SJed Brown mesh->coneOrientations[off+c] = o; 1367*552f7358SJed Brown } 1368*552f7358SJed Brown PetscFunctionReturn(0); 1369*552f7358SJed Brown } 1370*552f7358SJed Brown 1371*552f7358SJed Brown #undef __FUNCT__ 1372*552f7358SJed Brown #define __FUNCT__ "DMPlexInsertCone" 1373*552f7358SJed Brown PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1374*552f7358SJed Brown { 1375*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1376*552f7358SJed Brown PetscInt pStart, pEnd; 1377*552f7358SJed Brown PetscInt dof, off; 1378*552f7358SJed Brown PetscErrorCode ierr; 1379*552f7358SJed Brown 1380*552f7358SJed Brown PetscFunctionBegin; 1381*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1382*552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1383*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1384*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1385*552f7358SJed Brown if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1386*552f7358SJed Brown if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1387*552f7358SJed Brown if (conePos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1388*552f7358SJed Brown mesh->cones[off+conePos] = conePoint; 1389*552f7358SJed Brown PetscFunctionReturn(0); 1390*552f7358SJed Brown } 1391*552f7358SJed Brown 1392*552f7358SJed Brown #undef __FUNCT__ 1393*552f7358SJed Brown #define __FUNCT__ "DMPlexGetSupportSize" 1394*552f7358SJed Brown /*@ 1395*552f7358SJed Brown DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1396*552f7358SJed Brown 1397*552f7358SJed Brown Not collective 1398*552f7358SJed Brown 1399*552f7358SJed Brown Input Parameters: 1400*552f7358SJed Brown + mesh - The DMPlex 1401*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1402*552f7358SJed Brown 1403*552f7358SJed Brown Output Parameter: 1404*552f7358SJed Brown . size - The support size for point p 1405*552f7358SJed Brown 1406*552f7358SJed Brown Level: beginner 1407*552f7358SJed Brown 1408*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1409*552f7358SJed Brown @*/ 1410*552f7358SJed Brown PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1411*552f7358SJed Brown { 1412*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1413*552f7358SJed Brown PetscErrorCode ierr; 1414*552f7358SJed Brown 1415*552f7358SJed Brown PetscFunctionBegin; 1416*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1417*552f7358SJed Brown PetscValidPointer(size, 3); 1418*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1419*552f7358SJed Brown PetscFunctionReturn(0); 1420*552f7358SJed Brown } 1421*552f7358SJed Brown 1422*552f7358SJed Brown #undef __FUNCT__ 1423*552f7358SJed Brown #define __FUNCT__ "DMPlexSetSupportSize" 1424*552f7358SJed Brown /*@ 1425*552f7358SJed Brown DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1426*552f7358SJed Brown 1427*552f7358SJed Brown Not collective 1428*552f7358SJed Brown 1429*552f7358SJed Brown Input Parameters: 1430*552f7358SJed Brown + mesh - The DMPlex 1431*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1432*552f7358SJed Brown - size - The support size for point p 1433*552f7358SJed Brown 1434*552f7358SJed Brown Output Parameter: 1435*552f7358SJed Brown 1436*552f7358SJed Brown Note: 1437*552f7358SJed Brown This should be called after DMPlexSetChart(). 1438*552f7358SJed Brown 1439*552f7358SJed Brown Level: beginner 1440*552f7358SJed Brown 1441*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1442*552f7358SJed Brown @*/ 1443*552f7358SJed Brown PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1444*552f7358SJed Brown { 1445*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1446*552f7358SJed Brown PetscErrorCode ierr; 1447*552f7358SJed Brown 1448*552f7358SJed Brown PetscFunctionBegin; 1449*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1450*552f7358SJed Brown ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1451*552f7358SJed Brown mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1452*552f7358SJed Brown PetscFunctionReturn(0); 1453*552f7358SJed Brown } 1454*552f7358SJed Brown 1455*552f7358SJed Brown #undef __FUNCT__ 1456*552f7358SJed Brown #define __FUNCT__ "DMPlexGetSupport" 1457*552f7358SJed Brown /*@C 1458*552f7358SJed Brown DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1459*552f7358SJed Brown 1460*552f7358SJed Brown Not collective 1461*552f7358SJed Brown 1462*552f7358SJed Brown Input Parameters: 1463*552f7358SJed Brown + mesh - The DMPlex 1464*552f7358SJed Brown - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1465*552f7358SJed Brown 1466*552f7358SJed Brown Output Parameter: 1467*552f7358SJed Brown . support - An array of points which are on the out-edges for point p 1468*552f7358SJed Brown 1469*552f7358SJed Brown Level: beginner 1470*552f7358SJed Brown 1471*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1472*552f7358SJed Brown @*/ 1473*552f7358SJed Brown PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1474*552f7358SJed Brown { 1475*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1476*552f7358SJed Brown PetscInt off; 1477*552f7358SJed Brown PetscErrorCode ierr; 1478*552f7358SJed Brown 1479*552f7358SJed Brown PetscFunctionBegin; 1480*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1481*552f7358SJed Brown PetscValidPointer(support, 3); 1482*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1483*552f7358SJed Brown *support = &mesh->supports[off]; 1484*552f7358SJed Brown PetscFunctionReturn(0); 1485*552f7358SJed Brown } 1486*552f7358SJed Brown 1487*552f7358SJed Brown #undef __FUNCT__ 1488*552f7358SJed Brown #define __FUNCT__ "DMPlexSetSupport" 1489*552f7358SJed Brown /*@ 1490*552f7358SJed Brown DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1491*552f7358SJed Brown 1492*552f7358SJed Brown Not collective 1493*552f7358SJed Brown 1494*552f7358SJed Brown Input Parameters: 1495*552f7358SJed Brown + mesh - The DMPlex 1496*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1497*552f7358SJed Brown - support - An array of points which are on the in-edges for point p 1498*552f7358SJed Brown 1499*552f7358SJed Brown Output Parameter: 1500*552f7358SJed Brown 1501*552f7358SJed Brown Note: 1502*552f7358SJed Brown This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1503*552f7358SJed Brown 1504*552f7358SJed Brown Level: beginner 1505*552f7358SJed Brown 1506*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1507*552f7358SJed Brown @*/ 1508*552f7358SJed Brown PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1509*552f7358SJed Brown { 1510*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1511*552f7358SJed Brown PetscInt pStart, pEnd; 1512*552f7358SJed Brown PetscInt dof, off, c; 1513*552f7358SJed Brown PetscErrorCode ierr; 1514*552f7358SJed Brown 1515*552f7358SJed Brown PetscFunctionBegin; 1516*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1517*552f7358SJed Brown ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1518*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1519*552f7358SJed Brown if (dof) PetscValidPointer(support, 3); 1520*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1521*552f7358SJed Brown if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1522*552f7358SJed Brown for (c = 0; c < dof; ++c) { 1523*552f7358SJed Brown if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1524*552f7358SJed Brown mesh->supports[off+c] = support[c]; 1525*552f7358SJed Brown } 1526*552f7358SJed Brown PetscFunctionReturn(0); 1527*552f7358SJed Brown } 1528*552f7358SJed Brown 1529*552f7358SJed Brown #undef __FUNCT__ 1530*552f7358SJed Brown #define __FUNCT__ "DMPlexInsertSupport" 1531*552f7358SJed Brown PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1532*552f7358SJed Brown { 1533*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1534*552f7358SJed Brown PetscInt pStart, pEnd; 1535*552f7358SJed Brown PetscInt dof, off; 1536*552f7358SJed Brown PetscErrorCode ierr; 1537*552f7358SJed Brown 1538*552f7358SJed Brown PetscFunctionBegin; 1539*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1540*552f7358SJed Brown ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1541*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1542*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1543*552f7358SJed Brown if ((p < pStart) || (p >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1544*552f7358SJed Brown if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1545*552f7358SJed Brown if (supportPos >= dof) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1546*552f7358SJed Brown mesh->supports[off+supportPos] = supportPoint; 1547*552f7358SJed Brown PetscFunctionReturn(0); 1548*552f7358SJed Brown } 1549*552f7358SJed Brown 1550*552f7358SJed Brown #undef __FUNCT__ 1551*552f7358SJed Brown #define __FUNCT__ "DMPlexGetTransitiveClosure" 1552*552f7358SJed Brown /*@C 1553*552f7358SJed Brown DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1554*552f7358SJed Brown 1555*552f7358SJed Brown Not collective 1556*552f7358SJed Brown 1557*552f7358SJed Brown Input Parameters: 1558*552f7358SJed Brown + mesh - The DMPlex 1559*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1560*552f7358SJed Brown . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1561*552f7358SJed Brown - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1562*552f7358SJed Brown 1563*552f7358SJed Brown Output Parameters: 1564*552f7358SJed Brown + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1565*552f7358SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1566*552f7358SJed Brown 1567*552f7358SJed Brown Note: 1568*552f7358SJed Brown If using internal storage (points is PETSC_NULL on input), each call overwrites the last output. 1569*552f7358SJed Brown 1570*552f7358SJed Brown Level: beginner 1571*552f7358SJed Brown 1572*552f7358SJed Brown .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1573*552f7358SJed Brown @*/ 1574*552f7358SJed Brown PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1575*552f7358SJed Brown { 1576*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1577*552f7358SJed Brown PetscInt *closure, *fifo; 1578*552f7358SJed Brown const PetscInt *tmp = PETSC_NULL, *tmpO = PETSC_NULL; 1579*552f7358SJed Brown PetscInt tmpSize, t; 1580*552f7358SJed Brown PetscInt depth = 0, maxSize; 1581*552f7358SJed Brown PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1582*552f7358SJed Brown PetscErrorCode ierr; 1583*552f7358SJed Brown 1584*552f7358SJed Brown PetscFunctionBegin; 1585*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1586*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1587*552f7358SJed Brown maxSize = (PetscInt) (2*PetscMax(PetscMax(pow((PetscReal) mesh->maxConeSize, depth)+1, pow((PetscReal) mesh->maxSupportSize, depth)+1), depth+1)); 1588*552f7358SJed Brown ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1589*552f7358SJed Brown if (*points) { 1590*552f7358SJed Brown closure = *points; 1591*552f7358SJed Brown } else { 1592*552f7358SJed Brown ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1593*552f7358SJed Brown } 1594*552f7358SJed Brown closure[0] = p; closure[1] = 0; 1595*552f7358SJed Brown /* This is only 1-level */ 1596*552f7358SJed Brown if (useCone) { 1597*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1598*552f7358SJed Brown ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1599*552f7358SJed Brown ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1600*552f7358SJed Brown } else { 1601*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1602*552f7358SJed Brown ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1603*552f7358SJed Brown } 1604*552f7358SJed Brown for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1605*552f7358SJed Brown const PetscInt cp = tmp[t]; 1606*552f7358SJed Brown const PetscInt co = tmpO ? tmpO[t] : 0; 1607*552f7358SJed Brown 1608*552f7358SJed Brown closure[closureSize] = cp; 1609*552f7358SJed Brown closure[closureSize+1] = co; 1610*552f7358SJed Brown fifo[fifoSize] = cp; 1611*552f7358SJed Brown fifo[fifoSize+1] = co; 1612*552f7358SJed Brown } 1613*552f7358SJed Brown while(fifoSize - fifoStart) { 1614*552f7358SJed Brown const PetscInt q = fifo[fifoStart]; 1615*552f7358SJed Brown const PetscInt o = fifo[fifoStart+1]; 1616*552f7358SJed Brown const PetscInt rev = o >= 0 ? 0 : 1; 1617*552f7358SJed Brown const PetscInt off = rev ? -(o+1) : o; 1618*552f7358SJed Brown 1619*552f7358SJed Brown if (useCone) { 1620*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1621*552f7358SJed Brown ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1622*552f7358SJed Brown ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1623*552f7358SJed Brown } else { 1624*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1625*552f7358SJed Brown ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1626*552f7358SJed Brown tmpO = PETSC_NULL; 1627*552f7358SJed Brown } 1628*552f7358SJed Brown for (t = 0; t < tmpSize; ++t) { 1629*552f7358SJed Brown const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1630*552f7358SJed Brown const PetscInt cp = tmp[i]; 1631*552f7358SJed Brown /* Must propogate orientation */ 1632*552f7358SJed Brown const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; 1633*552f7358SJed Brown PetscInt c; 1634*552f7358SJed Brown 1635*552f7358SJed Brown /* Check for duplicate */ 1636*552f7358SJed Brown for (c = 0; c < closureSize; c += 2) { 1637*552f7358SJed Brown if (closure[c] == cp) break; 1638*552f7358SJed Brown } 1639*552f7358SJed Brown if (c == closureSize) { 1640*552f7358SJed Brown closure[closureSize] = cp; 1641*552f7358SJed Brown closure[closureSize+1] = co; 1642*552f7358SJed Brown fifo[fifoSize] = cp; 1643*552f7358SJed Brown fifo[fifoSize+1] = co; 1644*552f7358SJed Brown closureSize += 2; 1645*552f7358SJed Brown fifoSize += 2; 1646*552f7358SJed Brown } 1647*552f7358SJed Brown } 1648*552f7358SJed Brown fifoStart += 2; 1649*552f7358SJed Brown } 1650*552f7358SJed Brown if (numPoints) *numPoints = closureSize/2; 1651*552f7358SJed Brown if (points) *points = closure; 1652*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1653*552f7358SJed Brown PetscFunctionReturn(0); 1654*552f7358SJed Brown } 1655*552f7358SJed Brown 1656*552f7358SJed Brown #undef __FUNCT__ 1657*552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1658*552f7358SJed Brown /*@C 1659*552f7358SJed Brown DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1660*552f7358SJed Brown 1661*552f7358SJed Brown Not collective 1662*552f7358SJed Brown 1663*552f7358SJed Brown Input Parameters: 1664*552f7358SJed Brown + mesh - The DMPlex 1665*552f7358SJed Brown . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1666*552f7358SJed Brown . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1667*552f7358SJed Brown - points - If points is PETSC_NULL on input, internal storage will be returned, otherwise the provided array is used 1668*552f7358SJed Brown 1669*552f7358SJed Brown Output Parameters: 1670*552f7358SJed Brown + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1671*552f7358SJed Brown - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1672*552f7358SJed Brown 1673*552f7358SJed Brown Note: 1674*552f7358SJed Brown If not using internal storage (points is not PETSC_NULL on input), this call is unnecessary 1675*552f7358SJed Brown 1676*552f7358SJed Brown Level: beginner 1677*552f7358SJed Brown 1678*552f7358SJed Brown .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1679*552f7358SJed Brown @*/ 1680*552f7358SJed Brown PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1681*552f7358SJed Brown { 1682*552f7358SJed Brown PetscErrorCode ierr; 1683*552f7358SJed Brown 1684*552f7358SJed Brown PetscFunctionBegin; 1685*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1686*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1687*552f7358SJed Brown PetscFunctionReturn(0); 1688*552f7358SJed Brown } 1689*552f7358SJed Brown 1690*552f7358SJed Brown #undef __FUNCT__ 1691*552f7358SJed Brown #define __FUNCT__ "DMPlexGetFaces" 1692*552f7358SJed Brown /* 1693*552f7358SJed Brown DMPlexGetFaces - 1694*552f7358SJed Brown 1695*552f7358SJed Brown Note: This will only work for cell-vertex meshes. 1696*552f7358SJed Brown */ 1697*552f7358SJed Brown PetscErrorCode DMPlexGetFaces(DM dm, PetscInt p, PetscInt *numFaces, PetscInt *faceSize, const PetscInt *faces[]) 1698*552f7358SJed Brown { 1699*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1700*552f7358SJed Brown const PetscInt *cone = PETSC_NULL; 1701*552f7358SJed Brown PetscInt depth = 0, dim, coneSize; 1702*552f7358SJed Brown PetscErrorCode ierr; 1703*552f7358SJed Brown 1704*552f7358SJed Brown PetscFunctionBegin; 1705*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1706*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 1707*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1708*552f7358SJed Brown if (depth > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Faces can only be returned for cell-vertex meshes."); 1709*552f7358SJed Brown if (!mesh->facesTmp) {ierr = PetscMalloc(PetscSqr(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)) * sizeof(PetscInt), &mesh->facesTmp);CHKERRQ(ierr);} 1710*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1711*552f7358SJed Brown ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1712*552f7358SJed Brown switch(dim) { 1713*552f7358SJed Brown case 2: 1714*552f7358SJed Brown switch(coneSize) { 1715*552f7358SJed Brown case 3: 1716*552f7358SJed Brown mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1717*552f7358SJed Brown mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1718*552f7358SJed Brown mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1719*552f7358SJed Brown *numFaces = 3; 1720*552f7358SJed Brown *faceSize = 2; 1721*552f7358SJed Brown *faces = mesh->facesTmp; 1722*552f7358SJed Brown break; 1723*552f7358SJed Brown case 4: 1724*552f7358SJed Brown mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1725*552f7358SJed Brown mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1726*552f7358SJed Brown mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1727*552f7358SJed Brown mesh->facesTmp[6] = cone[3]; mesh->facesTmp[7] = cone[0]; 1728*552f7358SJed Brown *numFaces = 4; 1729*552f7358SJed Brown *faceSize = 2; 1730*552f7358SJed Brown *faces = mesh->facesTmp; 1731*552f7358SJed Brown break; 1732*552f7358SJed Brown default: 1733*552f7358SJed Brown SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1734*552f7358SJed Brown } 1735*552f7358SJed Brown break; 1736*552f7358SJed Brown case 3: 1737*552f7358SJed Brown switch(coneSize) { 1738*552f7358SJed Brown case 3: 1739*552f7358SJed Brown mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; 1740*552f7358SJed Brown mesh->facesTmp[2] = cone[1]; mesh->facesTmp[3] = cone[2]; 1741*552f7358SJed Brown mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[0]; 1742*552f7358SJed Brown *numFaces = 3; 1743*552f7358SJed Brown *faceSize = 2; 1744*552f7358SJed Brown *faces = mesh->facesTmp; 1745*552f7358SJed Brown break; 1746*552f7358SJed Brown case 4: 1747*552f7358SJed Brown mesh->facesTmp[0] = cone[0]; mesh->facesTmp[1] = cone[1]; mesh->facesTmp[2] = cone[2]; 1748*552f7358SJed Brown mesh->facesTmp[3] = cone[0]; mesh->facesTmp[4] = cone[2]; mesh->facesTmp[5] = cone[3]; 1749*552f7358SJed Brown mesh->facesTmp[6] = cone[0]; mesh->facesTmp[7] = cone[3]; mesh->facesTmp[8] = cone[1]; 1750*552f7358SJed Brown mesh->facesTmp[9] = cone[1]; mesh->facesTmp[10] = cone[3]; mesh->facesTmp[11] = cone[2]; 1751*552f7358SJed Brown *numFaces = 4; 1752*552f7358SJed Brown *faceSize = 3; 1753*552f7358SJed Brown *faces = mesh->facesTmp; 1754*552f7358SJed Brown break; 1755*552f7358SJed Brown default: 1756*552f7358SJed Brown SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size %D not supported for dimension %D", coneSize, dim); 1757*552f7358SJed Brown } 1758*552f7358SJed Brown break; 1759*552f7358SJed Brown default: 1760*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not supported", dim); 1761*552f7358SJed Brown } 1762*552f7358SJed Brown PetscFunctionReturn(0); 1763*552f7358SJed Brown } 1764*552f7358SJed Brown 1765*552f7358SJed Brown #undef __FUNCT__ 1766*552f7358SJed Brown #define __FUNCT__ "DMPlexGetMaxSizes" 1767*552f7358SJed Brown /*@ 1768*552f7358SJed Brown DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1769*552f7358SJed Brown 1770*552f7358SJed Brown Not collective 1771*552f7358SJed Brown 1772*552f7358SJed Brown Input Parameter: 1773*552f7358SJed Brown . mesh - The DMPlex 1774*552f7358SJed Brown 1775*552f7358SJed Brown Output Parameters: 1776*552f7358SJed Brown + maxConeSize - The maximum number of in-edges 1777*552f7358SJed Brown - maxSupportSize - The maximum number of out-edges 1778*552f7358SJed Brown 1779*552f7358SJed Brown Level: beginner 1780*552f7358SJed Brown 1781*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1782*552f7358SJed Brown @*/ 1783*552f7358SJed Brown PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1784*552f7358SJed Brown { 1785*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1786*552f7358SJed Brown 1787*552f7358SJed Brown PetscFunctionBegin; 1788*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1789*552f7358SJed Brown if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1790*552f7358SJed Brown if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1791*552f7358SJed Brown PetscFunctionReturn(0); 1792*552f7358SJed Brown } 1793*552f7358SJed Brown 1794*552f7358SJed Brown #undef __FUNCT__ 1795*552f7358SJed Brown #define __FUNCT__ "DMSetUp_Plex" 1796*552f7358SJed Brown PetscErrorCode DMSetUp_Plex(DM dm) 1797*552f7358SJed Brown { 1798*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1799*552f7358SJed Brown PetscInt size; 1800*552f7358SJed Brown PetscErrorCode ierr; 1801*552f7358SJed Brown 1802*552f7358SJed Brown PetscFunctionBegin; 1803*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1804*552f7358SJed Brown ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1805*552f7358SJed Brown ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1806*552f7358SJed Brown ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->cones);CHKERRQ(ierr); 1807*552f7358SJed Brown ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->coneOrientations);CHKERRQ(ierr); 1808*552f7358SJed Brown ierr = PetscMemzero(mesh->coneOrientations, size * sizeof(PetscInt));CHKERRQ(ierr); 1809*552f7358SJed Brown if (mesh->maxSupportSize) { 1810*552f7358SJed Brown ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1811*552f7358SJed Brown ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1812*552f7358SJed Brown ierr = PetscMalloc(size * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1813*552f7358SJed Brown } 1814*552f7358SJed Brown PetscFunctionReturn(0); 1815*552f7358SJed Brown } 1816*552f7358SJed Brown 1817*552f7358SJed Brown #undef __FUNCT__ 1818*552f7358SJed Brown #define __FUNCT__ "DMCreateSubDM_Plex" 1819*552f7358SJed Brown PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1820*552f7358SJed Brown { 1821*552f7358SJed Brown PetscSection section, sectionGlobal; 1822*552f7358SJed Brown PetscInt *subIndices; 1823*552f7358SJed Brown PetscInt subSize = 0, subOff = 0, nF, f, pStart, pEnd, p; 1824*552f7358SJed Brown PetscErrorCode ierr; 1825*552f7358SJed Brown 1826*552f7358SJed Brown PetscFunctionBegin; 1827*552f7358SJed Brown if (!numFields) PetscFunctionReturn(0); 1828*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1829*552f7358SJed Brown ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 1830*552f7358SJed Brown if (!section) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default section for DMPlex before splitting fields"); 1831*552f7358SJed Brown if (!sectionGlobal) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DMPlex before splitting fields"); 1832*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &nF);CHKERRQ(ierr); 1833*552f7358SJed Brown if (numFields > nF) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF); 1834*552f7358SJed Brown ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 1835*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 1836*552f7358SJed Brown PetscInt gdof; 1837*552f7358SJed Brown 1838*552f7358SJed Brown ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1839*552f7358SJed Brown if (gdof > 0) { 1840*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 1841*552f7358SJed Brown PetscInt fdof, fcdof; 1842*552f7358SJed Brown 1843*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1844*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1845*552f7358SJed Brown subSize += fdof-fcdof; 1846*552f7358SJed Brown } 1847*552f7358SJed Brown } 1848*552f7358SJed Brown } 1849*552f7358SJed Brown ierr = PetscMalloc(subSize * sizeof(PetscInt), &subIndices);CHKERRQ(ierr); 1850*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 1851*552f7358SJed Brown PetscInt gdof, goff; 1852*552f7358SJed Brown 1853*552f7358SJed Brown ierr = PetscSectionGetDof(sectionGlobal, p, &gdof);CHKERRQ(ierr); 1854*552f7358SJed Brown if (gdof > 0) { 1855*552f7358SJed Brown ierr = PetscSectionGetOffset(sectionGlobal, p, &goff);CHKERRQ(ierr); 1856*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 1857*552f7358SJed Brown PetscInt fdof, fcdof, fc, f2, poff = 0; 1858*552f7358SJed Brown 1859*552f7358SJed Brown /* Can get rid of this loop by storing field information in the global section */ 1860*552f7358SJed Brown for (f2 = 0; f2 < fields[f]; ++f2) { 1861*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, p, f2, &fdof);CHKERRQ(ierr); 1862*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);CHKERRQ(ierr); 1863*552f7358SJed Brown poff += fdof-fcdof; 1864*552f7358SJed Brown } 1865*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, p, fields[f], &fdof);CHKERRQ(ierr); 1866*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);CHKERRQ(ierr); 1867*552f7358SJed Brown for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) { 1868*552f7358SJed Brown subIndices[subOff] = goff+poff+fc; 1869*552f7358SJed Brown } 1870*552f7358SJed Brown } 1871*552f7358SJed Brown } 1872*552f7358SJed Brown } 1873*552f7358SJed Brown if (is) {ierr = ISCreateGeneral(((PetscObject) dm)->comm, subSize, subIndices, PETSC_OWN_POINTER, is);CHKERRQ(ierr);} 1874*552f7358SJed Brown if (subdm) { 1875*552f7358SJed Brown PetscSection subsection; 1876*552f7358SJed Brown PetscBool haveNull = PETSC_FALSE; 1877*552f7358SJed Brown PetscInt f, nf = 0; 1878*552f7358SJed Brown 1879*552f7358SJed Brown ierr = DMPlexClone(dm, subdm);CHKERRQ(ierr); 1880*552f7358SJed Brown ierr = PetscSectionCreateSubsection(section, numFields, fields, &subsection);CHKERRQ(ierr); 1881*552f7358SJed Brown ierr = DMSetDefaultSection(*subdm, subsection);CHKERRQ(ierr); 1882*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 1883*552f7358SJed Brown (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]]; 1884*552f7358SJed Brown if ((*subdm)->nullspaceConstructors[f]) { 1885*552f7358SJed Brown haveNull = PETSC_TRUE; 1886*552f7358SJed Brown nf = f; 1887*552f7358SJed Brown } 1888*552f7358SJed Brown } 1889*552f7358SJed Brown if (haveNull) { 1890*552f7358SJed Brown MatNullSpace nullSpace; 1891*552f7358SJed Brown 1892*552f7358SJed Brown ierr = (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);CHKERRQ(ierr); 1893*552f7358SJed Brown ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);CHKERRQ(ierr); 1894*552f7358SJed Brown ierr = MatNullSpaceDestroy(&nullSpace);CHKERRQ(ierr); 1895*552f7358SJed Brown } 1896*552f7358SJed Brown if (dm->fields) { 1897*552f7358SJed Brown if (nF != dm->numFields) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", dm->numFields, nF); 1898*552f7358SJed Brown ierr = DMSetNumFields(*subdm, numFields);CHKERRQ(ierr); 1899*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 1900*552f7358SJed Brown ierr = PetscOListDuplicate(dm->fields[fields[f]]->olist, &(*subdm)->fields[f]->olist); 1901*552f7358SJed Brown } 1902*552f7358SJed Brown if (numFields == 1) { 1903*552f7358SJed Brown MatNullSpace space; 1904*552f7358SJed Brown Mat pmat; 1905*552f7358SJed Brown 1906*552f7358SJed Brown ierr = PetscObjectQuery((*subdm)->fields[0], "nullspace", (PetscObject *) &space);CHKERRQ(ierr); 1907*552f7358SJed Brown if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) space);CHKERRQ(ierr);} 1908*552f7358SJed Brown ierr = PetscObjectQuery((*subdm)->fields[0], "nearnullspace", (PetscObject *) &space);CHKERRQ(ierr); 1909*552f7358SJed Brown if (space) {ierr = PetscObjectCompose((PetscObject) *is, "nearnullspace", (PetscObject) space);CHKERRQ(ierr);} 1910*552f7358SJed Brown ierr = PetscObjectQuery((*subdm)->fields[0], "pmat", (PetscObject *) &pmat);CHKERRQ(ierr); 1911*552f7358SJed Brown if (pmat) {ierr = PetscObjectCompose((PetscObject) *is, "pmat", (PetscObject) pmat);CHKERRQ(ierr);} 1912*552f7358SJed Brown } 1913*552f7358SJed Brown } 1914*552f7358SJed Brown } 1915*552f7358SJed Brown PetscFunctionReturn(0); 1916*552f7358SJed Brown } 1917*552f7358SJed Brown 1918*552f7358SJed Brown #undef __FUNCT__ 1919*552f7358SJed Brown #define __FUNCT__ "DMPlexSymmetrize" 1920*552f7358SJed Brown /*@ 1921*552f7358SJed Brown DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1922*552f7358SJed Brown 1923*552f7358SJed Brown Not collective 1924*552f7358SJed Brown 1925*552f7358SJed Brown Input Parameter: 1926*552f7358SJed Brown . mesh - The DMPlex 1927*552f7358SJed Brown 1928*552f7358SJed Brown Output Parameter: 1929*552f7358SJed Brown 1930*552f7358SJed Brown Note: 1931*552f7358SJed Brown This should be called after all calls to DMPlexSetCone() 1932*552f7358SJed Brown 1933*552f7358SJed Brown Level: beginner 1934*552f7358SJed Brown 1935*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1936*552f7358SJed Brown @*/ 1937*552f7358SJed Brown PetscErrorCode DMPlexSymmetrize(DM dm) 1938*552f7358SJed Brown { 1939*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 1940*552f7358SJed Brown PetscInt *offsets; 1941*552f7358SJed Brown PetscInt supportSize; 1942*552f7358SJed Brown PetscInt pStart, pEnd, p; 1943*552f7358SJed Brown PetscErrorCode ierr; 1944*552f7358SJed Brown 1945*552f7358SJed Brown PetscFunctionBegin; 1946*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1947*552f7358SJed Brown if (mesh->supports) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1948*552f7358SJed Brown /* Calculate support sizes */ 1949*552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1950*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 1951*552f7358SJed Brown PetscInt dof, off, c; 1952*552f7358SJed Brown 1953*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1954*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1955*552f7358SJed Brown for (c = off; c < off+dof; ++c) { 1956*552f7358SJed Brown ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1957*552f7358SJed Brown } 1958*552f7358SJed Brown } 1959*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 1960*552f7358SJed Brown PetscInt dof; 1961*552f7358SJed Brown 1962*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1963*552f7358SJed Brown mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1964*552f7358SJed Brown } 1965*552f7358SJed Brown ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1966*552f7358SJed Brown /* Calculate supports */ 1967*552f7358SJed Brown ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1968*552f7358SJed Brown ierr = PetscMalloc(supportSize * sizeof(PetscInt), &mesh->supports);CHKERRQ(ierr); 1969*552f7358SJed Brown ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &offsets);CHKERRQ(ierr); 1970*552f7358SJed Brown ierr = PetscMemzero(offsets, (pEnd - pStart) * sizeof(PetscInt));CHKERRQ(ierr); 1971*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 1972*552f7358SJed Brown PetscInt dof, off, c; 1973*552f7358SJed Brown 1974*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1975*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1976*552f7358SJed Brown for (c = off; c < off+dof; ++c) { 1977*552f7358SJed Brown const PetscInt q = mesh->cones[c]; 1978*552f7358SJed Brown PetscInt offS; 1979*552f7358SJed Brown 1980*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1981*552f7358SJed Brown mesh->supports[offS+offsets[q]] = p; 1982*552f7358SJed Brown ++offsets[q]; 1983*552f7358SJed Brown } 1984*552f7358SJed Brown } 1985*552f7358SJed Brown ierr = PetscFree(offsets);CHKERRQ(ierr); 1986*552f7358SJed Brown PetscFunctionReturn(0); 1987*552f7358SJed Brown } 1988*552f7358SJed Brown 1989*552f7358SJed Brown #undef __FUNCT__ 1990*552f7358SJed Brown #define __FUNCT__ "DMPlexSetDepth_Private" 1991*552f7358SJed Brown PetscErrorCode DMPlexSetDepth_Private(DM dm, PetscInt p, PetscInt *depth) 1992*552f7358SJed Brown { 1993*552f7358SJed Brown PetscInt d; 1994*552f7358SJed Brown PetscErrorCode ierr; 1995*552f7358SJed Brown 1996*552f7358SJed Brown PetscFunctionBegin; 1997*552f7358SJed Brown ierr = DMPlexGetLabelValue(dm, "depth", p, &d);CHKERRQ(ierr); 1998*552f7358SJed Brown if (d < 0) { 1999*552f7358SJed Brown /* We are guaranteed that the point has a cone since the depth was not yet set */ 2000*552f7358SJed Brown const PetscInt *cone = PETSC_NULL; 2001*552f7358SJed Brown PetscInt dCone; 2002*552f7358SJed Brown 2003*552f7358SJed Brown ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 2004*552f7358SJed Brown ierr = DMPlexSetDepth_Private(dm, cone[0], &dCone);CHKERRQ(ierr); 2005*552f7358SJed Brown d = dCone+1; 2006*552f7358SJed Brown ierr = DMPlexSetLabelValue(dm, "depth", p, d);CHKERRQ(ierr); 2007*552f7358SJed Brown } 2008*552f7358SJed Brown *depth = d; 2009*552f7358SJed Brown PetscFunctionReturn(0); 2010*552f7358SJed Brown } 2011*552f7358SJed Brown 2012*552f7358SJed Brown #undef __FUNCT__ 2013*552f7358SJed Brown #define __FUNCT__ "DMPlexStratify" 2014*552f7358SJed Brown /*@ 2015*552f7358SJed Brown DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 2016*552f7358SJed Brown can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 2017*552f7358SJed Brown same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 2018*552f7358SJed Brown the DAG. 2019*552f7358SJed Brown 2020*552f7358SJed Brown Not collective 2021*552f7358SJed Brown 2022*552f7358SJed Brown Input Parameter: 2023*552f7358SJed Brown . mesh - The DMPlex 2024*552f7358SJed Brown 2025*552f7358SJed Brown Output Parameter: 2026*552f7358SJed Brown 2027*552f7358SJed Brown Notes: 2028*552f7358SJed Brown The normal association for the point grade is element dimension (or co-dimension). For instance, all vertices would 2029*552f7358SJed Brown have depth 0, and all edges depth 1. Likewise, all cells heights would have height 0, and all faces height 1. 2030*552f7358SJed Brown 2031*552f7358SJed Brown This should be called after all calls to DMPlexSymmetrize() 2032*552f7358SJed Brown 2033*552f7358SJed Brown Level: beginner 2034*552f7358SJed Brown 2035*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexSymmetrize() 2036*552f7358SJed Brown @*/ 2037*552f7358SJed Brown PetscErrorCode DMPlexStratify(DM dm) 2038*552f7358SJed Brown { 2039*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 2040*552f7358SJed Brown PetscInt pStart, pEnd, p; 2041*552f7358SJed Brown PetscInt numRoots = 0, numLeaves = 0; 2042*552f7358SJed Brown PetscErrorCode ierr; 2043*552f7358SJed Brown 2044*552f7358SJed Brown PetscFunctionBegin; 2045*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2046*552f7358SJed Brown ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2047*552f7358SJed Brown /* Calculate depth */ 2048*552f7358SJed Brown ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 2049*552f7358SJed Brown /* Initialize roots and count leaves */ 2050*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 2051*552f7358SJed Brown PetscInt coneSize, supportSize; 2052*552f7358SJed Brown 2053*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2054*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2055*552f7358SJed Brown if (!coneSize && supportSize) { 2056*552f7358SJed Brown ++numRoots; 2057*552f7358SJed Brown ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2058*552f7358SJed Brown } else if (!supportSize && coneSize) { 2059*552f7358SJed Brown ++numLeaves; 2060*552f7358SJed Brown } else if (!supportSize && !coneSize) { 2061*552f7358SJed Brown /* Isolated points */ 2062*552f7358SJed Brown ierr = DMPlexSetLabelValue(dm, "depth", p, 0);CHKERRQ(ierr); 2063*552f7358SJed Brown } 2064*552f7358SJed Brown } 2065*552f7358SJed Brown if (numRoots + numLeaves == (pEnd - pStart)) { 2066*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 2067*552f7358SJed Brown PetscInt coneSize, supportSize; 2068*552f7358SJed Brown 2069*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 2070*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 2071*552f7358SJed Brown if (!supportSize && coneSize) { 2072*552f7358SJed Brown ierr = DMPlexSetLabelValue(dm, "depth", p, 1);CHKERRQ(ierr); 2073*552f7358SJed Brown } 2074*552f7358SJed Brown } 2075*552f7358SJed Brown } else { 2076*552f7358SJed Brown /* This might be slow since lookup is not fast */ 2077*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 2078*552f7358SJed Brown PetscInt depth; 2079*552f7358SJed Brown 2080*552f7358SJed Brown ierr = DMPlexSetDepth_Private(dm, p, &depth);CHKERRQ(ierr); 2081*552f7358SJed Brown } 2082*552f7358SJed Brown } 2083*552f7358SJed Brown ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 2084*552f7358SJed Brown PetscFunctionReturn(0); 2085*552f7358SJed Brown } 2086*552f7358SJed Brown 2087*552f7358SJed Brown #undef __FUNCT__ 2088*552f7358SJed Brown #define __FUNCT__ "DMPlexGetJoin" 2089*552f7358SJed Brown /*@C 2090*552f7358SJed Brown DMPlexGetJoin - Get an array for the join of the set of points 2091*552f7358SJed Brown 2092*552f7358SJed Brown Not Collective 2093*552f7358SJed Brown 2094*552f7358SJed Brown Input Parameters: 2095*552f7358SJed Brown + dm - The DMPlex object 2096*552f7358SJed Brown . numPoints - The number of input points for the join 2097*552f7358SJed Brown - points - The input points 2098*552f7358SJed Brown 2099*552f7358SJed Brown Output Parameters: 2100*552f7358SJed Brown + numCoveredPoints - The number of points in the join 2101*552f7358SJed Brown - coveredPoints - The points in the join 2102*552f7358SJed Brown 2103*552f7358SJed Brown Level: intermediate 2104*552f7358SJed Brown 2105*552f7358SJed Brown Note: Currently, this is restricted to a single level join 2106*552f7358SJed Brown 2107*552f7358SJed Brown .keywords: mesh 2108*552f7358SJed Brown .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2109*552f7358SJed Brown @*/ 2110*552f7358SJed Brown PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2111*552f7358SJed Brown { 2112*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 2113*552f7358SJed Brown PetscInt *join[2]; 2114*552f7358SJed Brown PetscInt joinSize, i = 0; 2115*552f7358SJed Brown PetscInt dof, off, p, c, m; 2116*552f7358SJed Brown PetscErrorCode ierr; 2117*552f7358SJed Brown 2118*552f7358SJed Brown PetscFunctionBegin; 2119*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2120*552f7358SJed Brown PetscValidPointer(points, 2); 2121*552f7358SJed Brown PetscValidPointer(numCoveredPoints, 3); 2122*552f7358SJed Brown PetscValidPointer(coveredPoints, 4); 2123*552f7358SJed Brown ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2124*552f7358SJed Brown ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2125*552f7358SJed Brown /* Copy in support of first point */ 2126*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2127*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2128*552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 2129*552f7358SJed Brown join[i][joinSize] = mesh->supports[off+joinSize]; 2130*552f7358SJed Brown } 2131*552f7358SJed Brown /* Check each successive support */ 2132*552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 2133*552f7358SJed Brown PetscInt newJoinSize = 0; 2134*552f7358SJed Brown 2135*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2136*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2137*552f7358SJed Brown for (c = 0; c < dof; ++c) { 2138*552f7358SJed Brown const PetscInt point = mesh->supports[off+c]; 2139*552f7358SJed Brown 2140*552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 2141*552f7358SJed Brown if (point == join[i][m]) { 2142*552f7358SJed Brown join[1-i][newJoinSize++] = point; 2143*552f7358SJed Brown break; 2144*552f7358SJed Brown } 2145*552f7358SJed Brown } 2146*552f7358SJed Brown } 2147*552f7358SJed Brown joinSize = newJoinSize; 2148*552f7358SJed Brown i = 1-i; 2149*552f7358SJed Brown } 2150*552f7358SJed Brown *numCoveredPoints = joinSize; 2151*552f7358SJed Brown *coveredPoints = join[i]; 2152*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2153*552f7358SJed Brown PetscFunctionReturn(0); 2154*552f7358SJed Brown } 2155*552f7358SJed Brown 2156*552f7358SJed Brown #undef __FUNCT__ 2157*552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreJoin" 2158*552f7358SJed Brown /*@C 2159*552f7358SJed Brown DMPlexRestoreJoin - Restore an array for the join of the set of points 2160*552f7358SJed Brown 2161*552f7358SJed Brown Not Collective 2162*552f7358SJed Brown 2163*552f7358SJed Brown Input Parameters: 2164*552f7358SJed Brown + dm - The DMPlex object 2165*552f7358SJed Brown . numPoints - The number of input points for the join 2166*552f7358SJed Brown - points - The input points 2167*552f7358SJed Brown 2168*552f7358SJed Brown Output Parameters: 2169*552f7358SJed Brown + numCoveredPoints - The number of points in the join 2170*552f7358SJed Brown - coveredPoints - The points in the join 2171*552f7358SJed Brown 2172*552f7358SJed Brown Level: intermediate 2173*552f7358SJed Brown 2174*552f7358SJed Brown .keywords: mesh 2175*552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2176*552f7358SJed Brown @*/ 2177*552f7358SJed Brown PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2178*552f7358SJed Brown { 2179*552f7358SJed Brown PetscErrorCode ierr; 2180*552f7358SJed Brown 2181*552f7358SJed Brown PetscFunctionBegin; 2182*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2183*552f7358SJed Brown PetscValidPointer(coveredPoints, 4); 2184*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2185*552f7358SJed Brown PetscFunctionReturn(0); 2186*552f7358SJed Brown } 2187*552f7358SJed Brown 2188*552f7358SJed Brown #undef __FUNCT__ 2189*552f7358SJed Brown #define __FUNCT__ "DMPlexGetFullJoin" 2190*552f7358SJed Brown /*@C 2191*552f7358SJed Brown DMPlexGetFullJoin - Get an array for the join of the set of points 2192*552f7358SJed Brown 2193*552f7358SJed Brown Not Collective 2194*552f7358SJed Brown 2195*552f7358SJed Brown Input Parameters: 2196*552f7358SJed Brown + dm - The DMPlex object 2197*552f7358SJed Brown . numPoints - The number of input points for the join 2198*552f7358SJed Brown - points - The input points 2199*552f7358SJed Brown 2200*552f7358SJed Brown Output Parameters: 2201*552f7358SJed Brown + numCoveredPoints - The number of points in the join 2202*552f7358SJed Brown - coveredPoints - The points in the join 2203*552f7358SJed Brown 2204*552f7358SJed Brown Level: intermediate 2205*552f7358SJed Brown 2206*552f7358SJed Brown .keywords: mesh 2207*552f7358SJed Brown .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2208*552f7358SJed Brown @*/ 2209*552f7358SJed Brown PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2210*552f7358SJed Brown { 2211*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 2212*552f7358SJed Brown PetscInt *offsets, **closures; 2213*552f7358SJed Brown PetscInt *join[2]; 2214*552f7358SJed Brown PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2215*552f7358SJed Brown PetscInt p, d, c, m; 2216*552f7358SJed Brown PetscErrorCode ierr; 2217*552f7358SJed Brown 2218*552f7358SJed Brown PetscFunctionBegin; 2219*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2220*552f7358SJed Brown PetscValidPointer(points, 2); 2221*552f7358SJed Brown PetscValidPointer(numCoveredPoints, 3); 2222*552f7358SJed Brown PetscValidPointer(coveredPoints, 4); 2223*552f7358SJed Brown 2224*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2225*552f7358SJed Brown ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2226*552f7358SJed Brown ierr = PetscMemzero(closures,numPoints*sizeof(PetscInt*));CHKERRQ(ierr); 2227*552f7358SJed Brown ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2228*552f7358SJed Brown maxSize = (PetscInt) (pow((PetscReal) mesh->maxSupportSize, depth)+1); 2229*552f7358SJed Brown ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2230*552f7358SJed Brown ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2231*552f7358SJed Brown 2232*552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 2233*552f7358SJed Brown PetscInt closureSize; 2234*552f7358SJed Brown 2235*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2236*552f7358SJed Brown offsets[p*(depth+2)+0] = 0; 2237*552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 2238*552f7358SJed Brown PetscInt pStart, pEnd, i; 2239*552f7358SJed Brown 2240*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2241*552f7358SJed Brown for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2242*552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2243*552f7358SJed Brown offsets[p*(depth+2)+d+1] = i; 2244*552f7358SJed Brown break; 2245*552f7358SJed Brown } 2246*552f7358SJed Brown } 2247*552f7358SJed Brown if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2248*552f7358SJed Brown } 2249*552f7358SJed Brown if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2250*552f7358SJed Brown } 2251*552f7358SJed Brown for (d = 0; d < depth+1; ++d) { 2252*552f7358SJed Brown PetscInt dof; 2253*552f7358SJed Brown 2254*552f7358SJed Brown /* Copy in support of first point */ 2255*552f7358SJed Brown dof = offsets[d+1] - offsets[d]; 2256*552f7358SJed Brown for (joinSize = 0; joinSize < dof; ++joinSize) { 2257*552f7358SJed Brown join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2258*552f7358SJed Brown } 2259*552f7358SJed Brown /* Check each successive cone */ 2260*552f7358SJed Brown for (p = 1; p < numPoints && joinSize; ++p) { 2261*552f7358SJed Brown PetscInt newJoinSize = 0; 2262*552f7358SJed Brown 2263*552f7358SJed Brown dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2264*552f7358SJed Brown for (c = 0; c < dof; ++c) { 2265*552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2266*552f7358SJed Brown 2267*552f7358SJed Brown for (m = 0; m < joinSize; ++m) { 2268*552f7358SJed Brown if (point == join[i][m]) { 2269*552f7358SJed Brown join[1-i][newJoinSize++] = point; 2270*552f7358SJed Brown break; 2271*552f7358SJed Brown } 2272*552f7358SJed Brown } 2273*552f7358SJed Brown } 2274*552f7358SJed Brown joinSize = newJoinSize; 2275*552f7358SJed Brown i = 1-i; 2276*552f7358SJed Brown } 2277*552f7358SJed Brown if (joinSize) break; 2278*552f7358SJed Brown } 2279*552f7358SJed Brown *numCoveredPoints = joinSize; 2280*552f7358SJed Brown *coveredPoints = join[i]; 2281*552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 2282*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2283*552f7358SJed Brown } 2284*552f7358SJed Brown ierr = PetscFree(closures);CHKERRQ(ierr); 2285*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2286*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2287*552f7358SJed Brown PetscFunctionReturn(0); 2288*552f7358SJed Brown } 2289*552f7358SJed Brown 2290*552f7358SJed Brown #undef __FUNCT__ 2291*552f7358SJed Brown #define __FUNCT__ "DMPlexGetMeet" 2292*552f7358SJed Brown /*@C 2293*552f7358SJed Brown DMPlexGetMeet - Get an array for the meet of the set of points 2294*552f7358SJed Brown 2295*552f7358SJed Brown Not Collective 2296*552f7358SJed Brown 2297*552f7358SJed Brown Input Parameters: 2298*552f7358SJed Brown + dm - The DMPlex object 2299*552f7358SJed Brown . numPoints - The number of input points for the meet 2300*552f7358SJed Brown - points - The input points 2301*552f7358SJed Brown 2302*552f7358SJed Brown Output Parameters: 2303*552f7358SJed Brown + numCoveredPoints - The number of points in the meet 2304*552f7358SJed Brown - coveredPoints - The points in the meet 2305*552f7358SJed Brown 2306*552f7358SJed Brown Level: intermediate 2307*552f7358SJed Brown 2308*552f7358SJed Brown Note: Currently, this is restricted to a single level meet 2309*552f7358SJed Brown 2310*552f7358SJed Brown .keywords: mesh 2311*552f7358SJed Brown .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2312*552f7358SJed Brown @*/ 2313*552f7358SJed Brown PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2314*552f7358SJed Brown { 2315*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 2316*552f7358SJed Brown PetscInt *meet[2]; 2317*552f7358SJed Brown PetscInt meetSize, i = 0; 2318*552f7358SJed Brown PetscInt dof, off, p, c, m; 2319*552f7358SJed Brown PetscErrorCode ierr; 2320*552f7358SJed Brown 2321*552f7358SJed Brown PetscFunctionBegin; 2322*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2323*552f7358SJed Brown PetscValidPointer(points, 2); 2324*552f7358SJed Brown PetscValidPointer(numCoveringPoints, 3); 2325*552f7358SJed Brown PetscValidPointer(coveringPoints, 4); 2326*552f7358SJed Brown ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2327*552f7358SJed Brown ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2328*552f7358SJed Brown /* Copy in cone of first point */ 2329*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2330*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2331*552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 2332*552f7358SJed Brown meet[i][meetSize] = mesh->cones[off+meetSize]; 2333*552f7358SJed Brown } 2334*552f7358SJed Brown /* Check each successive cone */ 2335*552f7358SJed Brown for (p = 1; p < numPoints; ++p) { 2336*552f7358SJed Brown PetscInt newMeetSize = 0; 2337*552f7358SJed Brown 2338*552f7358SJed Brown ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2339*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2340*552f7358SJed Brown for (c = 0; c < dof; ++c) { 2341*552f7358SJed Brown const PetscInt point = mesh->cones[off+c]; 2342*552f7358SJed Brown 2343*552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 2344*552f7358SJed Brown if (point == meet[i][m]) { 2345*552f7358SJed Brown meet[1-i][newMeetSize++] = point; 2346*552f7358SJed Brown break; 2347*552f7358SJed Brown } 2348*552f7358SJed Brown } 2349*552f7358SJed Brown } 2350*552f7358SJed Brown meetSize = newMeetSize; 2351*552f7358SJed Brown i = 1-i; 2352*552f7358SJed Brown } 2353*552f7358SJed Brown *numCoveringPoints = meetSize; 2354*552f7358SJed Brown *coveringPoints = meet[i]; 2355*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2356*552f7358SJed Brown PetscFunctionReturn(0); 2357*552f7358SJed Brown } 2358*552f7358SJed Brown 2359*552f7358SJed Brown #undef __FUNCT__ 2360*552f7358SJed Brown #define __FUNCT__ "DMPlexRestoreMeet" 2361*552f7358SJed Brown /*@C 2362*552f7358SJed Brown DMPlexRestoreMeet - Restore an array for the meet of the set of points 2363*552f7358SJed Brown 2364*552f7358SJed Brown Not Collective 2365*552f7358SJed Brown 2366*552f7358SJed Brown Input Parameters: 2367*552f7358SJed Brown + dm - The DMPlex object 2368*552f7358SJed Brown . numPoints - The number of input points for the meet 2369*552f7358SJed Brown - points - The input points 2370*552f7358SJed Brown 2371*552f7358SJed Brown Output Parameters: 2372*552f7358SJed Brown + numCoveredPoints - The number of points in the meet 2373*552f7358SJed Brown - coveredPoints - The points in the meet 2374*552f7358SJed Brown 2375*552f7358SJed Brown Level: intermediate 2376*552f7358SJed Brown 2377*552f7358SJed Brown .keywords: mesh 2378*552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2379*552f7358SJed Brown @*/ 2380*552f7358SJed Brown PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2381*552f7358SJed Brown { 2382*552f7358SJed Brown PetscErrorCode ierr; 2383*552f7358SJed Brown 2384*552f7358SJed Brown PetscFunctionBegin; 2385*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2386*552f7358SJed Brown PetscValidPointer(coveredPoints, 4); 2387*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void *) coveredPoints);CHKERRQ(ierr); 2388*552f7358SJed Brown PetscFunctionReturn(0); 2389*552f7358SJed Brown } 2390*552f7358SJed Brown 2391*552f7358SJed Brown #undef __FUNCT__ 2392*552f7358SJed Brown #define __FUNCT__ "DMPlexGetFullMeet" 2393*552f7358SJed Brown /*@C 2394*552f7358SJed Brown DMPlexGetFullMeet - Get an array for the meet of the set of points 2395*552f7358SJed Brown 2396*552f7358SJed Brown Not Collective 2397*552f7358SJed Brown 2398*552f7358SJed Brown Input Parameters: 2399*552f7358SJed Brown + dm - The DMPlex object 2400*552f7358SJed Brown . numPoints - The number of input points for the meet 2401*552f7358SJed Brown - points - The input points 2402*552f7358SJed Brown 2403*552f7358SJed Brown Output Parameters: 2404*552f7358SJed Brown + numCoveredPoints - The number of points in the meet 2405*552f7358SJed Brown - coveredPoints - The points in the meet 2406*552f7358SJed Brown 2407*552f7358SJed Brown Level: intermediate 2408*552f7358SJed Brown 2409*552f7358SJed Brown .keywords: mesh 2410*552f7358SJed Brown .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2411*552f7358SJed Brown @*/ 2412*552f7358SJed Brown PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2413*552f7358SJed Brown { 2414*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 2415*552f7358SJed Brown PetscInt *offsets, **closures; 2416*552f7358SJed Brown PetscInt *meet[2]; 2417*552f7358SJed Brown PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2418*552f7358SJed Brown PetscInt p, h, c, m; 2419*552f7358SJed Brown PetscErrorCode ierr; 2420*552f7358SJed Brown 2421*552f7358SJed Brown PetscFunctionBegin; 2422*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2423*552f7358SJed Brown PetscValidPointer(points, 2); 2424*552f7358SJed Brown PetscValidPointer(numCoveredPoints, 3); 2425*552f7358SJed Brown PetscValidPointer(coveredPoints, 4); 2426*552f7358SJed Brown 2427*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2428*552f7358SJed Brown ierr = PetscMalloc(numPoints * sizeof(PetscInt *), &closures);CHKERRQ(ierr); 2429*552f7358SJed Brown ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2430*552f7358SJed Brown maxSize = (PetscInt) (pow((PetscReal) mesh->maxConeSize, height)+1); 2431*552f7358SJed Brown ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2432*552f7358SJed Brown ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2433*552f7358SJed Brown 2434*552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 2435*552f7358SJed Brown PetscInt closureSize; 2436*552f7358SJed Brown 2437*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2438*552f7358SJed Brown offsets[p*(height+2)+0] = 0; 2439*552f7358SJed Brown for (h = 0; h < height+1; ++h) { 2440*552f7358SJed Brown PetscInt pStart, pEnd, i; 2441*552f7358SJed Brown 2442*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2443*552f7358SJed Brown for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2444*552f7358SJed Brown if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2445*552f7358SJed Brown offsets[p*(height+2)+h+1] = i; 2446*552f7358SJed Brown break; 2447*552f7358SJed Brown } 2448*552f7358SJed Brown } 2449*552f7358SJed Brown if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2450*552f7358SJed Brown } 2451*552f7358SJed Brown if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2452*552f7358SJed Brown } 2453*552f7358SJed Brown for (h = 0; h < height+1; ++h) { 2454*552f7358SJed Brown PetscInt dof; 2455*552f7358SJed Brown 2456*552f7358SJed Brown /* Copy in cone of first point */ 2457*552f7358SJed Brown dof = offsets[h+1] - offsets[h]; 2458*552f7358SJed Brown for (meetSize = 0; meetSize < dof; ++meetSize) { 2459*552f7358SJed Brown meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2460*552f7358SJed Brown } 2461*552f7358SJed Brown /* Check each successive cone */ 2462*552f7358SJed Brown for (p = 1; p < numPoints && meetSize; ++p) { 2463*552f7358SJed Brown PetscInt newMeetSize = 0; 2464*552f7358SJed Brown 2465*552f7358SJed Brown dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2466*552f7358SJed Brown for (c = 0; c < dof; ++c) { 2467*552f7358SJed Brown const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2468*552f7358SJed Brown 2469*552f7358SJed Brown for (m = 0; m < meetSize; ++m) { 2470*552f7358SJed Brown if (point == meet[i][m]) { 2471*552f7358SJed Brown meet[1-i][newMeetSize++] = point; 2472*552f7358SJed Brown break; 2473*552f7358SJed Brown } 2474*552f7358SJed Brown } 2475*552f7358SJed Brown } 2476*552f7358SJed Brown meetSize = newMeetSize; 2477*552f7358SJed Brown i = 1-i; 2478*552f7358SJed Brown } 2479*552f7358SJed Brown if (meetSize) break; 2480*552f7358SJed Brown } 2481*552f7358SJed Brown *numCoveredPoints = meetSize; 2482*552f7358SJed Brown *coveredPoints = meet[i]; 2483*552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 2484*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, PETSC_NULL, &closures[p]);CHKERRQ(ierr); 2485*552f7358SJed Brown } 2486*552f7358SJed Brown ierr = PetscFree(closures);CHKERRQ(ierr); 2487*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2488*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2489*552f7358SJed Brown PetscFunctionReturn(0); 2490*552f7358SJed Brown } 2491*552f7358SJed Brown 2492*552f7358SJed Brown #undef __FUNCT__ 2493*552f7358SJed Brown #define __FUNCT__ "DMPlexGetNumFaceVertices" 2494*552f7358SJed Brown static PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt numCorners, PetscInt *numFaceVertices) { 2495*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 2496*552f7358SJed Brown PetscInt cellDim; 2497*552f7358SJed Brown PetscErrorCode ierr; 2498*552f7358SJed Brown 2499*552f7358SJed Brown PetscFunctionBegin; 2500*552f7358SJed Brown PetscValidPointer(numFaceVertices,3); 2501*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 2502*552f7358SJed Brown switch(cellDim) { 2503*552f7358SJed Brown case 0: 2504*552f7358SJed Brown *numFaceVertices = 0; 2505*552f7358SJed Brown break; 2506*552f7358SJed Brown case 1: 2507*552f7358SJed Brown *numFaceVertices = 1; 2508*552f7358SJed Brown break; 2509*552f7358SJed Brown case 2: 2510*552f7358SJed Brown switch(numCorners) { 2511*552f7358SJed Brown case 3: // triangle 2512*552f7358SJed Brown *numFaceVertices = 2; // Edge has 2 vertices 2513*552f7358SJed Brown break; 2514*552f7358SJed Brown case 4: // quadrilateral 2515*552f7358SJed Brown *numFaceVertices = 2; // Edge has 2 vertices 2516*552f7358SJed Brown break; 2517*552f7358SJed Brown case 6: // quadratic triangle, tri and quad cohesive Lagrange cells 2518*552f7358SJed Brown *numFaceVertices = 3; // Edge has 3 vertices 2519*552f7358SJed Brown break; 2520*552f7358SJed Brown case 9: // quadratic quadrilateral, quadratic quad cohesive Lagrange cells 2521*552f7358SJed Brown *numFaceVertices = 3; // Edge has 3 vertices 2522*552f7358SJed Brown break; 2523*552f7358SJed Brown default: 2524*552f7358SJed Brown SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2525*552f7358SJed Brown } 2526*552f7358SJed Brown break; 2527*552f7358SJed Brown case 3: 2528*552f7358SJed Brown switch(numCorners) { 2529*552f7358SJed Brown case 4: // tetradehdron 2530*552f7358SJed Brown *numFaceVertices = 3; // Face has 3 vertices 2531*552f7358SJed Brown break; 2532*552f7358SJed Brown case 6: // tet cohesive cells 2533*552f7358SJed Brown *numFaceVertices = 4; // Face has 4 vertices 2534*552f7358SJed Brown break; 2535*552f7358SJed Brown case 8: // hexahedron 2536*552f7358SJed Brown *numFaceVertices = 4; // Face has 4 vertices 2537*552f7358SJed Brown break; 2538*552f7358SJed Brown case 9: // tet cohesive Lagrange cells 2539*552f7358SJed Brown *numFaceVertices = 6; // Face has 6 vertices 2540*552f7358SJed Brown break; 2541*552f7358SJed Brown case 10: // quadratic tetrahedron 2542*552f7358SJed Brown *numFaceVertices = 6; // Face has 6 vertices 2543*552f7358SJed Brown break; 2544*552f7358SJed Brown case 12: // hex cohesive Lagrange cells 2545*552f7358SJed Brown *numFaceVertices = 6; // Face has 6 vertices 2546*552f7358SJed Brown break; 2547*552f7358SJed Brown case 18: // quadratic tet cohesive Lagrange cells 2548*552f7358SJed Brown *numFaceVertices = 6; // Face has 6 vertices 2549*552f7358SJed Brown break; 2550*552f7358SJed Brown case 27: // quadratic hexahedron, quadratic hex cohesive Lagrange cells 2551*552f7358SJed Brown *numFaceVertices = 9; // Face has 9 vertices 2552*552f7358SJed Brown break; 2553*552f7358SJed Brown default: 2554*552f7358SJed Brown SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2555*552f7358SJed Brown } 2556*552f7358SJed Brown break; 2557*552f7358SJed Brown default: 2558*552f7358SJed Brown SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2559*552f7358SJed Brown } 2560*552f7358SJed Brown PetscFunctionReturn(0); 2561*552f7358SJed Brown } 2562*552f7358SJed Brown 2563*552f7358SJed Brown #undef __FUNCT__ 2564*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateNeighborCSR" 2565*552f7358SJed Brown PetscErrorCode DMPlexCreateNeighborCSR(DM dm, PetscInt *numVertices, PetscInt **offsets, PetscInt **adjacency) { 2566*552f7358SJed Brown const PetscInt maxFaceCases = 30; 2567*552f7358SJed Brown PetscInt numFaceCases = 0; 2568*552f7358SJed Brown PetscInt numFaceVertices[30]; /* maxFaceCases, C89 sucks sucks sucks */ 2569*552f7358SJed Brown PetscInt *off, *adj; 2570*552f7358SJed Brown PetscInt *neighborCells, *tmpClosure; 2571*552f7358SJed Brown PetscInt maxConeSize, maxSupportSize, maxClosure, maxNeighbors; 2572*552f7358SJed Brown PetscInt dim, depth = 0, cStart, cEnd, c, numCells, cell; 2573*552f7358SJed Brown PetscErrorCode ierr; 2574*552f7358SJed Brown 2575*552f7358SJed Brown PetscFunctionBegin; 2576*552f7358SJed Brown /* For parallel partitioning, I think you have to communicate supports */ 2577*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 2578*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2579*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2580*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 2581*552f7358SJed Brown if (cEnd - cStart == 0) { 2582*552f7358SJed Brown if (numVertices) *numVertices = 0; 2583*552f7358SJed Brown if (offsets) *offsets = PETSC_NULL; 2584*552f7358SJed Brown if (adjacency) *adjacency = PETSC_NULL; 2585*552f7358SJed Brown PetscFunctionReturn(0); 2586*552f7358SJed Brown } 2587*552f7358SJed Brown numCells = cEnd - cStart; 2588*552f7358SJed Brown /* Setup face recognition */ 2589*552f7358SJed Brown { 2590*552f7358SJed Brown PetscInt cornersSeen[30] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Could use PetscBT */ 2591*552f7358SJed Brown 2592*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 2593*552f7358SJed Brown PetscInt corners; 2594*552f7358SJed Brown 2595*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, c, &corners);CHKERRQ(ierr); 2596*552f7358SJed Brown if (!cornersSeen[corners]) { 2597*552f7358SJed Brown PetscInt nFV; 2598*552f7358SJed Brown 2599*552f7358SJed Brown if (numFaceCases >= maxFaceCases) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Exceeded maximum number of face recognition cases"); 2600*552f7358SJed Brown cornersSeen[corners] = 1; 2601*552f7358SJed Brown ierr = DMPlexGetNumFaceVertices(dm, corners, &nFV);CHKERRQ(ierr); 2602*552f7358SJed Brown numFaceVertices[numFaceCases++] = nFV; 2603*552f7358SJed Brown } 2604*552f7358SJed Brown } 2605*552f7358SJed Brown } 2606*552f7358SJed Brown maxClosure = (PetscInt) (2*PetscMax(pow((PetscReal) maxConeSize, depth)+1, pow((PetscReal) maxSupportSize, depth)+1)); 2607*552f7358SJed Brown maxNeighbors = (PetscInt) (pow((PetscReal) maxConeSize, depth)*pow((PetscReal) maxSupportSize, depth)+1); 2608*552f7358SJed Brown ierr = PetscMalloc2(maxNeighbors,PetscInt,&neighborCells,maxClosure,PetscInt,&tmpClosure);CHKERRQ(ierr); 2609*552f7358SJed Brown ierr = PetscMalloc((numCells+1) * sizeof(PetscInt), &off);CHKERRQ(ierr); 2610*552f7358SJed Brown ierr = PetscMemzero(off, (numCells+1) * sizeof(PetscInt));CHKERRQ(ierr); 2611*552f7358SJed Brown /* Count neighboring cells */ 2612*552f7358SJed Brown for (cell = cStart; cell < cEnd; ++cell) { 2613*552f7358SJed Brown PetscInt numNeighbors = maxNeighbors, n; 2614*552f7358SJed Brown 2615*552f7358SJed Brown ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2616*552f7358SJed Brown /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2617*552f7358SJed Brown for (n = 0; n < numNeighbors; ++n) { 2618*552f7358SJed Brown PetscInt cellPair[2] = {cell, neighborCells[n]}; 2619*552f7358SJed Brown PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2620*552f7358SJed Brown PetscInt meetSize = 0; 2621*552f7358SJed Brown const PetscInt *meet = PETSC_NULL; 2622*552f7358SJed Brown 2623*552f7358SJed Brown if (cellPair[0] == cellPair[1]) continue; 2624*552f7358SJed Brown if (!found) { 2625*552f7358SJed Brown ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2626*552f7358SJed Brown if (meetSize) { 2627*552f7358SJed Brown PetscInt f; 2628*552f7358SJed Brown 2629*552f7358SJed Brown for (f = 0; f < numFaceCases; ++f) { 2630*552f7358SJed Brown if (numFaceVertices[f] == meetSize) { 2631*552f7358SJed Brown found = PETSC_TRUE; 2632*552f7358SJed Brown break; 2633*552f7358SJed Brown } 2634*552f7358SJed Brown } 2635*552f7358SJed Brown } 2636*552f7358SJed Brown ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2637*552f7358SJed Brown } 2638*552f7358SJed Brown if (found) { 2639*552f7358SJed Brown ++off[cell-cStart+1]; 2640*552f7358SJed Brown } 2641*552f7358SJed Brown } 2642*552f7358SJed Brown } 2643*552f7358SJed Brown /* Prefix sum */ 2644*552f7358SJed Brown for (cell = 1; cell <= numCells; ++cell) { 2645*552f7358SJed Brown off[cell] += off[cell-1]; 2646*552f7358SJed Brown } 2647*552f7358SJed Brown if (adjacency) { 2648*552f7358SJed Brown ierr = PetscMalloc(off[numCells] * sizeof(PetscInt), &adj);CHKERRQ(ierr); 2649*552f7358SJed Brown /* Get neighboring cells */ 2650*552f7358SJed Brown for (cell = cStart; cell < cEnd; ++cell) { 2651*552f7358SJed Brown PetscInt numNeighbors = maxNeighbors, n; 2652*552f7358SJed Brown PetscInt cellOffset = 0; 2653*552f7358SJed Brown 2654*552f7358SJed Brown ierr = DMPlexGetAdjacencySingleLevel_Private(dm, cell, PETSC_TRUE, tmpClosure, &numNeighbors, neighborCells);CHKERRQ(ierr); 2655*552f7358SJed Brown /* Get meet with each cell, and check with recognizer (could optimize to check each pair only once) */ 2656*552f7358SJed Brown for (n = 0; n < numNeighbors; ++n) { 2657*552f7358SJed Brown PetscInt cellPair[2] = {cell, neighborCells[n]}; 2658*552f7358SJed Brown PetscBool found = depth > 1 ? PETSC_TRUE : PETSC_FALSE; 2659*552f7358SJed Brown PetscInt meetSize = 0; 2660*552f7358SJed Brown const PetscInt *meet = PETSC_NULL; 2661*552f7358SJed Brown 2662*552f7358SJed Brown if (cellPair[0] == cellPair[1]) continue; 2663*552f7358SJed Brown if (!found) { 2664*552f7358SJed Brown ierr = DMPlexGetMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2665*552f7358SJed Brown if (meetSize) { 2666*552f7358SJed Brown PetscInt f; 2667*552f7358SJed Brown 2668*552f7358SJed Brown for (f = 0; f < numFaceCases; ++f) { 2669*552f7358SJed Brown if (numFaceVertices[f] == meetSize) { 2670*552f7358SJed Brown found = PETSC_TRUE; 2671*552f7358SJed Brown break; 2672*552f7358SJed Brown } 2673*552f7358SJed Brown } 2674*552f7358SJed Brown } 2675*552f7358SJed Brown ierr = DMPlexRestoreMeet(dm, 2, cellPair, &meetSize, &meet);CHKERRQ(ierr); 2676*552f7358SJed Brown } 2677*552f7358SJed Brown if (found) { 2678*552f7358SJed Brown adj[off[cell-cStart]+cellOffset] = neighborCells[n]; 2679*552f7358SJed Brown ++cellOffset; 2680*552f7358SJed Brown } 2681*552f7358SJed Brown } 2682*552f7358SJed Brown } 2683*552f7358SJed Brown } 2684*552f7358SJed Brown ierr = PetscFree2(neighborCells,tmpClosure);CHKERRQ(ierr); 2685*552f7358SJed Brown if (numVertices) *numVertices = numCells; 2686*552f7358SJed Brown if (offsets) *offsets = off; 2687*552f7358SJed Brown if (adjacency) *adjacency = adj; 2688*552f7358SJed Brown PetscFunctionReturn(0); 2689*552f7358SJed Brown } 2690*552f7358SJed Brown 2691*552f7358SJed Brown #ifdef PETSC_HAVE_CHACO 2692*552f7358SJed Brown #ifdef PETSC_HAVE_UNISTD_H 2693*552f7358SJed Brown #include <unistd.h> 2694*552f7358SJed Brown #endif 2695*552f7358SJed Brown /* Chaco does not have an include file */ 2696*552f7358SJed Brown PETSC_EXTERN_C int interface(int nvtxs, int *start, int *adjacency, int *vwgts, 2697*552f7358SJed Brown float *ewgts, float *x, float *y, float *z, char *outassignname, 2698*552f7358SJed Brown char *outfilename, short *assignment, int architecture, int ndims_tot, 2699*552f7358SJed Brown int mesh_dims[3], double *goal, int global_method, int local_method, 2700*552f7358SJed Brown int rqi_flag, int vmax, int ndims, double eigtol, long seed); 2701*552f7358SJed Brown 2702*552f7358SJed Brown extern int FREE_GRAPH; 2703*552f7358SJed Brown 2704*552f7358SJed Brown #undef __FUNCT__ 2705*552f7358SJed Brown #define __FUNCT__ "DMPlexPartition_Chaco" 2706*552f7358SJed Brown PetscErrorCode DMPlexPartition_Chaco(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2707*552f7358SJed Brown { 2708*552f7358SJed Brown enum {DEFAULT_METHOD = 1, INERTIAL_METHOD = 3}; 2709*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 2710*552f7358SJed Brown int nvtxs = numVertices; /* number of vertices in full graph */ 2711*552f7358SJed Brown int *vwgts = NULL; /* weights for all vertices */ 2712*552f7358SJed Brown float *ewgts = NULL; /* weights for all edges */ 2713*552f7358SJed Brown float *x = NULL, *y = NULL, *z = NULL; /* coordinates for inertial method */ 2714*552f7358SJed Brown char *outassignname = NULL; /* name of assignment output file */ 2715*552f7358SJed Brown char *outfilename = NULL; /* output file name */ 2716*552f7358SJed Brown int architecture = 1; /* 0 => hypercube, d => d-dimensional mesh */ 2717*552f7358SJed Brown int ndims_tot = 0; /* total number of cube dimensions to divide */ 2718*552f7358SJed Brown int mesh_dims[3]; /* dimensions of mesh of processors */ 2719*552f7358SJed Brown double *goal = NULL; /* desired set sizes for each set */ 2720*552f7358SJed Brown int global_method = 1; /* global partitioning algorithm */ 2721*552f7358SJed Brown int local_method = 1; /* local partitioning algorithm */ 2722*552f7358SJed Brown int rqi_flag = 0; /* should I use RQI/Symmlq eigensolver? */ 2723*552f7358SJed Brown int vmax = 200; /* how many vertices to coarsen down to? */ 2724*552f7358SJed Brown int ndims = 1; /* number of eigenvectors (2^d sets) */ 2725*552f7358SJed Brown double eigtol = 0.001; /* tolerance on eigenvectors */ 2726*552f7358SJed Brown long seed = 123636512; /* for random graph mutations */ 2727*552f7358SJed Brown short int *assignment; /* Output partition */ 2728*552f7358SJed Brown int fd_stdout, fd_pipe[2]; 2729*552f7358SJed Brown PetscInt *points; 2730*552f7358SJed Brown PetscMPIInt commSize; 2731*552f7358SJed Brown int i, v, p; 2732*552f7358SJed Brown PetscErrorCode ierr; 2733*552f7358SJed Brown 2734*552f7358SJed Brown PetscFunctionBegin; 2735*552f7358SJed Brown ierr = MPI_Comm_size(comm, &commSize);CHKERRQ(ierr); 2736*552f7358SJed Brown if (!numVertices) { 2737*552f7358SJed Brown ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2738*552f7358SJed Brown ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2739*552f7358SJed Brown ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2740*552f7358SJed Brown ierr = ISCreateGeneral(comm, 0, PETSC_NULL, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2741*552f7358SJed Brown PetscFunctionReturn(0); 2742*552f7358SJed Brown } 2743*552f7358SJed Brown FREE_GRAPH = 0; /* Do not let Chaco free my memory */ 2744*552f7358SJed Brown for (i = 0; i < start[numVertices]; ++i) { 2745*552f7358SJed Brown ++adjacency[i]; 2746*552f7358SJed Brown } 2747*552f7358SJed Brown if (global_method == INERTIAL_METHOD) { 2748*552f7358SJed Brown /* manager.createCellCoordinates(nvtxs, &x, &y, &z); */ 2749*552f7358SJed Brown SETERRQ(comm, PETSC_ERR_SUP, "Inertial partitioning not yet supported"); 2750*552f7358SJed Brown } 2751*552f7358SJed Brown mesh_dims[0] = commSize; 2752*552f7358SJed Brown mesh_dims[1] = 1; 2753*552f7358SJed Brown mesh_dims[2] = 1; 2754*552f7358SJed Brown ierr = PetscMalloc(nvtxs * sizeof(short int), &assignment);CHKERRQ(ierr); 2755*552f7358SJed Brown /* Chaco outputs to stdout. We redirect this to a buffer. */ 2756*552f7358SJed Brown /* TODO: check error codes for UNIX calls */ 2757*552f7358SJed Brown #ifdef PETSC_HAVE_UNISTD_H 2758*552f7358SJed Brown { 2759*552f7358SJed Brown fd_stdout = dup(1); 2760*552f7358SJed Brown pipe(fd_pipe); 2761*552f7358SJed Brown close(1); 2762*552f7358SJed Brown dup2(fd_pipe[1], 1); 2763*552f7358SJed Brown } 2764*552f7358SJed Brown #endif 2765*552f7358SJed Brown ierr = interface(nvtxs, (int *) start, (int *) adjacency, vwgts, ewgts, x, y, z, outassignname, outfilename, 2766*552f7358SJed Brown assignment, architecture, ndims_tot, mesh_dims, goal, global_method, local_method, rqi_flag, 2767*552f7358SJed Brown vmax, ndims, eigtol, seed); 2768*552f7358SJed Brown #ifdef PETSC_HAVE_UNISTD_H 2769*552f7358SJed Brown { 2770*552f7358SJed Brown char msgLog[10000]; 2771*552f7358SJed Brown int count; 2772*552f7358SJed Brown 2773*552f7358SJed Brown fflush(stdout); 2774*552f7358SJed Brown count = read(fd_pipe[0], msgLog, (10000-1)*sizeof(char)); 2775*552f7358SJed Brown if (count < 0) count = 0; 2776*552f7358SJed Brown msgLog[count] = 0; 2777*552f7358SJed Brown close(1); 2778*552f7358SJed Brown dup2(fd_stdout, 1); 2779*552f7358SJed Brown close(fd_stdout); 2780*552f7358SJed Brown close(fd_pipe[0]); 2781*552f7358SJed Brown close(fd_pipe[1]); 2782*552f7358SJed Brown if (ierr) SETERRQ1(comm, PETSC_ERR_LIB, "Error in Chaco library: %s", msgLog); 2783*552f7358SJed Brown } 2784*552f7358SJed Brown #endif 2785*552f7358SJed Brown /* Convert to PetscSection+IS */ 2786*552f7358SJed Brown ierr = PetscSectionCreate(comm, partSection);CHKERRQ(ierr); 2787*552f7358SJed Brown ierr = PetscSectionSetChart(*partSection, 0, commSize);CHKERRQ(ierr); 2788*552f7358SJed Brown for (v = 0; v < nvtxs; ++v) { 2789*552f7358SJed Brown ierr = PetscSectionAddDof(*partSection, assignment[v], 1);CHKERRQ(ierr); 2790*552f7358SJed Brown } 2791*552f7358SJed Brown ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2792*552f7358SJed Brown ierr = PetscMalloc(nvtxs * sizeof(PetscInt), &points);CHKERRQ(ierr); 2793*552f7358SJed Brown for (p = 0, i = 0; p < commSize; ++p) { 2794*552f7358SJed Brown for (v = 0; v < nvtxs; ++v) { 2795*552f7358SJed Brown if (assignment[v] == p) points[i++] = v; 2796*552f7358SJed Brown } 2797*552f7358SJed Brown } 2798*552f7358SJed Brown if (i != nvtxs) SETERRQ2(comm, PETSC_ERR_PLIB, "Number of points %D should be %D", i, nvtxs); 2799*552f7358SJed Brown ierr = ISCreateGeneral(comm, nvtxs, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2800*552f7358SJed Brown if (global_method == INERTIAL_METHOD) { 2801*552f7358SJed Brown /* manager.destroyCellCoordinates(nvtxs, &x, &y, &z); */ 2802*552f7358SJed Brown } 2803*552f7358SJed Brown ierr = PetscFree(assignment);CHKERRQ(ierr); 2804*552f7358SJed Brown for (i = 0; i < start[numVertices]; ++i) { 2805*552f7358SJed Brown --adjacency[i]; 2806*552f7358SJed Brown } 2807*552f7358SJed Brown PetscFunctionReturn(0); 2808*552f7358SJed Brown } 2809*552f7358SJed Brown #endif 2810*552f7358SJed Brown 2811*552f7358SJed Brown #ifdef PETSC_HAVE_PARMETIS 2812*552f7358SJed Brown #undef __FUNCT__ 2813*552f7358SJed Brown #define __FUNCT__ "DMPlexPartition_ParMetis" 2814*552f7358SJed Brown PetscErrorCode DMPlexPartition_ParMetis(DM dm, PetscInt numVertices, PetscInt start[], PetscInt adjacency[], PetscSection *partSection, IS *partition) 2815*552f7358SJed Brown { 2816*552f7358SJed Brown PetscFunctionBegin; 2817*552f7358SJed Brown SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "ParMetis not yet supported"); 2818*552f7358SJed Brown PetscFunctionReturn(0); 2819*552f7358SJed Brown } 2820*552f7358SJed Brown #endif 2821*552f7358SJed Brown 2822*552f7358SJed Brown #undef __FUNCT__ 2823*552f7358SJed Brown #define __FUNCT__ "DMPlexEnlargePartition" 2824*552f7358SJed Brown /* Expand the partition by BFS on the adjacency graph */ 2825*552f7358SJed Brown PetscErrorCode DMPlexEnlargePartition(DM dm, const PetscInt start[], const PetscInt adjacency[], PetscSection origPartSection, IS origPartition, PetscSection *partSection, IS *partition) { 2826*552f7358SJed Brown PetscHashI h; 2827*552f7358SJed Brown const PetscInt *points; 2828*552f7358SJed Brown PetscInt **tmpPoints, *newPoints, totPoints = 0; 2829*552f7358SJed Brown PetscInt pStart, pEnd, part, q; 2830*552f7358SJed Brown PetscErrorCode ierr; 2831*552f7358SJed Brown 2832*552f7358SJed Brown PetscFunctionBegin; 2833*552f7358SJed Brown PetscHashICreate(h); 2834*552f7358SJed Brown ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2835*552f7358SJed Brown ierr = PetscSectionGetChart(origPartSection, &pStart, &pEnd);CHKERRQ(ierr); 2836*552f7358SJed Brown ierr = PetscSectionSetChart(*partSection, pStart, pEnd);CHKERRQ(ierr); 2837*552f7358SJed Brown ierr = ISGetIndices(origPartition, &points);CHKERRQ(ierr); 2838*552f7358SJed Brown ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt *), &tmpPoints);CHKERRQ(ierr); 2839*552f7358SJed Brown for(part = pStart; part < pEnd; ++part) { 2840*552f7358SJed Brown PetscInt numPoints, nP, numNewPoints, off, p, n = 0; 2841*552f7358SJed Brown 2842*552f7358SJed Brown PetscHashIClear(h); 2843*552f7358SJed Brown ierr = PetscSectionGetDof(origPartSection, part, &numPoints);CHKERRQ(ierr); 2844*552f7358SJed Brown ierr = PetscSectionGetOffset(origPartSection, part, &off);CHKERRQ(ierr); 2845*552f7358SJed Brown /* Add all existing points to h */ 2846*552f7358SJed Brown for(p = 0; p < numPoints; ++p) { 2847*552f7358SJed Brown const PetscInt point = points[off+p]; 2848*552f7358SJed Brown PetscHashIAdd(h, point, 1); 2849*552f7358SJed Brown } 2850*552f7358SJed Brown PetscHashISize(h, nP); 2851*552f7358SJed Brown if (nP != numPoints) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Invalid partition has %d points, but only %d were unique", numPoints, nP); 2852*552f7358SJed Brown /* Add all points in next BFS level */ 2853*552f7358SJed Brown /* TODO We are brute forcing here, but could check the adjacency size to find the boundary */ 2854*552f7358SJed Brown for(p = 0; p < numPoints; ++p) { 2855*552f7358SJed Brown const PetscInt point = points[off+p]; 2856*552f7358SJed Brown PetscInt s = start[point], e = start[point+1], a; 2857*552f7358SJed Brown 2858*552f7358SJed Brown for(a = s; a < e; ++a) { 2859*552f7358SJed Brown PetscHashIAdd(h, adjacency[a], 1); 2860*552f7358SJed Brown } 2861*552f7358SJed Brown } 2862*552f7358SJed Brown PetscHashISize(h, numNewPoints); 2863*552f7358SJed Brown ierr = PetscSectionSetDof(*partSection, part, numNewPoints);CHKERRQ(ierr); 2864*552f7358SJed Brown ierr = PetscMalloc(numNewPoints * sizeof(PetscInt), &tmpPoints[part]);CHKERRQ(ierr); 2865*552f7358SJed Brown if (numNewPoints) {PetscHashIGetKeys(h, n, tmpPoints[part]);} /* Should not need this conditional */ 2866*552f7358SJed Brown totPoints += numNewPoints; 2867*552f7358SJed Brown } 2868*552f7358SJed Brown ierr = ISRestoreIndices(origPartition, &points);CHKERRQ(ierr); 2869*552f7358SJed Brown PetscHashIDestroy(h); 2870*552f7358SJed Brown ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2871*552f7358SJed Brown ierr = PetscMalloc(totPoints * sizeof(PetscInt), &newPoints);CHKERRQ(ierr); 2872*552f7358SJed Brown for(part = pStart, q = 0; part < pEnd; ++part) { 2873*552f7358SJed Brown PetscInt numPoints, p; 2874*552f7358SJed Brown 2875*552f7358SJed Brown ierr = PetscSectionGetDof(*partSection, part, &numPoints);CHKERRQ(ierr); 2876*552f7358SJed Brown for(p = 0; p < numPoints; ++p, ++q) { 2877*552f7358SJed Brown newPoints[q] = tmpPoints[part][p]; 2878*552f7358SJed Brown } 2879*552f7358SJed Brown ierr = PetscFree(tmpPoints[part]);CHKERRQ(ierr); 2880*552f7358SJed Brown } 2881*552f7358SJed Brown ierr = PetscFree(tmpPoints);CHKERRQ(ierr); 2882*552f7358SJed Brown ierr = ISCreateGeneral(((PetscObject) dm)->comm, totPoints, newPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2883*552f7358SJed Brown PetscFunctionReturn(0); 2884*552f7358SJed Brown } 2885*552f7358SJed Brown 2886*552f7358SJed Brown #undef __FUNCT__ 2887*552f7358SJed Brown #define __FUNCT__ "DMPlexCreatePartition" 2888*552f7358SJed Brown /* 2889*552f7358SJed Brown DMPlexCreatePartition - Create a non-overlapping partition of the points at the given height 2890*552f7358SJed Brown 2891*552f7358SJed Brown Collective on DM 2892*552f7358SJed Brown 2893*552f7358SJed Brown Input Parameters: 2894*552f7358SJed Brown + dm - The DM 2895*552f7358SJed Brown . height - The height for points in the partition 2896*552f7358SJed Brown - enlarge - Expand each partition with neighbors 2897*552f7358SJed Brown 2898*552f7358SJed Brown Output Parameters: 2899*552f7358SJed Brown + partSection - The PetscSection giving the division of points by partition 2900*552f7358SJed Brown . partition - The list of points by partition 2901*552f7358SJed Brown . origPartSection - If enlarge is true, the PetscSection giving the division of points before enlarging by partition, otherwise PETSC_NULL 2902*552f7358SJed Brown - origPartition - If enlarge is true, the list of points before enlarging by partition, otherwise PETSC_NULL 2903*552f7358SJed Brown 2904*552f7358SJed Brown Level: developer 2905*552f7358SJed Brown 2906*552f7358SJed Brown .seealso DMPlexDistribute() 2907*552f7358SJed Brown */ 2908*552f7358SJed Brown PetscErrorCode DMPlexCreatePartition(DM dm, PetscInt height, PetscBool enlarge, PetscSection *partSection, IS *partition, PetscSection *origPartSection, IS *origPartition) { 2909*552f7358SJed Brown PetscMPIInt size; 2910*552f7358SJed Brown PetscErrorCode ierr; 2911*552f7358SJed Brown 2912*552f7358SJed Brown PetscFunctionBegin; 2913*552f7358SJed Brown ierr = MPI_Comm_size(((PetscObject) dm)->comm, &size);CHKERRQ(ierr); 2914*552f7358SJed Brown *origPartSection = PETSC_NULL; 2915*552f7358SJed Brown *origPartition = PETSC_NULL; 2916*552f7358SJed Brown if (size == 1) { 2917*552f7358SJed Brown PetscInt *points; 2918*552f7358SJed Brown PetscInt cStart, cEnd, c; 2919*552f7358SJed Brown 2920*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2921*552f7358SJed Brown ierr = PetscSectionCreate(((PetscObject) dm)->comm, partSection);CHKERRQ(ierr); 2922*552f7358SJed Brown ierr = PetscSectionSetChart(*partSection, 0, size);CHKERRQ(ierr); 2923*552f7358SJed Brown ierr = PetscSectionSetDof(*partSection, 0, cEnd-cStart);CHKERRQ(ierr); 2924*552f7358SJed Brown ierr = PetscSectionSetUp(*partSection);CHKERRQ(ierr); 2925*552f7358SJed Brown ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscInt), &points);CHKERRQ(ierr); 2926*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 2927*552f7358SJed Brown points[c] = c; 2928*552f7358SJed Brown } 2929*552f7358SJed Brown ierr = ISCreateGeneral(((PetscObject) dm)->comm, cEnd-cStart, points, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 2930*552f7358SJed Brown PetscFunctionReturn(0); 2931*552f7358SJed Brown } 2932*552f7358SJed Brown if (height == 0) { 2933*552f7358SJed Brown PetscInt numVertices; 2934*552f7358SJed Brown PetscInt *start = PETSC_NULL; 2935*552f7358SJed Brown PetscInt *adjacency = PETSC_NULL; 2936*552f7358SJed Brown 2937*552f7358SJed Brown ierr = DMPlexCreateNeighborCSR(dm, &numVertices, &start, &adjacency);CHKERRQ(ierr); 2938*552f7358SJed Brown if (1) { 2939*552f7358SJed Brown #ifdef PETSC_HAVE_CHACO 2940*552f7358SJed Brown ierr = DMPlexPartition_Chaco(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2941*552f7358SJed Brown #endif 2942*552f7358SJed Brown } else { 2943*552f7358SJed Brown #ifdef PETSC_HAVE_PARMETIS 2944*552f7358SJed Brown ierr = DMPlexPartition_ParMetis(dm, numVertices, start, adjacency, partSection, partition);CHKERRQ(ierr); 2945*552f7358SJed Brown #endif 2946*552f7358SJed Brown } 2947*552f7358SJed Brown if (enlarge) { 2948*552f7358SJed Brown *origPartSection = *partSection; 2949*552f7358SJed Brown *origPartition = *partition; 2950*552f7358SJed Brown ierr = DMPlexEnlargePartition(dm, start, adjacency, *origPartSection, *origPartition, partSection, partition);CHKERRQ(ierr); 2951*552f7358SJed Brown } 2952*552f7358SJed Brown ierr = PetscFree(start);CHKERRQ(ierr); 2953*552f7358SJed Brown ierr = PetscFree(adjacency);CHKERRQ(ierr); 2954*552f7358SJed Brown # if 0 2955*552f7358SJed Brown } else if (height == 1) { 2956*552f7358SJed Brown /* Build the dual graph for faces and partition the hypergraph */ 2957*552f7358SJed Brown PetscInt numEdges; 2958*552f7358SJed Brown 2959*552f7358SJed Brown buildFaceCSRV(mesh, mesh->getFactory()->getNumbering(mesh, mesh->depth()-1), &numEdges, &start, &adjacency, GraphPartitioner::zeroBase()); 2960*552f7358SJed Brown GraphPartitioner().partition(numEdges, start, adjacency, partition, manager); 2961*552f7358SJed Brown destroyCSR(numEdges, start, adjacency); 2962*552f7358SJed Brown #endif 2963*552f7358SJed Brown } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid partition height %D", height); 2964*552f7358SJed Brown PetscFunctionReturn(0); 2965*552f7358SJed Brown } 2966*552f7358SJed Brown 2967*552f7358SJed Brown #undef __FUNCT__ 2968*552f7358SJed Brown #define __FUNCT__ "DMPlexCreatePartitionClosure" 2969*552f7358SJed Brown PetscErrorCode DMPlexCreatePartitionClosure(DM dm, PetscSection pointSection, IS pointPartition, PetscSection *section, IS *partition) { 2970*552f7358SJed Brown /* const PetscInt height = 0; */ 2971*552f7358SJed Brown const PetscInt *partArray; 2972*552f7358SJed Brown PetscInt *allPoints, *partPoints = PETSC_NULL; 2973*552f7358SJed Brown PetscInt rStart, rEnd, rank, maxPartSize = 0, newSize; 2974*552f7358SJed Brown PetscErrorCode ierr; 2975*552f7358SJed Brown 2976*552f7358SJed Brown PetscFunctionBegin; 2977*552f7358SJed Brown ierr = PetscSectionGetChart(pointSection, &rStart, &rEnd);CHKERRQ(ierr); 2978*552f7358SJed Brown ierr = ISGetIndices(pointPartition, &partArray);CHKERRQ(ierr); 2979*552f7358SJed Brown ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 2980*552f7358SJed Brown ierr = PetscSectionSetChart(*section, rStart, rEnd);CHKERRQ(ierr); 2981*552f7358SJed Brown for (rank = rStart; rank < rEnd; ++rank) { 2982*552f7358SJed Brown PetscInt partSize = 0; 2983*552f7358SJed Brown PetscInt numPoints, offset, p; 2984*552f7358SJed Brown 2985*552f7358SJed Brown ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 2986*552f7358SJed Brown ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 2987*552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 2988*552f7358SJed Brown PetscInt point = partArray[offset+p], closureSize, c; 2989*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 2990*552f7358SJed Brown 2991*552f7358SJed Brown /* TODO Include support for height > 0 case */ 2992*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 2993*552f7358SJed Brown /* Merge into existing points */ 2994*552f7358SJed Brown if (partSize+closureSize > maxPartSize) { 2995*552f7358SJed Brown PetscInt *tmpPoints; 2996*552f7358SJed Brown 2997*552f7358SJed Brown maxPartSize = PetscMax(partSize+closureSize, 2*maxPartSize); 2998*552f7358SJed Brown ierr = PetscMalloc(maxPartSize * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 2999*552f7358SJed Brown ierr = PetscMemcpy(tmpPoints, partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3000*552f7358SJed Brown ierr = PetscFree(partPoints);CHKERRQ(ierr); 3001*552f7358SJed Brown partPoints = tmpPoints; 3002*552f7358SJed Brown } 3003*552f7358SJed Brown for (c = 0; c < closureSize; ++c) { 3004*552f7358SJed Brown partPoints[partSize+c] = closure[c*2]; 3005*552f7358SJed Brown } 3006*552f7358SJed Brown partSize += closureSize; 3007*552f7358SJed Brown ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3008*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3009*552f7358SJed Brown } 3010*552f7358SJed Brown ierr = PetscSectionSetDof(*section, rank, partSize);CHKERRQ(ierr); 3011*552f7358SJed Brown } 3012*552f7358SJed Brown ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3013*552f7358SJed Brown ierr = PetscSectionGetStorageSize(*section, &newSize);CHKERRQ(ierr); 3014*552f7358SJed Brown ierr = PetscMalloc(newSize * sizeof(PetscInt), &allPoints);CHKERRQ(ierr); 3015*552f7358SJed Brown 3016*552f7358SJed Brown for (rank = rStart; rank < rEnd; ++rank) { 3017*552f7358SJed Brown PetscInt partSize = 0, newOffset; 3018*552f7358SJed Brown PetscInt numPoints, offset, p; 3019*552f7358SJed Brown 3020*552f7358SJed Brown ierr = PetscSectionGetDof(pointSection, rank, &numPoints);CHKERRQ(ierr); 3021*552f7358SJed Brown ierr = PetscSectionGetOffset(pointSection, rank, &offset);CHKERRQ(ierr); 3022*552f7358SJed Brown for (p = 0; p < numPoints; ++p) { 3023*552f7358SJed Brown PetscInt point = partArray[offset+p], closureSize, c; 3024*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 3025*552f7358SJed Brown 3026*552f7358SJed Brown /* TODO Include support for height > 0 case */ 3027*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3028*552f7358SJed Brown /* Merge into existing points */ 3029*552f7358SJed Brown for (c = 0; c < closureSize; ++c) { 3030*552f7358SJed Brown partPoints[partSize+c] = closure[c*2]; 3031*552f7358SJed Brown } 3032*552f7358SJed Brown partSize += closureSize; 3033*552f7358SJed Brown ierr = PetscSortRemoveDupsInt(&partSize, partPoints);CHKERRQ(ierr); 3034*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 3035*552f7358SJed Brown } 3036*552f7358SJed Brown ierr = PetscSectionGetOffset(*section, rank, &newOffset);CHKERRQ(ierr); 3037*552f7358SJed Brown ierr = PetscMemcpy(&allPoints[newOffset], partPoints, partSize * sizeof(PetscInt));CHKERRQ(ierr); 3038*552f7358SJed Brown } 3039*552f7358SJed Brown ierr = ISRestoreIndices(pointPartition, &partArray);CHKERRQ(ierr); 3040*552f7358SJed Brown ierr = PetscFree(partPoints);CHKERRQ(ierr); 3041*552f7358SJed Brown ierr = ISCreateGeneral(((PetscObject) dm)->comm, newSize, allPoints, PETSC_OWN_POINTER, partition);CHKERRQ(ierr); 3042*552f7358SJed Brown PetscFunctionReturn(0); 3043*552f7358SJed Brown } 3044*552f7358SJed Brown 3045*552f7358SJed Brown #undef __FUNCT__ 3046*552f7358SJed Brown #define __FUNCT__ "DMPlexDistributeField" 3047*552f7358SJed Brown /* 3048*552f7358SJed Brown Input Parameters: 3049*552f7358SJed Brown . originalSection 3050*552f7358SJed Brown , originalVec 3051*552f7358SJed Brown 3052*552f7358SJed Brown Output Parameters: 3053*552f7358SJed Brown . newSection 3054*552f7358SJed Brown . newVec 3055*552f7358SJed Brown */ 3056*552f7358SJed Brown PetscErrorCode DMPlexDistributeField(DM dm, PetscSF pointSF, PetscSection originalSection, Vec originalVec, PetscSection newSection, Vec newVec) 3057*552f7358SJed Brown { 3058*552f7358SJed Brown PetscSF fieldSF; 3059*552f7358SJed Brown PetscInt *remoteOffsets, fieldSize; 3060*552f7358SJed Brown PetscScalar *originalValues, *newValues; 3061*552f7358SJed Brown PetscErrorCode ierr; 3062*552f7358SJed Brown 3063*552f7358SJed Brown PetscFunctionBegin; 3064*552f7358SJed Brown ierr = PetscSFDistributeSection(pointSF, originalSection, &remoteOffsets, newSection);CHKERRQ(ierr); 3065*552f7358SJed Brown 3066*552f7358SJed Brown ierr = PetscSectionGetStorageSize(newSection, &fieldSize);CHKERRQ(ierr); 3067*552f7358SJed Brown ierr = VecSetSizes(newVec, fieldSize, PETSC_DETERMINE);CHKERRQ(ierr); 3068*552f7358SJed Brown ierr = VecSetFromOptions(newVec);CHKERRQ(ierr); 3069*552f7358SJed Brown 3070*552f7358SJed Brown ierr = VecGetArray(originalVec, &originalValues);CHKERRQ(ierr); 3071*552f7358SJed Brown ierr = VecGetArray(newVec, &newValues);CHKERRQ(ierr); 3072*552f7358SJed Brown ierr = PetscSFCreateSectionSF(pointSF, originalSection, remoteOffsets, newSection, &fieldSF);CHKERRQ(ierr); 3073*552f7358SJed Brown ierr = PetscSFBcastBegin(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3074*552f7358SJed Brown ierr = PetscSFBcastEnd(fieldSF, MPIU_SCALAR, originalValues, newValues);CHKERRQ(ierr); 3075*552f7358SJed Brown ierr = PetscSFDestroy(&fieldSF);CHKERRQ(ierr); 3076*552f7358SJed Brown ierr = VecRestoreArray(newVec, &newValues);CHKERRQ(ierr); 3077*552f7358SJed Brown ierr = VecRestoreArray(originalVec, &originalValues);CHKERRQ(ierr); 3078*552f7358SJed Brown PetscFunctionReturn(0); 3079*552f7358SJed Brown } 3080*552f7358SJed Brown 3081*552f7358SJed Brown #undef __FUNCT__ 3082*552f7358SJed Brown #define __FUNCT__ "DMPlexDistribute" 3083*552f7358SJed Brown /*@C 3084*552f7358SJed Brown DMPlexDistribute - Distributes the mesh and any associated sections. 3085*552f7358SJed Brown 3086*552f7358SJed Brown Not Collective 3087*552f7358SJed Brown 3088*552f7358SJed Brown Input Parameter: 3089*552f7358SJed Brown + dm - The original DMPlex object 3090*552f7358SJed Brown . partitioner - The partitioning package, or NULL for the default 3091*552f7358SJed Brown - overlap - The overlap of partitions, 0 is the default 3092*552f7358SJed Brown 3093*552f7358SJed Brown Output Parameter: 3094*552f7358SJed Brown . parallelMesh - The distributed DMPlex object, or PETSC_NULL 3095*552f7358SJed Brown 3096*552f7358SJed Brown Note: If the mesh was not distributed, the return value is PETSC_NULL 3097*552f7358SJed Brown 3098*552f7358SJed Brown Level: intermediate 3099*552f7358SJed Brown 3100*552f7358SJed Brown .keywords: mesh, elements 3101*552f7358SJed Brown .seealso: DMPlexCreate(), DMPlexDistributeByFace() 3102*552f7358SJed Brown @*/ 3103*552f7358SJed Brown PetscErrorCode DMPlexDistribute(DM dm, const char partitioner[], PetscInt overlap, DM *dmParallel) 3104*552f7358SJed Brown { 3105*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data, *pmesh; 3106*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 3107*552f7358SJed Brown const PetscInt height = 0; 3108*552f7358SJed Brown PetscInt dim, numRemoteRanks; 3109*552f7358SJed Brown IS origCellPart, cellPart, part; 3110*552f7358SJed Brown PetscSection origCellPartSection, cellPartSection, partSection; 3111*552f7358SJed Brown PetscSFNode *remoteRanks; 3112*552f7358SJed Brown PetscSF partSF, pointSF, coneSF; 3113*552f7358SJed Brown ISLocalToGlobalMapping renumbering; 3114*552f7358SJed Brown PetscSection originalConeSection, newConeSection; 3115*552f7358SJed Brown PetscInt *remoteOffsets; 3116*552f7358SJed Brown PetscInt *cones, *newCones, newConesSize; 3117*552f7358SJed Brown PetscBool flg; 3118*552f7358SJed Brown PetscMPIInt rank, numProcs, p; 3119*552f7358SJed Brown PetscErrorCode ierr; 3120*552f7358SJed Brown 3121*552f7358SJed Brown PetscFunctionBegin; 3122*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3123*552f7358SJed Brown PetscValidPointer(dmParallel,4); 3124*552f7358SJed Brown ierr = PetscLogEventBegin(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3125*552f7358SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 3126*552f7358SJed Brown ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 3127*552f7358SJed Brown *dmParallel = PETSC_NULL; 3128*552f7358SJed Brown if (numProcs == 1) PetscFunctionReturn(0); 3129*552f7358SJed Brown 3130*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3131*552f7358SJed Brown /* Create cell partition - We need to rewrite to use IS, use the MatPartition stuff */ 3132*552f7358SJed Brown if (overlap > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Overlap > 1 not yet implemented"); 3133*552f7358SJed Brown ierr = DMPlexCreatePartition(dm, height, overlap > 0 ? PETSC_TRUE : PETSC_FALSE, &cellPartSection, &cellPart, &origCellPartSection, &origCellPart);CHKERRQ(ierr); 3134*552f7358SJed Brown /* Create SF assuming a serial partition for all processes: Could check for IS length here */ 3135*552f7358SJed Brown if (!rank) { 3136*552f7358SJed Brown numRemoteRanks = numProcs; 3137*552f7358SJed Brown } else { 3138*552f7358SJed Brown numRemoteRanks = 0; 3139*552f7358SJed Brown } 3140*552f7358SJed Brown ierr = PetscMalloc(numRemoteRanks * sizeof(PetscSFNode), &remoteRanks);CHKERRQ(ierr); 3141*552f7358SJed Brown for (p = 0; p < numRemoteRanks; ++p) { 3142*552f7358SJed Brown remoteRanks[p].rank = p; 3143*552f7358SJed Brown remoteRanks[p].index = 0; 3144*552f7358SJed Brown } 3145*552f7358SJed Brown ierr = PetscSFCreate(comm, &partSF);CHKERRQ(ierr); 3146*552f7358SJed Brown ierr = PetscSFSetGraph(partSF, 1, numRemoteRanks, PETSC_NULL, PETSC_OWN_POINTER, remoteRanks, PETSC_OWN_POINTER);CHKERRQ(ierr); 3147*552f7358SJed Brown ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-partition_view", &flg);CHKERRQ(ierr); 3148*552f7358SJed Brown if (flg) { 3149*552f7358SJed Brown ierr = PetscPrintf(comm, "Cell Partition:\n");CHKERRQ(ierr); 3150*552f7358SJed Brown ierr = PetscSectionView(cellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3151*552f7358SJed Brown ierr = ISView(cellPart, PETSC_NULL);CHKERRQ(ierr); 3152*552f7358SJed Brown if (origCellPart) { 3153*552f7358SJed Brown ierr = PetscPrintf(comm, "Original Cell Partition:\n");CHKERRQ(ierr); 3154*552f7358SJed Brown ierr = PetscSectionView(origCellPartSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3155*552f7358SJed Brown ierr = ISView(origCellPart, PETSC_NULL);CHKERRQ(ierr); 3156*552f7358SJed Brown } 3157*552f7358SJed Brown ierr = PetscSFView(partSF, PETSC_NULL);CHKERRQ(ierr); 3158*552f7358SJed Brown } 3159*552f7358SJed Brown /* Close the partition over the mesh */ 3160*552f7358SJed Brown ierr = DMPlexCreatePartitionClosure(dm, cellPartSection, cellPart, &partSection, &part);CHKERRQ(ierr); 3161*552f7358SJed Brown ierr = ISDestroy(&cellPart);CHKERRQ(ierr); 3162*552f7358SJed Brown ierr = PetscSectionDestroy(&cellPartSection);CHKERRQ(ierr); 3163*552f7358SJed Brown /* Create new mesh */ 3164*552f7358SJed Brown ierr = DMPlexCreate(comm, dmParallel);CHKERRQ(ierr); 3165*552f7358SJed Brown ierr = DMPlexSetDimension(*dmParallel, dim);CHKERRQ(ierr); 3166*552f7358SJed Brown ierr = PetscObjectSetName((PetscObject) *dmParallel, "Parallel Mesh");CHKERRQ(ierr); 3167*552f7358SJed Brown pmesh = (DM_Plex *) (*dmParallel)->data; 3168*552f7358SJed Brown /* Distribute sieve points and the global point numbering (replaces creating remote bases) */ 3169*552f7358SJed Brown ierr = PetscSFConvertPartition(partSF, partSection, part, &renumbering, &pointSF);CHKERRQ(ierr); 3170*552f7358SJed Brown if (flg) { 3171*552f7358SJed Brown ierr = PetscPrintf(comm, "Point Partition:\n");CHKERRQ(ierr); 3172*552f7358SJed Brown ierr = PetscSectionView(partSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3173*552f7358SJed Brown ierr = ISView(part, PETSC_NULL);CHKERRQ(ierr); 3174*552f7358SJed Brown ierr = PetscSFView(pointSF, PETSC_NULL);CHKERRQ(ierr); 3175*552f7358SJed Brown ierr = PetscPrintf(comm, "Point Renumbering after partition:\n");CHKERRQ(ierr); 3176*552f7358SJed Brown ierr = ISLocalToGlobalMappingView(renumbering, PETSC_NULL);CHKERRQ(ierr); 3177*552f7358SJed Brown } 3178*552f7358SJed Brown /* Distribute cone section */ 3179*552f7358SJed Brown ierr = DMPlexGetConeSection(dm, &originalConeSection);CHKERRQ(ierr); 3180*552f7358SJed Brown ierr = DMPlexGetConeSection(*dmParallel, &newConeSection);CHKERRQ(ierr); 3181*552f7358SJed Brown ierr = PetscSFDistributeSection(pointSF, originalConeSection, &remoteOffsets, newConeSection);CHKERRQ(ierr); 3182*552f7358SJed Brown ierr = DMSetUp(*dmParallel);CHKERRQ(ierr); 3183*552f7358SJed Brown { 3184*552f7358SJed Brown PetscInt pStart, pEnd, p; 3185*552f7358SJed Brown 3186*552f7358SJed Brown ierr = PetscSectionGetChart(newConeSection, &pStart, &pEnd);CHKERRQ(ierr); 3187*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 3188*552f7358SJed Brown PetscInt coneSize; 3189*552f7358SJed Brown ierr = PetscSectionGetDof(newConeSection, p, &coneSize);CHKERRQ(ierr); 3190*552f7358SJed Brown pmesh->maxConeSize = PetscMax(pmesh->maxConeSize, coneSize); 3191*552f7358SJed Brown } 3192*552f7358SJed Brown } 3193*552f7358SJed Brown /* Communicate and renumber cones */ 3194*552f7358SJed Brown ierr = PetscSFCreateSectionSF(pointSF, originalConeSection, remoteOffsets, newConeSection, &coneSF);CHKERRQ(ierr); 3195*552f7358SJed Brown ierr = DMPlexGetCones(dm, &cones);CHKERRQ(ierr); 3196*552f7358SJed Brown ierr = DMPlexGetCones(*dmParallel, &newCones);CHKERRQ(ierr); 3197*552f7358SJed Brown ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3198*552f7358SJed Brown ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3199*552f7358SJed Brown ierr = PetscSectionGetStorageSize(newConeSection, &newConesSize);CHKERRQ(ierr); 3200*552f7358SJed Brown ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newConesSize, newCones, PETSC_NULL, newCones);CHKERRQ(ierr); 3201*552f7358SJed Brown ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-cones_view", &flg);CHKERRQ(ierr); 3202*552f7358SJed Brown if (flg) { 3203*552f7358SJed Brown ierr = PetscPrintf(comm, "Serial Cone Section:\n");CHKERRQ(ierr); 3204*552f7358SJed Brown ierr = PetscSectionView(originalConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3205*552f7358SJed Brown ierr = PetscPrintf(comm, "Parallel Cone Section:\n");CHKERRQ(ierr); 3206*552f7358SJed Brown ierr = PetscSectionView(newConeSection, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3207*552f7358SJed Brown ierr = PetscSFView(coneSF, PETSC_NULL);CHKERRQ(ierr); 3208*552f7358SJed Brown } 3209*552f7358SJed Brown ierr = DMPlexGetConeOrientations(dm, &cones);CHKERRQ(ierr); 3210*552f7358SJed Brown ierr = DMPlexGetConeOrientations(*dmParallel, &newCones);CHKERRQ(ierr); 3211*552f7358SJed Brown ierr = PetscSFBcastBegin(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3212*552f7358SJed Brown ierr = PetscSFBcastEnd(coneSF, MPIU_INT, cones, newCones);CHKERRQ(ierr); 3213*552f7358SJed Brown ierr = PetscSFDestroy(&coneSF);CHKERRQ(ierr); 3214*552f7358SJed Brown /* Create supports and stratify sieve */ 3215*552f7358SJed Brown { 3216*552f7358SJed Brown PetscInt pStart, pEnd; 3217*552f7358SJed Brown 3218*552f7358SJed Brown ierr = PetscSectionGetChart(pmesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 3219*552f7358SJed Brown ierr = PetscSectionSetChart(pmesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 3220*552f7358SJed Brown } 3221*552f7358SJed Brown ierr = DMPlexSymmetrize(*dmParallel);CHKERRQ(ierr); 3222*552f7358SJed Brown ierr = DMPlexStratify(*dmParallel);CHKERRQ(ierr); 3223*552f7358SJed Brown /* Distribute Coordinates */ 3224*552f7358SJed Brown { 3225*552f7358SJed Brown PetscSection originalCoordSection, newCoordSection; 3226*552f7358SJed Brown Vec originalCoordinates, newCoordinates; 3227*552f7358SJed Brown const char *name; 3228*552f7358SJed Brown 3229*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &originalCoordSection);CHKERRQ(ierr); 3230*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(*dmParallel, &newCoordSection);CHKERRQ(ierr); 3231*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &originalCoordinates);CHKERRQ(ierr); 3232*552f7358SJed Brown ierr = VecCreate(comm, &newCoordinates);CHKERRQ(ierr); 3233*552f7358SJed Brown ierr = PetscObjectGetName((PetscObject) originalCoordinates, &name);CHKERRQ(ierr); 3234*552f7358SJed Brown ierr = PetscObjectSetName((PetscObject) newCoordinates, name);CHKERRQ(ierr); 3235*552f7358SJed Brown 3236*552f7358SJed Brown ierr = DMPlexDistributeField(dm, pointSF, originalCoordSection, originalCoordinates, newCoordSection, newCoordinates);CHKERRQ(ierr); 3237*552f7358SJed Brown ierr = DMSetCoordinatesLocal(*dmParallel, newCoordinates);CHKERRQ(ierr); 3238*552f7358SJed Brown ierr = VecDestroy(&newCoordinates);CHKERRQ(ierr); 3239*552f7358SJed Brown } 3240*552f7358SJed Brown /* Distribute labels */ 3241*552f7358SJed Brown { 3242*552f7358SJed Brown DMLabel next = mesh->labels, newNext = pmesh->labels; 3243*552f7358SJed Brown PetscInt numLabels = 0, l; 3244*552f7358SJed Brown 3245*552f7358SJed Brown /* Bcast number of labels */ 3246*552f7358SJed Brown while(next) {++numLabels; next = next->next;} 3247*552f7358SJed Brown ierr = MPI_Bcast(&numLabels, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3248*552f7358SJed Brown next = mesh->labels; 3249*552f7358SJed Brown for (l = 0; l < numLabels; ++l) { 3250*552f7358SJed Brown DMLabel newLabel; 3251*552f7358SJed Brown const PetscInt *partArray; 3252*552f7358SJed Brown char *name; 3253*552f7358SJed Brown PetscInt *stratumSizes = PETSC_NULL, *points = PETSC_NULL; 3254*552f7358SJed Brown PetscMPIInt *sendcnts = PETSC_NULL, *offsets = PETSC_NULL, *displs = PETSC_NULL; 3255*552f7358SJed Brown PetscInt nameSize, s, p; 3256*552f7358SJed Brown PetscBool isdepth; 3257*552f7358SJed Brown size_t len = 0; 3258*552f7358SJed Brown 3259*552f7358SJed Brown /* Bcast name (could filter for no points) */ 3260*552f7358SJed Brown if (!rank) {ierr = PetscStrlen(next->name, &len);CHKERRQ(ierr);} 3261*552f7358SJed Brown nameSize = len; 3262*552f7358SJed Brown ierr = MPI_Bcast(&nameSize, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3263*552f7358SJed Brown ierr = PetscMalloc(nameSize+1, &name);CHKERRQ(ierr); 3264*552f7358SJed Brown if (!rank) {ierr = PetscMemcpy(name, next->name, nameSize+1);CHKERRQ(ierr);} 3265*552f7358SJed Brown ierr = MPI_Bcast(name, nameSize+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 3266*552f7358SJed Brown ierr = PetscStrcmp(name, "depth", &isdepth);CHKERRQ(ierr); 3267*552f7358SJed Brown if (isdepth) {ierr = PetscFree(name);CHKERRQ(ierr); continue;} 3268*552f7358SJed Brown ierr = PetscNew(struct _n_DMLabel, &newLabel);CHKERRQ(ierr); 3269*552f7358SJed Brown newLabel->name = name; 3270*552f7358SJed Brown /* Bcast numStrata (could filter for no points in stratum) */ 3271*552f7358SJed Brown if (!rank) {newLabel->numStrata = next->numStrata;} 3272*552f7358SJed Brown ierr = MPI_Bcast(&newLabel->numStrata, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 3273*552f7358SJed Brown ierr = PetscMalloc3(newLabel->numStrata,PetscInt,&newLabel->stratumValues, 3274*552f7358SJed Brown newLabel->numStrata,PetscInt,&newLabel->stratumSizes, 3275*552f7358SJed Brown newLabel->numStrata+1,PetscInt,&newLabel->stratumOffsets);CHKERRQ(ierr); 3276*552f7358SJed Brown /* Bcast stratumValues (could filter for no points in stratum) */ 3277*552f7358SJed Brown if (!rank) {ierr = PetscMemcpy(newLabel->stratumValues, next->stratumValues, next->numStrata * sizeof(PetscInt));CHKERRQ(ierr);} 3278*552f7358SJed Brown ierr = MPI_Bcast(newLabel->stratumValues, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3279*552f7358SJed Brown /* Find size on each process and Scatter */ 3280*552f7358SJed Brown if (!rank) { 3281*552f7358SJed Brown ierr = ISGetIndices(part, &partArray);CHKERRQ(ierr); 3282*552f7358SJed Brown ierr = PetscMalloc(numProcs*next->numStrata * sizeof(PetscInt), &stratumSizes);CHKERRQ(ierr); 3283*552f7358SJed Brown ierr = PetscMemzero(stratumSizes, numProcs*next->numStrata * sizeof(PetscInt));CHKERRQ(ierr); 3284*552f7358SJed Brown for (s = 0; s < next->numStrata; ++s) { 3285*552f7358SJed Brown for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3286*552f7358SJed Brown const PetscInt point = next->points[p]; 3287*552f7358SJed Brown PetscInt proc; 3288*552f7358SJed Brown 3289*552f7358SJed Brown for (proc = 0; proc < numProcs; ++proc) { 3290*552f7358SJed Brown PetscInt dof, off, pPart; 3291*552f7358SJed Brown 3292*552f7358SJed Brown ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3293*552f7358SJed Brown ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3294*552f7358SJed Brown for (pPart = off; pPart < off+dof; ++pPart) { 3295*552f7358SJed Brown if (partArray[pPart] == point) { 3296*552f7358SJed Brown ++stratumSizes[proc*next->numStrata+s]; 3297*552f7358SJed Brown break; 3298*552f7358SJed Brown } 3299*552f7358SJed Brown } 3300*552f7358SJed Brown } 3301*552f7358SJed Brown } 3302*552f7358SJed Brown } 3303*552f7358SJed Brown ierr = ISRestoreIndices(part, &partArray);CHKERRQ(ierr); 3304*552f7358SJed Brown } 3305*552f7358SJed Brown ierr = MPI_Scatter(stratumSizes, newLabel->numStrata, MPIU_INT, newLabel->stratumSizes, newLabel->numStrata, MPIU_INT, 0, comm);CHKERRQ(ierr); 3306*552f7358SJed Brown /* Calculate stratumOffsets */ 3307*552f7358SJed Brown newLabel->stratumOffsets[0] = 0; 3308*552f7358SJed Brown for (s = 0; s < newLabel->numStrata; ++s) { 3309*552f7358SJed Brown newLabel->stratumOffsets[s+1] = newLabel->stratumSizes[s] + newLabel->stratumOffsets[s]; 3310*552f7358SJed Brown } 3311*552f7358SJed Brown /* Pack points and Scatter */ 3312*552f7358SJed Brown if (!rank) { 3313*552f7358SJed Brown ierr = PetscMalloc3(numProcs,PetscMPIInt,&sendcnts,numProcs,PetscMPIInt,&offsets,numProcs+1,PetscMPIInt,&displs);CHKERRQ(ierr); 3314*552f7358SJed Brown displs[0] = 0; 3315*552f7358SJed Brown for (p = 0; p < numProcs; ++p) { 3316*552f7358SJed Brown sendcnts[p] = 0; 3317*552f7358SJed Brown for (s = 0; s < next->numStrata; ++s) { 3318*552f7358SJed Brown sendcnts[p] += stratumSizes[p*next->numStrata+s]; 3319*552f7358SJed Brown } 3320*552f7358SJed Brown offsets[p] = displs[p]; 3321*552f7358SJed Brown displs[p+1] = displs[p] + sendcnts[p]; 3322*552f7358SJed Brown } 3323*552f7358SJed Brown ierr = PetscMalloc(displs[numProcs] * sizeof(PetscInt), &points);CHKERRQ(ierr); 3324*552f7358SJed Brown for (s = 0; s < next->numStrata; ++s) { 3325*552f7358SJed Brown for (p = next->stratumOffsets[s]; p < next->stratumOffsets[s]+next->stratumSizes[s]; ++p) { 3326*552f7358SJed Brown const PetscInt point = next->points[p]; 3327*552f7358SJed Brown PetscInt proc; 3328*552f7358SJed Brown 3329*552f7358SJed Brown for (proc = 0; proc < numProcs; ++proc) { 3330*552f7358SJed Brown PetscInt dof, off, pPart; 3331*552f7358SJed Brown 3332*552f7358SJed Brown ierr = PetscSectionGetDof(partSection, proc, &dof);CHKERRQ(ierr); 3333*552f7358SJed Brown ierr = PetscSectionGetOffset(partSection, proc, &off);CHKERRQ(ierr); 3334*552f7358SJed Brown for (pPart = off; pPart < off+dof; ++pPart) { 3335*552f7358SJed Brown if (partArray[pPart] == point) { 3336*552f7358SJed Brown points[offsets[proc]++] = point; 3337*552f7358SJed Brown break; 3338*552f7358SJed Brown } 3339*552f7358SJed Brown } 3340*552f7358SJed Brown } 3341*552f7358SJed Brown } 3342*552f7358SJed Brown } 3343*552f7358SJed Brown } 3344*552f7358SJed Brown ierr = PetscMalloc(newLabel->stratumOffsets[newLabel->numStrata] * sizeof(PetscInt), &newLabel->points);CHKERRQ(ierr); 3345*552f7358SJed Brown ierr = MPI_Scatterv(points, sendcnts, displs, MPIU_INT, newLabel->points, newLabel->stratumOffsets[newLabel->numStrata], MPIU_INT, 0, comm);CHKERRQ(ierr); 3346*552f7358SJed Brown ierr = PetscFree(points);CHKERRQ(ierr); 3347*552f7358SJed Brown ierr = PetscFree3(sendcnts,offsets,displs);CHKERRQ(ierr); 3348*552f7358SJed Brown ierr = PetscFree(stratumSizes);CHKERRQ(ierr); 3349*552f7358SJed Brown /* Renumber points */ 3350*552f7358SJed Brown ierr = ISGlobalToLocalMappingApply(renumbering, IS_GTOLM_MASK, newLabel->stratumOffsets[newLabel->numStrata], newLabel->points, PETSC_NULL, newLabel->points);CHKERRQ(ierr); 3351*552f7358SJed Brown /* Sort points */ 3352*552f7358SJed Brown for (s = 0; s < newLabel->numStrata; ++s) { 3353*552f7358SJed Brown ierr = PetscSortInt(newLabel->stratumSizes[s], &newLabel->points[newLabel->stratumOffsets[s]]);CHKERRQ(ierr); 3354*552f7358SJed Brown } 3355*552f7358SJed Brown /* Insert into list */ 3356*552f7358SJed Brown if (newNext) { 3357*552f7358SJed Brown newNext->next = newLabel; 3358*552f7358SJed Brown } else { 3359*552f7358SJed Brown pmesh->labels = newLabel; 3360*552f7358SJed Brown } 3361*552f7358SJed Brown newNext = newLabel; 3362*552f7358SJed Brown if (!rank) {next = next->next;} 3363*552f7358SJed Brown } 3364*552f7358SJed Brown } 3365*552f7358SJed Brown /* Cleanup Partition */ 3366*552f7358SJed Brown ierr = ISLocalToGlobalMappingDestroy(&renumbering);CHKERRQ(ierr); 3367*552f7358SJed Brown ierr = PetscSFDestroy(&partSF);CHKERRQ(ierr); 3368*552f7358SJed Brown ierr = PetscSectionDestroy(&partSection);CHKERRQ(ierr); 3369*552f7358SJed Brown ierr = ISDestroy(&part);CHKERRQ(ierr); 3370*552f7358SJed Brown /* Create point SF for parallel mesh */ 3371*552f7358SJed Brown { 3372*552f7358SJed Brown const PetscInt *leaves; 3373*552f7358SJed Brown PetscSFNode *remotePoints, *rowners, *lowners; 3374*552f7358SJed Brown PetscInt numRoots, numLeaves, numGhostPoints = 0, p, gp, *ghostPoints; 3375*552f7358SJed Brown PetscInt pStart, pEnd; 3376*552f7358SJed Brown 3377*552f7358SJed Brown ierr = DMPlexGetChart(*dmParallel, &pStart, &pEnd);CHKERRQ(ierr); 3378*552f7358SJed Brown ierr = PetscSFGetGraph(pointSF, &numRoots, &numLeaves, &leaves, PETSC_NULL);CHKERRQ(ierr); 3379*552f7358SJed Brown ierr = PetscMalloc2(numRoots,PetscSFNode,&rowners,numLeaves,PetscSFNode,&lowners);CHKERRQ(ierr); 3380*552f7358SJed Brown for (p=0; p<numRoots; p++) { 3381*552f7358SJed Brown rowners[p].rank = -1; 3382*552f7358SJed Brown rowners[p].index = -1; 3383*552f7358SJed Brown } 3384*552f7358SJed Brown if (origCellPart) { 3385*552f7358SJed Brown /* Make sure cells in the original partition are not assigned to other procs */ 3386*552f7358SJed Brown const PetscInt *origCells; 3387*552f7358SJed Brown 3388*552f7358SJed Brown ierr = ISGetIndices(origCellPart, &origCells);CHKERRQ(ierr); 3389*552f7358SJed Brown for (p = 0; p < numProcs; ++p) { 3390*552f7358SJed Brown PetscInt dof, off, d; 3391*552f7358SJed Brown 3392*552f7358SJed Brown ierr = PetscSectionGetDof(origCellPartSection, p, &dof);CHKERRQ(ierr); 3393*552f7358SJed Brown ierr = PetscSectionGetOffset(origCellPartSection, p, &off);CHKERRQ(ierr); 3394*552f7358SJed Brown for(d = off; d < off+dof; ++d) { 3395*552f7358SJed Brown rowners[origCells[d]].rank = p; 3396*552f7358SJed Brown } 3397*552f7358SJed Brown } 3398*552f7358SJed Brown ierr = ISRestoreIndices(origCellPart, &origCells);CHKERRQ(ierr); 3399*552f7358SJed Brown } 3400*552f7358SJed Brown ierr = ISDestroy(&origCellPart);CHKERRQ(ierr); 3401*552f7358SJed Brown ierr = PetscSectionDestroy(&origCellPartSection);CHKERRQ(ierr); 3402*552f7358SJed Brown 3403*552f7358SJed Brown ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3404*552f7358SJed Brown ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3405*552f7358SJed Brown for (p = 0; p < numLeaves; ++p) { 3406*552f7358SJed Brown if (lowners[p].rank < 0 || lowners[p].rank == rank) { /* Either put in a bid or we know we own it */ 3407*552f7358SJed Brown lowners[p].rank = rank; 3408*552f7358SJed Brown lowners[p].index = leaves ? leaves[p] : p; 3409*552f7358SJed Brown } else if (lowners[p].rank >= 0) { /* Point already claimed so flag so that MAXLOC does not listen to us */ 3410*552f7358SJed Brown lowners[p].rank = -2; 3411*552f7358SJed Brown lowners[p].index = -2; 3412*552f7358SJed Brown } 3413*552f7358SJed Brown } 3414*552f7358SJed Brown for (p=0; p<numRoots; p++) { /* Root must not participate in the rediction, flag so that MAXLOC does not use */ 3415*552f7358SJed Brown rowners[p].rank = -3; 3416*552f7358SJed Brown rowners[p].index = -3; 3417*552f7358SJed Brown } 3418*552f7358SJed Brown ierr = PetscSFReduceBegin(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3419*552f7358SJed Brown ierr = PetscSFReduceEnd(pointSF, MPIU_2INT, lowners, rowners, MPI_MAXLOC);CHKERRQ(ierr); 3420*552f7358SJed Brown ierr = PetscSFBcastBegin(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3421*552f7358SJed Brown ierr = PetscSFBcastEnd(pointSF, MPIU_2INT, rowners, lowners);CHKERRQ(ierr); 3422*552f7358SJed Brown for (p = 0; p < numLeaves; ++p) { 3423*552f7358SJed Brown if (lowners[p].rank < 0 || lowners[p].index < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Cell partition corrupt: point not claimed"); 3424*552f7358SJed Brown if (lowners[p].rank != rank) ++numGhostPoints; 3425*552f7358SJed Brown } 3426*552f7358SJed Brown ierr = PetscMalloc(numGhostPoints * sizeof(PetscInt), &ghostPoints);CHKERRQ(ierr); 3427*552f7358SJed Brown ierr = PetscMalloc(numGhostPoints * sizeof(PetscSFNode), &remotePoints);CHKERRQ(ierr); 3428*552f7358SJed Brown for (p = 0, gp = 0; p < numLeaves; ++p) { 3429*552f7358SJed Brown if (lowners[p].rank != rank) { 3430*552f7358SJed Brown ghostPoints[gp] = leaves ? leaves[p] : p; 3431*552f7358SJed Brown remotePoints[gp].rank = lowners[p].rank; 3432*552f7358SJed Brown remotePoints[gp].index = lowners[p].index; 3433*552f7358SJed Brown ++gp; 3434*552f7358SJed Brown } 3435*552f7358SJed Brown } 3436*552f7358SJed Brown ierr = PetscFree2(rowners,lowners);CHKERRQ(ierr); 3437*552f7358SJed Brown ierr = PetscSFSetGraph((*dmParallel)->sf, pEnd - pStart, numGhostPoints, ghostPoints, PETSC_OWN_POINTER, remotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3438*552f7358SJed Brown ierr = PetscSFSetFromOptions((*dmParallel)->sf);CHKERRQ(ierr); 3439*552f7358SJed Brown } 3440*552f7358SJed Brown /* Cleanup */ 3441*552f7358SJed Brown ierr = PetscSFDestroy(&pointSF);CHKERRQ(ierr); 3442*552f7358SJed Brown ierr = DMSetFromOptions(*dmParallel);CHKERRQ(ierr); 3443*552f7358SJed Brown ierr = PetscLogEventEnd(DMPLEX_Distribute,dm,0,0,0);CHKERRQ(ierr); 3444*552f7358SJed Brown PetscFunctionReturn(0); 3445*552f7358SJed Brown } 3446*552f7358SJed Brown 3447*552f7358SJed Brown #undef __FUNCT__ 3448*552f7358SJed Brown #define __FUNCT__ "DMPlexRenumber_Private" 3449*552f7358SJed Brown /* 3450*552f7358SJed Brown Reasons to renumber: 3451*552f7358SJed Brown 3452*552f7358SJed Brown 1) Permute points, e.g. bandwidth reduction (Renumber) 3453*552f7358SJed Brown 3454*552f7358SJed Brown a) Must not mix strata 3455*552f7358SJed Brown 3456*552f7358SJed Brown 2) Shift numbers for point insertion (Shift) 3457*552f7358SJed Brown 3458*552f7358SJed Brown a) Want operation brken into parts so that insertion can be interleaved 3459*552f7358SJed Brown 3460*552f7358SJed Brown renumbering - An IS which provides the new numbering 3461*552f7358SJed Brown */ 3462*552f7358SJed Brown PetscErrorCode DMPlexRenumber_Private(DM dm, IS renumbering) 3463*552f7358SJed Brown { 3464*552f7358SJed Brown PetscFunctionBegin; 3465*552f7358SJed Brown PetscFunctionReturn(0); 3466*552f7358SJed Brown } 3467*552f7358SJed Brown 3468*552f7358SJed Brown #undef __FUNCT__ 3469*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftPoint_Private" 3470*552f7358SJed Brown PETSC_STATIC_INLINE PetscInt DMPlexShiftPoint_Private(PetscInt p, PetscInt depth, PetscInt depthEnd[], PetscInt depthShift[]) 3471*552f7358SJed Brown { 3472*552f7358SJed Brown if (depth < 0) return p; 3473*552f7358SJed Brown /* Cells */ if (p < depthEnd[depth]) return p; 3474*552f7358SJed Brown /* Vertices */ if (p < depthEnd[0]) return p + depthShift[depth]; 3475*552f7358SJed Brown /* Faces */ if (p < depthEnd[depth-1]) return p + depthShift[depth] + depthShift[0]; 3476*552f7358SJed Brown /* Edges */ return p + depthShift[depth] + depthShift[0] + depthShift[depth-1]; 3477*552f7358SJed Brown } 3478*552f7358SJed Brown 3479*552f7358SJed Brown #undef __FUNCT__ 3480*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftSizes_Private" 3481*552f7358SJed Brown PetscErrorCode DMPlexShiftSizes_Private(DM dm, PetscInt depthShift[], DM dmNew) 3482*552f7358SJed Brown { 3483*552f7358SJed Brown PetscInt *depthEnd; 3484*552f7358SJed Brown PetscInt depth = 0, d, pStart, pEnd, p; 3485*552f7358SJed Brown PetscErrorCode ierr; 3486*552f7358SJed Brown 3487*552f7358SJed Brown PetscFunctionBegin; 3488*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3489*552f7358SJed Brown if (depth < 0) PetscFunctionReturn(0); 3490*552f7358SJed Brown ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3491*552f7358SJed Brown /* Step 1: Expand chart */ 3492*552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3493*552f7358SJed Brown for(d = 0; d <= depth; ++d) { 3494*552f7358SJed Brown pEnd += depthShift[d]; 3495*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3496*552f7358SJed Brown } 3497*552f7358SJed Brown ierr = DMPlexSetChart(dmNew, pStart, pEnd);CHKERRQ(ierr); 3498*552f7358SJed Brown /* Step 2: Set cone and support sizes */ 3499*552f7358SJed Brown for(d = 0; d <= depth; ++d) { 3500*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 3501*552f7358SJed Brown for(p = pStart; p < pEnd; ++p) { 3502*552f7358SJed Brown PetscInt newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3503*552f7358SJed Brown PetscInt size; 3504*552f7358SJed Brown 3505*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3506*552f7358SJed Brown ierr = DMPlexSetConeSize(dmNew, newp, size);CHKERRQ(ierr); 3507*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3508*552f7358SJed Brown ierr = DMPlexSetSupportSize(dmNew, newp, size);CHKERRQ(ierr); 3509*552f7358SJed Brown } 3510*552f7358SJed Brown } 3511*552f7358SJed Brown ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3512*552f7358SJed Brown PetscFunctionReturn(0); 3513*552f7358SJed Brown } 3514*552f7358SJed Brown 3515*552f7358SJed Brown #undef __FUNCT__ 3516*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftPoints_Private" 3517*552f7358SJed Brown PetscErrorCode DMPlexShiftPoints_Private(DM dm, PetscInt depthShift[], DM dmNew) 3518*552f7358SJed Brown { 3519*552f7358SJed Brown PetscInt *depthEnd, *newpoints; 3520*552f7358SJed Brown PetscInt depth = 0, d, maxConeSize, maxSupportSize, pStart, pEnd, p; 3521*552f7358SJed Brown PetscErrorCode ierr; 3522*552f7358SJed Brown 3523*552f7358SJed Brown PetscFunctionBegin; 3524*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3525*552f7358SJed Brown if (depth < 0) PetscFunctionReturn(0); 3526*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 3527*552f7358SJed Brown ierr = PetscMalloc2(depth+1,PetscInt,&depthEnd,PetscMax(maxConeSize, maxSupportSize),PetscInt,&newpoints);CHKERRQ(ierr); 3528*552f7358SJed Brown for(d = 0; d <= depth; ++d) { 3529*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3530*552f7358SJed Brown } 3531*552f7358SJed Brown /* Step 5: Set cones and supports */ 3532*552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3533*552f7358SJed Brown for(p = pStart; p < pEnd; ++p) { 3534*552f7358SJed Brown const PetscInt *points = PETSC_NULL, *orientations = PETSC_NULL; 3535*552f7358SJed Brown PetscInt size, i, newp = DMPlexShiftPoint_Private(p, depth, depthEnd, depthShift); 3536*552f7358SJed Brown 3537*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, p, &size);CHKERRQ(ierr); 3538*552f7358SJed Brown ierr = DMPlexGetCone(dm, p, &points);CHKERRQ(ierr); 3539*552f7358SJed Brown ierr = DMPlexGetConeOrientation(dm, p, &orientations);CHKERRQ(ierr); 3540*552f7358SJed Brown for(i = 0; i < size; ++i) { 3541*552f7358SJed Brown newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3542*552f7358SJed Brown } 3543*552f7358SJed Brown ierr = DMPlexSetCone(dmNew, newp, newpoints);CHKERRQ(ierr); 3544*552f7358SJed Brown ierr = DMPlexSetConeOrientation(dmNew, newp, orientations);CHKERRQ(ierr); 3545*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, p, &size);CHKERRQ(ierr); 3546*552f7358SJed Brown ierr = DMPlexGetSupport(dm, p, &points);CHKERRQ(ierr); 3547*552f7358SJed Brown for(i = 0; i < size; ++i) { 3548*552f7358SJed Brown newpoints[i] = DMPlexShiftPoint_Private(points[i], depth, depthEnd, depthShift); 3549*552f7358SJed Brown } 3550*552f7358SJed Brown ierr = DMPlexSetSupport(dmNew, newp, newpoints);CHKERRQ(ierr); 3551*552f7358SJed Brown } 3552*552f7358SJed Brown ierr = PetscFree2(depthEnd,newpoints);CHKERRQ(ierr); 3553*552f7358SJed Brown PetscFunctionReturn(0); 3554*552f7358SJed Brown } 3555*552f7358SJed Brown 3556*552f7358SJed Brown #undef __FUNCT__ 3557*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftCoordinates_Private" 3558*552f7358SJed Brown PetscErrorCode DMPlexShiftCoordinates_Private(DM dm, PetscInt depthShift[], DM dmNew) 3559*552f7358SJed Brown { 3560*552f7358SJed Brown PetscSection coordSection, newCoordSection; 3561*552f7358SJed Brown Vec coordinates; 3562*552f7358SJed Brown PetscInt *depthEnd; 3563*552f7358SJed Brown PetscInt dim, depth = 0, d, vStart, vEnd, v; 3564*552f7358SJed Brown PetscErrorCode ierr; 3565*552f7358SJed Brown 3566*552f7358SJed Brown PetscFunctionBegin; 3567*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3568*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3569*552f7358SJed Brown ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3570*552f7358SJed Brown for(d = 0; d <= depth; ++d) { 3571*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3572*552f7358SJed Brown } 3573*552f7358SJed Brown /* Step 8: Convert coordinates */ 3574*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3575*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 3576*552f7358SJed Brown ierr = PetscSectionCreate(((PetscObject) dm)->comm, &newCoordSection);CHKERRQ(ierr); 3577*552f7358SJed Brown ierr = PetscSectionSetNumFields(newCoordSection, 1);CHKERRQ(ierr); 3578*552f7358SJed Brown ierr = PetscSectionSetFieldComponents(newCoordSection, 0, dim);CHKERRQ(ierr); 3579*552f7358SJed Brown ierr = PetscSectionSetChart(newCoordSection, DMPlexShiftPoint_Private(vStart, depth, depthEnd, depthShift), DMPlexShiftPoint_Private(vEnd, depth, depthEnd, depthShift));CHKERRQ(ierr); 3580*552f7358SJed Brown for(v = vStart; v < vEnd; ++v) { 3581*552f7358SJed Brown const PetscInt newv = DMPlexShiftPoint_Private(v, depth, depthEnd, depthShift); 3582*552f7358SJed Brown ierr = PetscSectionSetDof(newCoordSection, newv, dim);CHKERRQ(ierr); 3583*552f7358SJed Brown ierr = PetscSectionSetFieldDof(newCoordSection, newv, 0, dim);CHKERRQ(ierr); 3584*552f7358SJed Brown } 3585*552f7358SJed Brown ierr = PetscSectionSetUp(newCoordSection);CHKERRQ(ierr); 3586*552f7358SJed Brown ierr = DMPlexSetCoordinateSection(dmNew, newCoordSection);CHKERRQ(ierr); 3587*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 3588*552f7358SJed Brown ierr = DMSetCoordinatesLocal(dmNew, coordinates);CHKERRQ(ierr); 3589*552f7358SJed Brown ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3590*552f7358SJed Brown PetscFunctionReturn(0); 3591*552f7358SJed Brown } 3592*552f7358SJed Brown 3593*552f7358SJed Brown #undef __FUNCT__ 3594*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftSF_Private" 3595*552f7358SJed Brown PetscErrorCode DMPlexShiftSF_Private(DM dm, PetscInt depthShift[], DM dmNew) 3596*552f7358SJed Brown { 3597*552f7358SJed Brown PetscInt *depthEnd; 3598*552f7358SJed Brown PetscInt depth = 0, d; 3599*552f7358SJed Brown PetscSF sfPoint, sfPointNew; 3600*552f7358SJed Brown const PetscSFNode *remotePoints; 3601*552f7358SJed Brown PetscSFNode *gremotePoints; 3602*552f7358SJed Brown const PetscInt *localPoints; 3603*552f7358SJed Brown PetscInt *glocalPoints, *newLocation, *newRemoteLocation; 3604*552f7358SJed Brown PetscInt numRoots, numLeaves, l, pStart, pEnd, totShift = 0; 3605*552f7358SJed Brown PetscMPIInt numProcs; 3606*552f7358SJed Brown PetscErrorCode ierr; 3607*552f7358SJed Brown 3608*552f7358SJed Brown PetscFunctionBegin; 3609*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3610*552f7358SJed Brown ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3611*552f7358SJed Brown for(d = 0; d <= depth; ++d) { 3612*552f7358SJed Brown totShift += depthShift[d]; 3613*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3614*552f7358SJed Brown } 3615*552f7358SJed Brown /* Step 9: Convert pointSF */ 3616*552f7358SJed Brown ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 3617*552f7358SJed Brown ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3618*552f7358SJed Brown ierr = DMGetPointSF(dmNew, &sfPointNew);CHKERRQ(ierr); 3619*552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 3620*552f7358SJed Brown ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 3621*552f7358SJed Brown if (numRoots >= 0) { 3622*552f7358SJed Brown ierr = PetscMalloc2(numRoots,PetscInt,&newLocation,pEnd-pStart,PetscInt,&newRemoteLocation);CHKERRQ(ierr); 3623*552f7358SJed Brown for(l=0; l<numRoots; l++) newLocation[l] = DMPlexShiftPoint_Private(l, depth, depthEnd, depthShift); 3624*552f7358SJed Brown ierr = PetscSFBcastBegin(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3625*552f7358SJed Brown ierr = PetscSFBcastEnd(sfPoint, MPIU_INT, newLocation, newRemoteLocation);CHKERRQ(ierr); 3626*552f7358SJed Brown ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &glocalPoints);CHKERRQ(ierr); 3627*552f7358SJed Brown ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &gremotePoints);CHKERRQ(ierr); 3628*552f7358SJed Brown for(l = 0; l < numLeaves; ++l) { 3629*552f7358SJed Brown glocalPoints[l] = DMPlexShiftPoint_Private(localPoints[l], depth, depthEnd, depthShift); 3630*552f7358SJed Brown gremotePoints[l].rank = remotePoints[l].rank; 3631*552f7358SJed Brown gremotePoints[l].index = newRemoteLocation[localPoints[l]]; 3632*552f7358SJed Brown } 3633*552f7358SJed Brown ierr = PetscFree2(newLocation,newRemoteLocation);CHKERRQ(ierr); 3634*552f7358SJed Brown ierr = PetscSFSetGraph(sfPointNew, numRoots + totShift, numLeaves, glocalPoints, PETSC_OWN_POINTER, gremotePoints, PETSC_OWN_POINTER);CHKERRQ(ierr); 3635*552f7358SJed Brown } 3636*552f7358SJed Brown ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3637*552f7358SJed Brown PetscFunctionReturn(0); 3638*552f7358SJed Brown } 3639*552f7358SJed Brown 3640*552f7358SJed Brown #undef __FUNCT__ 3641*552f7358SJed Brown #define __FUNCT__ "DMPlexShiftLabels_Private" 3642*552f7358SJed Brown PetscErrorCode DMPlexShiftLabels_Private(DM dm, PetscInt depthShift[], DM dmNew) 3643*552f7358SJed Brown { 3644*552f7358SJed Brown PetscSF sfPoint; 3645*552f7358SJed Brown DMLabel vtkLabel, ghostLabel; 3646*552f7358SJed Brown PetscInt *depthEnd; 3647*552f7358SJed Brown const PetscSFNode *leafRemote; 3648*552f7358SJed Brown const PetscInt *leafLocal; 3649*552f7358SJed Brown PetscInt depth = 0, d, numLeaves, numLabels, l, cStart, cEnd, c, fStart, fEnd, f; 3650*552f7358SJed Brown PetscMPIInt rank; 3651*552f7358SJed Brown PetscErrorCode ierr; 3652*552f7358SJed Brown 3653*552f7358SJed Brown PetscFunctionBegin; 3654*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3655*552f7358SJed Brown ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthEnd);CHKERRQ(ierr); 3656*552f7358SJed Brown for(d = 0; d <= depth; ++d) { 3657*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, PETSC_NULL, &depthEnd[d]);CHKERRQ(ierr); 3658*552f7358SJed Brown } 3659*552f7358SJed Brown /* Step 10: Convert labels */ 3660*552f7358SJed Brown ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 3661*552f7358SJed Brown for(l = 0; l < numLabels; ++l) { 3662*552f7358SJed Brown DMLabel label, newlabel; 3663*552f7358SJed Brown const char *lname; 3664*552f7358SJed Brown PetscBool isDepth; 3665*552f7358SJed Brown IS valueIS; 3666*552f7358SJed Brown const PetscInt *values; 3667*552f7358SJed Brown PetscInt numValues, val; 3668*552f7358SJed Brown 3669*552f7358SJed Brown ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 3670*552f7358SJed Brown ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 3671*552f7358SJed Brown if (isDepth) continue; 3672*552f7358SJed Brown ierr = DMPlexCreateLabel(dmNew, lname);CHKERRQ(ierr); 3673*552f7358SJed Brown ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 3674*552f7358SJed Brown ierr = DMPlexGetLabel(dmNew, lname, &newlabel);CHKERRQ(ierr); 3675*552f7358SJed Brown ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3676*552f7358SJed Brown ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 3677*552f7358SJed Brown ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3678*552f7358SJed Brown for(val = 0; val < numValues; ++val) { 3679*552f7358SJed Brown IS pointIS; 3680*552f7358SJed Brown const PetscInt *points; 3681*552f7358SJed Brown PetscInt numPoints, p; 3682*552f7358SJed Brown 3683*552f7358SJed Brown ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 3684*552f7358SJed Brown ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 3685*552f7358SJed Brown ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 3686*552f7358SJed Brown for(p = 0; p < numPoints; ++p) { 3687*552f7358SJed Brown const PetscInt newpoint = DMPlexShiftPoint_Private(points[p], depth, depthEnd, depthShift); 3688*552f7358SJed Brown 3689*552f7358SJed Brown ierr = DMLabelSetValue(newlabel, newpoint, values[val]);CHKERRQ(ierr); 3690*552f7358SJed Brown } 3691*552f7358SJed Brown ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 3692*552f7358SJed Brown ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 3693*552f7358SJed Brown } 3694*552f7358SJed Brown ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3695*552f7358SJed Brown ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3696*552f7358SJed Brown } 3697*552f7358SJed Brown ierr = PetscFree(depthEnd);CHKERRQ(ierr); 3698*552f7358SJed Brown /* Step 11: Make label for output (vtk) and to mark ghost points (ghost) */ 3699*552f7358SJed Brown ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 3700*552f7358SJed Brown ierr = DMGetPointSF(dm, &sfPoint);CHKERRQ(ierr); 3701*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3702*552f7358SJed Brown ierr = PetscSFGetGraph(sfPoint, PETSC_NULL, &numLeaves, &leafLocal, &leafRemote);CHKERRQ(ierr); 3703*552f7358SJed Brown ierr = DMPlexCreateLabel(dmNew, "vtk");CHKERRQ(ierr); 3704*552f7358SJed Brown ierr = DMPlexCreateLabel(dmNew, "ghost");CHKERRQ(ierr); 3705*552f7358SJed Brown ierr = DMPlexGetLabel(dmNew, "vtk", &vtkLabel);CHKERRQ(ierr); 3706*552f7358SJed Brown ierr = DMPlexGetLabel(dmNew, "ghost", &ghostLabel);CHKERRQ(ierr); 3707*552f7358SJed Brown for(l = 0, c = cStart; l < numLeaves && c < cEnd; ++l, ++c) { 3708*552f7358SJed Brown for(; c < leafLocal[l] && c < cEnd; ++c) { 3709*552f7358SJed Brown ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3710*552f7358SJed Brown } 3711*552f7358SJed Brown if (leafLocal[l] >= cEnd) break; 3712*552f7358SJed Brown if (leafRemote[l].rank == rank) { 3713*552f7358SJed Brown ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3714*552f7358SJed Brown } else { 3715*552f7358SJed Brown ierr = DMLabelSetValue(ghostLabel, c, 2);CHKERRQ(ierr); 3716*552f7358SJed Brown } 3717*552f7358SJed Brown } 3718*552f7358SJed Brown for(; c < cEnd; ++c) { 3719*552f7358SJed Brown ierr = DMLabelSetValue(vtkLabel, c, 1);CHKERRQ(ierr); 3720*552f7358SJed Brown } 3721*552f7358SJed Brown if (0) { 3722*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3723*552f7358SJed Brown ierr = DMLabelView(vtkLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3724*552f7358SJed Brown ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3725*552f7358SJed Brown } 3726*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dmNew, 1, &fStart, &fEnd);CHKERRQ(ierr); 3727*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 3728*552f7358SJed Brown PetscInt numCells; 3729*552f7358SJed Brown 3730*552f7358SJed Brown ierr = DMPlexGetSupportSize(dmNew, f, &numCells);CHKERRQ(ierr); 3731*552f7358SJed Brown if (numCells < 2) { 3732*552f7358SJed Brown ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr); 3733*552f7358SJed Brown } else { 3734*552f7358SJed Brown const PetscInt *cells = PETSC_NULL; 3735*552f7358SJed Brown PetscInt vA, vB; 3736*552f7358SJed Brown 3737*552f7358SJed Brown ierr = DMPlexGetSupport(dmNew, f, &cells);CHKERRQ(ierr); 3738*552f7358SJed Brown ierr = DMLabelGetValue(vtkLabel, cells[0], &vA);CHKERRQ(ierr); 3739*552f7358SJed Brown ierr = DMLabelGetValue(vtkLabel, cells[1], &vB);CHKERRQ(ierr); 3740*552f7358SJed Brown if (!vA && !vB) {ierr = DMLabelSetValue(ghostLabel, f, 1);CHKERRQ(ierr);} 3741*552f7358SJed Brown } 3742*552f7358SJed Brown } 3743*552f7358SJed Brown if (0) { 3744*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 3745*552f7358SJed Brown ierr = DMLabelView(ghostLabel, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3746*552f7358SJed Brown ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 3747*552f7358SJed Brown } 3748*552f7358SJed Brown PetscFunctionReturn(0); 3749*552f7358SJed Brown } 3750*552f7358SJed Brown 3751*552f7358SJed Brown #undef __FUNCT__ 3752*552f7358SJed Brown #define __FUNCT__ "DMPlexConstructGhostCells_2D" 3753*552f7358SJed Brown /*@C 3754*552f7358SJed Brown DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3755*552f7358SJed Brown 3756*552f7358SJed Brown Collective on dm 3757*552f7358SJed Brown 3758*552f7358SJed Brown Input Parameters: 3759*552f7358SJed Brown + dm - The original DM 3760*552f7358SJed Brown - labelName - The label specifying the boundary faces (this could be auto-generated) 3761*552f7358SJed Brown 3762*552f7358SJed Brown Output Parameters: 3763*552f7358SJed Brown + numGhostCells - The number of ghost cells added to the DM 3764*552f7358SJed Brown - dmGhosted - The new DM 3765*552f7358SJed Brown 3766*552f7358SJed Brown Level: developer 3767*552f7358SJed Brown 3768*552f7358SJed Brown .seealso: DMCreate() 3769*552f7358SJed Brown */ 3770*552f7358SJed Brown PetscErrorCode DMPlexConstructGhostCells_2D(DM dm, const char labelName[], PetscInt *numGhostCells, DM gdm) 3771*552f7358SJed Brown { 3772*552f7358SJed Brown DMLabel label; 3773*552f7358SJed Brown IS valueIS; 3774*552f7358SJed Brown const PetscInt *values; 3775*552f7358SJed Brown PetscInt *depthShift; 3776*552f7358SJed Brown PetscInt depth = 0, numFS, fs, ghostCell, cEnd, c; 3777*552f7358SJed Brown PetscErrorCode ierr; 3778*552f7358SJed Brown 3779*552f7358SJed Brown PetscFunctionBegin; 3780*552f7358SJed Brown /* Count ghost cells */ 3781*552f7358SJed Brown ierr = DMPlexGetLabel(dm, labelName ? labelName : "Face Sets", &label);CHKERRQ(ierr); 3782*552f7358SJed Brown ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 3783*552f7358SJed Brown ierr = ISGetLocalSize(valueIS, &numFS);CHKERRQ(ierr); 3784*552f7358SJed Brown ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 3785*552f7358SJed Brown *numGhostCells = 0; 3786*552f7358SJed Brown for(fs = 0; fs < numFS; ++fs) { 3787*552f7358SJed Brown PetscInt numBdFaces; 3788*552f7358SJed Brown 3789*552f7358SJed Brown ierr = DMLabelGetStratumSize(label, values[fs], &numBdFaces);CHKERRQ(ierr); 3790*552f7358SJed Brown *numGhostCells += numBdFaces; 3791*552f7358SJed Brown } 3792*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3793*552f7358SJed Brown ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthShift);CHKERRQ(ierr); 3794*552f7358SJed Brown ierr = PetscMemzero(depthShift, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 3795*552f7358SJed Brown if (depth >= 0) {depthShift[depth] = *numGhostCells;} 3796*552f7358SJed Brown ierr = DMPlexShiftSizes_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3797*552f7358SJed Brown /* Step 3: Set cone/support sizes for new points */ 3798*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, PETSC_NULL, &cEnd);CHKERRQ(ierr); 3799*552f7358SJed Brown for(c = cEnd; c < cEnd + *numGhostCells; ++c) { 3800*552f7358SJed Brown ierr = DMPlexSetConeSize(gdm, c, 1);CHKERRQ(ierr); 3801*552f7358SJed Brown } 3802*552f7358SJed Brown for(fs = 0; fs < numFS; ++fs) { 3803*552f7358SJed Brown IS faceIS; 3804*552f7358SJed Brown const PetscInt *faces; 3805*552f7358SJed Brown PetscInt numFaces, f; 3806*552f7358SJed Brown 3807*552f7358SJed Brown ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3808*552f7358SJed Brown ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3809*552f7358SJed Brown ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3810*552f7358SJed Brown for(f = 0; f < numFaces; ++f) { 3811*552f7358SJed Brown PetscInt size; 3812*552f7358SJed Brown 3813*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, faces[f], &size);CHKERRQ(ierr); 3814*552f7358SJed Brown if (size != 1) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "DM has boundary face %d with %d support cells", faces[f], size); 3815*552f7358SJed Brown ierr = DMPlexSetSupportSize(gdm, faces[f] + *numGhostCells, 2);CHKERRQ(ierr); 3816*552f7358SJed Brown } 3817*552f7358SJed Brown ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3818*552f7358SJed Brown ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3819*552f7358SJed Brown } 3820*552f7358SJed Brown /* Step 4: Setup ghosted DM */ 3821*552f7358SJed Brown ierr = DMSetUp(gdm);CHKERRQ(ierr); 3822*552f7358SJed Brown ierr = DMPlexShiftPoints_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3823*552f7358SJed Brown /* Step 6: Set cones and supports for new points */ 3824*552f7358SJed Brown ghostCell = cEnd; 3825*552f7358SJed Brown for(fs = 0; fs < numFS; ++fs) { 3826*552f7358SJed Brown IS faceIS; 3827*552f7358SJed Brown const PetscInt *faces; 3828*552f7358SJed Brown PetscInt numFaces, f; 3829*552f7358SJed Brown 3830*552f7358SJed Brown ierr = DMLabelGetStratumIS(label, values[fs], &faceIS);CHKERRQ(ierr); 3831*552f7358SJed Brown ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 3832*552f7358SJed Brown ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 3833*552f7358SJed Brown for(f = 0; f < numFaces; ++f, ++ghostCell) { 3834*552f7358SJed Brown PetscInt newFace = faces[f] + *numGhostCells; 3835*552f7358SJed Brown 3836*552f7358SJed Brown ierr = DMPlexSetCone(gdm, ghostCell, &newFace);CHKERRQ(ierr); 3837*552f7358SJed Brown ierr = DMPlexInsertSupport(gdm, newFace, 1, ghostCell);CHKERRQ(ierr); 3838*552f7358SJed Brown } 3839*552f7358SJed Brown ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 3840*552f7358SJed Brown ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 3841*552f7358SJed Brown } 3842*552f7358SJed Brown ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 3843*552f7358SJed Brown ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 3844*552f7358SJed Brown /* Step 7: Stratify */ 3845*552f7358SJed Brown ierr = DMPlexStratify(gdm);CHKERRQ(ierr); 3846*552f7358SJed Brown ierr = DMPlexShiftCoordinates_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3847*552f7358SJed Brown ierr = DMPlexShiftSF_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3848*552f7358SJed Brown ierr = DMPlexShiftLabels_Private(dm, depthShift, gdm);CHKERRQ(ierr); 3849*552f7358SJed Brown ierr = PetscFree(depthShift);CHKERRQ(ierr); 3850*552f7358SJed Brown PetscFunctionReturn(0); 3851*552f7358SJed Brown } 3852*552f7358SJed Brown 3853*552f7358SJed Brown #undef __FUNCT__ 3854*552f7358SJed Brown #define __FUNCT__ "DMPlexConstructGhostCells" 3855*552f7358SJed Brown /*@C 3856*552f7358SJed Brown DMPlexConstructGhostCells - Construct ghost cells which connect to every boundary face 3857*552f7358SJed Brown 3858*552f7358SJed Brown Collective on dm 3859*552f7358SJed Brown 3860*552f7358SJed Brown Input Parameters: 3861*552f7358SJed Brown + dm - The original DM 3862*552f7358SJed Brown - labelName - The label specifying the boundary faces (this could be auto-generated) 3863*552f7358SJed Brown 3864*552f7358SJed Brown Output Parameters: 3865*552f7358SJed Brown + numGhostCells - The number of ghost cells added to the DM 3866*552f7358SJed Brown - dmGhosted - The new DM 3867*552f7358SJed Brown 3868*552f7358SJed Brown Level: developer 3869*552f7358SJed Brown 3870*552f7358SJed Brown .seealso: DMCreate() 3871*552f7358SJed Brown */ 3872*552f7358SJed Brown PetscErrorCode DMPlexConstructGhostCells(DM dm, const char labelName[], PetscInt *numGhostCells, DM *dmGhosted) 3873*552f7358SJed Brown { 3874*552f7358SJed Brown DM gdm; 3875*552f7358SJed Brown PetscInt dim; 3876*552f7358SJed Brown PetscErrorCode ierr; 3877*552f7358SJed Brown 3878*552f7358SJed Brown PetscFunctionBegin; 3879*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3880*552f7358SJed Brown PetscValidPointer(numGhostCells, 3); 3881*552f7358SJed Brown PetscValidPointer(dmGhosted, 4); 3882*552f7358SJed Brown ierr = DMCreate(((PetscObject) dm)->comm, &gdm);CHKERRQ(ierr); 3883*552f7358SJed Brown ierr = DMSetType(gdm, DMPLEX);CHKERRQ(ierr); 3884*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3885*552f7358SJed Brown ierr = DMPlexSetDimension(gdm, dim);CHKERRQ(ierr); 3886*552f7358SJed Brown switch(dim) { 3887*552f7358SJed Brown case 2: 3888*552f7358SJed Brown ierr = DMPlexConstructGhostCells_2D(dm, labelName, numGhostCells, gdm);CHKERRQ(ierr); 3889*552f7358SJed Brown break; 3890*552f7358SJed Brown default: 3891*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot construct ghost cells for dimension %d", dim); 3892*552f7358SJed Brown } 3893*552f7358SJed Brown ierr = DMSetFromOptions(gdm);CHKERRQ(ierr); 3894*552f7358SJed Brown *dmGhosted = gdm; 3895*552f7358SJed Brown PetscFunctionReturn(0); 3896*552f7358SJed Brown } 3897*552f7358SJed Brown 3898*552f7358SJed Brown #undef __FUNCT__ 3899*552f7358SJed Brown #define __FUNCT__ "DMPlexInterpolate_2D" 3900*552f7358SJed Brown PetscErrorCode DMPlexInterpolate_2D(DM dm, DM *dmInt) 3901*552f7358SJed Brown { 3902*552f7358SJed Brown DM idm; 3903*552f7358SJed Brown DM_Plex *mesh; 3904*552f7358SJed Brown PetscHashIJ edgeTable; 3905*552f7358SJed Brown PetscInt *off; 3906*552f7358SJed Brown PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 3907*552f7358SJed Brown PetscInt numEdges, firstEdge, edge, e; 3908*552f7358SJed Brown PetscErrorCode ierr; 3909*552f7358SJed Brown 3910*552f7358SJed Brown PetscFunctionBegin; 3911*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 3912*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 3913*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 3914*552f7358SJed Brown numCells = cEnd - cStart; 3915*552f7358SJed Brown numVertices = vEnd - vStart; 3916*552f7358SJed Brown firstEdge = numCells + numVertices; 3917*552f7358SJed Brown numEdges = 0 ; 3918*552f7358SJed Brown /* Count edges using algorithm from CreateNeighborCSR */ 3919*552f7358SJed Brown ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 3920*552f7358SJed Brown if (off) { 3921*552f7358SJed Brown PetscInt numCorners = 0; 3922*552f7358SJed Brown 3923*552f7358SJed Brown numEdges = off[numCells]/2; 3924*552f7358SJed Brown #if 0 3925*552f7358SJed Brown /* Account for boundary edges: \sum_c 3 - neighbors = 3*numCells - totalNeighbors */ 3926*552f7358SJed Brown numEdges += 3*numCells - off[numCells]; 3927*552f7358SJed Brown #else 3928*552f7358SJed Brown /* Account for boundary edges: \sum_c #faces - #neighbors = \sum_c #cellVertices - #neighbors = totalCorners - totalNeighbors */ 3929*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 3930*552f7358SJed Brown PetscInt coneSize; 3931*552f7358SJed Brown 3932*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 3933*552f7358SJed Brown numCorners += coneSize; 3934*552f7358SJed Brown } 3935*552f7358SJed Brown numEdges += numCorners - off[numCells]; 3936*552f7358SJed Brown #endif 3937*552f7358SJed Brown } 3938*552f7358SJed Brown #if 0 3939*552f7358SJed Brown /* Check Euler characteristic V - E + F = 1 */ 3940*552f7358SJed Brown if (numVertices && (numVertices-numEdges+numCells != 1)) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Euler characteristic of mesh is %d != 1", numVertices-numEdges+numCells); 3941*552f7358SJed Brown #endif 3942*552f7358SJed Brown /* Create interpolated mesh */ 3943*552f7358SJed Brown ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 3944*552f7358SJed Brown ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 3945*552f7358SJed Brown ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 3946*552f7358SJed Brown ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numEdges);CHKERRQ(ierr); 3947*552f7358SJed Brown for (c = 0; c < numCells; ++c) { 3948*552f7358SJed Brown PetscInt numCorners; 3949*552f7358SJed Brown 3950*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, c, &numCorners);CHKERRQ(ierr); 3951*552f7358SJed Brown ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 3952*552f7358SJed Brown } 3953*552f7358SJed Brown for (e = firstEdge; e < firstEdge+numEdges; ++e) { 3954*552f7358SJed Brown ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 3955*552f7358SJed Brown } 3956*552f7358SJed Brown ierr = DMSetUp(idm);CHKERRQ(ierr); 3957*552f7358SJed Brown /* Get edge cones from subsets of cell vertices */ 3958*552f7358SJed Brown ierr = PetscHashIJCreate(&edgeTable);CHKERRQ(ierr); 3959*552f7358SJed Brown ierr = PetscHashIJSetMultivalued(edgeTable, PETSC_FALSE);CHKERRQ(ierr); 3960*552f7358SJed Brown 3961*552f7358SJed Brown for (c = 0, edge = firstEdge; c < numCells; ++c) { 3962*552f7358SJed Brown const PetscInt *cellFaces; 3963*552f7358SJed Brown PetscInt numCellFaces, faceSize, cf; 3964*552f7358SJed Brown 3965*552f7358SJed Brown ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 3966*552f7358SJed Brown if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 3967*552f7358SJed Brown for (cf = 0; cf < numCellFaces; ++cf) { 3968*552f7358SJed Brown #if 1 3969*552f7358SJed Brown PetscHashIJKey key = {PetscMin(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1]), 3970*552f7358SJed Brown PetscMax(cellFaces[cf*faceSize+0], cellFaces[cf*faceSize+1])}; 3971*552f7358SJed Brown 3972*552f7358SJed Brown ierr = PetscHashIJGet(edgeTable, key, &e);CHKERRQ(ierr); 3973*552f7358SJed Brown if (e < 0) { 3974*552f7358SJed Brown ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3975*552f7358SJed Brown ierr = PetscHashIJAdd(edgeTable, key, edge);CHKERRQ(ierr); 3976*552f7358SJed Brown e = edge++; 3977*552f7358SJed Brown } 3978*552f7358SJed Brown #else 3979*552f7358SJed Brown PetscBool found = PETSC_FALSE; 3980*552f7358SJed Brown 3981*552f7358SJed Brown /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 3982*552f7358SJed Brown for (e = firstEdge; e < edge; ++e) { 3983*552f7358SJed Brown const PetscInt *cone; 3984*552f7358SJed Brown 3985*552f7358SJed Brown ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 3986*552f7358SJed Brown if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 3987*552f7358SJed Brown ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 3988*552f7358SJed Brown found = PETSC_TRUE; 3989*552f7358SJed Brown break; 3990*552f7358SJed Brown } 3991*552f7358SJed Brown } 3992*552f7358SJed Brown if (!found) { 3993*552f7358SJed Brown ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 3994*552f7358SJed Brown ++edge; 3995*552f7358SJed Brown } 3996*552f7358SJed Brown #endif 3997*552f7358SJed Brown ierr = DMPlexInsertCone(idm, c, cf, e);CHKERRQ(ierr); 3998*552f7358SJed Brown } 3999*552f7358SJed Brown } 4000*552f7358SJed Brown if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4001*552f7358SJed Brown ierr = PetscHashIJDestroy(&edgeTable);CHKERRQ(ierr); 4002*552f7358SJed Brown ierr = PetscFree(off);CHKERRQ(ierr); 4003*552f7358SJed Brown ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4004*552f7358SJed Brown ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4005*552f7358SJed Brown mesh = (DM_Plex *) (idm)->data; 4006*552f7358SJed Brown /* Orient edges */ 4007*552f7358SJed Brown for (c = 0; c < numCells; ++c) { 4008*552f7358SJed Brown const PetscInt *cone = PETSC_NULL, *cellFaces; 4009*552f7358SJed Brown PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4010*552f7358SJed Brown 4011*552f7358SJed Brown ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4012*552f7358SJed Brown ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4013*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4014*552f7358SJed Brown ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4015*552f7358SJed Brown if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4016*552f7358SJed Brown for (cf = 0; cf < numCellFaces; ++cf) { 4017*552f7358SJed Brown const PetscInt *econe = PETSC_NULL; 4018*552f7358SJed Brown PetscInt esize; 4019*552f7358SJed Brown 4020*552f7358SJed Brown ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4021*552f7358SJed Brown ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4022*552f7358SJed Brown if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4023*552f7358SJed Brown if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4024*552f7358SJed Brown /* Correctly oriented */ 4025*552f7358SJed Brown mesh->coneOrientations[coff+cf] = 0; 4026*552f7358SJed Brown } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4027*552f7358SJed Brown /* Start at index 1, and reverse orientation */ 4028*552f7358SJed Brown mesh->coneOrientations[coff+cf] = -(1+1); 4029*552f7358SJed Brown } 4030*552f7358SJed Brown } 4031*552f7358SJed Brown } 4032*552f7358SJed Brown *dmInt = idm; 4033*552f7358SJed Brown PetscFunctionReturn(0); 4034*552f7358SJed Brown } 4035*552f7358SJed Brown 4036*552f7358SJed Brown #undef __FUNCT__ 4037*552f7358SJed Brown #define __FUNCT__ "DMPlexInterpolate_3D" 4038*552f7358SJed Brown PetscErrorCode DMPlexInterpolate_3D(DM dm, DM *dmInt) 4039*552f7358SJed Brown { 4040*552f7358SJed Brown DM idm, fdm; 4041*552f7358SJed Brown DM_Plex *mesh; 4042*552f7358SJed Brown PetscInt *off; 4043*552f7358SJed Brown const PetscInt numCorners = 4; 4044*552f7358SJed Brown PetscInt dim, numCells, cStart, cEnd, c, numVertices, vStart, vEnd; 4045*552f7358SJed Brown PetscInt numFaces, firstFace, face, f, numEdges, firstEdge, edge, e; 4046*552f7358SJed Brown PetscErrorCode ierr; 4047*552f7358SJed Brown 4048*552f7358SJed Brown PetscFunctionBegin; 4049*552f7358SJed Brown { 4050*552f7358SJed Brown ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4051*552f7358SJed Brown ierr = DMView(dm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4052*552f7358SJed Brown ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4053*552f7358SJed Brown } 4054*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 4055*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4056*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4057*552f7358SJed Brown numCells = cEnd - cStart; 4058*552f7358SJed Brown numVertices = vEnd - vStart; 4059*552f7358SJed Brown firstFace = numCells + numVertices; 4060*552f7358SJed Brown numFaces = 0 ; 4061*552f7358SJed Brown /* Count faces using algorithm from CreateNeighborCSR */ 4062*552f7358SJed Brown ierr = DMPlexCreateNeighborCSR(dm, PETSC_NULL, &off, PETSC_NULL);CHKERRQ(ierr); 4063*552f7358SJed Brown if (off) { 4064*552f7358SJed Brown numFaces = off[numCells]/2; 4065*552f7358SJed Brown /* Account for boundary faces: \sum_c 4 - neighbors = 4*numCells - totalNeighbors */ 4066*552f7358SJed Brown numFaces += 4*numCells - off[numCells]; 4067*552f7358SJed Brown } 4068*552f7358SJed Brown /* Use Euler characteristic to get edges V - E + F - C = 1 */ 4069*552f7358SJed Brown firstEdge = firstFace + numFaces; 4070*552f7358SJed Brown numEdges = numVertices + numFaces - numCells - 1; 4071*552f7358SJed Brown /* Create interpolated mesh */ 4072*552f7358SJed Brown ierr = DMCreate(((PetscObject) dm)->comm, &idm);CHKERRQ(ierr); 4073*552f7358SJed Brown ierr = DMSetType(idm, DMPLEX);CHKERRQ(ierr); 4074*552f7358SJed Brown ierr = DMPlexSetDimension(idm, dim);CHKERRQ(ierr); 4075*552f7358SJed Brown ierr = DMPlexSetChart(idm, 0, numCells+numVertices+numFaces+numEdges);CHKERRQ(ierr); 4076*552f7358SJed Brown for (c = 0; c < numCells; ++c) { 4077*552f7358SJed Brown ierr = DMPlexSetConeSize(idm, c, numCorners);CHKERRQ(ierr); 4078*552f7358SJed Brown } 4079*552f7358SJed Brown for (f = firstFace; f < firstFace+numFaces; ++f) { 4080*552f7358SJed Brown ierr = DMPlexSetConeSize(idm, f, 3);CHKERRQ(ierr); 4081*552f7358SJed Brown } 4082*552f7358SJed Brown for (e = firstEdge; e < firstEdge+numEdges; ++e) { 4083*552f7358SJed Brown ierr = DMPlexSetConeSize(idm, e, 2);CHKERRQ(ierr); 4084*552f7358SJed Brown } 4085*552f7358SJed Brown ierr = DMSetUp(idm);CHKERRQ(ierr); 4086*552f7358SJed Brown /* Get face cones from subsets of cell vertices */ 4087*552f7358SJed Brown ierr = DMCreate(((PetscObject) dm)->comm, &fdm);CHKERRQ(ierr); 4088*552f7358SJed Brown ierr = DMSetType(fdm, DMPLEX);CHKERRQ(ierr); 4089*552f7358SJed Brown ierr = DMPlexSetDimension(fdm, dim);CHKERRQ(ierr); 4090*552f7358SJed Brown ierr = DMPlexSetChart(fdm, numCells, firstFace+numFaces);CHKERRQ(ierr); 4091*552f7358SJed Brown for (f = firstFace; f < firstFace+numFaces; ++f) { 4092*552f7358SJed Brown ierr = DMPlexSetConeSize(fdm, f, 3);CHKERRQ(ierr); 4093*552f7358SJed Brown } 4094*552f7358SJed Brown ierr = DMSetUp(fdm);CHKERRQ(ierr); 4095*552f7358SJed Brown for (c = 0, face = firstFace; c < numCells; ++c) { 4096*552f7358SJed Brown const PetscInt *cellFaces; 4097*552f7358SJed Brown PetscInt numCellFaces, faceSize, cf; 4098*552f7358SJed Brown 4099*552f7358SJed Brown ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4100*552f7358SJed Brown if (faceSize != 3) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Tetrahedra cannot have face of size %D", faceSize); 4101*552f7358SJed Brown for (cf = 0; cf < numCellFaces; ++cf) { 4102*552f7358SJed Brown PetscBool found = PETSC_FALSE; 4103*552f7358SJed Brown 4104*552f7358SJed Brown /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4105*552f7358SJed Brown for (f = firstFace; f < face; ++f) { 4106*552f7358SJed Brown const PetscInt *cone = PETSC_NULL; 4107*552f7358SJed Brown 4108*552f7358SJed Brown ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4109*552f7358SJed Brown if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[2])) || 4110*552f7358SJed Brown ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4111*552f7358SJed Brown ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4112*552f7358SJed Brown ((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[2]) && (cellFaces[cf*faceSize+2] == cone[1])) || 4113*552f7358SJed Brown ((cellFaces[cf*faceSize+0] == cone[2]) && (cellFaces[cf*faceSize+1] == cone[1]) && (cellFaces[cf*faceSize+2] == cone[0])) || 4114*552f7358SJed Brown ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]) && (cellFaces[cf*faceSize+2] == cone[2]))) { 4115*552f7358SJed Brown found = PETSC_TRUE; 4116*552f7358SJed Brown break; 4117*552f7358SJed Brown } 4118*552f7358SJed Brown } 4119*552f7358SJed Brown if (!found) { 4120*552f7358SJed Brown ierr = DMPlexSetCone(idm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4121*552f7358SJed Brown /* Save the vertices for orientation calculation */ 4122*552f7358SJed Brown ierr = DMPlexSetCone(fdm, face, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4123*552f7358SJed Brown ++face; 4124*552f7358SJed Brown } 4125*552f7358SJed Brown ierr = DMPlexInsertCone(idm, c, cf, f);CHKERRQ(ierr); 4126*552f7358SJed Brown } 4127*552f7358SJed Brown } 4128*552f7358SJed Brown if (face != firstFace+numFaces) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of faces %D should be %D", face-firstFace, numFaces); 4129*552f7358SJed Brown /* Get edge cones from subsets of face vertices */ 4130*552f7358SJed Brown for (f = firstFace, edge = firstEdge; f < firstFace+numFaces; ++f) { 4131*552f7358SJed Brown const PetscInt *cellFaces; 4132*552f7358SJed Brown PetscInt numCellFaces, faceSize, cf; 4133*552f7358SJed Brown 4134*552f7358SJed Brown ierr = DMPlexGetFaces(idm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4135*552f7358SJed Brown if (faceSize != 2) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Triangles cannot have face of size %D", faceSize); 4136*552f7358SJed Brown for (cf = 0; cf < numCellFaces; ++cf) { 4137*552f7358SJed Brown PetscBool found = PETSC_FALSE; 4138*552f7358SJed Brown 4139*552f7358SJed Brown /* TODO Need join of vertices to check for existence of edges, which needs support (could set edge support), so just brute force for now */ 4140*552f7358SJed Brown for (e = firstEdge; e < edge; ++e) { 4141*552f7358SJed Brown const PetscInt *cone = PETSC_NULL; 4142*552f7358SJed Brown 4143*552f7358SJed Brown ierr = DMPlexGetCone(idm, e, &cone);CHKERRQ(ierr); 4144*552f7358SJed Brown if (((cellFaces[cf*faceSize+0] == cone[0]) && (cellFaces[cf*faceSize+1] == cone[1])) || 4145*552f7358SJed Brown ((cellFaces[cf*faceSize+0] == cone[1]) && (cellFaces[cf*faceSize+1] == cone[0]))) { 4146*552f7358SJed Brown found = PETSC_TRUE; 4147*552f7358SJed Brown break; 4148*552f7358SJed Brown } 4149*552f7358SJed Brown } 4150*552f7358SJed Brown if (!found) { 4151*552f7358SJed Brown ierr = DMPlexSetCone(idm, edge, &cellFaces[cf*faceSize]);CHKERRQ(ierr); 4152*552f7358SJed Brown ++edge; 4153*552f7358SJed Brown } 4154*552f7358SJed Brown ierr = DMPlexInsertCone(idm, f, cf, e);CHKERRQ(ierr); 4155*552f7358SJed Brown } 4156*552f7358SJed Brown } 4157*552f7358SJed Brown if (edge != firstEdge+numEdges) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D should be %D", edge-firstEdge, numEdges); 4158*552f7358SJed Brown ierr = PetscFree(off);CHKERRQ(ierr); 4159*552f7358SJed Brown ierr = DMPlexSymmetrize(idm);CHKERRQ(ierr); 4160*552f7358SJed Brown ierr = DMPlexStratify(idm);CHKERRQ(ierr); 4161*552f7358SJed Brown mesh = (DM_Plex *) (idm)->data; 4162*552f7358SJed Brown /* Orient edges */ 4163*552f7358SJed Brown for (f = firstFace; f < firstFace+numFaces; ++f) { 4164*552f7358SJed Brown const PetscInt *cone, *cellFaces; 4165*552f7358SJed Brown PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4166*552f7358SJed Brown 4167*552f7358SJed Brown ierr = DMPlexGetConeSize(idm, f, &coneSize);CHKERRQ(ierr); 4168*552f7358SJed Brown ierr = DMPlexGetCone(idm, f, &cone);CHKERRQ(ierr); 4169*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, f, &coff);CHKERRQ(ierr); 4170*552f7358SJed Brown ierr = DMPlexGetFaces(fdm, f, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4171*552f7358SJed Brown if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for face %D should be %D", coneSize, f, numCellFaces); 4172*552f7358SJed Brown for (cf = 0; cf < numCellFaces; ++cf) { 4173*552f7358SJed Brown const PetscInt *econe; 4174*552f7358SJed Brown PetscInt esize; 4175*552f7358SJed Brown 4176*552f7358SJed Brown ierr = DMPlexGetConeSize(idm, cone[cf], &esize);CHKERRQ(ierr); 4177*552f7358SJed Brown ierr = DMPlexGetCone(idm, cone[cf], &econe);CHKERRQ(ierr); 4178*552f7358SJed Brown if (esize != 2) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edge endpoints %D for edge %D should be 2", esize, cone[cf]); 4179*552f7358SJed Brown if ((cellFaces[cf*faceSize+0] == econe[0]) && (cellFaces[cf*faceSize+1] == econe[1])) { 4180*552f7358SJed Brown /* Correctly oriented */ 4181*552f7358SJed Brown mesh->coneOrientations[coff+cf] = 0; 4182*552f7358SJed Brown } else if ((cellFaces[cf*faceSize+0] == econe[1]) && (cellFaces[cf*faceSize+1] == econe[0])) { 4183*552f7358SJed Brown /* Start at index 1, and reverse orientation */ 4184*552f7358SJed Brown mesh->coneOrientations[coff+cf] = -(1+1); 4185*552f7358SJed Brown } 4186*552f7358SJed Brown } 4187*552f7358SJed Brown } 4188*552f7358SJed Brown ierr = DMDestroy(&fdm);CHKERRQ(ierr); 4189*552f7358SJed Brown /* Orient faces */ 4190*552f7358SJed Brown for (c = 0; c < numCells; ++c) { 4191*552f7358SJed Brown const PetscInt *cone, *cellFaces; 4192*552f7358SJed Brown PetscInt coneSize, coff, numCellFaces, faceSize, cf; 4193*552f7358SJed Brown 4194*552f7358SJed Brown ierr = DMPlexGetConeSize(idm, c, &coneSize);CHKERRQ(ierr); 4195*552f7358SJed Brown ierr = DMPlexGetCone(idm, c, &cone);CHKERRQ(ierr); 4196*552f7358SJed Brown ierr = PetscSectionGetOffset(mesh->coneSection, c, &coff);CHKERRQ(ierr); 4197*552f7358SJed Brown ierr = DMPlexGetFaces(dm, c, &numCellFaces, &faceSize, &cellFaces);CHKERRQ(ierr); 4198*552f7358SJed Brown if (coneSize != numCellFaces) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid number of edges %D for cell %D should be %D", coneSize, c, numCellFaces); 4199*552f7358SJed Brown for (cf = 0; cf < numCellFaces; ++cf) { 4200*552f7358SJed Brown PetscInt *origClosure = PETSC_NULL, *closure; 4201*552f7358SJed Brown PetscInt closureSize, i; 4202*552f7358SJed Brown 4203*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4204*552f7358SJed Brown if (closureSize != 7) SETERRQ2(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure size %D for face %D should be 7", closureSize, cone[cf]); 4205*552f7358SJed Brown for (i = 4; i < 7; ++i) { 4206*552f7358SJed Brown if ((origClosure[i*2] < vStart) || (origClosure[i*2] >= vEnd)) SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Invalid closure point %D should be a vertex in [%D, %D)", origClosure[i*2], vStart, vEnd); 4207*552f7358SJed Brown } 4208*552f7358SJed Brown closure = &origClosure[4*2]; 4209*552f7358SJed Brown /* Remember that this is the orientation for edges, not vertices */ 4210*552f7358SJed Brown if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4211*552f7358SJed Brown /* Correctly oriented */ 4212*552f7358SJed Brown mesh->coneOrientations[coff+cf] = 0; 4213*552f7358SJed Brown } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4214*552f7358SJed Brown /* Shifted by 1 */ 4215*552f7358SJed Brown mesh->coneOrientations[coff+cf] = 1; 4216*552f7358SJed Brown } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4217*552f7358SJed Brown /* Shifted by 2 */ 4218*552f7358SJed Brown mesh->coneOrientations[coff+cf] = 2; 4219*552f7358SJed Brown } else if ((cellFaces[cf*faceSize+0] == closure[2*2]) && (cellFaces[cf*faceSize+1] == closure[1*2]) && (cellFaces[cf*faceSize+2] == closure[0*2])) { 4220*552f7358SJed Brown /* Start at edge 1, and reverse orientation */ 4221*552f7358SJed Brown mesh->coneOrientations[coff+cf] = -(1+1); 4222*552f7358SJed Brown } else if ((cellFaces[cf*faceSize+0] == closure[1*2]) && (cellFaces[cf*faceSize+1] == closure[0*2]) && (cellFaces[cf*faceSize+2] == closure[2*2])) { 4223*552f7358SJed Brown /* Start at index 0, and reverse orientation */ 4224*552f7358SJed Brown mesh->coneOrientations[coff+cf] = -(0+1); 4225*552f7358SJed Brown } else if ((cellFaces[cf*faceSize+0] == closure[0*2]) && (cellFaces[cf*faceSize+1] == closure[2*2]) && (cellFaces[cf*faceSize+2] == closure[1*2])) { 4226*552f7358SJed Brown /* Start at index 2, and reverse orientation */ 4227*552f7358SJed Brown mesh->coneOrientations[coff+cf] = -(2+1); 4228*552f7358SJed Brown } else SETERRQ3(((PetscObject) idm)->comm, PETSC_ERR_PLIB, "Face %D did not match local face %D in cell %D for any orientation", cone[cf], cf, c); 4229*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(idm, cone[cf], PETSC_TRUE, &closureSize, &origClosure);CHKERRQ(ierr); 4230*552f7358SJed Brown } 4231*552f7358SJed Brown } 4232*552f7358SJed Brown { 4233*552f7358SJed Brown ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO_DETAIL);CHKERRQ(ierr); 4234*552f7358SJed Brown ierr = DMView(idm, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4235*552f7358SJed Brown ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 4236*552f7358SJed Brown } 4237*552f7358SJed Brown *dmInt = idm; 4238*552f7358SJed Brown PetscFunctionReturn(0); 4239*552f7358SJed Brown } 4240*552f7358SJed Brown 4241*552f7358SJed Brown #undef __FUNCT__ 4242*552f7358SJed Brown #define __FUNCT__ "DMPlexBuildFromCellList_Private" 4243*552f7358SJed Brown /* 4244*552f7358SJed Brown This takes as input the common mesh generator output, a list of the vertices for each cell 4245*552f7358SJed Brown */ 4246*552f7358SJed Brown PetscErrorCode DMPlexBuildFromCellList_Private(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const int cells[]) 4247*552f7358SJed Brown { 4248*552f7358SJed Brown PetscInt *cone, c, p; 4249*552f7358SJed Brown PetscErrorCode ierr; 4250*552f7358SJed Brown 4251*552f7358SJed Brown PetscFunctionBegin; 4252*552f7358SJed Brown ierr = DMPlexSetChart(dm, 0, numCells+numVertices);CHKERRQ(ierr); 4253*552f7358SJed Brown for (c = 0; c < numCells; ++c) { 4254*552f7358SJed Brown ierr = DMPlexSetConeSize(dm, c, numCorners);CHKERRQ(ierr); 4255*552f7358SJed Brown } 4256*552f7358SJed Brown ierr = DMSetUp(dm);CHKERRQ(ierr); 4257*552f7358SJed Brown ierr = DMGetWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4258*552f7358SJed Brown for (c = 0; c < numCells; ++c) { 4259*552f7358SJed Brown for (p = 0; p < numCorners; ++p) { 4260*552f7358SJed Brown cone[p] = cells[c*numCorners+p]+numCells; 4261*552f7358SJed Brown } 4262*552f7358SJed Brown ierr = DMPlexSetCone(dm, c, cone);CHKERRQ(ierr); 4263*552f7358SJed Brown } 4264*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, numCorners, PETSC_INT, &cone);CHKERRQ(ierr); 4265*552f7358SJed Brown ierr = DMPlexSymmetrize(dm);CHKERRQ(ierr); 4266*552f7358SJed Brown ierr = DMPlexStratify(dm);CHKERRQ(ierr); 4267*552f7358SJed Brown PetscFunctionReturn(0); 4268*552f7358SJed Brown } 4269*552f7358SJed Brown 4270*552f7358SJed Brown #undef __FUNCT__ 4271*552f7358SJed Brown #define __FUNCT__ "DMPlexBuildCoordinates_Private" 4272*552f7358SJed Brown /* 4273*552f7358SJed Brown This takes as input the coordinates for each vertex 4274*552f7358SJed Brown */ 4275*552f7358SJed Brown PetscErrorCode DMPlexBuildCoordinates_Private(DM dm, PetscInt spaceDim, PetscInt numCells, PetscInt numVertices, const double vertexCoords[]) 4276*552f7358SJed Brown { 4277*552f7358SJed Brown PetscSection coordSection; 4278*552f7358SJed Brown Vec coordinates; 4279*552f7358SJed Brown PetscScalar *coords; 4280*552f7358SJed Brown PetscInt coordSize, v, d; 4281*552f7358SJed Brown PetscErrorCode ierr; 4282*552f7358SJed Brown 4283*552f7358SJed Brown PetscFunctionBegin; 4284*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4285*552f7358SJed Brown ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 4286*552f7358SJed Brown ierr = PetscSectionSetFieldComponents(coordSection, 0, spaceDim);CHKERRQ(ierr); 4287*552f7358SJed Brown ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 4288*552f7358SJed Brown for (v = numCells; v < numCells+numVertices; ++v) { 4289*552f7358SJed Brown ierr = PetscSectionSetDof(coordSection, v, spaceDim);CHKERRQ(ierr); 4290*552f7358SJed Brown ierr = PetscSectionSetFieldDof(coordSection, v, 0, spaceDim);CHKERRQ(ierr); 4291*552f7358SJed Brown } 4292*552f7358SJed Brown ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 4293*552f7358SJed Brown ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 4294*552f7358SJed Brown ierr = VecCreate(((PetscObject) dm)->comm, &coordinates);CHKERRQ(ierr); 4295*552f7358SJed Brown ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 4296*552f7358SJed Brown ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 4297*552f7358SJed Brown ierr = VecSetFromOptions(coordinates);CHKERRQ(ierr); 4298*552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 4299*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 4300*552f7358SJed Brown for (d = 0; d < spaceDim; ++d) { 4301*552f7358SJed Brown coords[v*spaceDim+d] = vertexCoords[v*spaceDim+d]; 4302*552f7358SJed Brown } 4303*552f7358SJed Brown } 4304*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 4305*552f7358SJed Brown ierr = DMSetCoordinatesLocal(dm, coordinates);CHKERRQ(ierr); 4306*552f7358SJed Brown ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 4307*552f7358SJed Brown PetscFunctionReturn(0); 4308*552f7358SJed Brown } 4309*552f7358SJed Brown 4310*552f7358SJed Brown #undef __FUNCT__ 4311*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateFromCellList" 4312*552f7358SJed Brown /* 4313*552f7358SJed Brown This takes as input the common mesh generator output, a list of the vertices for each cell 4314*552f7358SJed Brown */ 4315*552f7358SJed Brown PetscErrorCode DMPlexCreateFromCellList(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const int cells[], const double vertexCoords[], DM *dm) 4316*552f7358SJed Brown { 4317*552f7358SJed Brown PetscErrorCode ierr; 4318*552f7358SJed Brown 4319*552f7358SJed Brown PetscFunctionBegin; 4320*552f7358SJed Brown ierr = DMCreate(comm, dm);CHKERRQ(ierr); 4321*552f7358SJed Brown ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 4322*552f7358SJed Brown ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 4323*552f7358SJed Brown ierr = DMPlexBuildFromCellList_Private(*dm, numCells, numVertices, numCorners, cells);CHKERRQ(ierr); 4324*552f7358SJed Brown if (interpolate) { 4325*552f7358SJed Brown DM idm; 4326*552f7358SJed Brown 4327*552f7358SJed Brown switch(dim) { 4328*552f7358SJed Brown case 2: 4329*552f7358SJed Brown ierr = DMPlexInterpolate_2D(*dm, &idm);CHKERRQ(ierr);break; 4330*552f7358SJed Brown case 3: 4331*552f7358SJed Brown ierr = DMPlexInterpolate_3D(*dm, &idm);CHKERRQ(ierr);break; 4332*552f7358SJed Brown default: 4333*552f7358SJed Brown SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No mesh interpolation support for dimension %D", dim); 4334*552f7358SJed Brown } 4335*552f7358SJed Brown ierr = DMDestroy(dm);CHKERRQ(ierr); 4336*552f7358SJed Brown *dm = idm; 4337*552f7358SJed Brown } 4338*552f7358SJed Brown ierr = DMPlexBuildCoordinates_Private(*dm, dim, numCells, numVertices, vertexCoords);CHKERRQ(ierr); 4339*552f7358SJed Brown PetscFunctionReturn(0); 4340*552f7358SJed Brown } 4341*552f7358SJed Brown 4342*552f7358SJed Brown #ifdef PETSC_HAVE_TRIANGLE 4343*552f7358SJed Brown #include <triangle.h> 4344*552f7358SJed Brown 4345*552f7358SJed Brown #undef __FUNCT__ 4346*552f7358SJed Brown #define __FUNCT__ "InitInput_Triangle" 4347*552f7358SJed Brown PetscErrorCode InitInput_Triangle(struct triangulateio *inputCtx) { 4348*552f7358SJed Brown PetscFunctionBegin; 4349*552f7358SJed Brown inputCtx->numberofpoints = 0; 4350*552f7358SJed Brown inputCtx->numberofpointattributes = 0; 4351*552f7358SJed Brown inputCtx->pointlist = PETSC_NULL; 4352*552f7358SJed Brown inputCtx->pointattributelist = PETSC_NULL; 4353*552f7358SJed Brown inputCtx->pointmarkerlist = PETSC_NULL; 4354*552f7358SJed Brown inputCtx->numberofsegments = 0; 4355*552f7358SJed Brown inputCtx->segmentlist = PETSC_NULL; 4356*552f7358SJed Brown inputCtx->segmentmarkerlist = PETSC_NULL; 4357*552f7358SJed Brown inputCtx->numberoftriangleattributes = 0; 4358*552f7358SJed Brown inputCtx->trianglelist = PETSC_NULL; 4359*552f7358SJed Brown inputCtx->numberofholes = 0; 4360*552f7358SJed Brown inputCtx->holelist = PETSC_NULL; 4361*552f7358SJed Brown inputCtx->numberofregions = 0; 4362*552f7358SJed Brown inputCtx->regionlist = PETSC_NULL; 4363*552f7358SJed Brown PetscFunctionReturn(0); 4364*552f7358SJed Brown } 4365*552f7358SJed Brown 4366*552f7358SJed Brown #undef __FUNCT__ 4367*552f7358SJed Brown #define __FUNCT__ "InitOutput_Triangle" 4368*552f7358SJed Brown PetscErrorCode InitOutput_Triangle(struct triangulateio *outputCtx) { 4369*552f7358SJed Brown PetscFunctionBegin; 4370*552f7358SJed Brown outputCtx->numberofpoints = 0; 4371*552f7358SJed Brown outputCtx->pointlist = PETSC_NULL; 4372*552f7358SJed Brown outputCtx->pointattributelist = PETSC_NULL; 4373*552f7358SJed Brown outputCtx->pointmarkerlist = PETSC_NULL; 4374*552f7358SJed Brown outputCtx->numberoftriangles = 0; 4375*552f7358SJed Brown outputCtx->trianglelist = PETSC_NULL; 4376*552f7358SJed Brown outputCtx->triangleattributelist = PETSC_NULL; 4377*552f7358SJed Brown outputCtx->neighborlist = PETSC_NULL; 4378*552f7358SJed Brown outputCtx->segmentlist = PETSC_NULL; 4379*552f7358SJed Brown outputCtx->segmentmarkerlist = PETSC_NULL; 4380*552f7358SJed Brown outputCtx->numberofedges = 0; 4381*552f7358SJed Brown outputCtx->edgelist = PETSC_NULL; 4382*552f7358SJed Brown outputCtx->edgemarkerlist = PETSC_NULL; 4383*552f7358SJed Brown PetscFunctionReturn(0); 4384*552f7358SJed Brown } 4385*552f7358SJed Brown 4386*552f7358SJed Brown #undef __FUNCT__ 4387*552f7358SJed Brown #define __FUNCT__ "FiniOutput_Triangle" 4388*552f7358SJed Brown PetscErrorCode FiniOutput_Triangle(struct triangulateio *outputCtx) { 4389*552f7358SJed Brown PetscFunctionBegin; 4390*552f7358SJed Brown free(outputCtx->pointmarkerlist); 4391*552f7358SJed Brown free(outputCtx->edgelist); 4392*552f7358SJed Brown free(outputCtx->edgemarkerlist); 4393*552f7358SJed Brown free(outputCtx->trianglelist); 4394*552f7358SJed Brown free(outputCtx->neighborlist); 4395*552f7358SJed Brown PetscFunctionReturn(0); 4396*552f7358SJed Brown } 4397*552f7358SJed Brown 4398*552f7358SJed Brown #undef __FUNCT__ 4399*552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_Triangle" 4400*552f7358SJed Brown PetscErrorCode DMPlexGenerate_Triangle(DM boundary, PetscBool interpolate, DM *dm) 4401*552f7358SJed Brown { 4402*552f7358SJed Brown MPI_Comm comm = ((PetscObject) boundary)->comm; 4403*552f7358SJed Brown PetscInt dim = 2; 4404*552f7358SJed Brown const PetscBool createConvexHull = PETSC_FALSE; 4405*552f7358SJed Brown const PetscBool constrained = PETSC_FALSE; 4406*552f7358SJed Brown struct triangulateio in; 4407*552f7358SJed Brown struct triangulateio out; 4408*552f7358SJed Brown PetscInt vStart, vEnd, v, eStart, eEnd, e; 4409*552f7358SJed Brown PetscMPIInt rank; 4410*552f7358SJed Brown PetscErrorCode ierr; 4411*552f7358SJed Brown 4412*552f7358SJed Brown PetscFunctionBegin; 4413*552f7358SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4414*552f7358SJed Brown ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4415*552f7358SJed Brown ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4416*552f7358SJed Brown ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4417*552f7358SJed Brown in.numberofpoints = vEnd - vStart; 4418*552f7358SJed Brown if (in.numberofpoints > 0) { 4419*552f7358SJed Brown PetscSection coordSection; 4420*552f7358SJed Brown Vec coordinates; 4421*552f7358SJed Brown PetscScalar *array; 4422*552f7358SJed Brown 4423*552f7358SJed Brown ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4424*552f7358SJed Brown ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4425*552f7358SJed Brown ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4426*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4427*552f7358SJed Brown ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4428*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 4429*552f7358SJed Brown const PetscInt idx = v - vStart; 4430*552f7358SJed Brown PetscInt off, d; 4431*552f7358SJed Brown 4432*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4433*552f7358SJed Brown for (d = 0; d < dim; ++d) { 4434*552f7358SJed Brown in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4435*552f7358SJed Brown } 4436*552f7358SJed Brown ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4437*552f7358SJed Brown } 4438*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4439*552f7358SJed Brown } 4440*552f7358SJed Brown ierr = DMPlexGetHeightStratum(boundary, 0, &eStart, &eEnd);CHKERRQ(ierr); 4441*552f7358SJed Brown in.numberofsegments = eEnd - eStart; 4442*552f7358SJed Brown if (in.numberofsegments > 0) { 4443*552f7358SJed Brown ierr = PetscMalloc(in.numberofsegments*2 * sizeof(int), &in.segmentlist);CHKERRQ(ierr); 4444*552f7358SJed Brown ierr = PetscMalloc(in.numberofsegments * sizeof(int), &in.segmentmarkerlist);CHKERRQ(ierr); 4445*552f7358SJed Brown for (e = eStart; e < eEnd; ++e) { 4446*552f7358SJed Brown const PetscInt idx = e - eStart; 4447*552f7358SJed Brown const PetscInt *cone; 4448*552f7358SJed Brown 4449*552f7358SJed Brown ierr = DMPlexGetCone(boundary, e, &cone);CHKERRQ(ierr); 4450*552f7358SJed Brown in.segmentlist[idx*2+0] = cone[0] - vStart; 4451*552f7358SJed Brown in.segmentlist[idx*2+1] = cone[1] - vStart; 4452*552f7358SJed Brown ierr = DMPlexGetLabelValue(boundary, "marker", e, &in.segmentmarkerlist[idx]);CHKERRQ(ierr); 4453*552f7358SJed Brown } 4454*552f7358SJed Brown } 4455*552f7358SJed Brown #if 0 /* Do not currently support holes */ 4456*552f7358SJed Brown PetscReal *holeCoords; 4457*552f7358SJed Brown PetscInt h, d; 4458*552f7358SJed Brown 4459*552f7358SJed Brown ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4460*552f7358SJed Brown if (in.numberofholes > 0) { 4461*552f7358SJed Brown ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4462*552f7358SJed Brown for (h = 0; h < in.numberofholes; ++h) { 4463*552f7358SJed Brown for (d = 0; d < dim; ++d) { 4464*552f7358SJed Brown in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4465*552f7358SJed Brown } 4466*552f7358SJed Brown } 4467*552f7358SJed Brown } 4468*552f7358SJed Brown #endif 4469*552f7358SJed Brown if (!rank) { 4470*552f7358SJed Brown char args[32]; 4471*552f7358SJed Brown 4472*552f7358SJed Brown /* Take away 'Q' for verbose output */ 4473*552f7358SJed Brown ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4474*552f7358SJed Brown if (createConvexHull) { 4475*552f7358SJed Brown ierr = PetscStrcat(args, "c");CHKERRQ(ierr); 4476*552f7358SJed Brown } 4477*552f7358SJed Brown if (constrained) { 4478*552f7358SJed Brown ierr = PetscStrcpy(args, "zepDQ");CHKERRQ(ierr); 4479*552f7358SJed Brown } 4480*552f7358SJed Brown triangulate(args, &in, &out, PETSC_NULL); 4481*552f7358SJed Brown } 4482*552f7358SJed Brown ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4483*552f7358SJed Brown ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4484*552f7358SJed Brown ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4485*552f7358SJed Brown ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4486*552f7358SJed Brown ierr = PetscFree(in.holelist);CHKERRQ(ierr); 4487*552f7358SJed Brown 4488*552f7358SJed Brown { 4489*552f7358SJed Brown const PetscInt numCorners = 3; 4490*552f7358SJed Brown const PetscInt numCells = out.numberoftriangles; 4491*552f7358SJed Brown const PetscInt numVertices = out.numberofpoints; 4492*552f7358SJed Brown const int *cells = out.trianglelist; 4493*552f7358SJed Brown const double *meshCoords = out.pointlist; 4494*552f7358SJed Brown 4495*552f7358SJed Brown ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4496*552f7358SJed Brown /* Set labels */ 4497*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 4498*552f7358SJed Brown if (out.pointmarkerlist[v]) { 4499*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4500*552f7358SJed Brown } 4501*552f7358SJed Brown } 4502*552f7358SJed Brown if (interpolate) { 4503*552f7358SJed Brown for (e = 0; e < out.numberofedges; e++) { 4504*552f7358SJed Brown if (out.edgemarkerlist[e]) { 4505*552f7358SJed Brown const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4506*552f7358SJed Brown const PetscInt *edges; 4507*552f7358SJed Brown PetscInt numEdges; 4508*552f7358SJed Brown 4509*552f7358SJed Brown ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4510*552f7358SJed Brown if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4511*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4512*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4513*552f7358SJed Brown } 4514*552f7358SJed Brown } 4515*552f7358SJed Brown } 4516*552f7358SJed Brown ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4517*552f7358SJed Brown } 4518*552f7358SJed Brown #if 0 /* Do not currently support holes */ 4519*552f7358SJed Brown ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4520*552f7358SJed Brown #endif 4521*552f7358SJed Brown ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4522*552f7358SJed Brown PetscFunctionReturn(0); 4523*552f7358SJed Brown } 4524*552f7358SJed Brown 4525*552f7358SJed Brown #undef __FUNCT__ 4526*552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_Triangle" 4527*552f7358SJed Brown PetscErrorCode DMPlexRefine_Triangle(DM dm, double *maxVolumes, DM *dmRefined) 4528*552f7358SJed Brown { 4529*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 4530*552f7358SJed Brown PetscInt dim = 2; 4531*552f7358SJed Brown struct triangulateio in; 4532*552f7358SJed Brown struct triangulateio out; 4533*552f7358SJed Brown PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4534*552f7358SJed Brown PetscMPIInt rank; 4535*552f7358SJed Brown PetscErrorCode ierr; 4536*552f7358SJed Brown 4537*552f7358SJed Brown PetscFunctionBegin; 4538*552f7358SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4539*552f7358SJed Brown ierr = InitInput_Triangle(&in);CHKERRQ(ierr); 4540*552f7358SJed Brown ierr = InitOutput_Triangle(&out);CHKERRQ(ierr); 4541*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4542*552f7358SJed Brown ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4543*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4544*552f7358SJed Brown in.numberofpoints = vEnd - vStart; 4545*552f7358SJed Brown if (in.numberofpoints > 0) { 4546*552f7358SJed Brown PetscSection coordSection; 4547*552f7358SJed Brown Vec coordinates; 4548*552f7358SJed Brown PetscScalar *array; 4549*552f7358SJed Brown 4550*552f7358SJed Brown ierr = PetscMalloc(in.numberofpoints*dim * sizeof(double), &in.pointlist);CHKERRQ(ierr); 4551*552f7358SJed Brown ierr = PetscMalloc(in.numberofpoints * sizeof(int), &in.pointmarkerlist);CHKERRQ(ierr); 4552*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4553*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4554*552f7358SJed Brown ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4555*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 4556*552f7358SJed Brown const PetscInt idx = v - vStart; 4557*552f7358SJed Brown PetscInt off, d; 4558*552f7358SJed Brown 4559*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4560*552f7358SJed Brown for (d = 0; d < dim; ++d) { 4561*552f7358SJed Brown in.pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4562*552f7358SJed Brown } 4563*552f7358SJed Brown ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4564*552f7358SJed Brown } 4565*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4566*552f7358SJed Brown } 4567*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4568*552f7358SJed Brown in.numberofcorners = 3; 4569*552f7358SJed Brown in.numberoftriangles = cEnd - cStart; 4570*552f7358SJed Brown in.trianglearealist = (double *) maxVolumes; 4571*552f7358SJed Brown if (in.numberoftriangles > 0) { 4572*552f7358SJed Brown ierr = PetscMalloc(in.numberoftriangles*in.numberofcorners * sizeof(int), &in.trianglelist);CHKERRQ(ierr); 4573*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 4574*552f7358SJed Brown const PetscInt idx = c - cStart; 4575*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 4576*552f7358SJed Brown PetscInt closureSize; 4577*552f7358SJed Brown 4578*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4579*552f7358SJed Brown if ((closureSize != 4) && (closureSize != 7)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a triangle, %D vertices in closure", closureSize); 4580*552f7358SJed Brown for (v = 0; v < 3; ++v) { 4581*552f7358SJed Brown in.trianglelist[idx*in.numberofcorners + v] = closure[(v+closureSize-3)*2] - vStart; 4582*552f7358SJed Brown } 4583*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4584*552f7358SJed Brown } 4585*552f7358SJed Brown } 4586*552f7358SJed Brown /* TODO: Segment markers are missing on input */ 4587*552f7358SJed Brown #if 0 /* Do not currently support holes */ 4588*552f7358SJed Brown PetscReal *holeCoords; 4589*552f7358SJed Brown PetscInt h, d; 4590*552f7358SJed Brown 4591*552f7358SJed Brown ierr = DMPlexGetHoles(boundary, &in.numberofholes, &holeCords);CHKERRQ(ierr); 4592*552f7358SJed Brown if (in.numberofholes > 0) { 4593*552f7358SJed Brown ierr = PetscMalloc(in.numberofholes*dim * sizeof(double), &in.holelist);CHKERRQ(ierr); 4594*552f7358SJed Brown for (h = 0; h < in.numberofholes; ++h) { 4595*552f7358SJed Brown for (d = 0; d < dim; ++d) { 4596*552f7358SJed Brown in.holelist[h*dim+d] = holeCoords[h*dim+d]; 4597*552f7358SJed Brown } 4598*552f7358SJed Brown } 4599*552f7358SJed Brown } 4600*552f7358SJed Brown #endif 4601*552f7358SJed Brown if (!rank) { 4602*552f7358SJed Brown char args[32]; 4603*552f7358SJed Brown 4604*552f7358SJed Brown /* Take away 'Q' for verbose output */ 4605*552f7358SJed Brown ierr = PetscStrcpy(args, "pqezQra");CHKERRQ(ierr); 4606*552f7358SJed Brown triangulate(args, &in, &out, PETSC_NULL); 4607*552f7358SJed Brown } 4608*552f7358SJed Brown ierr = PetscFree(in.pointlist);CHKERRQ(ierr); 4609*552f7358SJed Brown ierr = PetscFree(in.pointmarkerlist);CHKERRQ(ierr); 4610*552f7358SJed Brown ierr = PetscFree(in.segmentlist);CHKERRQ(ierr); 4611*552f7358SJed Brown ierr = PetscFree(in.segmentmarkerlist);CHKERRQ(ierr); 4612*552f7358SJed Brown ierr = PetscFree(in.trianglelist);CHKERRQ(ierr); 4613*552f7358SJed Brown 4614*552f7358SJed Brown { 4615*552f7358SJed Brown const PetscInt numCorners = 3; 4616*552f7358SJed Brown const PetscInt numCells = out.numberoftriangles; 4617*552f7358SJed Brown const PetscInt numVertices = out.numberofpoints; 4618*552f7358SJed Brown const int *cells = out.trianglelist; 4619*552f7358SJed Brown const double *meshCoords = out.pointlist; 4620*552f7358SJed Brown PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4621*552f7358SJed Brown 4622*552f7358SJed Brown ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4623*552f7358SJed Brown /* Set labels */ 4624*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 4625*552f7358SJed Brown if (out.pointmarkerlist[v]) { 4626*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4627*552f7358SJed Brown } 4628*552f7358SJed Brown } 4629*552f7358SJed Brown if (interpolate) { 4630*552f7358SJed Brown PetscInt e; 4631*552f7358SJed Brown 4632*552f7358SJed Brown for (e = 0; e < out.numberofedges; e++) { 4633*552f7358SJed Brown if (out.edgemarkerlist[e]) { 4634*552f7358SJed Brown const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4635*552f7358SJed Brown const PetscInt *edges; 4636*552f7358SJed Brown PetscInt numEdges; 4637*552f7358SJed Brown 4638*552f7358SJed Brown ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4639*552f7358SJed Brown if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4640*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4641*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4642*552f7358SJed Brown } 4643*552f7358SJed Brown } 4644*552f7358SJed Brown } 4645*552f7358SJed Brown ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4646*552f7358SJed Brown } 4647*552f7358SJed Brown #if 0 /* Do not currently support holes */ 4648*552f7358SJed Brown ierr = DMPlexCopyHoles(*dm, boundary);CHKERRQ(ierr); 4649*552f7358SJed Brown #endif 4650*552f7358SJed Brown ierr = FiniOutput_Triangle(&out);CHKERRQ(ierr); 4651*552f7358SJed Brown PetscFunctionReturn(0); 4652*552f7358SJed Brown } 4653*552f7358SJed Brown #endif 4654*552f7358SJed Brown 4655*552f7358SJed Brown #ifdef PETSC_HAVE_TETGEN 4656*552f7358SJed Brown #include <tetgen.h> 4657*552f7358SJed Brown #undef __FUNCT__ 4658*552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_Tetgen" 4659*552f7358SJed Brown PetscErrorCode DMPlexGenerate_Tetgen(DM boundary, PetscBool interpolate, DM *dm) 4660*552f7358SJed Brown { 4661*552f7358SJed Brown MPI_Comm comm = ((PetscObject) boundary)->comm; 4662*552f7358SJed Brown const PetscInt dim = 3; 4663*552f7358SJed Brown ::tetgenio in; 4664*552f7358SJed Brown ::tetgenio out; 4665*552f7358SJed Brown PetscInt vStart, vEnd, v, fStart, fEnd, f; 4666*552f7358SJed Brown PetscMPIInt rank; 4667*552f7358SJed Brown PetscErrorCode ierr; 4668*552f7358SJed Brown 4669*552f7358SJed Brown PetscFunctionBegin; 4670*552f7358SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4671*552f7358SJed Brown ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4672*552f7358SJed Brown in.numberofpoints = vEnd - vStart; 4673*552f7358SJed Brown if (in.numberofpoints > 0) { 4674*552f7358SJed Brown PetscSection coordSection; 4675*552f7358SJed Brown Vec coordinates; 4676*552f7358SJed Brown PetscScalar *array; 4677*552f7358SJed Brown 4678*552f7358SJed Brown in.pointlist = new double[in.numberofpoints*dim]; 4679*552f7358SJed Brown in.pointmarkerlist = new int[in.numberofpoints]; 4680*552f7358SJed Brown ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4681*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4682*552f7358SJed Brown ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4683*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 4684*552f7358SJed Brown const PetscInt idx = v - vStart; 4685*552f7358SJed Brown PetscInt off, d; 4686*552f7358SJed Brown 4687*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4688*552f7358SJed Brown for (d = 0; d < dim; ++d) { 4689*552f7358SJed Brown in.pointlist[idx*dim + d] = array[off+d]; 4690*552f7358SJed Brown } 4691*552f7358SJed Brown ierr = DMPlexGetLabelValue(boundary, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4692*552f7358SJed Brown } 4693*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4694*552f7358SJed Brown } 4695*552f7358SJed Brown ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4696*552f7358SJed Brown in.numberoffacets = fEnd - fStart; 4697*552f7358SJed Brown if (in.numberoffacets > 0) { 4698*552f7358SJed Brown in.facetlist = new tetgenio::facet[in.numberoffacets]; 4699*552f7358SJed Brown in.facetmarkerlist = new int[in.numberoffacets]; 4700*552f7358SJed Brown for (f = fStart; f < fEnd; ++f) { 4701*552f7358SJed Brown const PetscInt idx = f - fStart; 4702*552f7358SJed Brown PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v; 4703*552f7358SJed Brown 4704*552f7358SJed Brown in.facetlist[idx].numberofpolygons = 1; 4705*552f7358SJed Brown in.facetlist[idx].polygonlist = new tetgenio::polygon[in.facetlist[idx].numberofpolygons]; 4706*552f7358SJed Brown in.facetlist[idx].numberofholes = 0; 4707*552f7358SJed Brown in.facetlist[idx].holelist = NULL; 4708*552f7358SJed Brown 4709*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4710*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 4711*552f7358SJed Brown const PetscInt point = points[p]; 4712*552f7358SJed Brown if ((point >= vStart) && (point < vEnd)) { 4713*552f7358SJed Brown points[numVertices++] = point; 4714*552f7358SJed Brown } 4715*552f7358SJed Brown } 4716*552f7358SJed Brown 4717*552f7358SJed Brown tetgenio::polygon *poly = in.facetlist[idx].polygonlist; 4718*552f7358SJed Brown poly->numberofvertices = numVertices; 4719*552f7358SJed Brown poly->vertexlist = new int[poly->numberofvertices]; 4720*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 4721*552f7358SJed Brown const PetscInt vIdx = points[v] - vStart; 4722*552f7358SJed Brown poly->vertexlist[v] = vIdx; 4723*552f7358SJed Brown } 4724*552f7358SJed Brown ierr = DMPlexGetLabelValue(boundary, "marker", f, &in.facetmarkerlist[idx]);CHKERRQ(ierr); 4725*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4726*552f7358SJed Brown } 4727*552f7358SJed Brown } 4728*552f7358SJed Brown if (!rank) { 4729*552f7358SJed Brown char args[32]; 4730*552f7358SJed Brown 4731*552f7358SJed Brown /* Take away 'Q' for verbose output */ 4732*552f7358SJed Brown ierr = PetscStrcpy(args, "pqezQ");CHKERRQ(ierr); 4733*552f7358SJed Brown ::tetrahedralize(args, &in, &out); 4734*552f7358SJed Brown } 4735*552f7358SJed Brown { 4736*552f7358SJed Brown const PetscInt numCorners = 4; 4737*552f7358SJed Brown const PetscInt numCells = out.numberoftetrahedra; 4738*552f7358SJed Brown const PetscInt numVertices = out.numberofpoints; 4739*552f7358SJed Brown const int *cells = out.tetrahedronlist; 4740*552f7358SJed Brown const double *meshCoords = out.pointlist; 4741*552f7358SJed Brown 4742*552f7358SJed Brown ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 4743*552f7358SJed Brown /* Set labels */ 4744*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 4745*552f7358SJed Brown if (out.pointmarkerlist[v]) { 4746*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4747*552f7358SJed Brown } 4748*552f7358SJed Brown } 4749*552f7358SJed Brown if (interpolate) { 4750*552f7358SJed Brown PetscInt e; 4751*552f7358SJed Brown 4752*552f7358SJed Brown for (e = 0; e < out.numberofedges; e++) { 4753*552f7358SJed Brown if (out.edgemarkerlist[e]) { 4754*552f7358SJed Brown const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4755*552f7358SJed Brown const PetscInt *edges; 4756*552f7358SJed Brown PetscInt numEdges; 4757*552f7358SJed Brown 4758*552f7358SJed Brown ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4759*552f7358SJed Brown if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4760*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4761*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4762*552f7358SJed Brown } 4763*552f7358SJed Brown } 4764*552f7358SJed Brown for (f = 0; f < out.numberoftrifaces; f++) { 4765*552f7358SJed Brown if (out.trifacemarkerlist[f]) { 4766*552f7358SJed Brown const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4767*552f7358SJed Brown const PetscInt *faces; 4768*552f7358SJed Brown PetscInt numFaces; 4769*552f7358SJed Brown 4770*552f7358SJed Brown ierr = DMPlexGetJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4771*552f7358SJed Brown if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4772*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4773*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4774*552f7358SJed Brown } 4775*552f7358SJed Brown } 4776*552f7358SJed Brown } 4777*552f7358SJed Brown ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 4778*552f7358SJed Brown } 4779*552f7358SJed Brown PetscFunctionReturn(0); 4780*552f7358SJed Brown } 4781*552f7358SJed Brown 4782*552f7358SJed Brown #undef __FUNCT__ 4783*552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_Tetgen" 4784*552f7358SJed Brown PetscErrorCode DMPlexRefine_Tetgen(DM dm, double *maxVolumes, DM *dmRefined) 4785*552f7358SJed Brown { 4786*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 4787*552f7358SJed Brown const PetscInt dim = 3; 4788*552f7358SJed Brown ::tetgenio in; 4789*552f7358SJed Brown ::tetgenio out; 4790*552f7358SJed Brown PetscInt vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 4791*552f7358SJed Brown PetscMPIInt rank; 4792*552f7358SJed Brown PetscErrorCode ierr; 4793*552f7358SJed Brown 4794*552f7358SJed Brown PetscFunctionBegin; 4795*552f7358SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4796*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 4797*552f7358SJed Brown ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 4798*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 4799*552f7358SJed Brown in.numberofpoints = vEnd - vStart; 4800*552f7358SJed Brown if (in.numberofpoints > 0) { 4801*552f7358SJed Brown PetscSection coordSection; 4802*552f7358SJed Brown Vec coordinates; 4803*552f7358SJed Brown PetscScalar *array; 4804*552f7358SJed Brown 4805*552f7358SJed Brown in.pointlist = new double[in.numberofpoints*dim]; 4806*552f7358SJed Brown in.pointmarkerlist = new int[in.numberofpoints]; 4807*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 4808*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 4809*552f7358SJed Brown ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4810*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 4811*552f7358SJed Brown const PetscInt idx = v - vStart; 4812*552f7358SJed Brown PetscInt off, d; 4813*552f7358SJed Brown 4814*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4815*552f7358SJed Brown for (d = 0; d < dim; ++d) { 4816*552f7358SJed Brown in.pointlist[idx*dim + d] = array[off+d]; 4817*552f7358SJed Brown } 4818*552f7358SJed Brown ierr = DMPlexGetLabelValue(dm, "marker", v, &in.pointmarkerlist[idx]);CHKERRQ(ierr); 4819*552f7358SJed Brown } 4820*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4821*552f7358SJed Brown } 4822*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 4823*552f7358SJed Brown in.numberofcorners = 4; 4824*552f7358SJed Brown in.numberoftetrahedra = cEnd - cStart; 4825*552f7358SJed Brown in.tetrahedronvolumelist = (double *) maxVolumes; 4826*552f7358SJed Brown if (in.numberoftetrahedra > 0) { 4827*552f7358SJed Brown in.tetrahedronlist = new int[in.numberoftetrahedra*in.numberofcorners]; 4828*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 4829*552f7358SJed Brown const PetscInt idx = c - cStart; 4830*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 4831*552f7358SJed Brown PetscInt closureSize; 4832*552f7358SJed Brown 4833*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4834*552f7358SJed Brown if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 4835*552f7358SJed Brown for (v = 0; v < 4; ++v) { 4836*552f7358SJed Brown in.tetrahedronlist[idx*in.numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 4837*552f7358SJed Brown } 4838*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 4839*552f7358SJed Brown } 4840*552f7358SJed Brown } 4841*552f7358SJed Brown // TODO: Put in boundary faces with markers 4842*552f7358SJed Brown if (!rank) { 4843*552f7358SJed Brown char args[32]; 4844*552f7358SJed Brown 4845*552f7358SJed Brown /* Take away 'Q' for verbose output */ 4846*552f7358SJed Brown //ierr = PetscStrcpy(args, "qezQra");CHKERRQ(ierr); 4847*552f7358SJed Brown ierr = PetscStrcpy(args, "qezraVVVV");CHKERRQ(ierr); 4848*552f7358SJed Brown ::tetrahedralize(args, &in, &out); 4849*552f7358SJed Brown } 4850*552f7358SJed Brown in.tetrahedronvolumelist = NULL; 4851*552f7358SJed Brown 4852*552f7358SJed Brown { 4853*552f7358SJed Brown const PetscInt numCorners = 4; 4854*552f7358SJed Brown const PetscInt numCells = out.numberoftetrahedra; 4855*552f7358SJed Brown const PetscInt numVertices = out.numberofpoints; 4856*552f7358SJed Brown const int *cells = out.tetrahedronlist; 4857*552f7358SJed Brown const double *meshCoords = out.pointlist; 4858*552f7358SJed Brown PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 4859*552f7358SJed Brown 4860*552f7358SJed Brown ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 4861*552f7358SJed Brown /* Set labels */ 4862*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 4863*552f7358SJed Brown if (out.pointmarkerlist[v]) { 4864*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out.pointmarkerlist[v]);CHKERRQ(ierr); 4865*552f7358SJed Brown } 4866*552f7358SJed Brown } 4867*552f7358SJed Brown if (interpolate) { 4868*552f7358SJed Brown PetscInt e, f; 4869*552f7358SJed Brown 4870*552f7358SJed Brown for (e = 0; e < out.numberofedges; e++) { 4871*552f7358SJed Brown if (out.edgemarkerlist[e]) { 4872*552f7358SJed Brown const PetscInt vertices[2] = {out.edgelist[e*2+0]+numCells, out.edgelist[e*2+1]+numCells}; 4873*552f7358SJed Brown const PetscInt *edges; 4874*552f7358SJed Brown PetscInt numEdges; 4875*552f7358SJed Brown 4876*552f7358SJed Brown ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4877*552f7358SJed Brown if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 4878*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out.edgemarkerlist[e]);CHKERRQ(ierr); 4879*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 4880*552f7358SJed Brown } 4881*552f7358SJed Brown } 4882*552f7358SJed Brown for (f = 0; f < out.numberoftrifaces; f++) { 4883*552f7358SJed Brown if (out.trifacemarkerlist[f]) { 4884*552f7358SJed Brown const PetscInt vertices[3] = {out.trifacelist[f*3+0]+numCells, out.trifacelist[f*3+1]+numCells, out.trifacelist[f*3+2]+numCells}; 4885*552f7358SJed Brown const PetscInt *faces; 4886*552f7358SJed Brown PetscInt numFaces; 4887*552f7358SJed Brown 4888*552f7358SJed Brown ierr = DMPlexGetJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4889*552f7358SJed Brown if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 4890*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out.trifacemarkerlist[f]);CHKERRQ(ierr); 4891*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 4892*552f7358SJed Brown } 4893*552f7358SJed Brown } 4894*552f7358SJed Brown } 4895*552f7358SJed Brown ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 4896*552f7358SJed Brown } 4897*552f7358SJed Brown PetscFunctionReturn(0); 4898*552f7358SJed Brown } 4899*552f7358SJed Brown #endif 4900*552f7358SJed Brown 4901*552f7358SJed Brown #ifdef PETSC_HAVE_CTETGEN 4902*552f7358SJed Brown #include "ctetgen.h" 4903*552f7358SJed Brown 4904*552f7358SJed Brown #undef __FUNCT__ 4905*552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate_CTetgen" 4906*552f7358SJed Brown PetscErrorCode DMPlexGenerate_CTetgen(DM boundary, PetscBool interpolate, DM *dm) 4907*552f7358SJed Brown { 4908*552f7358SJed Brown MPI_Comm comm = ((PetscObject) boundary)->comm; 4909*552f7358SJed Brown const PetscInt dim = 3; 4910*552f7358SJed Brown PLC *in, *out; 4911*552f7358SJed Brown PetscInt verbose = 0, vStart, vEnd, v, fStart, fEnd, f; 4912*552f7358SJed Brown PetscMPIInt rank; 4913*552f7358SJed Brown PetscErrorCode ierr; 4914*552f7358SJed Brown 4915*552f7358SJed Brown PetscFunctionBegin; 4916*552f7358SJed Brown ierr = PetscOptionsGetInt(((PetscObject) boundary)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 4917*552f7358SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 4918*552f7358SJed Brown ierr = DMPlexGetDepthStratum(boundary, 0, &vStart, &vEnd);CHKERRQ(ierr); 4919*552f7358SJed Brown ierr = PLCCreate(&in);CHKERRQ(ierr); 4920*552f7358SJed Brown ierr = PLCCreate(&out);CHKERRQ(ierr); 4921*552f7358SJed Brown in->numberofpoints = vEnd - vStart; 4922*552f7358SJed Brown if (in->numberofpoints > 0) { 4923*552f7358SJed Brown PetscSection coordSection; 4924*552f7358SJed Brown Vec coordinates; 4925*552f7358SJed Brown PetscScalar *array; 4926*552f7358SJed Brown 4927*552f7358SJed Brown ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 4928*552f7358SJed Brown ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 4929*552f7358SJed Brown ierr = DMGetCoordinatesLocal(boundary, &coordinates);CHKERRQ(ierr); 4930*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(boundary, &coordSection);CHKERRQ(ierr); 4931*552f7358SJed Brown ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 4932*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 4933*552f7358SJed Brown const PetscInt idx = v - vStart; 4934*552f7358SJed Brown PetscInt off, d, m; 4935*552f7358SJed Brown 4936*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 4937*552f7358SJed Brown for (d = 0; d < dim; ++d) { 4938*552f7358SJed Brown in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 4939*552f7358SJed Brown } 4940*552f7358SJed Brown ierr = DMPlexGetLabelValue(boundary, "marker", v, &m);CHKERRQ(ierr); 4941*552f7358SJed Brown in->pointmarkerlist[idx] = (int) m; 4942*552f7358SJed Brown } 4943*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 4944*552f7358SJed Brown } 4945*552f7358SJed Brown ierr = DMPlexGetHeightStratum(boundary, 0, &fStart, &fEnd);CHKERRQ(ierr); 4946*552f7358SJed Brown in->numberoffacets = fEnd - fStart; 4947*552f7358SJed Brown if (in->numberoffacets > 0) { 4948*552f7358SJed Brown ierr = PetscMalloc(in->numberoffacets * sizeof(facet), &in->facetlist);CHKERRQ(ierr); 4949*552f7358SJed Brown ierr = PetscMalloc(in->numberoffacets * sizeof(int), &in->facetmarkerlist);CHKERRQ(ierr); 4950*552f7358SJed Brown for (f = fStart; f < fEnd; ++f) { 4951*552f7358SJed Brown const PetscInt idx = f - fStart; 4952*552f7358SJed Brown PetscInt *points = PETSC_NULL, numPoints, p, numVertices = 0, v, m; 4953*552f7358SJed Brown polygon *poly; 4954*552f7358SJed Brown 4955*552f7358SJed Brown in->facetlist[idx].numberofpolygons = 1; 4956*552f7358SJed Brown ierr = PetscMalloc(in->facetlist[idx].numberofpolygons * sizeof(polygon), &in->facetlist[idx].polygonlist);CHKERRQ(ierr); 4957*552f7358SJed Brown in->facetlist[idx].numberofholes = 0; 4958*552f7358SJed Brown in->facetlist[idx].holelist = PETSC_NULL; 4959*552f7358SJed Brown 4960*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4961*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 4962*552f7358SJed Brown const PetscInt point = points[p]; 4963*552f7358SJed Brown if ((point >= vStart) && (point < vEnd)) { 4964*552f7358SJed Brown points[numVertices++] = point; 4965*552f7358SJed Brown } 4966*552f7358SJed Brown } 4967*552f7358SJed Brown 4968*552f7358SJed Brown poly = in->facetlist[idx].polygonlist; 4969*552f7358SJed Brown poly->numberofvertices = numVertices; 4970*552f7358SJed Brown ierr = PetscMalloc(poly->numberofvertices * sizeof(int), &poly->vertexlist);CHKERRQ(ierr); 4971*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 4972*552f7358SJed Brown const PetscInt vIdx = points[v] - vStart; 4973*552f7358SJed Brown poly->vertexlist[v] = vIdx; 4974*552f7358SJed Brown } 4975*552f7358SJed Brown ierr = DMPlexGetLabelValue(boundary, "marker", f, &m);CHKERRQ(ierr); 4976*552f7358SJed Brown in->facetmarkerlist[idx] = (int) m; 4977*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(boundary, f, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4978*552f7358SJed Brown } 4979*552f7358SJed Brown } 4980*552f7358SJed Brown if (!rank) { 4981*552f7358SJed Brown TetGenOpts t; 4982*552f7358SJed Brown 4983*552f7358SJed Brown ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 4984*552f7358SJed Brown t.in = boundary; /* Should go away */ 4985*552f7358SJed Brown t.plc = 1; 4986*552f7358SJed Brown t.quality = 1; 4987*552f7358SJed Brown t.edgesout = 1; 4988*552f7358SJed Brown t.zeroindex = 1; 4989*552f7358SJed Brown t.quiet = 1; 4990*552f7358SJed Brown t.verbose = verbose; 4991*552f7358SJed Brown ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 4992*552f7358SJed Brown ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 4993*552f7358SJed Brown } 4994*552f7358SJed Brown { 4995*552f7358SJed Brown const PetscInt numCorners = 4; 4996*552f7358SJed Brown const PetscInt numCells = out->numberoftetrahedra; 4997*552f7358SJed Brown const PetscInt numVertices = out->numberofpoints; 4998*552f7358SJed Brown const int *cells = out->tetrahedronlist; 4999*552f7358SJed Brown const double *meshCoords = out->pointlist; 5000*552f7358SJed Brown 5001*552f7358SJed Brown ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dm);CHKERRQ(ierr); 5002*552f7358SJed Brown /* Set labels */ 5003*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 5004*552f7358SJed Brown if (out->pointmarkerlist[v]) { 5005*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dm, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5006*552f7358SJed Brown } 5007*552f7358SJed Brown } 5008*552f7358SJed Brown if (interpolate) { 5009*552f7358SJed Brown PetscInt e; 5010*552f7358SJed Brown 5011*552f7358SJed Brown for (e = 0; e < out->numberofedges; e++) { 5012*552f7358SJed Brown if (out->edgemarkerlist[e]) { 5013*552f7358SJed Brown const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5014*552f7358SJed Brown const PetscInt *edges; 5015*552f7358SJed Brown PetscInt numEdges; 5016*552f7358SJed Brown 5017*552f7358SJed Brown ierr = DMPlexGetJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5018*552f7358SJed Brown if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5019*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dm, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5020*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dm, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5021*552f7358SJed Brown } 5022*552f7358SJed Brown } 5023*552f7358SJed Brown for (f = 0; f < out->numberoftrifaces; f++) { 5024*552f7358SJed Brown if (out->trifacemarkerlist[f]) { 5025*552f7358SJed Brown const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5026*552f7358SJed Brown const PetscInt *faces; 5027*552f7358SJed Brown PetscInt numFaces; 5028*552f7358SJed Brown 5029*552f7358SJed Brown ierr = DMPlexGetFullJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5030*552f7358SJed Brown if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5031*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dm, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5032*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dm, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5033*552f7358SJed Brown } 5034*552f7358SJed Brown } 5035*552f7358SJed Brown } 5036*552f7358SJed Brown ierr = DMPlexSetRefinementUniform(*dm, PETSC_FALSE);CHKERRQ(ierr); 5037*552f7358SJed Brown } 5038*552f7358SJed Brown 5039*552f7358SJed Brown ierr = PLCDestroy(&in);CHKERRQ(ierr); 5040*552f7358SJed Brown ierr = PLCDestroy(&out);CHKERRQ(ierr); 5041*552f7358SJed Brown PetscFunctionReturn(0); 5042*552f7358SJed Brown } 5043*552f7358SJed Brown 5044*552f7358SJed Brown #undef __FUNCT__ 5045*552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_CTetgen" 5046*552f7358SJed Brown PetscErrorCode DMPlexRefine_CTetgen(DM dm, PetscReal *maxVolumes, DM *dmRefined) 5047*552f7358SJed Brown { 5048*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 5049*552f7358SJed Brown const PetscInt dim = 3; 5050*552f7358SJed Brown PLC *in, *out; 5051*552f7358SJed Brown PetscInt verbose = 0, vStart, vEnd, v, cStart, cEnd, c, depth, depthGlobal; 5052*552f7358SJed Brown PetscMPIInt rank; 5053*552f7358SJed Brown PetscErrorCode ierr; 5054*552f7358SJed Brown 5055*552f7358SJed Brown PetscFunctionBegin; 5056*552f7358SJed Brown ierr = PetscOptionsGetInt(((PetscObject) dm)->prefix, "-ctetgen_verbose", &verbose, PETSC_NULL);CHKERRQ(ierr); 5057*552f7358SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 5058*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5059*552f7358SJed Brown ierr = MPI_Allreduce(&depth, &depthGlobal, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 5060*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5061*552f7358SJed Brown ierr = PLCCreate(&in);CHKERRQ(ierr); 5062*552f7358SJed Brown ierr = PLCCreate(&out);CHKERRQ(ierr); 5063*552f7358SJed Brown in->numberofpoints = vEnd - vStart; 5064*552f7358SJed Brown if (in->numberofpoints > 0) { 5065*552f7358SJed Brown PetscSection coordSection; 5066*552f7358SJed Brown Vec coordinates; 5067*552f7358SJed Brown PetscScalar *array; 5068*552f7358SJed Brown 5069*552f7358SJed Brown ierr = PetscMalloc(in->numberofpoints*dim * sizeof(PetscReal), &in->pointlist);CHKERRQ(ierr); 5070*552f7358SJed Brown ierr = PetscMalloc(in->numberofpoints * sizeof(int), &in->pointmarkerlist);CHKERRQ(ierr); 5071*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5072*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5073*552f7358SJed Brown ierr = VecGetArray(coordinates, &array);CHKERRQ(ierr); 5074*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 5075*552f7358SJed Brown const PetscInt idx = v - vStart; 5076*552f7358SJed Brown PetscInt off, d, m; 5077*552f7358SJed Brown 5078*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5079*552f7358SJed Brown for (d = 0; d < dim; ++d) { 5080*552f7358SJed Brown in->pointlist[idx*dim + d] = PetscRealPart(array[off+d]); 5081*552f7358SJed Brown } 5082*552f7358SJed Brown ierr = DMPlexGetLabelValue(dm, "marker", v, &m);CHKERRQ(ierr); 5083*552f7358SJed Brown in->pointmarkerlist[idx] = (int) m; 5084*552f7358SJed Brown } 5085*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &array);CHKERRQ(ierr); 5086*552f7358SJed Brown } 5087*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5088*552f7358SJed Brown in->numberofcorners = 4; 5089*552f7358SJed Brown in->numberoftetrahedra = cEnd - cStart; 5090*552f7358SJed Brown in->tetrahedronvolumelist = maxVolumes; 5091*552f7358SJed Brown if (in->numberoftetrahedra > 0) { 5092*552f7358SJed Brown ierr = PetscMalloc(in->numberoftetrahedra*in->numberofcorners * sizeof(int), &in->tetrahedronlist);CHKERRQ(ierr); 5093*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 5094*552f7358SJed Brown const PetscInt idx = c - cStart; 5095*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 5096*552f7358SJed Brown PetscInt closureSize; 5097*552f7358SJed Brown 5098*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5099*552f7358SJed Brown if ((closureSize != 5) && (closureSize != 15)) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Mesh has cell which is not a tetrahedron, %D vertices in closure", closureSize); 5100*552f7358SJed Brown for (v = 0; v < 4; ++v) { 5101*552f7358SJed Brown in->tetrahedronlist[idx*in->numberofcorners + v] = closure[(v+closureSize-4)*2] - vStart; 5102*552f7358SJed Brown } 5103*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5104*552f7358SJed Brown } 5105*552f7358SJed Brown } 5106*552f7358SJed Brown if (!rank) { 5107*552f7358SJed Brown TetGenOpts t; 5108*552f7358SJed Brown 5109*552f7358SJed Brown ierr = TetGenOptsInitialize(&t);CHKERRQ(ierr); 5110*552f7358SJed Brown t.in = dm; /* Should go away */ 5111*552f7358SJed Brown t.refine = 1; 5112*552f7358SJed Brown t.varvolume = 1; 5113*552f7358SJed Brown t.quality = 1; 5114*552f7358SJed Brown t.edgesout = 1; 5115*552f7358SJed Brown t.zeroindex = 1; 5116*552f7358SJed Brown t.quiet = 1; 5117*552f7358SJed Brown t.verbose = verbose; /* Change this */ 5118*552f7358SJed Brown ierr = TetGenCheckOpts(&t);CHKERRQ(ierr); 5119*552f7358SJed Brown ierr = TetGenTetrahedralize(&t, in, out);CHKERRQ(ierr); 5120*552f7358SJed Brown } 5121*552f7358SJed Brown { 5122*552f7358SJed Brown const PetscInt numCorners = 4; 5123*552f7358SJed Brown const PetscInt numCells = out->numberoftetrahedra; 5124*552f7358SJed Brown const PetscInt numVertices = out->numberofpoints; 5125*552f7358SJed Brown const int *cells = out->tetrahedronlist; 5126*552f7358SJed Brown const double *meshCoords = out->pointlist; 5127*552f7358SJed Brown PetscBool interpolate = depthGlobal > 1 ? PETSC_TRUE : PETSC_FALSE; 5128*552f7358SJed Brown 5129*552f7358SJed Brown ierr = DMPlexCreateFromCellList(comm, dim, numCells, numVertices, numCorners, interpolate, cells, meshCoords, dmRefined);CHKERRQ(ierr); 5130*552f7358SJed Brown /* Set labels */ 5131*552f7358SJed Brown for (v = 0; v < numVertices; ++v) { 5132*552f7358SJed Brown if (out->pointmarkerlist[v]) { 5133*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dmRefined, "marker", v+numCells, out->pointmarkerlist[v]);CHKERRQ(ierr); 5134*552f7358SJed Brown } 5135*552f7358SJed Brown } 5136*552f7358SJed Brown if (interpolate) { 5137*552f7358SJed Brown PetscInt e, f; 5138*552f7358SJed Brown 5139*552f7358SJed Brown for (e = 0; e < out->numberofedges; e++) { 5140*552f7358SJed Brown if (out->edgemarkerlist[e]) { 5141*552f7358SJed Brown const PetscInt vertices[2] = {out->edgelist[e*2+0]+numCells, out->edgelist[e*2+1]+numCells}; 5142*552f7358SJed Brown const PetscInt *edges; 5143*552f7358SJed Brown PetscInt numEdges; 5144*552f7358SJed Brown 5145*552f7358SJed Brown ierr = DMPlexGetJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5146*552f7358SJed Brown if (numEdges != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Two vertices must cover only one edge, not %D", numEdges); 5147*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dmRefined, "marker", edges[0], out->edgemarkerlist[e]);CHKERRQ(ierr); 5148*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dmRefined, 2, vertices, &numEdges, &edges);CHKERRQ(ierr); 5149*552f7358SJed Brown } 5150*552f7358SJed Brown } 5151*552f7358SJed Brown for (f = 0; f < out->numberoftrifaces; f++) { 5152*552f7358SJed Brown if (out->trifacemarkerlist[f]) { 5153*552f7358SJed Brown const PetscInt vertices[3] = {out->trifacelist[f*3+0]+numCells, out->trifacelist[f*3+1]+numCells, out->trifacelist[f*3+2]+numCells}; 5154*552f7358SJed Brown const PetscInt *faces; 5155*552f7358SJed Brown PetscInt numFaces; 5156*552f7358SJed Brown 5157*552f7358SJed Brown ierr = DMPlexGetFullJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5158*552f7358SJed Brown if (numFaces != 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Three vertices must cover only one face, not %D", numFaces); 5159*552f7358SJed Brown ierr = DMPlexSetLabelValue(*dmRefined, "marker", faces[0], out->trifacemarkerlist[f]);CHKERRQ(ierr); 5160*552f7358SJed Brown ierr = DMPlexRestoreJoin(*dmRefined, 3, vertices, &numFaces, &faces);CHKERRQ(ierr); 5161*552f7358SJed Brown } 5162*552f7358SJed Brown } 5163*552f7358SJed Brown } 5164*552f7358SJed Brown ierr = DMPlexSetRefinementUniform(*dmRefined, PETSC_FALSE);CHKERRQ(ierr); 5165*552f7358SJed Brown } 5166*552f7358SJed Brown ierr = PLCDestroy(&in);CHKERRQ(ierr); 5167*552f7358SJed Brown ierr = PLCDestroy(&out);CHKERRQ(ierr); 5168*552f7358SJed Brown PetscFunctionReturn(0); 5169*552f7358SJed Brown } 5170*552f7358SJed Brown #endif 5171*552f7358SJed Brown 5172*552f7358SJed Brown #undef __FUNCT__ 5173*552f7358SJed Brown #define __FUNCT__ "DMPlexGenerate" 5174*552f7358SJed Brown /*@C 5175*552f7358SJed Brown DMPlexGenerate - Generates a mesh. 5176*552f7358SJed Brown 5177*552f7358SJed Brown Not Collective 5178*552f7358SJed Brown 5179*552f7358SJed Brown Input Parameters: 5180*552f7358SJed Brown + boundary - The DMPlex boundary object 5181*552f7358SJed Brown . name - The mesh generation package name 5182*552f7358SJed Brown - interpolate - Flag to create intermediate mesh elements 5183*552f7358SJed Brown 5184*552f7358SJed Brown Output Parameter: 5185*552f7358SJed Brown . mesh - The DMPlex object 5186*552f7358SJed Brown 5187*552f7358SJed Brown Level: intermediate 5188*552f7358SJed Brown 5189*552f7358SJed Brown .keywords: mesh, elements 5190*552f7358SJed Brown .seealso: DMPlexCreate(), DMRefine() 5191*552f7358SJed Brown @*/ 5192*552f7358SJed Brown PetscErrorCode DMPlexGenerate(DM boundary, const char name[], PetscBool interpolate, DM *mesh) 5193*552f7358SJed Brown { 5194*552f7358SJed Brown PetscInt dim; 5195*552f7358SJed Brown char genname[1024]; 5196*552f7358SJed Brown PetscBool isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 5197*552f7358SJed Brown PetscErrorCode ierr; 5198*552f7358SJed Brown 5199*552f7358SJed Brown PetscFunctionBegin; 5200*552f7358SJed Brown PetscValidHeaderSpecific(boundary, DM_CLASSID, 1); 5201*552f7358SJed Brown PetscValidLogicalCollectiveBool(boundary, interpolate, 2); 5202*552f7358SJed Brown ierr = DMPlexGetDimension(boundary, &dim);CHKERRQ(ierr); 5203*552f7358SJed Brown ierr = PetscOptionsGetString(((PetscObject) boundary)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 5204*552f7358SJed Brown if (flg) {name = genname;} 5205*552f7358SJed Brown if (name) { 5206*552f7358SJed Brown ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 5207*552f7358SJed Brown ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 5208*552f7358SJed Brown ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 5209*552f7358SJed Brown } 5210*552f7358SJed Brown switch(dim) { 5211*552f7358SJed Brown case 1: 5212*552f7358SJed Brown if (!name || isTriangle) { 5213*552f7358SJed Brown #ifdef PETSC_HAVE_TRIANGLE 5214*552f7358SJed Brown ierr = DMPlexGenerate_Triangle(boundary, interpolate, mesh);CHKERRQ(ierr); 5215*552f7358SJed Brown #else 5216*552f7358SJed Brown SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation needs external package support.\nPlease reconfigure with --download-triangle."); 5217*552f7358SJed Brown #endif 5218*552f7358SJed Brown } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 5219*552f7358SJed Brown break; 5220*552f7358SJed Brown case 2: 5221*552f7358SJed Brown if (!name || isCTetgen) { 5222*552f7358SJed Brown #ifdef PETSC_HAVE_CTETGEN 5223*552f7358SJed Brown ierr = DMPlexGenerate_CTetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5224*552f7358SJed Brown #else 5225*552f7358SJed Brown SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 5226*552f7358SJed Brown #endif 5227*552f7358SJed Brown } else if (isTetgen) { 5228*552f7358SJed Brown #ifdef PETSC_HAVE_TETGEN 5229*552f7358SJed Brown ierr = DMPlexGenerate_Tetgen(boundary, interpolate, mesh);CHKERRQ(ierr); 5230*552f7358SJed Brown #else 5231*552f7358SJed Brown SETERRQ(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 5232*552f7358SJed Brown #endif 5233*552f7358SJed Brown } else SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 5234*552f7358SJed Brown break; 5235*552f7358SJed Brown default: 5236*552f7358SJed Brown SETERRQ1(((PetscObject) boundary)->comm, PETSC_ERR_SUP, "Mesh generation for a dimension %d boundary is not supported.", dim); 5237*552f7358SJed Brown } 5238*552f7358SJed Brown PetscFunctionReturn(0); 5239*552f7358SJed Brown } 5240*552f7358SJed Brown 5241*552f7358SJed Brown typedef PetscInt CellRefiner; 5242*552f7358SJed Brown 5243*552f7358SJed Brown #undef __FUNCT__ 5244*552f7358SJed Brown #define __FUNCT__ "GetDepthStart_Private" 5245*552f7358SJed Brown PETSC_STATIC_INLINE PetscErrorCode GetDepthStart_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cStart, PetscInt *fStart, PetscInt *eStart, PetscInt *vStart) 5246*552f7358SJed Brown { 5247*552f7358SJed Brown PetscFunctionBegin; 5248*552f7358SJed Brown if (cStart) *cStart = 0; 5249*552f7358SJed Brown if (vStart) *vStart = depthSize[depth]; 5250*552f7358SJed Brown if (fStart) *fStart = depthSize[depth] + depthSize[0]; 5251*552f7358SJed Brown if (eStart) *eStart = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5252*552f7358SJed Brown PetscFunctionReturn(0); 5253*552f7358SJed Brown } 5254*552f7358SJed Brown 5255*552f7358SJed Brown #undef __FUNCT__ 5256*552f7358SJed Brown #define __FUNCT__ "GetDepthEnd_Private" 5257*552f7358SJed Brown PETSC_STATIC_INLINE PetscErrorCode GetDepthEnd_Private(PetscInt depth, PetscInt depthSize[], PetscInt *cEnd, PetscInt *fEnd, PetscInt *eEnd, PetscInt *vEnd) 5258*552f7358SJed Brown { 5259*552f7358SJed Brown PetscFunctionBegin; 5260*552f7358SJed Brown if (cEnd) *cEnd = depthSize[depth]; 5261*552f7358SJed Brown if (vEnd) *vEnd = depthSize[depth] + depthSize[0]; 5262*552f7358SJed Brown if (fEnd) *fEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1]; 5263*552f7358SJed Brown if (eEnd) *eEnd = depthSize[depth] + depthSize[0] + depthSize[depth-1] + depthSize[1]; 5264*552f7358SJed Brown PetscFunctionReturn(0); 5265*552f7358SJed Brown } 5266*552f7358SJed Brown 5267*552f7358SJed Brown #undef __FUNCT__ 5268*552f7358SJed Brown #define __FUNCT__ "CellRefinerGetSizes" 5269*552f7358SJed Brown PetscErrorCode CellRefinerGetSizes(CellRefiner refiner, DM dm, PetscInt depthSize[]) 5270*552f7358SJed Brown { 5271*552f7358SJed Brown PetscInt cStart, cEnd, vStart, vEnd, fStart, fEnd, eStart, eEnd; 5272*552f7358SJed Brown PetscErrorCode ierr; 5273*552f7358SJed Brown 5274*552f7358SJed Brown PetscFunctionBegin; 5275*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5276*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5277*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5278*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5279*552f7358SJed Brown switch(refiner) { 5280*552f7358SJed Brown case 1: 5281*552f7358SJed Brown /* Simplicial 2D */ 5282*552f7358SJed Brown depthSize[0] = vEnd - vStart + fEnd - fStart; /* Add a vertex on every face */ 5283*552f7358SJed Brown depthSize[1] = 2*(fEnd - fStart) + 3*(cEnd - cStart); /* Every face is split into 2 faces and 3 faces are added for each cell */ 5284*552f7358SJed Brown depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5285*552f7358SJed Brown break; 5286*552f7358SJed Brown case 2: 5287*552f7358SJed Brown /* Hex 2D */ 5288*552f7358SJed Brown depthSize[0] = vEnd - vStart + cEnd - cStart + fEnd - fStart; /* Add a vertex on every face and cell */ 5289*552f7358SJed Brown depthSize[1] = 2*(fEnd - fStart) + 4*(cEnd - cStart); /* Every face is split into 2 faces and 4 faces are added for each cell */ 5290*552f7358SJed Brown depthSize[2] = 4*(cEnd - cStart); /* Every cell split into 4 cells */ 5291*552f7358SJed Brown break; 5292*552f7358SJed Brown default: 5293*552f7358SJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5294*552f7358SJed Brown } 5295*552f7358SJed Brown PetscFunctionReturn(0); 5296*552f7358SJed Brown } 5297*552f7358SJed Brown 5298*552f7358SJed Brown #undef __FUNCT__ 5299*552f7358SJed Brown #define __FUNCT__ "CellRefinerSetConeSizes" 5300*552f7358SJed Brown PetscErrorCode CellRefinerSetConeSizes(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5301*552f7358SJed Brown { 5302*552f7358SJed Brown PetscInt depth, cStart, cStartNew, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fStartNew, fEnd, f, eStart, eStartNew, eEnd, r; 5303*552f7358SJed Brown PetscErrorCode ierr; 5304*552f7358SJed Brown 5305*552f7358SJed Brown PetscFunctionBegin; 5306*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5307*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5308*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5309*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5310*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5311*552f7358SJed Brown ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5312*552f7358SJed Brown switch(refiner) { 5313*552f7358SJed Brown case 1: 5314*552f7358SJed Brown /* Simplicial 2D */ 5315*552f7358SJed Brown /* All cells have 3 faces */ 5316*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5317*552f7358SJed Brown for(r = 0; r < 4; ++r) { 5318*552f7358SJed Brown const PetscInt newp = (c - cStart)*4 + r; 5319*552f7358SJed Brown 5320*552f7358SJed Brown ierr = DMPlexSetConeSize(rdm, newp, 3);CHKERRQ(ierr); 5321*552f7358SJed Brown } 5322*552f7358SJed Brown } 5323*552f7358SJed Brown /* Split faces have 2 vertices and the same cells as the parent */ 5324*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5325*552f7358SJed Brown for(r = 0; r < 2; ++r) { 5326*552f7358SJed Brown const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5327*552f7358SJed Brown PetscInt size; 5328*552f7358SJed Brown 5329*552f7358SJed Brown ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5330*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5331*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5332*552f7358SJed Brown } 5333*552f7358SJed Brown } 5334*552f7358SJed Brown /* Interior faces have 2 vertices and 2 cells */ 5335*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5336*552f7358SJed Brown for(r = 0; r < 3; ++r) { 5337*552f7358SJed Brown const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5338*552f7358SJed Brown 5339*552f7358SJed Brown ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5340*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5341*552f7358SJed Brown } 5342*552f7358SJed Brown } 5343*552f7358SJed Brown /* Old vertices have identical supports */ 5344*552f7358SJed Brown for(v = vStart; v < vEnd; ++v) { 5345*552f7358SJed Brown const PetscInt newp = vStartNew + (v - vStart); 5346*552f7358SJed Brown PetscInt size; 5347*552f7358SJed Brown 5348*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5349*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5350*552f7358SJed Brown } 5351*552f7358SJed Brown /* Face vertices have 2 + cells*2 supports */ 5352*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5353*552f7358SJed Brown const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5354*552f7358SJed Brown PetscInt size; 5355*552f7358SJed Brown 5356*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5357*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, 2 + size*2);CHKERRQ(ierr); 5358*552f7358SJed Brown } 5359*552f7358SJed Brown break; 5360*552f7358SJed Brown case 2: 5361*552f7358SJed Brown /* Hex 2D */ 5362*552f7358SJed Brown /* All cells have 4 faces */ 5363*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5364*552f7358SJed Brown for(r = 0; r < 4; ++r) { 5365*552f7358SJed Brown const PetscInt newp = (c - cStart)*4 + r; 5366*552f7358SJed Brown 5367*552f7358SJed Brown ierr = DMPlexSetConeSize(rdm, newp, 4);CHKERRQ(ierr); 5368*552f7358SJed Brown } 5369*552f7358SJed Brown } 5370*552f7358SJed Brown /* Split faces have 2 vertices and the same cells as the parent */ 5371*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5372*552f7358SJed Brown for(r = 0; r < 2; ++r) { 5373*552f7358SJed Brown const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5374*552f7358SJed Brown PetscInt size; 5375*552f7358SJed Brown 5376*552f7358SJed Brown ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5377*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5378*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5379*552f7358SJed Brown } 5380*552f7358SJed Brown } 5381*552f7358SJed Brown /* Interior faces have 2 vertices and 2 cells */ 5382*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5383*552f7358SJed Brown for(r = 0; r < 4; ++r) { 5384*552f7358SJed Brown const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5385*552f7358SJed Brown 5386*552f7358SJed Brown ierr = DMPlexSetConeSize(rdm, newp, 2);CHKERRQ(ierr); 5387*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, 2);CHKERRQ(ierr); 5388*552f7358SJed Brown } 5389*552f7358SJed Brown } 5390*552f7358SJed Brown /* Old vertices have identical supports */ 5391*552f7358SJed Brown for(v = vStart; v < vEnd; ++v) { 5392*552f7358SJed Brown const PetscInt newp = vStartNew + (v - vStart); 5393*552f7358SJed Brown PetscInt size; 5394*552f7358SJed Brown 5395*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5396*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, size);CHKERRQ(ierr); 5397*552f7358SJed Brown } 5398*552f7358SJed Brown /* Face vertices have 2 + cells supports */ 5399*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5400*552f7358SJed Brown const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5401*552f7358SJed Brown PetscInt size; 5402*552f7358SJed Brown 5403*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5404*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, 2 + size);CHKERRQ(ierr); 5405*552f7358SJed Brown } 5406*552f7358SJed Brown /* Cell vertices have 4 supports */ 5407*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5408*552f7358SJed Brown const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5409*552f7358SJed Brown 5410*552f7358SJed Brown ierr = DMPlexSetSupportSize(rdm, newp, 4);CHKERRQ(ierr); 5411*552f7358SJed Brown } 5412*552f7358SJed Brown break; 5413*552f7358SJed Brown default: 5414*552f7358SJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5415*552f7358SJed Brown } 5416*552f7358SJed Brown PetscFunctionReturn(0); 5417*552f7358SJed Brown } 5418*552f7358SJed Brown 5419*552f7358SJed Brown #undef __FUNCT__ 5420*552f7358SJed Brown #define __FUNCT__ "CellRefinerSetCones" 5421*552f7358SJed Brown PetscErrorCode CellRefinerSetCones(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5422*552f7358SJed Brown { 5423*552f7358SJed Brown PetscInt depth, cStart, cEnd, cStartNew, cEndNew, c, vStart, vEnd, vStartNew, vEndNew, v, fStart, fEnd, fStartNew, fEndNew, f, eStart, eEnd, eStartNew, eEndNew, r, p; 5424*552f7358SJed Brown PetscInt maxSupportSize, *supportRef; 5425*552f7358SJed Brown PetscErrorCode ierr; 5426*552f7358SJed Brown 5427*552f7358SJed Brown PetscFunctionBegin; 5428*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5429*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5430*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 5431*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5432*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5433*552f7358SJed Brown ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 5434*552f7358SJed Brown ierr = GetDepthEnd_Private(depth, depthSize, &cEndNew, &fEndNew, &eEndNew, &vEndNew);CHKERRQ(ierr); 5435*552f7358SJed Brown switch(refiner) { 5436*552f7358SJed Brown case 1: 5437*552f7358SJed Brown /* Simplicial 2D */ 5438*552f7358SJed Brown /* 5439*552f7358SJed Brown 2 5440*552f7358SJed Brown |\ 5441*552f7358SJed Brown | \ 5442*552f7358SJed Brown | \ 5443*552f7358SJed Brown | \ 5444*552f7358SJed Brown | C \ 5445*552f7358SJed Brown | \ 5446*552f7358SJed Brown | \ 5447*552f7358SJed Brown 2---1---1 5448*552f7358SJed Brown |\ D / \ 5449*552f7358SJed Brown | 2 0 \ 5450*552f7358SJed Brown |A \ / B \ 5451*552f7358SJed Brown 0---0-------1 5452*552f7358SJed Brown */ 5453*552f7358SJed Brown /* All cells have 3 faces */ 5454*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5455*552f7358SJed Brown const PetscInt newp = (c - cStart)*4; 5456*552f7358SJed Brown const PetscInt *cone, *ornt; 5457*552f7358SJed Brown PetscInt coneNew[3], orntNew[3]; 5458*552f7358SJed Brown 5459*552f7358SJed Brown ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5460*552f7358SJed Brown ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5461*552f7358SJed Brown /* A triangle */ 5462*552f7358SJed Brown coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5463*552f7358SJed Brown orntNew[0] = ornt[0]; 5464*552f7358SJed Brown coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5465*552f7358SJed Brown orntNew[1] = -2; 5466*552f7358SJed Brown coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5467*552f7358SJed Brown orntNew[2] = ornt[2]; 5468*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5469*552f7358SJed Brown ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5470*552f7358SJed Brown #if 1 5471*552f7358SJed Brown if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5472*552f7358SJed Brown for(p = 0; p < 3; ++p) { 5473*552f7358SJed Brown if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5474*552f7358SJed Brown } 5475*552f7358SJed Brown #endif 5476*552f7358SJed Brown /* B triangle */ 5477*552f7358SJed Brown coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5478*552f7358SJed Brown orntNew[0] = ornt[0]; 5479*552f7358SJed Brown coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5480*552f7358SJed Brown orntNew[1] = ornt[1]; 5481*552f7358SJed Brown coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5482*552f7358SJed Brown orntNew[2] = -2; 5483*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5484*552f7358SJed Brown ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5485*552f7358SJed Brown #if 1 5486*552f7358SJed Brown if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 5487*552f7358SJed Brown for(p = 0; p < 3; ++p) { 5488*552f7358SJed Brown if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5489*552f7358SJed Brown } 5490*552f7358SJed Brown #endif 5491*552f7358SJed Brown /* C triangle */ 5492*552f7358SJed Brown coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5493*552f7358SJed Brown orntNew[0] = -2; 5494*552f7358SJed Brown coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5495*552f7358SJed Brown orntNew[1] = ornt[1]; 5496*552f7358SJed Brown coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5497*552f7358SJed Brown orntNew[2] = ornt[2]; 5498*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5499*552f7358SJed Brown ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5500*552f7358SJed Brown #if 1 5501*552f7358SJed Brown if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 5502*552f7358SJed Brown for(p = 0; p < 3; ++p) { 5503*552f7358SJed Brown if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5504*552f7358SJed Brown } 5505*552f7358SJed Brown #endif 5506*552f7358SJed Brown /* D triangle */ 5507*552f7358SJed Brown coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 0; 5508*552f7358SJed Brown orntNew[0] = 0; 5509*552f7358SJed Brown coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 1; 5510*552f7358SJed Brown orntNew[1] = 0; 5511*552f7358SJed Brown coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + 2; 5512*552f7358SJed Brown orntNew[2] = 0; 5513*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5514*552f7358SJed Brown ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5515*552f7358SJed Brown #if 1 5516*552f7358SJed Brown if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 5517*552f7358SJed Brown for(p = 0; p < 3; ++p) { 5518*552f7358SJed Brown if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5519*552f7358SJed Brown } 5520*552f7358SJed Brown #endif 5521*552f7358SJed Brown } 5522*552f7358SJed Brown /* Split faces have 2 vertices and the same cells as the parent */ 5523*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5524*552f7358SJed Brown ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5525*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5526*552f7358SJed Brown const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5527*552f7358SJed Brown 5528*552f7358SJed Brown for(r = 0; r < 2; ++r) { 5529*552f7358SJed Brown const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5530*552f7358SJed Brown const PetscInt *cone, *support; 5531*552f7358SJed Brown PetscInt coneNew[2], coneSize, c, supportSize, s; 5532*552f7358SJed Brown 5533*552f7358SJed Brown ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5534*552f7358SJed Brown coneNew[0] = vStartNew + (cone[0] - vStart); 5535*552f7358SJed Brown coneNew[1] = vStartNew + (cone[1] - vStart); 5536*552f7358SJed Brown coneNew[(r+1)%2] = newv; 5537*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5538*552f7358SJed Brown #if 1 5539*552f7358SJed Brown if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5540*552f7358SJed Brown for(p = 0; p < 2; ++p) { 5541*552f7358SJed Brown if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5542*552f7358SJed Brown } 5543*552f7358SJed Brown #endif 5544*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5545*552f7358SJed Brown ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5546*552f7358SJed Brown for(s = 0; s < supportSize; ++s) { 5547*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5548*552f7358SJed Brown ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5549*552f7358SJed Brown for(c = 0; c < coneSize; ++c) { 5550*552f7358SJed Brown if (cone[c] == f) { 5551*552f7358SJed Brown break; 5552*552f7358SJed Brown } 5553*552f7358SJed Brown } 5554*552f7358SJed Brown supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%3; 5555*552f7358SJed Brown } 5556*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5557*552f7358SJed Brown #if 1 5558*552f7358SJed Brown if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5559*552f7358SJed Brown for(p = 0; p < supportSize; ++p) { 5560*552f7358SJed Brown if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 5561*552f7358SJed Brown } 5562*552f7358SJed Brown #endif 5563*552f7358SJed Brown } 5564*552f7358SJed Brown } 5565*552f7358SJed Brown /* Interior faces have 2 vertices and 2 cells */ 5566*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5567*552f7358SJed Brown const PetscInt *cone; 5568*552f7358SJed Brown 5569*552f7358SJed Brown ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5570*552f7358SJed Brown for(r = 0; r < 3; ++r) { 5571*552f7358SJed Brown const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*3 + r; 5572*552f7358SJed Brown PetscInt coneNew[2]; 5573*552f7358SJed Brown PetscInt supportNew[2]; 5574*552f7358SJed Brown 5575*552f7358SJed Brown coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5576*552f7358SJed Brown coneNew[1] = vStartNew + (vEnd - vStart) + (cone[(r+1)%3] - fStart); 5577*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5578*552f7358SJed Brown #if 1 5579*552f7358SJed Brown if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5580*552f7358SJed Brown for(p = 0; p < 2; ++p) { 5581*552f7358SJed Brown if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5582*552f7358SJed Brown } 5583*552f7358SJed Brown #endif 5584*552f7358SJed Brown supportNew[0] = (c - cStart)*4 + r; 5585*552f7358SJed Brown supportNew[1] = (c - cStart)*4 + 3; 5586*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5587*552f7358SJed Brown #if 1 5588*552f7358SJed Brown if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5589*552f7358SJed Brown for(p = 0; p < 2; ++p) { 5590*552f7358SJed Brown if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5591*552f7358SJed Brown } 5592*552f7358SJed Brown #endif 5593*552f7358SJed Brown } 5594*552f7358SJed Brown } 5595*552f7358SJed Brown /* Old vertices have identical supports */ 5596*552f7358SJed Brown for(v = vStart; v < vEnd; ++v) { 5597*552f7358SJed Brown const PetscInt newp = vStartNew + (v - vStart); 5598*552f7358SJed Brown const PetscInt *support, *cone; 5599*552f7358SJed Brown PetscInt size, s; 5600*552f7358SJed Brown 5601*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5602*552f7358SJed Brown ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5603*552f7358SJed Brown for(s = 0; s < size; ++s) { 5604*552f7358SJed Brown PetscInt r = 0; 5605*552f7358SJed Brown 5606*552f7358SJed Brown ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5607*552f7358SJed Brown if (cone[1] == v) r = 1; 5608*552f7358SJed Brown supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5609*552f7358SJed Brown } 5610*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5611*552f7358SJed Brown #if 1 5612*552f7358SJed Brown if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5613*552f7358SJed Brown for(p = 0; p < size; ++p) { 5614*552f7358SJed Brown if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5615*552f7358SJed Brown } 5616*552f7358SJed Brown #endif 5617*552f7358SJed Brown } 5618*552f7358SJed Brown /* Face vertices have 2 + cells*2 supports */ 5619*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5620*552f7358SJed Brown const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5621*552f7358SJed Brown const PetscInt *cone, *support; 5622*552f7358SJed Brown PetscInt size, s; 5623*552f7358SJed Brown 5624*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5625*552f7358SJed Brown ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5626*552f7358SJed Brown supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5627*552f7358SJed Brown supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5628*552f7358SJed Brown for(s = 0; s < size; ++s) { 5629*552f7358SJed Brown PetscInt r = 0; 5630*552f7358SJed Brown 5631*552f7358SJed Brown ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5632*552f7358SJed Brown if (cone[1] == f) r = 1; 5633*552f7358SJed Brown else if (cone[2] == f) r = 2; 5634*552f7358SJed Brown supportRef[2+s*2+0] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + (r+2)%3; 5635*552f7358SJed Brown supportRef[2+s*2+1] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*3 + r; 5636*552f7358SJed Brown } 5637*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5638*552f7358SJed Brown #if 1 5639*552f7358SJed Brown if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5640*552f7358SJed Brown for(p = 0; p < 2+size*2; ++p) { 5641*552f7358SJed Brown if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5642*552f7358SJed Brown } 5643*552f7358SJed Brown #endif 5644*552f7358SJed Brown } 5645*552f7358SJed Brown ierr = PetscFree(supportRef);CHKERRQ(ierr); 5646*552f7358SJed Brown break; 5647*552f7358SJed Brown case 2: 5648*552f7358SJed Brown /* Hex 2D */ 5649*552f7358SJed Brown /* 5650*552f7358SJed Brown 3---------2---------2 5651*552f7358SJed Brown | | | 5652*552f7358SJed Brown | D 2 C | 5653*552f7358SJed Brown | | | 5654*552f7358SJed Brown 3----3----0----1----1 5655*552f7358SJed Brown | | | 5656*552f7358SJed Brown | A 0 B | 5657*552f7358SJed Brown | | | 5658*552f7358SJed Brown 0---------0---------1 5659*552f7358SJed Brown */ 5660*552f7358SJed Brown /* All cells have 4 faces */ 5661*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5662*552f7358SJed Brown const PetscInt newp = (c - cStart)*4; 5663*552f7358SJed Brown const PetscInt *cone, *ornt; 5664*552f7358SJed Brown PetscInt coneNew[4], orntNew[4]; 5665*552f7358SJed Brown 5666*552f7358SJed Brown ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5667*552f7358SJed Brown ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5668*552f7358SJed Brown /* A quad */ 5669*552f7358SJed Brown coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 1 : 0); 5670*552f7358SJed Brown orntNew[0] = ornt[0]; 5671*552f7358SJed Brown coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5672*552f7358SJed Brown orntNew[1] = 0; 5673*552f7358SJed Brown coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5674*552f7358SJed Brown orntNew[2] = -2; 5675*552f7358SJed Brown coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 0 : 1); 5676*552f7358SJed Brown orntNew[3] = ornt[3]; 5677*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp+0, coneNew);CHKERRQ(ierr); 5678*552f7358SJed Brown ierr = DMPlexSetConeOrientation(rdm, newp+0, orntNew);CHKERRQ(ierr); 5679*552f7358SJed Brown #if 1 5680*552f7358SJed Brown if ((newp+0 < cStartNew) || (newp+0 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+0, cStartNew, cEndNew); 5681*552f7358SJed Brown for(p = 0; p < 4; ++p) { 5682*552f7358SJed Brown if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5683*552f7358SJed Brown } 5684*552f7358SJed Brown #endif 5685*552f7358SJed Brown /* B quad */ 5686*552f7358SJed Brown coneNew[0] = fStartNew + (cone[0] - fStart)*2 + (ornt[0] < 0 ? 0 : 1); 5687*552f7358SJed Brown orntNew[0] = ornt[0]; 5688*552f7358SJed Brown coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 1 : 0); 5689*552f7358SJed Brown orntNew[1] = ornt[1]; 5690*552f7358SJed Brown coneNew[2] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5691*552f7358SJed Brown orntNew[2] = 0; 5692*552f7358SJed Brown coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 0; 5693*552f7358SJed Brown orntNew[3] = -2; 5694*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp+1, coneNew);CHKERRQ(ierr); 5695*552f7358SJed Brown ierr = DMPlexSetConeOrientation(rdm, newp+1, orntNew);CHKERRQ(ierr); 5696*552f7358SJed Brown #if 1 5697*552f7358SJed Brown if ((newp+1 < cStartNew) || (newp+1 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+1, cStartNew, cEndNew); 5698*552f7358SJed Brown for(p = 0; p < 4; ++p) { 5699*552f7358SJed Brown if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5700*552f7358SJed Brown } 5701*552f7358SJed Brown #endif 5702*552f7358SJed Brown /* C quad */ 5703*552f7358SJed Brown coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 1; 5704*552f7358SJed Brown orntNew[0] = -2; 5705*552f7358SJed Brown coneNew[1] = fStartNew + (cone[1] - fStart)*2 + (ornt[1] < 0 ? 0 : 1); 5706*552f7358SJed Brown orntNew[1] = ornt[1]; 5707*552f7358SJed Brown coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 1 : 0); 5708*552f7358SJed Brown orntNew[2] = ornt[2]; 5709*552f7358SJed Brown coneNew[3] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5710*552f7358SJed Brown orntNew[3] = 0; 5711*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp+2, coneNew);CHKERRQ(ierr); 5712*552f7358SJed Brown ierr = DMPlexSetConeOrientation(rdm, newp+2, orntNew);CHKERRQ(ierr); 5713*552f7358SJed Brown #if 1 5714*552f7358SJed Brown if ((newp+2 < cStartNew) || (newp+2 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+2, cStartNew, cEndNew); 5715*552f7358SJed Brown for(p = 0; p < 4; ++p) { 5716*552f7358SJed Brown if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5717*552f7358SJed Brown } 5718*552f7358SJed Brown #endif 5719*552f7358SJed Brown /* D quad */ 5720*552f7358SJed Brown coneNew[0] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 3; 5721*552f7358SJed Brown orntNew[0] = 0; 5722*552f7358SJed Brown coneNew[1] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + 2; 5723*552f7358SJed Brown orntNew[1] = -2; 5724*552f7358SJed Brown coneNew[2] = fStartNew + (cone[2] - fStart)*2 + (ornt[2] < 0 ? 0 : 1); 5725*552f7358SJed Brown orntNew[2] = ornt[2]; 5726*552f7358SJed Brown coneNew[3] = fStartNew + (cone[3] - fStart)*2 + (ornt[3] < 0 ? 1 : 0); 5727*552f7358SJed Brown orntNew[3] = ornt[3]; 5728*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp+3, coneNew);CHKERRQ(ierr); 5729*552f7358SJed Brown ierr = DMPlexSetConeOrientation(rdm, newp+3, orntNew);CHKERRQ(ierr); 5730*552f7358SJed Brown #if 1 5731*552f7358SJed Brown if ((newp+3 < cStartNew) || (newp+3 >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", newp+3, cStartNew, cEndNew); 5732*552f7358SJed Brown for(p = 0; p < 4; ++p) { 5733*552f7358SJed Brown if ((coneNew[p] < fStartNew) || (coneNew[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", coneNew[p], fStartNew, fEndNew); 5734*552f7358SJed Brown } 5735*552f7358SJed Brown #endif 5736*552f7358SJed Brown } 5737*552f7358SJed Brown /* Split faces have 2 vertices and the same cells as the parent */ 5738*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, PETSC_NULL, &maxSupportSize);CHKERRQ(ierr); 5739*552f7358SJed Brown ierr = PetscMalloc((2 + maxSupportSize*2) * sizeof(PetscInt), &supportRef);CHKERRQ(ierr); 5740*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5741*552f7358SJed Brown const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5742*552f7358SJed Brown 5743*552f7358SJed Brown for(r = 0; r < 2; ++r) { 5744*552f7358SJed Brown const PetscInt newp = fStartNew + (f - fStart)*2 + r; 5745*552f7358SJed Brown const PetscInt *cone, *support; 5746*552f7358SJed Brown PetscInt coneNew[2], coneSize, c, supportSize, s; 5747*552f7358SJed Brown 5748*552f7358SJed Brown ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5749*552f7358SJed Brown coneNew[0] = vStartNew + (cone[0] - vStart); 5750*552f7358SJed Brown coneNew[1] = vStartNew + (cone[1] - vStart); 5751*552f7358SJed Brown coneNew[(r+1)%2] = newv; 5752*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5753*552f7358SJed Brown #if 1 5754*552f7358SJed Brown if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5755*552f7358SJed Brown for(p = 0; p < 2; ++p) { 5756*552f7358SJed Brown if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5757*552f7358SJed Brown } 5758*552f7358SJed Brown #endif 5759*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, f, &supportSize);CHKERRQ(ierr); 5760*552f7358SJed Brown ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5761*552f7358SJed Brown for(s = 0; s < supportSize; ++s) { 5762*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5763*552f7358SJed Brown ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5764*552f7358SJed Brown for(c = 0; c < coneSize; ++c) { 5765*552f7358SJed Brown if (cone[c] == f) { 5766*552f7358SJed Brown break; 5767*552f7358SJed Brown } 5768*552f7358SJed Brown } 5769*552f7358SJed Brown supportRef[s] = cStartNew + (support[s] - cStart)*4 + (c+r)%4; 5770*552f7358SJed Brown } 5771*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5772*552f7358SJed Brown #if 1 5773*552f7358SJed Brown if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5774*552f7358SJed Brown for(p = 0; p < supportSize; ++p) { 5775*552f7358SJed Brown if ((supportRef[p] < cStartNew) || (supportRef[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportRef[p], cStartNew, cEndNew); 5776*552f7358SJed Brown } 5777*552f7358SJed Brown #endif 5778*552f7358SJed Brown } 5779*552f7358SJed Brown } 5780*552f7358SJed Brown /* Interior faces have 2 vertices and 2 cells */ 5781*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5782*552f7358SJed Brown const PetscInt *cone; 5783*552f7358SJed Brown PetscInt coneNew[2], supportNew[2]; 5784*552f7358SJed Brown 5785*552f7358SJed Brown ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5786*552f7358SJed Brown for(r = 0; r < 4; ++r) { 5787*552f7358SJed Brown const PetscInt newp = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5788*552f7358SJed Brown 5789*552f7358SJed Brown coneNew[0] = vStartNew + (vEnd - vStart) + (cone[r] - fStart); 5790*552f7358SJed Brown coneNew[1] = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5791*552f7358SJed Brown ierr = DMPlexSetCone(rdm, newp, coneNew);CHKERRQ(ierr); 5792*552f7358SJed Brown #if 1 5793*552f7358SJed Brown if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5794*552f7358SJed Brown for(p = 0; p < 2; ++p) { 5795*552f7358SJed Brown if ((coneNew[p] < vStartNew) || (coneNew[p] >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", coneNew[p], vStartNew, vEndNew); 5796*552f7358SJed Brown } 5797*552f7358SJed Brown #endif 5798*552f7358SJed Brown supportNew[0] = (c - cStart)*4 + r; 5799*552f7358SJed Brown supportNew[1] = (c - cStart)*4 + (r+1)%4; 5800*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5801*552f7358SJed Brown #if 1 5802*552f7358SJed Brown if ((newp < fStartNew) || (newp >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", newp, fStartNew, fEndNew); 5803*552f7358SJed Brown for(p = 0; p < 2; ++p) { 5804*552f7358SJed Brown if ((supportNew[p] < cStartNew) || (supportNew[p] >= cEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a cell [%d, %d)", supportNew[p], cStartNew, cEndNew); 5805*552f7358SJed Brown } 5806*552f7358SJed Brown #endif 5807*552f7358SJed Brown } 5808*552f7358SJed Brown } 5809*552f7358SJed Brown /* Old vertices have identical supports */ 5810*552f7358SJed Brown for(v = vStart; v < vEnd; ++v) { 5811*552f7358SJed Brown const PetscInt newp = vStartNew + (v - vStart); 5812*552f7358SJed Brown const PetscInt *support, *cone; 5813*552f7358SJed Brown PetscInt size, s; 5814*552f7358SJed Brown 5815*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, v, &size);CHKERRQ(ierr); 5816*552f7358SJed Brown ierr = DMPlexGetSupport(dm, v, &support);CHKERRQ(ierr); 5817*552f7358SJed Brown for(s = 0; s < size; ++s) { 5818*552f7358SJed Brown PetscInt r = 0; 5819*552f7358SJed Brown 5820*552f7358SJed Brown ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5821*552f7358SJed Brown if (cone[1] == v) r = 1; 5822*552f7358SJed Brown supportRef[s] = fStartNew + (support[s] - fStart)*2 + r; 5823*552f7358SJed Brown } 5824*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5825*552f7358SJed Brown #if 1 5826*552f7358SJed Brown if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5827*552f7358SJed Brown for(p = 0; p < size; ++p) { 5828*552f7358SJed Brown if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5829*552f7358SJed Brown } 5830*552f7358SJed Brown #endif 5831*552f7358SJed Brown } 5832*552f7358SJed Brown /* Face vertices have 2 + cells supports */ 5833*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5834*552f7358SJed Brown const PetscInt newp = vStartNew + (vEnd - vStart) + (f - fStart); 5835*552f7358SJed Brown const PetscInt *cone, *support; 5836*552f7358SJed Brown PetscInt size, s; 5837*552f7358SJed Brown 5838*552f7358SJed Brown ierr = DMPlexGetSupportSize(dm, f, &size);CHKERRQ(ierr); 5839*552f7358SJed Brown ierr = DMPlexGetSupport(dm, f, &support);CHKERRQ(ierr); 5840*552f7358SJed Brown supportRef[0] = fStartNew + (f - fStart)*2 + 0; 5841*552f7358SJed Brown supportRef[1] = fStartNew + (f - fStart)*2 + 1; 5842*552f7358SJed Brown for(s = 0; s < size; ++s) { 5843*552f7358SJed Brown PetscInt r = 0; 5844*552f7358SJed Brown 5845*552f7358SJed Brown ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5846*552f7358SJed Brown if (cone[1] == f) r = 1; 5847*552f7358SJed Brown else if (cone[2] == f) r = 2; 5848*552f7358SJed Brown else if (cone[3] == f) r = 3; 5849*552f7358SJed Brown supportRef[2+s] = fStartNew + (fEnd - fStart)*2 + (support[s] - cStart)*4 + r; 5850*552f7358SJed Brown } 5851*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportRef);CHKERRQ(ierr); 5852*552f7358SJed Brown #if 1 5853*552f7358SJed Brown if ((newp < vStartNew) || (newp >= vEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a vertex [%d, %d)", newp, vStartNew, vEndNew); 5854*552f7358SJed Brown for(p = 0; p < 2+size; ++p) { 5855*552f7358SJed Brown if ((supportRef[p] < fStartNew) || (supportRef[p] >= fEndNew)) SETERRQ3(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Point %d is not a face [%d, %d)", supportRef[p], fStartNew, fEndNew); 5856*552f7358SJed Brown } 5857*552f7358SJed Brown #endif 5858*552f7358SJed Brown } 5859*552f7358SJed Brown /* Cell vertices have 4 supports */ 5860*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5861*552f7358SJed Brown const PetscInt newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5862*552f7358SJed Brown PetscInt supportNew[4]; 5863*552f7358SJed Brown 5864*552f7358SJed Brown for(r = 0; r < 4; ++r) { 5865*552f7358SJed Brown supportNew[r] = fStartNew + (fEnd - fStart)*2 + (c - cStart)*4 + r; 5866*552f7358SJed Brown } 5867*552f7358SJed Brown ierr = DMPlexSetSupport(rdm, newp, supportNew);CHKERRQ(ierr); 5868*552f7358SJed Brown } 5869*552f7358SJed Brown break; 5870*552f7358SJed Brown default: 5871*552f7358SJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5872*552f7358SJed Brown } 5873*552f7358SJed Brown PetscFunctionReturn(0); 5874*552f7358SJed Brown } 5875*552f7358SJed Brown 5876*552f7358SJed Brown #undef __FUNCT__ 5877*552f7358SJed Brown #define __FUNCT__ "CellRefinerSetCoordinates" 5878*552f7358SJed Brown PetscErrorCode CellRefinerSetCoordinates(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 5879*552f7358SJed Brown { 5880*552f7358SJed Brown PetscSection coordSection, coordSectionNew; 5881*552f7358SJed Brown Vec coordinates, coordinatesNew; 5882*552f7358SJed Brown PetscScalar *coords, *coordsNew; 5883*552f7358SJed Brown PetscInt dim, depth, coordSizeNew, cStart, cEnd, c, vStart, vStartNew, vEnd, v, fStart, fEnd, f; 5884*552f7358SJed Brown PetscErrorCode ierr; 5885*552f7358SJed Brown 5886*552f7358SJed Brown PetscFunctionBegin; 5887*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 5888*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5889*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5890*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5891*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 5892*552f7358SJed Brown ierr = GetDepthStart_Private(depth, depthSize, PETSC_NULL, PETSC_NULL, PETSC_NULL, &vStartNew);CHKERRQ(ierr); 5893*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 5894*552f7358SJed Brown ierr = PetscSectionCreate(((PetscObject) dm)->comm, &coordSectionNew);CHKERRQ(ierr); 5895*552f7358SJed Brown ierr = PetscSectionSetNumFields(coordSectionNew, 1);CHKERRQ(ierr); 5896*552f7358SJed Brown ierr = PetscSectionSetFieldComponents(coordSectionNew, 0, dim);CHKERRQ(ierr); 5897*552f7358SJed Brown ierr = PetscSectionSetChart(coordSectionNew, vStartNew, vStartNew+depthSize[0]);CHKERRQ(ierr); 5898*552f7358SJed Brown switch(refiner) { 5899*552f7358SJed Brown case 1: 5900*552f7358SJed Brown case 2: 5901*552f7358SJed Brown /* Simplicial and Hex 2D */ 5902*552f7358SJed Brown /* All vertices have the dim coordinates */ 5903*552f7358SJed Brown for(v = vStartNew; v < vStartNew+depthSize[0]; ++v) { 5904*552f7358SJed Brown ierr = PetscSectionSetDof(coordSectionNew, v, dim);CHKERRQ(ierr); 5905*552f7358SJed Brown ierr = PetscSectionSetFieldDof(coordSectionNew, v, 0, dim);CHKERRQ(ierr); 5906*552f7358SJed Brown } 5907*552f7358SJed Brown ierr = PetscSectionSetUp(coordSectionNew);CHKERRQ(ierr); 5908*552f7358SJed Brown ierr = DMPlexSetCoordinateSection(rdm, coordSectionNew);CHKERRQ(ierr); 5909*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 5910*552f7358SJed Brown ierr = PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew);CHKERRQ(ierr); 5911*552f7358SJed Brown ierr = VecCreate(((PetscObject) dm)->comm, &coordinatesNew);CHKERRQ(ierr); 5912*552f7358SJed Brown ierr = PetscObjectSetName((PetscObject) coordinatesNew, "coordinates");CHKERRQ(ierr); 5913*552f7358SJed Brown ierr = VecSetSizes(coordinatesNew, coordSizeNew, PETSC_DETERMINE);CHKERRQ(ierr); 5914*552f7358SJed Brown ierr = VecSetFromOptions(coordinatesNew);CHKERRQ(ierr); 5915*552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 5916*552f7358SJed Brown ierr = VecGetArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5917*552f7358SJed Brown /* Old vertices have the same coordinates */ 5918*552f7358SJed Brown for(v = vStart; v < vEnd; ++v) { 5919*552f7358SJed Brown const PetscInt newv = vStartNew + (v - vStart); 5920*552f7358SJed Brown PetscInt off, offnew, d; 5921*552f7358SJed Brown 5922*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 5923*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5924*552f7358SJed Brown for(d = 0; d < dim; ++d) { 5925*552f7358SJed Brown coordsNew[offnew+d] = coords[off+d]; 5926*552f7358SJed Brown } 5927*552f7358SJed Brown } 5928*552f7358SJed Brown /* Face vertices have the average of endpoint coordinates */ 5929*552f7358SJed Brown for(f = fStart; f < fEnd; ++f) { 5930*552f7358SJed Brown const PetscInt newv = vStartNew + (vEnd - vStart) + (f - fStart); 5931*552f7358SJed Brown const PetscInt *cone; 5932*552f7358SJed Brown PetscInt coneSize, offA, offB, offnew, d; 5933*552f7358SJed Brown 5934*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, f, &coneSize);CHKERRQ(ierr); 5935*552f7358SJed Brown if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Face %d cone should have two vertices, not %d", f, coneSize); 5936*552f7358SJed Brown ierr = DMPlexGetCone(dm, f, &cone);CHKERRQ(ierr); 5937*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5938*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5939*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5940*552f7358SJed Brown for(d = 0; d < dim; ++d) { 5941*552f7358SJed Brown coordsNew[offnew+d] = 0.5*(coords[offA+d] + coords[offB+d]); 5942*552f7358SJed Brown } 5943*552f7358SJed Brown } 5944*552f7358SJed Brown /* Just Hex 2D */ 5945*552f7358SJed Brown if (refiner == 2) { 5946*552f7358SJed Brown /* Cell vertices have the average of corner coordinates */ 5947*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 5948*552f7358SJed Brown const PetscInt newv = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (c - cStart); 5949*552f7358SJed Brown PetscInt *cone = PETSC_NULL; 5950*552f7358SJed Brown PetscInt closureSize, coneSize = 0, offA, offB, offC, offD, offnew, p, d; 5951*552f7358SJed Brown 5952*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5953*552f7358SJed Brown for(p = 0; p < closureSize*2; p += 2) { 5954*552f7358SJed Brown const PetscInt point = cone[p]; 5955*552f7358SJed Brown if ((point >= vStart) && (point < vEnd)) { 5956*552f7358SJed Brown cone[coneSize++] = point; 5957*552f7358SJed Brown } 5958*552f7358SJed Brown } 5959*552f7358SJed Brown if (coneSize != 4) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Quad %d cone should have four vertices, not %d", c, coneSize); 5960*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 5961*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 5962*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[2], &offC);CHKERRQ(ierr); 5963*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, cone[3], &offD);CHKERRQ(ierr); 5964*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSectionNew, newv, &offnew);CHKERRQ(ierr); 5965*552f7358SJed Brown for(d = 0; d < dim; ++d) { 5966*552f7358SJed Brown coordsNew[offnew+d] = 0.25*(coords[offA+d] + coords[offB+d] + coords[offC+d] + coords[offD+d]); 5967*552f7358SJed Brown } 5968*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &cone);CHKERRQ(ierr); 5969*552f7358SJed Brown } 5970*552f7358SJed Brown } 5971*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 5972*552f7358SJed Brown ierr = VecRestoreArray(coordinatesNew, &coordsNew);CHKERRQ(ierr); 5973*552f7358SJed Brown ierr = DMSetCoordinatesLocal(rdm, coordinatesNew);CHKERRQ(ierr); 5974*552f7358SJed Brown ierr = VecDestroy(&coordinatesNew);CHKERRQ(ierr); 5975*552f7358SJed Brown break; 5976*552f7358SJed Brown default: 5977*552f7358SJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 5978*552f7358SJed Brown } 5979*552f7358SJed Brown PetscFunctionReturn(0); 5980*552f7358SJed Brown } 5981*552f7358SJed Brown 5982*552f7358SJed Brown #undef __FUNCT__ 5983*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateProcessSF" 5984*552f7358SJed Brown PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 5985*552f7358SJed Brown { 5986*552f7358SJed Brown PetscInt numRoots, numLeaves, l; 5987*552f7358SJed Brown const PetscInt *localPoints; 5988*552f7358SJed Brown const PetscSFNode *remotePoints; 5989*552f7358SJed Brown PetscInt *localPointsNew; 5990*552f7358SJed Brown PetscSFNode *remotePointsNew; 5991*552f7358SJed Brown PetscInt *ranks, *ranksNew; 5992*552f7358SJed Brown PetscErrorCode ierr; 5993*552f7358SJed Brown 5994*552f7358SJed Brown PetscFunctionBegin; 5995*552f7358SJed Brown ierr = PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 5996*552f7358SJed Brown ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranks);CHKERRQ(ierr); 5997*552f7358SJed Brown for(l = 0; l < numLeaves; ++l) { 5998*552f7358SJed Brown ranks[l] = remotePoints[l].rank; 5999*552f7358SJed Brown } 6000*552f7358SJed Brown ierr = PetscSortRemoveDupsInt(&numLeaves, ranks);CHKERRQ(ierr); 6001*552f7358SJed Brown ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &ranksNew);CHKERRQ(ierr); 6002*552f7358SJed Brown ierr = PetscMalloc(numLeaves * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6003*552f7358SJed Brown ierr = PetscMalloc(numLeaves * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6004*552f7358SJed Brown for(l = 0; l < numLeaves; ++l) { 6005*552f7358SJed Brown ranksNew[l] = ranks[l]; 6006*552f7358SJed Brown localPointsNew[l] = l; 6007*552f7358SJed Brown remotePointsNew[l].index = 0; 6008*552f7358SJed Brown remotePointsNew[l].rank = ranksNew[l]; 6009*552f7358SJed Brown } 6010*552f7358SJed Brown ierr = PetscFree(ranks);CHKERRQ(ierr); 6011*552f7358SJed Brown ierr = ISCreateGeneral(((PetscObject) dm)->comm, numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks);CHKERRQ(ierr); 6012*552f7358SJed Brown ierr = PetscSFCreate(((PetscObject) dm)->comm, sfProcess);CHKERRQ(ierr); 6013*552f7358SJed Brown ierr = PetscSFSetFromOptions(*sfProcess);CHKERRQ(ierr); 6014*552f7358SJed Brown ierr = PetscSFSetGraph(*sfProcess, 1, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6015*552f7358SJed Brown PetscFunctionReturn(0); 6016*552f7358SJed Brown } 6017*552f7358SJed Brown 6018*552f7358SJed Brown #undef __FUNCT__ 6019*552f7358SJed Brown #define __FUNCT__ "CellRefinerCreateSF" 6020*552f7358SJed Brown PetscErrorCode CellRefinerCreateSF(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6021*552f7358SJed Brown { 6022*552f7358SJed Brown PetscSF sf, sfNew, sfProcess; 6023*552f7358SJed Brown IS processRanks; 6024*552f7358SJed Brown MPI_Datatype depthType; 6025*552f7358SJed Brown PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 6026*552f7358SJed Brown const PetscInt *localPoints, *neighbors; 6027*552f7358SJed Brown const PetscSFNode *remotePoints; 6028*552f7358SJed Brown PetscInt *localPointsNew; 6029*552f7358SJed Brown PetscSFNode *remotePointsNew; 6030*552f7358SJed Brown PetscInt *depthSizeOld, *rdepthSize, *rdepthSizeOld, *rvStart, *rvStartNew, *reStart, *reStartNew, *rfStart, *rfStartNew, *rcStart, *rcStartNew; 6031*552f7358SJed Brown PetscInt depth, numNeighbors, pStartNew, pEndNew, cStart, cStartNew, cEnd, vStart, vStartNew, vEnd, fStart, fStartNew, fEnd, eStart, eStartNew, eEnd, r, n; 6032*552f7358SJed Brown PetscErrorCode ierr; 6033*552f7358SJed Brown 6034*552f7358SJed Brown PetscFunctionBegin; 6035*552f7358SJed Brown ierr = DMPlexGetChart(rdm, &pStartNew, &pEndNew);CHKERRQ(ierr); 6036*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6037*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6038*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6039*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6040*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6041*552f7358SJed Brown ierr = GetDepthStart_Private(depth, depthSize, &cStartNew, &fStartNew, &eStartNew, &vStartNew);CHKERRQ(ierr); 6042*552f7358SJed Brown ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 6043*552f7358SJed Brown ierr = DMGetPointSF(rdm, &sfNew);CHKERRQ(ierr); 6044*552f7358SJed Brown /* Caculate size of new SF */ 6045*552f7358SJed Brown ierr = PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints);CHKERRQ(ierr); 6046*552f7358SJed Brown if (numRoots < 0) PetscFunctionReturn(0); 6047*552f7358SJed Brown for(l = 0; l < numLeaves; ++l) { 6048*552f7358SJed Brown const PetscInt p = localPoints[l]; 6049*552f7358SJed Brown 6050*552f7358SJed Brown switch(refiner) { 6051*552f7358SJed Brown case 1: 6052*552f7358SJed Brown /* Simplicial 2D */ 6053*552f7358SJed Brown if ((p >= vStart) && (p < vEnd)) { 6054*552f7358SJed Brown /* Old vertices stay the same */ 6055*552f7358SJed Brown ++numLeavesNew; 6056*552f7358SJed Brown } else if ((p >= fStart) && (p < fEnd)) { 6057*552f7358SJed Brown /* Old faces add new faces and vertex */ 6058*552f7358SJed Brown numLeavesNew += 1 + 2; 6059*552f7358SJed Brown } else if ((p >= cStart) && (p < cEnd)) { 6060*552f7358SJed Brown /* Old cells add new cells and interior faces */ 6061*552f7358SJed Brown numLeavesNew += 4 + 3; 6062*552f7358SJed Brown } 6063*552f7358SJed Brown break; 6064*552f7358SJed Brown case 2: 6065*552f7358SJed Brown /* Hex 2D */ 6066*552f7358SJed Brown if ((p >= vStart) && (p < vEnd)) { 6067*552f7358SJed Brown /* Old vertices stay the same */ 6068*552f7358SJed Brown ++numLeavesNew; 6069*552f7358SJed Brown } else if ((p >= fStart) && (p < fEnd)) { 6070*552f7358SJed Brown /* Old faces add new faces and vertex */ 6071*552f7358SJed Brown numLeavesNew += 1 + 2; 6072*552f7358SJed Brown } else if ((p >= cStart) && (p < cEnd)) { 6073*552f7358SJed Brown /* Old cells add new cells and interior faces */ 6074*552f7358SJed Brown numLeavesNew += 4 + 4; 6075*552f7358SJed Brown } 6076*552f7358SJed Brown break; 6077*552f7358SJed Brown default: 6078*552f7358SJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6079*552f7358SJed Brown } 6080*552f7358SJed Brown } 6081*552f7358SJed Brown /* Communicate depthSizes for each remote rank */ 6082*552f7358SJed Brown ierr = DMPlexCreateProcessSF(dm, sf, &processRanks, &sfProcess);CHKERRQ(ierr); 6083*552f7358SJed Brown ierr = ISGetLocalSize(processRanks, &numNeighbors);CHKERRQ(ierr); 6084*552f7358SJed Brown ierr = PetscMalloc5((depth+1)*numNeighbors,PetscInt,&rdepthSize,numNeighbors,PetscInt,&rvStartNew,numNeighbors,PetscInt,&reStartNew,numNeighbors,PetscInt,&rfStartNew,numNeighbors,PetscInt,&rcStartNew);CHKERRQ(ierr); 6085*552f7358SJed Brown ierr = PetscMalloc6(depth+1,PetscInt,&depthSizeOld,(depth+1)*numNeighbors,PetscInt,&rdepthSizeOld,numNeighbors,PetscInt,&rvStart,numNeighbors,PetscInt,&reStart,numNeighbors,PetscInt,&rfStart,numNeighbors,PetscInt,&rcStart);CHKERRQ(ierr); 6086*552f7358SJed Brown ierr = MPI_Type_contiguous(depth+1, MPIU_INT, &depthType);CHKERRQ(ierr); 6087*552f7358SJed Brown ierr = MPI_Type_commit(&depthType);CHKERRQ(ierr); 6088*552f7358SJed Brown ierr = PetscSFBcastBegin(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6089*552f7358SJed Brown ierr = PetscSFBcastEnd(sfProcess, depthType, depthSize, rdepthSize);CHKERRQ(ierr); 6090*552f7358SJed Brown for(n = 0; n < numNeighbors; ++n) { 6091*552f7358SJed Brown ierr = GetDepthStart_Private(depth, &rdepthSize[n*(depth+1)], &rcStartNew[n], &rfStartNew[n], &reStartNew[n], &rvStartNew[n]);CHKERRQ(ierr); 6092*552f7358SJed Brown } 6093*552f7358SJed Brown depthSizeOld[depth] = cEnd - cStart; 6094*552f7358SJed Brown depthSizeOld[0] = vEnd - vStart; 6095*552f7358SJed Brown depthSizeOld[depth-1] = fEnd - fStart; 6096*552f7358SJed Brown depthSizeOld[1] = eEnd - eStart; 6097*552f7358SJed Brown ierr = PetscSFBcastBegin(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6098*552f7358SJed Brown ierr = PetscSFBcastEnd(sfProcess, depthType, depthSizeOld, rdepthSizeOld);CHKERRQ(ierr); 6099*552f7358SJed Brown for(n = 0; n < numNeighbors; ++n) { 6100*552f7358SJed Brown ierr = GetDepthStart_Private(depth, &rdepthSizeOld[n*(depth+1)], &rcStart[n], &rfStart[n], &reStart[n], &rvStart[n]);CHKERRQ(ierr); 6101*552f7358SJed Brown } 6102*552f7358SJed Brown ierr = MPI_Type_free(&depthType);CHKERRQ(ierr); 6103*552f7358SJed Brown ierr = PetscSFDestroy(&sfProcess);CHKERRQ(ierr); 6104*552f7358SJed Brown /* Calculate new point SF */ 6105*552f7358SJed Brown ierr = PetscMalloc(numLeavesNew * sizeof(PetscInt), &localPointsNew);CHKERRQ(ierr); 6106*552f7358SJed Brown ierr = PetscMalloc(numLeavesNew * sizeof(PetscSFNode), &remotePointsNew);CHKERRQ(ierr); 6107*552f7358SJed Brown ierr = ISGetIndices(processRanks, &neighbors);CHKERRQ(ierr); 6108*552f7358SJed Brown for(l = 0, m = 0; l < numLeaves; ++l) { 6109*552f7358SJed Brown PetscInt p = localPoints[l]; 6110*552f7358SJed Brown PetscInt rp = remotePoints[l].index, n; 6111*552f7358SJed Brown PetscMPIInt rrank = remotePoints[l].rank; 6112*552f7358SJed Brown 6113*552f7358SJed Brown ierr = PetscFindInt(rrank, numNeighbors, neighbors, &n);CHKERRQ(ierr); 6114*552f7358SJed Brown if (n < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not locate remote rank %d", rrank); 6115*552f7358SJed Brown switch(refiner) { 6116*552f7358SJed Brown case 1: 6117*552f7358SJed Brown /* Simplicial 2D */ 6118*552f7358SJed Brown if ((p >= vStart) && (p < vEnd)) { 6119*552f7358SJed Brown /* Old vertices stay the same */ 6120*552f7358SJed Brown localPointsNew[m] = vStartNew + (p - vStart); 6121*552f7358SJed Brown remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6122*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6123*552f7358SJed Brown ++m; 6124*552f7358SJed Brown } else if ((p >= fStart) && (p < fEnd)) { 6125*552f7358SJed Brown /* Old faces add new faces and vertex */ 6126*552f7358SJed Brown localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6127*552f7358SJed Brown remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6128*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6129*552f7358SJed Brown ++m; 6130*552f7358SJed Brown for(r = 0; r < 2; ++r, ++m) { 6131*552f7358SJed Brown localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6132*552f7358SJed Brown remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6133*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6134*552f7358SJed Brown } 6135*552f7358SJed Brown } else if ((p >= cStart) && (p < cEnd)) { 6136*552f7358SJed Brown /* Old cells add new cells and interior faces */ 6137*552f7358SJed Brown for(r = 0; r < 4; ++r, ++m) { 6138*552f7358SJed Brown localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6139*552f7358SJed Brown remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6140*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6141*552f7358SJed Brown } 6142*552f7358SJed Brown for(r = 0; r < 3; ++r, ++m) { 6143*552f7358SJed Brown localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6144*552f7358SJed Brown remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*3 + r; 6145*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6146*552f7358SJed Brown } 6147*552f7358SJed Brown } 6148*552f7358SJed Brown break; 6149*552f7358SJed Brown case 2: 6150*552f7358SJed Brown /* Hex 2D */ 6151*552f7358SJed Brown if ((p >= vStart) && (p < vEnd)) { 6152*552f7358SJed Brown /* Old vertices stay the same */ 6153*552f7358SJed Brown localPointsNew[m] = vStartNew + (p - vStart); 6154*552f7358SJed Brown remotePointsNew[m].index = rvStartNew[n] + (rp - rvStart[n]); 6155*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6156*552f7358SJed Brown ++m; 6157*552f7358SJed Brown } else if ((p >= fStart) && (p < fEnd)) { 6158*552f7358SJed Brown /* Old faces add new faces and vertex */ 6159*552f7358SJed Brown localPointsNew[m] = vStartNew + (vEnd - vStart) + (p - fStart); 6160*552f7358SJed Brown remotePointsNew[m].index = rvStartNew[n] + rdepthSizeOld[n*(depth+1)+0] + (rp - rfStart[n]); 6161*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6162*552f7358SJed Brown ++m; 6163*552f7358SJed Brown for(r = 0; r < 2; ++r, ++m) { 6164*552f7358SJed Brown localPointsNew[m] = fStartNew + (p - fStart)*2 + r; 6165*552f7358SJed Brown remotePointsNew[m].index = rfStartNew[n] + (rp - rfStart[n])*2 + r; 6166*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6167*552f7358SJed Brown } 6168*552f7358SJed Brown } else if ((p >= cStart) && (p < cEnd)) { 6169*552f7358SJed Brown /* Old cells add new cells and interior faces */ 6170*552f7358SJed Brown for(r = 0; r < 4; ++r, ++m) { 6171*552f7358SJed Brown localPointsNew[m] = cStartNew + (p - cStart)*4 + r; 6172*552f7358SJed Brown remotePointsNew[m].index = rcStartNew[n] + (rp - rcStart[n])*4 + r; 6173*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6174*552f7358SJed Brown } 6175*552f7358SJed Brown for(r = 0; r < 4; ++r, ++m) { 6176*552f7358SJed Brown localPointsNew[m] = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6177*552f7358SJed Brown remotePointsNew[m].index = rfStartNew[n] + rdepthSizeOld[n*(depth+1)+depth-1]*2 + (rp - rcStart[n])*4 + r; 6178*552f7358SJed Brown remotePointsNew[m].rank = rrank; 6179*552f7358SJed Brown } 6180*552f7358SJed Brown } 6181*552f7358SJed Brown break; 6182*552f7358SJed Brown default: 6183*552f7358SJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6184*552f7358SJed Brown } 6185*552f7358SJed Brown } 6186*552f7358SJed Brown ierr = ISRestoreIndices(processRanks, &neighbors);CHKERRQ(ierr); 6187*552f7358SJed Brown ierr = ISDestroy(&processRanks);CHKERRQ(ierr); 6188*552f7358SJed Brown ierr = PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER);CHKERRQ(ierr); 6189*552f7358SJed Brown ierr = PetscFree5(rdepthSize,rvStartNew,reStartNew,rfStartNew,rcStartNew);CHKERRQ(ierr); 6190*552f7358SJed Brown ierr = PetscFree6(depthSizeOld,rdepthSizeOld,rvStart,reStart,rfStart,rcStart);CHKERRQ(ierr); 6191*552f7358SJed Brown PetscFunctionReturn(0); 6192*552f7358SJed Brown } 6193*552f7358SJed Brown 6194*552f7358SJed Brown #undef __FUNCT__ 6195*552f7358SJed Brown #define __FUNCT__ "CellRefinerCreateLabels" 6196*552f7358SJed Brown PetscErrorCode CellRefinerCreateLabels(CellRefiner refiner, DM dm, PetscInt depthSize[], DM rdm) 6197*552f7358SJed Brown { 6198*552f7358SJed Brown PetscInt numLabels, l; 6199*552f7358SJed Brown PetscInt newp, cStart, cEnd, vStart, vStartNew, vEnd, fStart, fStartNew, fEnd, eStart, eEnd, r; 6200*552f7358SJed Brown PetscErrorCode ierr; 6201*552f7358SJed Brown 6202*552f7358SJed Brown PetscFunctionBegin; 6203*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6204*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 6205*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6206*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 6207*552f7358SJed Brown vStartNew = depthSize[2]; 6208*552f7358SJed Brown fStartNew = depthSize[2] + depthSize[0]; 6209*552f7358SJed Brown ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 6210*552f7358SJed Brown for(l = 0; l < numLabels; ++l) { 6211*552f7358SJed Brown DMLabel label, labelNew; 6212*552f7358SJed Brown const char *lname; 6213*552f7358SJed Brown PetscBool isDepth; 6214*552f7358SJed Brown IS valueIS; 6215*552f7358SJed Brown const PetscInt *values; 6216*552f7358SJed Brown PetscInt numValues, val; 6217*552f7358SJed Brown 6218*552f7358SJed Brown ierr = DMPlexGetLabelName(dm, l, &lname);CHKERRQ(ierr); 6219*552f7358SJed Brown ierr = PetscStrcmp(lname, "depth", &isDepth);CHKERRQ(ierr); 6220*552f7358SJed Brown if (isDepth) continue; 6221*552f7358SJed Brown ierr = DMPlexCreateLabel(rdm, lname);CHKERRQ(ierr); 6222*552f7358SJed Brown ierr = DMPlexGetLabel(dm, lname, &label);CHKERRQ(ierr); 6223*552f7358SJed Brown ierr = DMPlexGetLabel(rdm, lname, &labelNew);CHKERRQ(ierr); 6224*552f7358SJed Brown ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 6225*552f7358SJed Brown ierr = ISGetLocalSize(valueIS, &numValues);CHKERRQ(ierr); 6226*552f7358SJed Brown ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 6227*552f7358SJed Brown for(val = 0; val < numValues; ++val) { 6228*552f7358SJed Brown IS pointIS; 6229*552f7358SJed Brown const PetscInt *points; 6230*552f7358SJed Brown PetscInt numPoints, n; 6231*552f7358SJed Brown 6232*552f7358SJed Brown ierr = DMLabelGetStratumIS(label, values[val], &pointIS);CHKERRQ(ierr); 6233*552f7358SJed Brown ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr); 6234*552f7358SJed Brown ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 6235*552f7358SJed Brown for(n = 0; n < numPoints; ++n) { 6236*552f7358SJed Brown const PetscInt p = points[n]; 6237*552f7358SJed Brown switch(refiner) { 6238*552f7358SJed Brown case 1: 6239*552f7358SJed Brown /* Simplicial 2D */ 6240*552f7358SJed Brown if ((p >= vStart) && (p < vEnd)) { 6241*552f7358SJed Brown /* Old vertices stay the same */ 6242*552f7358SJed Brown newp = vStartNew + (p - vStart); 6243*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6244*552f7358SJed Brown } else if ((p >= fStart) && (p < fEnd)) { 6245*552f7358SJed Brown /* Old faces add new faces and vertex */ 6246*552f7358SJed Brown newp = vStartNew + (vEnd - vStart) + (p - fStart); 6247*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6248*552f7358SJed Brown for(r = 0; r < 2; ++r) { 6249*552f7358SJed Brown newp = fStartNew + (p - fStart)*2 + r; 6250*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6251*552f7358SJed Brown } 6252*552f7358SJed Brown } else if ((p >= cStart) && (p < cEnd)) { 6253*552f7358SJed Brown /* Old cells add new cells and interior faces */ 6254*552f7358SJed Brown for(r = 0; r < 4; ++r) { 6255*552f7358SJed Brown newp = (p - cStart)*4 + r; 6256*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6257*552f7358SJed Brown } 6258*552f7358SJed Brown for(r = 0; r < 3; ++r) { 6259*552f7358SJed Brown newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*3 + r; 6260*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6261*552f7358SJed Brown } 6262*552f7358SJed Brown } 6263*552f7358SJed Brown break; 6264*552f7358SJed Brown case 2: 6265*552f7358SJed Brown /* Hex 2D */ 6266*552f7358SJed Brown if ((p >= vStart) && (p < vEnd)) { 6267*552f7358SJed Brown /* Old vertices stay the same */ 6268*552f7358SJed Brown newp = vStartNew + (p - vStart); 6269*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6270*552f7358SJed Brown } else if ((p >= fStart) && (p < fEnd)) { 6271*552f7358SJed Brown /* Old faces add new faces and vertex */ 6272*552f7358SJed Brown newp = vStartNew + (vEnd - vStart) + (p - fStart); 6273*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6274*552f7358SJed Brown for(r = 0; r < 2; ++r) { 6275*552f7358SJed Brown newp = fStartNew + (p - fStart)*2 + r; 6276*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6277*552f7358SJed Brown } 6278*552f7358SJed Brown } else if ((p >= cStart) && (p < cEnd)) { 6279*552f7358SJed Brown /* Old cells add new cells and interior faces and vertex */ 6280*552f7358SJed Brown for(r = 0; r < 4; ++r) { 6281*552f7358SJed Brown newp = (p - cStart)*4 + r; 6282*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6283*552f7358SJed Brown } 6284*552f7358SJed Brown for(r = 0; r < 4; ++r) { 6285*552f7358SJed Brown newp = fStartNew + (fEnd - fStart)*2 + (p - cStart)*4 + r; 6286*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6287*552f7358SJed Brown } 6288*552f7358SJed Brown newp = vStartNew + (vEnd - vStart) + (fEnd - fStart) + (p - cStart); 6289*552f7358SJed Brown ierr = DMLabelSetValue(labelNew, newp, values[val]);CHKERRQ(ierr); 6290*552f7358SJed Brown } 6291*552f7358SJed Brown break; 6292*552f7358SJed Brown default: 6293*552f7358SJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown cell refiner %d", refiner); 6294*552f7358SJed Brown } 6295*552f7358SJed Brown } 6296*552f7358SJed Brown ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 6297*552f7358SJed Brown ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 6298*552f7358SJed Brown } 6299*552f7358SJed Brown ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 6300*552f7358SJed Brown ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 6301*552f7358SJed Brown if (0) { 6302*552f7358SJed Brown ierr = PetscViewerASCIISynchronizedAllow(PETSC_VIEWER_STDOUT_WORLD, PETSC_TRUE);CHKERRQ(ierr); 6303*552f7358SJed Brown ierr = DMLabelView(labelNew, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6304*552f7358SJed Brown ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 6305*552f7358SJed Brown } 6306*552f7358SJed Brown } 6307*552f7358SJed Brown PetscFunctionReturn(0); 6308*552f7358SJed Brown } 6309*552f7358SJed Brown 6310*552f7358SJed Brown #undef __FUNCT__ 6311*552f7358SJed Brown #define __FUNCT__ "DMPlexRefine_Uniform" 6312*552f7358SJed Brown /* This will only work for interpolated meshes */ 6313*552f7358SJed Brown PetscErrorCode DMPlexRefine_Uniform(DM dm, CellRefiner cellRefiner, DM *dmRefined) 6314*552f7358SJed Brown { 6315*552f7358SJed Brown DM rdm; 6316*552f7358SJed Brown PetscInt *depthSize; 6317*552f7358SJed Brown PetscInt dim, depth = 0, d, pStart = 0, pEnd = 0; 6318*552f7358SJed Brown PetscErrorCode ierr; 6319*552f7358SJed Brown 6320*552f7358SJed Brown PetscFunctionBegin; 6321*552f7358SJed Brown ierr = DMCreate(((PetscObject) dm)->comm, &rdm);CHKERRQ(ierr); 6322*552f7358SJed Brown ierr = DMSetType(rdm, DMPLEX);CHKERRQ(ierr); 6323*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6324*552f7358SJed Brown ierr = DMPlexSetDimension(rdm, dim);CHKERRQ(ierr); 6325*552f7358SJed Brown /* Calculate number of new points of each depth */ 6326*552f7358SJed Brown ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 6327*552f7358SJed Brown ierr = PetscMalloc((depth+1) * sizeof(PetscInt), &depthSize);CHKERRQ(ierr); 6328*552f7358SJed Brown ierr = PetscMemzero(depthSize, (depth+1) * sizeof(PetscInt));CHKERRQ(ierr); 6329*552f7358SJed Brown ierr = CellRefinerGetSizes(cellRefiner, dm, depthSize);CHKERRQ(ierr); 6330*552f7358SJed Brown /* Step 1: Set chart */ 6331*552f7358SJed Brown for(d = 0; d <= depth; ++d) { 6332*552f7358SJed Brown pEnd += depthSize[d]; 6333*552f7358SJed Brown } 6334*552f7358SJed Brown ierr = DMPlexSetChart(rdm, pStart, pEnd);CHKERRQ(ierr); 6335*552f7358SJed Brown /* Step 2: Set cone/support sizes */ 6336*552f7358SJed Brown ierr = CellRefinerSetConeSizes(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6337*552f7358SJed Brown /* Step 3: Setup refined DM */ 6338*552f7358SJed Brown ierr = DMSetUp(rdm);CHKERRQ(ierr); 6339*552f7358SJed Brown /* Step 4: Set cones and supports */ 6340*552f7358SJed Brown ierr = CellRefinerSetCones(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6341*552f7358SJed Brown /* Step 5: Stratify */ 6342*552f7358SJed Brown ierr = DMPlexStratify(rdm);CHKERRQ(ierr); 6343*552f7358SJed Brown /* Step 6: Set coordinates for vertices */ 6344*552f7358SJed Brown ierr = CellRefinerSetCoordinates(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6345*552f7358SJed Brown /* Step 7: Create pointSF */ 6346*552f7358SJed Brown ierr = CellRefinerCreateSF(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6347*552f7358SJed Brown /* Step 8: Create labels */ 6348*552f7358SJed Brown ierr = CellRefinerCreateLabels(cellRefiner, dm, depthSize, rdm);CHKERRQ(ierr); 6349*552f7358SJed Brown ierr = PetscFree(depthSize);CHKERRQ(ierr); 6350*552f7358SJed Brown 6351*552f7358SJed Brown *dmRefined = rdm; 6352*552f7358SJed Brown #if 0 6353*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 6354*552f7358SJed Brown PetscInt dim, cStart, cEnd, cMax, c, vStart, vEnd, vMax; 6355*552f7358SJed Brown //ALE::ISieveVisitor::PointRetriever<mesh_type::sieve_type> cV(std::max(1, sieve->getMaxConeSize())); 6356*552f7358SJed Brown 6357*552f7358SJed Brown PetscFunctionBegin; 6358*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6359*552f7358SJed Brown /* PyLith: _refineCensored(newMesh, mesh, refiner); */ 6360*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6361*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 6362*552f7358SJed Brown ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr); 6363*552f7358SJed Brown 6364*552f7358SJed Brown /* Count number of new cells which are normal and extra */ 6365*552f7358SJed Brown PetscInt cEnd2 = cMax >= 0 ? cMax : cEnd; 6366*552f7358SJed Brown PetscInt newNumCellsNormal = 0, newNumCellsExtra = 0, newNumCells; 6367*552f7358SJed Brown for(c = cStart; c < cEnd2; ++c) { 6368*552f7358SJed Brown PetscInt n; 6369*552f7358SJed Brown ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); // refiner.numNewCells 6370*552f7358SJed Brown newNumCellsNormal += n; 6371*552f7358SJed Brown } 6372*552f7358SJed Brown for(c = cEnd2; c < cEnd; ++c) { 6373*552f7358SJed Brown PetscInt n; 6374*552f7358SJed Brown ierr = CellRefinerGetNumSubcells(c, &n);CHKERRQ(ierr); // refiner.numNewCells 6375*552f7358SJed Brown newNumCellsExtra += n; 6376*552f7358SJed Brown } 6377*552f7358SJed Brown newNumCells = newNumCellsNormal + newNumCellsExtra; 6378*552f7358SJed Brown /* Count number of new vertices which are normal and extra */ 6379*552f7358SJed Brown PetscInt vEnd2 = vMax >= 0 ? vMax : vEnd; 6380*552f7358SJed Brown PetscInt newNumVertices, newNumVerticesNormal, newNumVerticesExtra, newFirstVertex = newNumCells + (vEnd2 - vStart), newVertex = newFirstVertex; 6381*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 6382*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 6383*552f7358SJed Brown PetscInt closureSize, numCorners = 0, p; 6384*552f7358SJed Brown 6385*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6386*552f7358SJed Brown for(p = 0; p < closureSize*2; p += 2) { 6387*552f7358SJed Brown const PetscInt point = closure[p]; 6388*552f7358SJed Brown if ((point >= vStart) && (point < vEnd)) { 6389*552f7358SJed Brown closure[numCorners++] = point; 6390*552f7358SJed Brown } 6391*552f7358SJed Brown } 6392*552f7358SJed Brown ierr = CellRefinerSplitCell(c, closure, numCorners, &newVertex);CHKERRQ(ierr); // refiner.splitCell 6393*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6394*552f7358SJed Brown } 6395*552f7358SJed Brown newNumVerticesNormal = newVertex - newFirstVertex + (vEnd2 - vStart); 6396*552f7358SJed Brown for(c = cEnd2; c < cEnd; ++c) { 6397*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 6398*552f7358SJed Brown PetscInt closureSize, numCorners = 0, p; 6399*552f7358SJed Brown 6400*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6401*552f7358SJed Brown for(p = 0; p < closureSize*2; p += 2) { 6402*552f7358SJed Brown const PetscInt point = closure[p]; 6403*552f7358SJed Brown if ((point >= vStart) && (point < vEnd)) { 6404*552f7358SJed Brown closure[numCorners++] = point; 6405*552f7358SJed Brown } 6406*552f7358SJed Brown } 6407*552f7358SJed Brown ierr = CellRefinerSplitCellExtra(c, closure, numCorners, &newVertex);CHKERRQ(ierr); // refiner.splitCellUncensored 6408*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6409*552f7358SJed Brown } // for 6410*552f7358SJed Brown newNumVerticesExtra = newVertex - newFirstVertex - newNumVerticesNormal; 6411*552f7358SJed Brown newNumVertices = newNumVerticesNormal + newNumVerticesExtra; 6412*552f7358SJed Brown 6413*552f7358SJed Brown #if 1 6414*552f7358SJed Brown PetscInt oldNumCellsNormal = cEnd2 - cStart; 6415*552f7358SJed Brown PetscInt oldNumCellsExtra = cEnd - cEnd2; 6416*552f7358SJed Brown ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal cells [%d, %d)\n", rank, 0, oldNumCellsNormal); 6417*552f7358SJed Brown ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault cells [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra+oldNumCellsExtra); 6418*552f7358SJed Brown ierr = PetscSynchronizedPrintf(comm, "[%d]Old normal vertices [%d, %d)\n", rank, oldNumCellsNormal, oldNumCellsNormal+oldNumVerticesNormal); 6419*552f7358SJed Brown ierr = PetscSynchronizedPrintf(comm, "[%d]Old fault vertices [%d, %d)\n", rank, oldNumCellsNormal+oldNumVerticesNormal, oldNumCellsNormal+oldNumVerticesNormal+oldNumVerticesExtra); 6420*552f7358SJed Brown ierr = PetscSynchronizedPrintf(comm, "[%d]New normal cells [%d, %d)\n", rank, 0, newNumCellsNormal); 6421*552f7358SJed Brown ierr = PetscSynchronizedPrintf(comm, "[%d]New fault cells [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra+newNumCellsExtra); 6422*552f7358SJed Brown ierr = PetscSynchronizedPrintf(comm, "[%d]New normal vertices [%d, %d)\n", rank, newNumCellsNormal, newNumCellsNormal+newNumVerticesNormal); 6423*552f7358SJed Brown ierr = PetscSynchronizedPrintf(comm, "[%d]New fault vertices [%d, %d)\n", rank, newNumCellsNormal+newNumVerticesNormal, newNumCellsNormal+newNumVerticesNormal+newNumVerticesExtra); 6424*552f7358SJed Brown ierr = PetscSynchronizedFlush(comm); 6425*552f7358SJed Brown #endif 6426*552f7358SJed Brown 6427*552f7358SJed Brown ierr = DMCreate(comm, dmRefined);CHKERRQ(ierr); 6428*552f7358SJed Brown ierr = DMSetType(*dmRefined, DMPLEX);CHKERRQ(ierr); 6429*552f7358SJed Brown ierr = DMPlexSetDimension(*dm, dim);CHKERRQ(ierr); 6430*552f7358SJed Brown ierr = DMPlexSetChart(*dmRefined, 0, newNumCells+newNumVertices);CHKERRQ(ierr); 6431*552f7358SJed Brown ierr = DMPlexGetVTKBounds(*dmRefined, newNumCellsNormal, newFirstVertex+newNumVerticesNormal);CHKERRQ(ierr); 6432*552f7358SJed Brown /* Set cone and support sizes for new normal cells */ 6433*552f7358SJed Brown PetscInt newCell = 0; 6434*552f7358SJed Brown for(c = cStart; c < cEnd2; ++c) { 6435*552f7358SJed Brown PetscInt coneSize, n, i; 6436*552f7358SJed Brown 6437*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 6438*552f7358SJed Brown ierr = CellRefinerGetNumSubcells(refiner, c, &n); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6439*552f7358SJed Brown for(i = 0; i < n; ++i, ++newCell) { 6440*552f7358SJed Brown ierr = DMPlexSetConeSize(*dmRefined, newCell, coneSize);CHKERRQ(ierr); 6441*552f7358SJed Brown } 6442*552f7358SJed Brown 6443*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 6444*552f7358SJed Brown PetscInt closureSize, numCorners = 0, p; 6445*552f7358SJed Brown 6446*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6447*552f7358SJed Brown for(p = 0; p < closureSize*2; p += 2) { 6448*552f7358SJed Brown const PetscInt point = closure[p]; 6449*552f7358SJed Brown if ((point >= vStart) && (point < vEnd)) { 6450*552f7358SJed Brown closure[numCorners++] = point; 6451*552f7358SJed Brown } 6452*552f7358SJed Brown } 6453*552f7358SJed Brown // ierr = CellRefinerGetSubcells(refiner, c, numCorners, closure, &numNewCells, &newCells);CHKERRQ(ierr); // refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6454*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 6455*552f7358SJed Brown } 6456*552f7358SJed Brown 6457*552f7358SJed Brown // Reset current new cell value and loop over censored cells. 6458*552f7358SJed Brown curNewCell = _orderNewMesh->cellsCensored().min(); 6459*552f7358SJed Brown oldCellsEnd = _orderOldMesh->cellsCensored().end(); 6460*552f7358SJed Brown for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 6461*552f7358SJed Brown // Set new cone and support sizes 6462*552f7358SJed Brown cV.clear(); 6463*552f7358SJed Brown sieve->cone(*c_iter, cV); 6464*552f7358SJed Brown const point_type* cone = cV.getPoints(); 6465*552f7358SJed Brown const int coneSize = cV.getSize(); 6466*552f7358SJed Brown 6467*552f7358SJed Brown const point_type* newCells; 6468*552f7358SJed Brown int numNewCells = 0; 6469*552f7358SJed Brown refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6470*552f7358SJed Brown 6471*552f7358SJed Brown for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6472*552f7358SJed Brown newSieve->setConeSize(curNewCell, coneSize); 6473*552f7358SJed Brown for(int iVertex=0; iVertex < coneSize; ++iVertex) { 6474*552f7358SJed Brown newSieve->addSupportSize(newCells[iCell*coneSize+iVertex], 1); 6475*552f7358SJed Brown } // for 6476*552f7358SJed Brown } // for 6477*552f7358SJed Brown } // for 6478*552f7358SJed Brown newSieve->allocate(); 6479*552f7358SJed Brown 6480*552f7358SJed Brown ierr = DMPlexSymmetrizeSizes();CHKERRQ(ierr); 6481*552f7358SJed Brown 6482*552f7358SJed Brown // Create refined cells in new sieve. 6483*552f7358SJed Brown curNewCell = _orderNewMesh->cellsNormal().min(); 6484*552f7358SJed Brown oldCellsEnd = _orderOldMesh->cellsNormal().end(); 6485*552f7358SJed Brown for (interval_type::const_iterator c_iter=_orderOldMesh->cellsNormal().begin(); c_iter != oldCellsEnd; ++c_iter) { 6486*552f7358SJed Brown cV.clear(); 6487*552f7358SJed Brown sieve->cone(*c_iter, cV); 6488*552f7358SJed Brown const point_type *cone = cV.getPoints(); 6489*552f7358SJed Brown const int coneSize = cV.getSize(); 6490*552f7358SJed Brown 6491*552f7358SJed Brown const point_type* newCells; 6492*552f7358SJed Brown int numNewCells = 0; 6493*552f7358SJed Brown refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6494*552f7358SJed Brown 6495*552f7358SJed Brown for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6496*552f7358SJed Brown newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 6497*552f7358SJed Brown } // for 6498*552f7358SJed Brown } // for 6499*552f7358SJed Brown curNewCell = _orderNewMesh->cellsCensored().min(); 6500*552f7358SJed Brown oldCellsEnd = _orderOldMesh->cellsCensored().end(); 6501*552f7358SJed Brown for (interval_type::const_iterator c_iter=_orderOldMesh->cellsCensored().begin(); c_iter != oldCellsEnd; ++c_iter) { 6502*552f7358SJed Brown cV.clear(); 6503*552f7358SJed Brown sieve->cone(*c_iter, cV); 6504*552f7358SJed Brown const point_type *cone = cV.getPoints(); 6505*552f7358SJed Brown const int coneSize = cV.getSize(); 6506*552f7358SJed Brown 6507*552f7358SJed Brown const point_type* newCells; 6508*552f7358SJed Brown int numNewCells = 0; 6509*552f7358SJed Brown refiner.getNewCells(&newCells, &numNewCells, *c_iter, cone, coneSize, *_orderOldMesh, *_orderNewMesh); 6510*552f7358SJed Brown 6511*552f7358SJed Brown for(int iCell=0; iCell < numNewCells; ++iCell, ++curNewCell) { 6512*552f7358SJed Brown newSieve->setCone(&newCells[iCell*coneSize], curNewCell); 6513*552f7358SJed Brown } // for 6514*552f7358SJed Brown } // for 6515*552f7358SJed Brown newSieve->symmetrize(); 6516*552f7358SJed Brown 6517*552f7358SJed Brown // Set coordinates in refined mesh. 6518*552f7358SJed Brown const Obj<mesh_type::real_section_type>& coordinates = mesh->getRealSection("coordinates"); 6519*552f7358SJed Brown assert(!coordinates.isNull()); 6520*552f7358SJed Brown const Obj<mesh_type::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates"); 6521*552f7358SJed Brown assert(!newCoordinates.isNull()); 6522*552f7358SJed Brown 6523*552f7358SJed Brown const mesh_type::label_sequence::const_iterator verticesEnd = vertices->end(); 6524*552f7358SJed Brown assert(vertices->size() > 0); 6525*552f7358SJed Brown const int spaceDim = coordinates->getFiberDimension(*vertices->begin()); 6526*552f7358SJed Brown assert(spaceDim > 0); 6527*552f7358SJed Brown newCoordinates->setChart(mesh_type::sieve_type::chart_type(_orderNewMesh->verticesNormal().min(), _orderNewMesh->verticesCensored().max())); 6528*552f7358SJed Brown 6529*552f7358SJed Brown const interval_type::const_iterator newVerticesEnd = _orderNewMesh->verticesCensored().end(); 6530*552f7358SJed Brown for (interval_type::const_iterator v_iter=_orderNewMesh->verticesNormal().begin(); v_iter != newVerticesEnd; ++v_iter) { 6531*552f7358SJed Brown newCoordinates->setFiberDimension(*v_iter, spaceDim); 6532*552f7358SJed Brown } // for 6533*552f7358SJed Brown newCoordinates->allocatePoint(); 6534*552f7358SJed Brown 6535*552f7358SJed Brown interval_type::const_iterator oldVerticesEnd = _orderOldMesh->verticesNormal().end(); 6536*552f7358SJed Brown for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesNormal().begin(), vNew_iter=_orderNewMesh->verticesNormal().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 6537*552f7358SJed Brown //std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; 6538*552f7358SJed Brown newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 6539*552f7358SJed Brown } // for 6540*552f7358SJed Brown oldVerticesEnd = _orderOldMesh->verticesCensored().end(); 6541*552f7358SJed Brown for (interval_type::const_iterator vOld_iter=_orderOldMesh->verticesCensored().begin(), vNew_iter=_orderNewMesh->verticesCensored().begin(); vOld_iter != oldVerticesEnd; ++vOld_iter, ++vNew_iter) { 6542*552f7358SJed Brown //std::cout << "Copy coordinates from old vertex " << *vOld_iter << " to new vertex " << *vNew_iter << std::endl; 6543*552f7358SJed Brown newCoordinates->updatePoint(*vNew_iter, coordinates->restrictPoint(*vOld_iter)); 6544*552f7358SJed Brown } // for 6545*552f7358SJed Brown 6546*552f7358SJed Brown refiner.setCoordsNewVertices(newCoordinates, coordinates); 6547*552f7358SJed Brown 6548*552f7358SJed Brown // Create sensored depth 6549*552f7358SJed Brown const ALE::Obj<SieveFlexMesh::label_type>& censoredLabel = newMesh->createLabel("censored depth"); 6550*552f7358SJed Brown assert(!censoredLabel.isNull()); 6551*552f7358SJed Brown 6552*552f7358SJed Brown mesh_type::DepthVisitor depthVisitor(*newSieve, _orderNewMesh->verticesCensored().min(), *censoredLabel); 6553*552f7358SJed Brown 6554*552f7358SJed Brown newSieve->roots(depthVisitor); 6555*552f7358SJed Brown while(depthVisitor.isModified()) { 6556*552f7358SJed Brown // FIX: Avoid the copy here somehow by fixing the traversal 6557*552f7358SJed Brown std::vector<mesh_type::point_type> modifiedPoints(depthVisitor.getModifiedPoints().begin(), depthVisitor.getModifiedPoints().end()); 6558*552f7358SJed Brown 6559*552f7358SJed Brown depthVisitor.clear(); 6560*552f7358SJed Brown newSieve->support(modifiedPoints, depthVisitor); 6561*552f7358SJed Brown } // while 6562*552f7358SJed Brown // Stratify refined mesh 6563*552f7358SJed Brown // Calculate new point SF 6564*552f7358SJed Brown _calcNewOverlap(newMesh, mesh, refiner); 6565*552f7358SJed Brown // Calculate new labels 6566*552f7358SJed Brown _createLabels(newMesh, mesh, refiner); 6567*552f7358SJed Brown #endif 6568*552f7358SJed Brown PetscFunctionReturn(0); 6569*552f7358SJed Brown } 6570*552f7358SJed Brown 6571*552f7358SJed Brown #undef __FUNCT__ 6572*552f7358SJed Brown #define __FUNCT__ "DMPlexSetRefinementUniform" 6573*552f7358SJed Brown PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 6574*552f7358SJed Brown { 6575*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 6576*552f7358SJed Brown 6577*552f7358SJed Brown PetscFunctionBegin; 6578*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6579*552f7358SJed Brown mesh->refinementUniform = refinementUniform; 6580*552f7358SJed Brown PetscFunctionReturn(0); 6581*552f7358SJed Brown } 6582*552f7358SJed Brown 6583*552f7358SJed Brown #undef __FUNCT__ 6584*552f7358SJed Brown #define __FUNCT__ "DMPlexGetRefinementUniform" 6585*552f7358SJed Brown PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 6586*552f7358SJed Brown { 6587*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 6588*552f7358SJed Brown 6589*552f7358SJed Brown PetscFunctionBegin; 6590*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6591*552f7358SJed Brown PetscValidPointer(refinementUniform, 2); 6592*552f7358SJed Brown *refinementUniform = mesh->refinementUniform; 6593*552f7358SJed Brown PetscFunctionReturn(0); 6594*552f7358SJed Brown } 6595*552f7358SJed Brown 6596*552f7358SJed Brown #undef __FUNCT__ 6597*552f7358SJed Brown #define __FUNCT__ "DMPlexSetRefinementLimit" 6598*552f7358SJed Brown PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 6599*552f7358SJed Brown { 6600*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 6601*552f7358SJed Brown 6602*552f7358SJed Brown PetscFunctionBegin; 6603*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6604*552f7358SJed Brown mesh->refinementLimit = refinementLimit; 6605*552f7358SJed Brown PetscFunctionReturn(0); 6606*552f7358SJed Brown } 6607*552f7358SJed Brown 6608*552f7358SJed Brown #undef __FUNCT__ 6609*552f7358SJed Brown #define __FUNCT__ "DMPlexGetRefinementLimit" 6610*552f7358SJed Brown PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 6611*552f7358SJed Brown { 6612*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 6613*552f7358SJed Brown 6614*552f7358SJed Brown PetscFunctionBegin; 6615*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6616*552f7358SJed Brown PetscValidPointer(refinementLimit, 2); 6617*552f7358SJed Brown /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 6618*552f7358SJed Brown *refinementLimit = mesh->refinementLimit; 6619*552f7358SJed Brown PetscFunctionReturn(0); 6620*552f7358SJed Brown } 6621*552f7358SJed Brown 6622*552f7358SJed Brown #undef __FUNCT__ 6623*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCellRefiner_Private" 6624*552f7358SJed Brown PetscErrorCode DMPlexGetCellRefiner_Private(DM dm, CellRefiner *cellRefiner) 6625*552f7358SJed Brown { 6626*552f7358SJed Brown PetscInt dim, cStart, coneSize; 6627*552f7358SJed Brown PetscErrorCode ierr; 6628*552f7358SJed Brown 6629*552f7358SJed Brown PetscFunctionBegin; 6630*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6631*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, PETSC_NULL);CHKERRQ(ierr); 6632*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, cStart, &coneSize);CHKERRQ(ierr); 6633*552f7358SJed Brown switch(dim) { 6634*552f7358SJed Brown case 2: 6635*552f7358SJed Brown switch(coneSize) { 6636*552f7358SJed Brown case 3: 6637*552f7358SJed Brown *cellRefiner = 1;break; 6638*552f7358SJed Brown case 4: 6639*552f7358SJed Brown *cellRefiner = 2;break; 6640*552f7358SJed Brown default: 6641*552f7358SJed Brown SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown coneSize %d in dimension %d for cell refiner", coneSize, dim); 6642*552f7358SJed Brown } 6643*552f7358SJed Brown break; 6644*552f7358SJed Brown default: 6645*552f7358SJed Brown SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown dimension %d for cell refiner", dim); 6646*552f7358SJed Brown } 6647*552f7358SJed Brown PetscFunctionReturn(0); 6648*552f7358SJed Brown } 6649*552f7358SJed Brown 6650*552f7358SJed Brown #undef __FUNCT__ 6651*552f7358SJed Brown #define __FUNCT__ "DMRefine_Plex" 6652*552f7358SJed Brown PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *dmRefined) 6653*552f7358SJed Brown { 6654*552f7358SJed Brown PetscReal refinementLimit; 6655*552f7358SJed Brown PetscInt dim, cStart, cEnd; 6656*552f7358SJed Brown char genname[1024], *name = PETSC_NULL; 6657*552f7358SJed Brown PetscBool isUniform, isTriangle = PETSC_FALSE, isTetgen = PETSC_FALSE, isCTetgen = PETSC_FALSE, flg; 6658*552f7358SJed Brown PetscErrorCode ierr; 6659*552f7358SJed Brown 6660*552f7358SJed Brown PetscFunctionBegin; 6661*552f7358SJed Brown ierr = DMPlexGetRefinementUniform(dm, &isUniform);CHKERRQ(ierr); 6662*552f7358SJed Brown if (isUniform) { 6663*552f7358SJed Brown CellRefiner cellRefiner; 6664*552f7358SJed Brown 6665*552f7358SJed Brown ierr = DMPlexGetCellRefiner_Private(dm, &cellRefiner);CHKERRQ(ierr); 6666*552f7358SJed Brown ierr = DMPlexRefine_Uniform(dm, cellRefiner, dmRefined);CHKERRQ(ierr); 6667*552f7358SJed Brown PetscFunctionReturn(0); 6668*552f7358SJed Brown } 6669*552f7358SJed Brown ierr = DMPlexGetRefinementLimit(dm, &refinementLimit);CHKERRQ(ierr); 6670*552f7358SJed Brown if (refinementLimit == 0.0) PetscFunctionReturn(0); 6671*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 6672*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 6673*552f7358SJed Brown ierr = PetscOptionsGetString(((PetscObject) dm)->prefix, "-dm_plex_generator", genname, 1024, &flg);CHKERRQ(ierr); 6674*552f7358SJed Brown if (flg) {name = genname;} 6675*552f7358SJed Brown if (name) { 6676*552f7358SJed Brown ierr = PetscStrcmp(name, "triangle", &isTriangle);CHKERRQ(ierr); 6677*552f7358SJed Brown ierr = PetscStrcmp(name, "tetgen", &isTetgen);CHKERRQ(ierr); 6678*552f7358SJed Brown ierr = PetscStrcmp(name, "ctetgen", &isCTetgen);CHKERRQ(ierr); 6679*552f7358SJed Brown } 6680*552f7358SJed Brown switch(dim) { 6681*552f7358SJed Brown case 2: 6682*552f7358SJed Brown if (!name || isTriangle) { 6683*552f7358SJed Brown #ifdef PETSC_HAVE_TRIANGLE 6684*552f7358SJed Brown double *maxVolumes; 6685*552f7358SJed Brown PetscInt c; 6686*552f7358SJed Brown 6687*552f7358SJed Brown ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 6688*552f7358SJed Brown for (c = 0; c < cEnd-cStart; ++c) { 6689*552f7358SJed Brown maxVolumes[c] = refinementLimit; 6690*552f7358SJed Brown } 6691*552f7358SJed Brown ierr = DMPlexRefine_Triangle(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6692*552f7358SJed Brown #else 6693*552f7358SJed Brown SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement needs external package support.\nPlease reconfigure with --download-triangle."); 6694*552f7358SJed Brown #endif 6695*552f7358SJed Brown } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 2D mesh generation package %s", name); 6696*552f7358SJed Brown break; 6697*552f7358SJed Brown case 3: 6698*552f7358SJed Brown if (!name || isCTetgen) { 6699*552f7358SJed Brown #ifdef PETSC_HAVE_CTETGEN 6700*552f7358SJed Brown PetscReal *maxVolumes; 6701*552f7358SJed Brown PetscInt c; 6702*552f7358SJed Brown 6703*552f7358SJed Brown ierr = PetscMalloc((cEnd - cStart) * sizeof(PetscReal), &maxVolumes);CHKERRQ(ierr); 6704*552f7358SJed Brown for (c = 0; c < cEnd-cStart; ++c) { 6705*552f7358SJed Brown maxVolumes[c] = refinementLimit; 6706*552f7358SJed Brown } 6707*552f7358SJed Brown ierr = DMPlexRefine_CTetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6708*552f7358SJed Brown #else 6709*552f7358SJed Brown SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "CTetgen needs external package support.\nPlease reconfigure with --download-ctetgen."); 6710*552f7358SJed Brown #endif 6711*552f7358SJed Brown } else if (isTetgen) { 6712*552f7358SJed Brown #ifdef PETSC_HAVE_TETGEN 6713*552f7358SJed Brown double *maxVolumes; 6714*552f7358SJed Brown PetscInt c; 6715*552f7358SJed Brown 6716*552f7358SJed Brown ierr = PetscMalloc((cEnd - cStart) * sizeof(double), &maxVolumes);CHKERRQ(ierr); 6717*552f7358SJed Brown for (c = 0; c < cEnd-cStart; ++c) { 6718*552f7358SJed Brown maxVolumes[c] = refinementLimit; 6719*552f7358SJed Brown } 6720*552f7358SJed Brown ierr = DMPlexRefine_Tetgen(dm, maxVolumes, dmRefined);CHKERRQ(ierr); 6721*552f7358SJed Brown #else 6722*552f7358SJed Brown SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Tetgen needs external package support.\nPlease reconfigure with --with-c-language=cxx --download-tetgen."); 6723*552f7358SJed Brown #endif 6724*552f7358SJed Brown } else SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unknown 3D mesh generation package %s", name); 6725*552f7358SJed Brown break; 6726*552f7358SJed Brown default: 6727*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Mesh refinement in dimension %d is not supported.", dim); 6728*552f7358SJed Brown } 6729*552f7358SJed Brown PetscFunctionReturn(0); 6730*552f7358SJed Brown } 6731*552f7358SJed Brown 6732*552f7358SJed Brown #undef __FUNCT__ 6733*552f7358SJed Brown #define __FUNCT__ "DMPlexGetDepth" 6734*552f7358SJed Brown /*@ 6735*552f7358SJed Brown DMPlexGetDepth - get the number of strata 6736*552f7358SJed Brown 6737*552f7358SJed Brown Not Collective 6738*552f7358SJed Brown 6739*552f7358SJed Brown Input Parameters: 6740*552f7358SJed Brown . dm - The DMPlex object 6741*552f7358SJed Brown 6742*552f7358SJed Brown Output Parameters: 6743*552f7358SJed Brown . depth - number of strata 6744*552f7358SJed Brown 6745*552f7358SJed Brown Level: developer 6746*552f7358SJed Brown 6747*552f7358SJed Brown Notes: 6748*552f7358SJed Brown DMPlexGetHeightStratum(dm,0,..) should return the same points as DMPlexGetDepthStratum(dm,depth,..). 6749*552f7358SJed Brown 6750*552f7358SJed Brown .keywords: mesh, points 6751*552f7358SJed Brown .seealso: DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 6752*552f7358SJed Brown @*/ 6753*552f7358SJed Brown PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 6754*552f7358SJed Brown { 6755*552f7358SJed Brown PetscInt d; 6756*552f7358SJed Brown PetscErrorCode ierr; 6757*552f7358SJed Brown 6758*552f7358SJed Brown PetscFunctionBegin; 6759*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6760*552f7358SJed Brown PetscValidPointer(depth, 2); 6761*552f7358SJed Brown ierr = DMPlexGetLabelSize(dm, "depth", &d);CHKERRQ(ierr); 6762*552f7358SJed Brown *depth = d-1; 6763*552f7358SJed Brown PetscFunctionReturn(0); 6764*552f7358SJed Brown } 6765*552f7358SJed Brown 6766*552f7358SJed Brown #undef __FUNCT__ 6767*552f7358SJed Brown #define __FUNCT__ "DMPlexGetDepthStratum" 6768*552f7358SJed Brown /*@ 6769*552f7358SJed Brown DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 6770*552f7358SJed Brown 6771*552f7358SJed Brown Not Collective 6772*552f7358SJed Brown 6773*552f7358SJed Brown Input Parameters: 6774*552f7358SJed Brown + dm - The DMPlex object 6775*552f7358SJed Brown - stratumValue - The requested depth 6776*552f7358SJed Brown 6777*552f7358SJed Brown Output Parameters: 6778*552f7358SJed Brown + start - The first point at this depth 6779*552f7358SJed Brown - end - One beyond the last point at this depth 6780*552f7358SJed Brown 6781*552f7358SJed Brown Level: developer 6782*552f7358SJed Brown 6783*552f7358SJed Brown .keywords: mesh, points 6784*552f7358SJed Brown .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 6785*552f7358SJed Brown @*/ 6786*552f7358SJed Brown PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) { 6787*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 6788*552f7358SJed Brown DMLabel next = mesh->labels; 6789*552f7358SJed Brown PetscBool flg = PETSC_FALSE; 6790*552f7358SJed Brown PetscInt depth; 6791*552f7358SJed Brown PetscErrorCode ierr; 6792*552f7358SJed Brown 6793*552f7358SJed Brown PetscFunctionBegin; 6794*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6795*552f7358SJed Brown if (stratumValue < 0) { 6796*552f7358SJed Brown ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6797*552f7358SJed Brown PetscFunctionReturn(0); 6798*552f7358SJed Brown } else { 6799*552f7358SJed Brown PetscInt pStart, pEnd; 6800*552f7358SJed Brown 6801*552f7358SJed Brown if (start) {*start = 0;} 6802*552f7358SJed Brown if (end) {*end = 0;} 6803*552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6804*552f7358SJed Brown if (pStart == pEnd) {PetscFunctionReturn(0);} 6805*552f7358SJed Brown } 6806*552f7358SJed Brown ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6807*552f7358SJed Brown if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6808*552f7358SJed Brown /* We should have a generic GetLabel() and a Label class */ 6809*552f7358SJed Brown while(next) { 6810*552f7358SJed Brown ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6811*552f7358SJed Brown if (flg) break; 6812*552f7358SJed Brown next = next->next; 6813*552f7358SJed Brown } 6814*552f7358SJed Brown /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6815*552f7358SJed Brown depth = stratumValue; 6816*552f7358SJed Brown if ((depth < 0) || (depth >= next->numStrata)) { 6817*552f7358SJed Brown if (start) {*start = 0;} 6818*552f7358SJed Brown if (end) {*end = 0;} 6819*552f7358SJed Brown } else { 6820*552f7358SJed Brown if (start) {*start = next->points[next->stratumOffsets[depth]];} 6821*552f7358SJed Brown if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 6822*552f7358SJed Brown } 6823*552f7358SJed Brown PetscFunctionReturn(0); 6824*552f7358SJed Brown } 6825*552f7358SJed Brown 6826*552f7358SJed Brown #undef __FUNCT__ 6827*552f7358SJed Brown #define __FUNCT__ "DMPlexGetHeightStratum" 6828*552f7358SJed Brown /*@ 6829*552f7358SJed Brown DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 6830*552f7358SJed Brown 6831*552f7358SJed Brown Not Collective 6832*552f7358SJed Brown 6833*552f7358SJed Brown Input Parameters: 6834*552f7358SJed Brown + dm - The DMPlex object 6835*552f7358SJed Brown - stratumValue - The requested height 6836*552f7358SJed Brown 6837*552f7358SJed Brown Output Parameters: 6838*552f7358SJed Brown + start - The first point at this height 6839*552f7358SJed Brown - end - One beyond the last point at this height 6840*552f7358SJed Brown 6841*552f7358SJed Brown Level: developer 6842*552f7358SJed Brown 6843*552f7358SJed Brown .keywords: mesh, points 6844*552f7358SJed Brown .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 6845*552f7358SJed Brown @*/ 6846*552f7358SJed Brown PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) { 6847*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 6848*552f7358SJed Brown DMLabel next = mesh->labels; 6849*552f7358SJed Brown PetscBool flg = PETSC_FALSE; 6850*552f7358SJed Brown PetscInt depth; 6851*552f7358SJed Brown PetscErrorCode ierr; 6852*552f7358SJed Brown 6853*552f7358SJed Brown PetscFunctionBegin; 6854*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6855*552f7358SJed Brown if (stratumValue < 0) { 6856*552f7358SJed Brown ierr = DMPlexGetChart(dm, start, end);CHKERRQ(ierr); 6857*552f7358SJed Brown } else { 6858*552f7358SJed Brown PetscInt pStart, pEnd; 6859*552f7358SJed Brown 6860*552f7358SJed Brown if (start) {*start = 0;} 6861*552f7358SJed Brown if (end) {*end = 0;} 6862*552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6863*552f7358SJed Brown if (pStart == pEnd) {PetscFunctionReturn(0);} 6864*552f7358SJed Brown } 6865*552f7358SJed Brown ierr = DMPlexHasLabel(dm, "depth", &flg);CHKERRQ(ierr); 6866*552f7358SJed Brown if (!flg) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 6867*552f7358SJed Brown /* We should have a generic GetLabel() and a Label class */ 6868*552f7358SJed Brown while(next) { 6869*552f7358SJed Brown ierr = PetscStrcmp("depth", next->name, &flg);CHKERRQ(ierr); 6870*552f7358SJed Brown if (flg) break; 6871*552f7358SJed Brown next = next->next; 6872*552f7358SJed Brown } 6873*552f7358SJed Brown /* Strata are sorted and contiguous -- In addition, depth/height is either full or 1-level */ 6874*552f7358SJed Brown depth = next->stratumValues[next->numStrata-1] - stratumValue; 6875*552f7358SJed Brown if ((depth < 0) || (depth >= next->numStrata)) { 6876*552f7358SJed Brown if (start) {*start = 0;} 6877*552f7358SJed Brown if (end) {*end = 0;} 6878*552f7358SJed Brown } else { 6879*552f7358SJed Brown if (start) {*start = next->points[next->stratumOffsets[depth]];} 6880*552f7358SJed Brown if (end) {*end = next->points[next->stratumOffsets[depth]+next->stratumSizes[depth]-1]+1;} 6881*552f7358SJed Brown } 6882*552f7358SJed Brown PetscFunctionReturn(0); 6883*552f7358SJed Brown } 6884*552f7358SJed Brown 6885*552f7358SJed Brown #undef __FUNCT__ 6886*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionInitial" 6887*552f7358SJed Brown /* Set the number of dof on each point and separate by fields */ 6888*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) { 6889*552f7358SJed Brown PetscInt *numDofTot; 6890*552f7358SJed Brown PetscInt pStart = 0, pEnd = 0; 6891*552f7358SJed Brown PetscInt p, d, f; 6892*552f7358SJed Brown PetscErrorCode ierr; 6893*552f7358SJed Brown 6894*552f7358SJed Brown PetscFunctionBegin; 6895*552f7358SJed Brown ierr = PetscMalloc((dim+1) * sizeof(PetscInt), &numDofTot);CHKERRQ(ierr); 6896*552f7358SJed Brown for(d = 0; d <= dim; ++d) { 6897*552f7358SJed Brown numDofTot[d] = 0; 6898*552f7358SJed Brown for(f = 0; f < numFields; ++f) { 6899*552f7358SJed Brown numDofTot[d] += numDof[f*(dim+1)+d]; 6900*552f7358SJed Brown } 6901*552f7358SJed Brown } 6902*552f7358SJed Brown ierr = PetscSectionCreate(((PetscObject) dm)->comm, section);CHKERRQ(ierr); 6903*552f7358SJed Brown if (numFields > 0) { 6904*552f7358SJed Brown ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 6905*552f7358SJed Brown if (numComp) { 6906*552f7358SJed Brown for(f = 0; f < numFields; ++f) { 6907*552f7358SJed Brown ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 6908*552f7358SJed Brown } 6909*552f7358SJed Brown } 6910*552f7358SJed Brown } 6911*552f7358SJed Brown ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 6912*552f7358SJed Brown ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 6913*552f7358SJed Brown for(d = 0; d <= dim; ++d) { 6914*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 6915*552f7358SJed Brown for(p = pStart; p < pEnd; ++p) { 6916*552f7358SJed Brown for(f = 0; f < numFields; ++f) { 6917*552f7358SJed Brown ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 6918*552f7358SJed Brown } 6919*552f7358SJed Brown ierr = PetscSectionSetDof(*section, p, numDofTot[d]);CHKERRQ(ierr); 6920*552f7358SJed Brown } 6921*552f7358SJed Brown } 6922*552f7358SJed Brown ierr = PetscFree(numDofTot);CHKERRQ(ierr); 6923*552f7358SJed Brown PetscFunctionReturn(0); 6924*552f7358SJed Brown } 6925*552f7358SJed Brown 6926*552f7358SJed Brown #undef __FUNCT__ 6927*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCDof" 6928*552f7358SJed Brown /* Set the number of dof on each point and separate by fields 6929*552f7358SJed Brown If constDof is PETSC_DETERMINE, constrain every dof on the point 6930*552f7358SJed Brown */ 6931*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscInt constDof, PetscSection section) { 6932*552f7358SJed Brown PetscInt numFields; 6933*552f7358SJed Brown PetscInt bc; 6934*552f7358SJed Brown PetscErrorCode ierr; 6935*552f7358SJed Brown 6936*552f7358SJed Brown PetscFunctionBegin; 6937*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6938*552f7358SJed Brown for (bc = 0; bc < numBC; ++bc) { 6939*552f7358SJed Brown PetscInt field = 0; 6940*552f7358SJed Brown const PetscInt *idx; 6941*552f7358SJed Brown PetscInt n, i; 6942*552f7358SJed Brown 6943*552f7358SJed Brown if (numFields) {field = bcField[bc];} 6944*552f7358SJed Brown ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 6945*552f7358SJed Brown ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6946*552f7358SJed Brown for (i = 0; i < n; ++i) { 6947*552f7358SJed Brown const PetscInt p = idx[i]; 6948*552f7358SJed Brown PetscInt numConst = constDof; 6949*552f7358SJed Brown 6950*552f7358SJed Brown /* Constrain every dof on the point */ 6951*552f7358SJed Brown if (numConst < 0) { 6952*552f7358SJed Brown if (numFields) { 6953*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 6954*552f7358SJed Brown } else { 6955*552f7358SJed Brown ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 6956*552f7358SJed Brown } 6957*552f7358SJed Brown } 6958*552f7358SJed Brown if (numFields) { 6959*552f7358SJed Brown ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr); 6960*552f7358SJed Brown } 6961*552f7358SJed Brown ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 6962*552f7358SJed Brown } 6963*552f7358SJed Brown ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 6964*552f7358SJed Brown } 6965*552f7358SJed Brown PetscFunctionReturn(0); 6966*552f7358SJed Brown } 6967*552f7358SJed Brown 6968*552f7358SJed Brown #undef __FUNCT__ 6969*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndicesAll" 6970*552f7358SJed Brown /* Set the constrained indices on each point and separate by fields */ 6971*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionBCIndicesAll(DM dm, PetscSection section) { 6972*552f7358SJed Brown PetscInt *maxConstraints; 6973*552f7358SJed Brown PetscInt numFields, f, pStart = 0, pEnd = 0, p; 6974*552f7358SJed Brown PetscErrorCode ierr; 6975*552f7358SJed Brown 6976*552f7358SJed Brown PetscFunctionBegin; 6977*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 6978*552f7358SJed Brown ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 6979*552f7358SJed Brown ierr = PetscMalloc((numFields+1) * sizeof(PetscInt), &maxConstraints);CHKERRQ(ierr); 6980*552f7358SJed Brown for(f = 0; f <= numFields; ++f) {maxConstraints[f] = 0;} 6981*552f7358SJed Brown for(p = pStart; p < pEnd; ++p) { 6982*552f7358SJed Brown PetscInt cdof; 6983*552f7358SJed Brown 6984*552f7358SJed Brown if (numFields) { 6985*552f7358SJed Brown for(f = 0; f < numFields; ++f) { 6986*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cdof);CHKERRQ(ierr); 6987*552f7358SJed Brown maxConstraints[f] = PetscMax(maxConstraints[f], cdof); 6988*552f7358SJed Brown } 6989*552f7358SJed Brown } else { 6990*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 6991*552f7358SJed Brown maxConstraints[0] = PetscMax(maxConstraints[0], cdof); 6992*552f7358SJed Brown } 6993*552f7358SJed Brown } 6994*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 6995*552f7358SJed Brown maxConstraints[numFields] += maxConstraints[f]; 6996*552f7358SJed Brown } 6997*552f7358SJed Brown if (maxConstraints[numFields]) { 6998*552f7358SJed Brown PetscInt *indices; 6999*552f7358SJed Brown 7000*552f7358SJed Brown ierr = PetscMalloc(maxConstraints[numFields] * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7001*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 7002*552f7358SJed Brown PetscInt cdof, d; 7003*552f7358SJed Brown 7004*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7005*552f7358SJed Brown if (cdof) { 7006*552f7358SJed Brown if (cdof > maxConstraints[numFields]) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_LIB, "Likely memory corruption, point %D cDof %D > maxConstraints %D", p, cdof, maxConstraints[numFields]); 7007*552f7358SJed Brown if (numFields) { 7008*552f7358SJed Brown PetscInt numConst = 0, foff = 0; 7009*552f7358SJed Brown 7010*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 7011*552f7358SJed Brown PetscInt cfdof, fdof; 7012*552f7358SJed Brown 7013*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7014*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, p, f, &cfdof);CHKERRQ(ierr); 7015*552f7358SJed Brown /* Change constraint numbering from absolute local dof number to field relative local dof number */ 7016*552f7358SJed Brown for(d = 0; d < cfdof; ++d) { 7017*552f7358SJed Brown indices[numConst+d] = d; 7018*552f7358SJed Brown } 7019*552f7358SJed Brown ierr = PetscSectionSetFieldConstraintIndices(section, p, f, &indices[numConst]);CHKERRQ(ierr); 7020*552f7358SJed Brown for(d = 0; d < cfdof; ++d) { 7021*552f7358SJed Brown indices[numConst+d] += foff; 7022*552f7358SJed Brown } 7023*552f7358SJed Brown numConst += cfdof; 7024*552f7358SJed Brown foff += fdof; 7025*552f7358SJed Brown } 7026*552f7358SJed Brown if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7027*552f7358SJed Brown } else { 7028*552f7358SJed Brown for (d = 0; d < cdof; ++d) { 7029*552f7358SJed Brown indices[d] = d; 7030*552f7358SJed Brown } 7031*552f7358SJed Brown } 7032*552f7358SJed Brown ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7033*552f7358SJed Brown } 7034*552f7358SJed Brown } 7035*552f7358SJed Brown ierr = PetscFree(indices);CHKERRQ(ierr); 7036*552f7358SJed Brown } 7037*552f7358SJed Brown ierr = PetscFree(maxConstraints);CHKERRQ(ierr); 7038*552f7358SJed Brown PetscFunctionReturn(0); 7039*552f7358SJed Brown } 7040*552f7358SJed Brown 7041*552f7358SJed Brown #undef __FUNCT__ 7042*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 7043*552f7358SJed Brown /* Set the constrained field indices on each point */ 7044*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt field, IS bcPoints, IS constraintIndices, PetscSection section) { 7045*552f7358SJed Brown const PetscInt *points, *indices; 7046*552f7358SJed Brown PetscInt numFields, maxDof, numPoints, p, numConstraints; 7047*552f7358SJed Brown PetscErrorCode ierr; 7048*552f7358SJed Brown 7049*552f7358SJed Brown PetscFunctionBegin; 7050*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7051*552f7358SJed Brown if ((field < 0) || (field >= numFields)) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Section field %d should be in [%d, %d)", field, 0, numFields); 7052*552f7358SJed Brown 7053*552f7358SJed Brown ierr = ISGetLocalSize(bcPoints, &numPoints);CHKERRQ(ierr); 7054*552f7358SJed Brown ierr = ISGetIndices(bcPoints, &points);CHKERRQ(ierr); 7055*552f7358SJed Brown if (!constraintIndices) { 7056*552f7358SJed Brown PetscInt *idx, i; 7057*552f7358SJed Brown 7058*552f7358SJed Brown ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7059*552f7358SJed Brown ierr = PetscMalloc(maxDof * sizeof(PetscInt), &idx);CHKERRQ(ierr); 7060*552f7358SJed Brown for(i = 0; i < maxDof; ++i) {idx[i] = i;} 7061*552f7358SJed Brown for(p = 0; p < numPoints; ++p) { 7062*552f7358SJed Brown ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, idx);CHKERRQ(ierr); 7063*552f7358SJed Brown } 7064*552f7358SJed Brown ierr = PetscFree(idx);CHKERRQ(ierr); 7065*552f7358SJed Brown } else { 7066*552f7358SJed Brown ierr = ISGetLocalSize(constraintIndices, &numConstraints);CHKERRQ(ierr); 7067*552f7358SJed Brown ierr = ISGetIndices(constraintIndices, &indices);CHKERRQ(ierr); 7068*552f7358SJed Brown for(p = 0; p < numPoints; ++p) { 7069*552f7358SJed Brown PetscInt fcdof; 7070*552f7358SJed Brown 7071*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, points[p], field, &fcdof);CHKERRQ(ierr); 7072*552f7358SJed Brown if (fcdof != numConstraints) SETERRQ4(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Section point %d field %d has %d constraints, but yo ugave %d indices", p, field, fcdof, numConstraints); 7073*552f7358SJed Brown ierr = PetscSectionSetFieldConstraintIndices(section, points[p], field, indices);CHKERRQ(ierr); 7074*552f7358SJed Brown } 7075*552f7358SJed Brown ierr = ISRestoreIndices(constraintIndices, &indices);CHKERRQ(ierr); 7076*552f7358SJed Brown } 7077*552f7358SJed Brown ierr = ISRestoreIndices(bcPoints, &points);CHKERRQ(ierr); 7078*552f7358SJed Brown PetscFunctionReturn(0); 7079*552f7358SJed Brown } 7080*552f7358SJed Brown 7081*552f7358SJed Brown #undef __FUNCT__ 7082*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSectionBCIndices" 7083*552f7358SJed Brown /* Set the constrained indices on each point and separate by fields */ 7084*552f7358SJed Brown PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) { 7085*552f7358SJed Brown PetscInt *indices; 7086*552f7358SJed Brown PetscInt numFields, maxDof, f, pStart = 0, pEnd = 0, p; 7087*552f7358SJed Brown PetscErrorCode ierr; 7088*552f7358SJed Brown 7089*552f7358SJed Brown PetscFunctionBegin; 7090*552f7358SJed Brown ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 7091*552f7358SJed Brown ierr = PetscMalloc(maxDof * sizeof(PetscInt), &indices);CHKERRQ(ierr); 7092*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7093*552f7358SJed Brown if (!numFields) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "This function only works after users have set field constraint indices."); 7094*552f7358SJed Brown ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7095*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 7096*552f7358SJed Brown PetscInt cdof, d; 7097*552f7358SJed Brown 7098*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 7099*552f7358SJed Brown if (cdof) { 7100*552f7358SJed Brown PetscInt numConst = 0, foff = 0; 7101*552f7358SJed Brown 7102*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 7103*552f7358SJed Brown const PetscInt *fcind; 7104*552f7358SJed Brown PetscInt fdof, fcdof; 7105*552f7358SJed Brown 7106*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 7107*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 7108*552f7358SJed Brown if (fcdof) {ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &fcind);CHKERRQ(ierr);} 7109*552f7358SJed Brown /* Change constraint numbering from field relative local dof number to absolute local dof number */ 7110*552f7358SJed Brown for(d = 0; d < fcdof; ++d) { 7111*552f7358SJed Brown indices[numConst+d] = fcind[d]+foff; 7112*552f7358SJed Brown } 7113*552f7358SJed Brown foff += fdof; 7114*552f7358SJed Brown numConst += fcdof; 7115*552f7358SJed Brown } 7116*552f7358SJed Brown if (cdof != numConst) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 7117*552f7358SJed Brown ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 7118*552f7358SJed Brown } 7119*552f7358SJed Brown } 7120*552f7358SJed Brown ierr = PetscFree(indices);CHKERRQ(ierr); 7121*552f7358SJed Brown PetscFunctionReturn(0); 7122*552f7358SJed Brown } 7123*552f7358SJed Brown 7124*552f7358SJed Brown #undef __FUNCT__ 7125*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSection" 7126*552f7358SJed Brown /*@C 7127*552f7358SJed Brown DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 7128*552f7358SJed Brown 7129*552f7358SJed Brown Not Collective 7130*552f7358SJed Brown 7131*552f7358SJed Brown Input Parameters: 7132*552f7358SJed Brown + dm - The DMPlex object 7133*552f7358SJed Brown . dim - The spatial dimension of the problem 7134*552f7358SJed Brown . numFields - The number of fields in the problem 7135*552f7358SJed Brown . numComp - An array of size numFields that holds the number of components for each field 7136*552f7358SJed Brown . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 7137*552f7358SJed Brown . numBC - The number of boundary conditions 7138*552f7358SJed Brown . bcField - An array of size numBC giving the field number for each boundry condition 7139*552f7358SJed Brown - bcPoints - An array of size numBC giving an IS holding the sieve points to which each boundary condition applies 7140*552f7358SJed Brown 7141*552f7358SJed Brown Output Parameter: 7142*552f7358SJed Brown . section - The PetscSection object 7143*552f7358SJed Brown 7144*552f7358SJed Brown Notes: numDof[f*(dim+1)+d] gives the number of dof for field f on sieve points of dimension d. For instance, numDof[1] is the 7145*552f7358SJed Brown nubmer of dof for field 0 on each edge. 7146*552f7358SJed Brown 7147*552f7358SJed Brown Level: developer 7148*552f7358SJed Brown 7149*552f7358SJed Brown .keywords: mesh, elements 7150*552f7358SJed Brown .seealso: DMPlexCreate(), PetscSectionCreate() 7151*552f7358SJed Brown @*/ 7152*552f7358SJed Brown PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[],const IS bcPoints[], PetscSection *section) { 7153*552f7358SJed Brown PetscErrorCode ierr; 7154*552f7358SJed Brown 7155*552f7358SJed Brown PetscFunctionBegin; 7156*552f7358SJed Brown ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 7157*552f7358SJed Brown ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcPoints, PETSC_DETERMINE, *section);CHKERRQ(ierr); 7158*552f7358SJed Brown ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 7159*552f7358SJed Brown if (numBC) {ierr = DMPlexCreateSectionBCIndicesAll(dm, *section);CHKERRQ(ierr);} 7160*552f7358SJed Brown { 7161*552f7358SJed Brown PetscBool view = PETSC_FALSE; 7162*552f7358SJed Brown 7163*552f7358SJed Brown ierr = PetscOptionsHasName(((PetscObject) dm)->prefix, "-section_view", &view);CHKERRQ(ierr); 7164*552f7358SJed Brown if (view) {ierr = PetscSectionView(*section, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} 7165*552f7358SJed Brown } 7166*552f7358SJed Brown PetscFunctionReturn(0); 7167*552f7358SJed Brown } 7168*552f7358SJed Brown 7169*552f7358SJed Brown #undef __FUNCT__ 7170*552f7358SJed Brown #define __FUNCT__ "DMCreateCoordinateDM_Plex" 7171*552f7358SJed Brown PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) { 7172*552f7358SJed Brown PetscSection section; 7173*552f7358SJed Brown PetscErrorCode ierr; 7174*552f7358SJed Brown 7175*552f7358SJed Brown PetscFunctionBegin; 7176*552f7358SJed Brown ierr = DMPlexClone(dm, cdm);CHKERRQ(ierr); 7177*552f7358SJed Brown ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 7178*552f7358SJed Brown ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 7179*552f7358SJed Brown PetscFunctionReturn(0); 7180*552f7358SJed Brown } 7181*552f7358SJed Brown 7182*552f7358SJed Brown #undef __FUNCT__ 7183*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCoordinateSection" 7184*552f7358SJed Brown /*@ 7185*552f7358SJed Brown DMPlexGetCoordinateSection - Retrieve the layout of coordinate values over the mesh. 7186*552f7358SJed Brown 7187*552f7358SJed Brown Not Collective 7188*552f7358SJed Brown 7189*552f7358SJed Brown Input Parameter: 7190*552f7358SJed Brown . dm - The DMPlex object 7191*552f7358SJed Brown 7192*552f7358SJed Brown Output Parameter: 7193*552f7358SJed Brown . section - The PetscSection object 7194*552f7358SJed Brown 7195*552f7358SJed Brown Level: intermediate 7196*552f7358SJed Brown 7197*552f7358SJed Brown .keywords: mesh, coordinates 7198*552f7358SJed Brown .seealso: DMGetCoordinateDM(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7199*552f7358SJed Brown @*/ 7200*552f7358SJed Brown PetscErrorCode DMPlexGetCoordinateSection(DM dm, PetscSection *section) { 7201*552f7358SJed Brown DM cdm; 7202*552f7358SJed Brown PetscErrorCode ierr; 7203*552f7358SJed Brown 7204*552f7358SJed Brown PetscFunctionBegin; 7205*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7206*552f7358SJed Brown PetscValidPointer(section, 2); 7207*552f7358SJed Brown ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7208*552f7358SJed Brown ierr = DMGetDefaultSection(cdm, section);CHKERRQ(ierr); 7209*552f7358SJed Brown PetscFunctionReturn(0); 7210*552f7358SJed Brown } 7211*552f7358SJed Brown 7212*552f7358SJed Brown #undef __FUNCT__ 7213*552f7358SJed Brown #define __FUNCT__ "DMPlexSetCoordinateSection" 7214*552f7358SJed Brown /*@ 7215*552f7358SJed Brown DMPlexSetCoordinateSection - Set the layout of coordinate values over the mesh. 7216*552f7358SJed Brown 7217*552f7358SJed Brown Not Collective 7218*552f7358SJed Brown 7219*552f7358SJed Brown Input Parameters: 7220*552f7358SJed Brown + dm - The DMPlex object 7221*552f7358SJed Brown - section - The PetscSection object 7222*552f7358SJed Brown 7223*552f7358SJed Brown Level: intermediate 7224*552f7358SJed Brown 7225*552f7358SJed Brown .keywords: mesh, coordinates 7226*552f7358SJed Brown .seealso: DMPlexGetCoordinateSection(), DMPlexGetDefaultSection(), DMPlexSetDefaultSection() 7227*552f7358SJed Brown @*/ 7228*552f7358SJed Brown PetscErrorCode DMPlexSetCoordinateSection(DM dm, PetscSection section) { 7229*552f7358SJed Brown DM cdm; 7230*552f7358SJed Brown PetscErrorCode ierr; 7231*552f7358SJed Brown 7232*552f7358SJed Brown PetscFunctionBegin; 7233*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7234*552f7358SJed Brown ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 7235*552f7358SJed Brown ierr = DMSetDefaultSection(cdm, section);CHKERRQ(ierr); 7236*552f7358SJed Brown PetscFunctionReturn(0); 7237*552f7358SJed Brown } 7238*552f7358SJed Brown 7239*552f7358SJed Brown #undef __FUNCT__ 7240*552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeSection" 7241*552f7358SJed Brown PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) { 7242*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 7243*552f7358SJed Brown 7244*552f7358SJed Brown PetscFunctionBegin; 7245*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7246*552f7358SJed Brown if (section) *section = mesh->coneSection; 7247*552f7358SJed Brown PetscFunctionReturn(0); 7248*552f7358SJed Brown } 7249*552f7358SJed Brown 7250*552f7358SJed Brown #undef __FUNCT__ 7251*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCones" 7252*552f7358SJed Brown PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) { 7253*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 7254*552f7358SJed Brown 7255*552f7358SJed Brown PetscFunctionBegin; 7256*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7257*552f7358SJed Brown if (cones) *cones = mesh->cones; 7258*552f7358SJed Brown PetscFunctionReturn(0); 7259*552f7358SJed Brown } 7260*552f7358SJed Brown 7261*552f7358SJed Brown #undef __FUNCT__ 7262*552f7358SJed Brown #define __FUNCT__ "DMPlexGetConeOrientations" 7263*552f7358SJed Brown PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) { 7264*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 7265*552f7358SJed Brown 7266*552f7358SJed Brown PetscFunctionBegin; 7267*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7268*552f7358SJed Brown if (coneOrientations) *coneOrientations = mesh->coneOrientations; 7269*552f7358SJed Brown PetscFunctionReturn(0); 7270*552f7358SJed Brown } 7271*552f7358SJed Brown 7272*552f7358SJed Brown #undef __FUNCT__ 7273*552f7358SJed Brown #define __FUNCT__ "DMPlexLocatePoint_Simplex_2D" 7274*552f7358SJed Brown PetscErrorCode DMPlexLocatePoint_Simplex_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7275*552f7358SJed Brown { 7276*552f7358SJed Brown const PetscInt embedDim = 2; 7277*552f7358SJed Brown PetscReal v0[2], J[4], invJ[4], detJ; 7278*552f7358SJed Brown PetscErrorCode ierr; 7279*552f7358SJed Brown 7280*552f7358SJed Brown PetscFunctionBegin; 7281*552f7358SJed Brown ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7282*552f7358SJed Brown PetscReal xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]); 7283*552f7358SJed Brown PetscReal eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]); 7284*552f7358SJed Brown 7285*552f7358SJed Brown if ((xi >= 0.0) && (eta >= 0.0) && (xi + eta <= 2.0)) { 7286*552f7358SJed Brown *cell = c; 7287*552f7358SJed Brown } else { 7288*552f7358SJed Brown *cell = -1; 7289*552f7358SJed Brown } 7290*552f7358SJed Brown PetscFunctionReturn(0); 7291*552f7358SJed Brown } 7292*552f7358SJed Brown 7293*552f7358SJed Brown #undef __FUNCT__ 7294*552f7358SJed Brown #define __FUNCT__ "DMPlexLocatePoint_General_2D" 7295*552f7358SJed Brown PetscErrorCode DMPlexLocatePoint_General_2D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7296*552f7358SJed Brown { 7297*552f7358SJed Brown PetscSection coordSection; 7298*552f7358SJed Brown Vec coordsLocal; 7299*552f7358SJed Brown const PetscScalar *coords; 7300*552f7358SJed Brown const PetscInt faces[8] = {0, 1, 1, 2, 2, 3, 3, 0}; 7301*552f7358SJed Brown PetscInt crossings = 0, f; 7302*552f7358SJed Brown PetscErrorCode ierr; 7303*552f7358SJed Brown 7304*552f7358SJed Brown PetscFunctionBegin; 7305*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7306*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7307*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7308*552f7358SJed Brown for(f = 0; f < 4; ++f) { 7309*552f7358SJed Brown PetscReal x_i = coords[faces[2*f+0]*2+0]; 7310*552f7358SJed Brown PetscReal y_i = coords[faces[2*f+0]*2+1]; 7311*552f7358SJed Brown PetscReal x_j = coords[faces[2*f+1]*2+0]; 7312*552f7358SJed Brown PetscReal y_j = coords[faces[2*f+1]*2+1]; 7313*552f7358SJed Brown PetscReal slope = (y_j - y_i) / (x_j - x_i); 7314*552f7358SJed Brown PetscBool cond1 = (x_i <= point[0]) && (point[0] < x_j) ? PETSC_TRUE : PETSC_FALSE; 7315*552f7358SJed Brown PetscBool cond2 = (x_j <= point[0]) && (point[0] < x_i) ? PETSC_TRUE : PETSC_FALSE; 7316*552f7358SJed Brown PetscBool above = (point[1] < slope * (point[0] - x_i) + y_i) ? PETSC_TRUE : PETSC_FALSE; 7317*552f7358SJed Brown if ((cond1 || cond2) && above) ++crossings; 7318*552f7358SJed Brown } 7319*552f7358SJed Brown if (crossings % 2) { 7320*552f7358SJed Brown *cell = c; 7321*552f7358SJed Brown } else { 7322*552f7358SJed Brown *cell = -1; 7323*552f7358SJed Brown } 7324*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7325*552f7358SJed Brown PetscFunctionReturn(0); 7326*552f7358SJed Brown } 7327*552f7358SJed Brown 7328*552f7358SJed Brown #undef __FUNCT__ 7329*552f7358SJed Brown #define __FUNCT__ "DMPlexLocatePoint_Simplex_3D" 7330*552f7358SJed Brown PetscErrorCode DMPlexLocatePoint_Simplex_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7331*552f7358SJed Brown { 7332*552f7358SJed Brown const PetscInt embedDim = 3; 7333*552f7358SJed Brown PetscReal v0[3], J[9], invJ[9], detJ; 7334*552f7358SJed Brown PetscErrorCode ierr; 7335*552f7358SJed Brown 7336*552f7358SJed Brown PetscFunctionBegin; 7337*552f7358SJed Brown ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 7338*552f7358SJed Brown PetscReal xi = invJ[0*embedDim+0]*(point[0] - v0[0]) + invJ[0*embedDim+1]*(point[1] - v0[1]) + invJ[0*embedDim+2]*(point[2] - v0[2]); 7339*552f7358SJed Brown PetscReal eta = invJ[1*embedDim+0]*(point[0] - v0[0]) + invJ[1*embedDim+1]*(point[1] - v0[1]) + invJ[1*embedDim+2]*(point[2] - v0[2]); 7340*552f7358SJed Brown PetscReal zeta = invJ[2*embedDim+0]*(point[0] - v0[0]) + invJ[2*embedDim+1]*(point[1] - v0[1]) + invJ[2*embedDim+2]*(point[2] - v0[2]); 7341*552f7358SJed Brown 7342*552f7358SJed Brown if ((xi >= 0.0) && (eta >= 0.0) && (zeta >= 0.0) && (xi + eta + zeta <= 2.0)) { 7343*552f7358SJed Brown *cell = c; 7344*552f7358SJed Brown } else { 7345*552f7358SJed Brown *cell = -1; 7346*552f7358SJed Brown } 7347*552f7358SJed Brown PetscFunctionReturn(0); 7348*552f7358SJed Brown } 7349*552f7358SJed Brown 7350*552f7358SJed Brown #undef __FUNCT__ 7351*552f7358SJed Brown #define __FUNCT__ "DMPlexLocatePoint_General_3D" 7352*552f7358SJed Brown PetscErrorCode DMPlexLocatePoint_General_3D(DM dm, const PetscScalar point[], PetscInt c, PetscInt *cell) 7353*552f7358SJed Brown { 7354*552f7358SJed Brown PetscSection coordSection; 7355*552f7358SJed Brown Vec coordsLocal; 7356*552f7358SJed Brown const PetscScalar *coords; 7357*552f7358SJed Brown const PetscInt faces[24] = {0, 1, 2, 3, 5, 4, 7, 6, 1, 0, 4, 5, 7358*552f7358SJed Brown 3, 2, 6, 7, 1, 5, 6, 2, 0, 3, 7, 4}; 7359*552f7358SJed Brown PetscBool found = PETSC_TRUE; 7360*552f7358SJed Brown PetscInt f; 7361*552f7358SJed Brown PetscErrorCode ierr; 7362*552f7358SJed Brown 7363*552f7358SJed Brown PetscFunctionBegin; 7364*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordsLocal);CHKERRQ(ierr); 7365*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 7366*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7367*552f7358SJed Brown for(f = 0; f < 6; ++f) { 7368*552f7358SJed Brown /* Check the point is under plane */ 7369*552f7358SJed Brown /* Get face normal */ 7370*552f7358SJed Brown PetscReal v_i[3] = {coords[faces[f*4+3]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+3]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+3]*3+2]-coords[faces[f*4+0]*3+2]}; 7371*552f7358SJed Brown PetscReal v_j[3] = {coords[faces[f*4+1]*3+0]-coords[faces[f*4+0]*3+0],coords[faces[f*4+1]*3+1]-coords[faces[f*4+0]*3+1],coords[faces[f*4+1]*3+2]-coords[faces[f*4+0]*3+2]}; 7372*552f7358SJed Brown PetscReal normal[3] = {v_i[1]*v_j[2] - v_i[2]*v_j[1], v_i[2]*v_j[0] - v_i[0]*v_j[2], v_i[0]*v_j[1] - v_i[1]*v_j[0]}; 7373*552f7358SJed Brown PetscReal pp[3] = {coords[faces[f*4+0]*3+0] - point[0],coords[faces[f*4+0]*3+1] - point[1],coords[faces[f*4+0]*3+2] - point[2]}; 7374*552f7358SJed Brown PetscReal dot = normal[0]*pp[0] + normal[1]*pp[1] + normal[2]*pp[2]; 7375*552f7358SJed Brown /* Check that projected point is in face (2D location problem) */ 7376*552f7358SJed Brown if (dot < 0.0) { 7377*552f7358SJed Brown found = PETSC_FALSE; 7378*552f7358SJed Brown break; 7379*552f7358SJed Brown } 7380*552f7358SJed Brown } 7381*552f7358SJed Brown if (found) { 7382*552f7358SJed Brown *cell = c; 7383*552f7358SJed Brown } else { 7384*552f7358SJed Brown *cell = -1; 7385*552f7358SJed Brown } 7386*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, c, PETSC_NULL, &coords);CHKERRQ(ierr); 7387*552f7358SJed Brown PetscFunctionReturn(0); 7388*552f7358SJed Brown } 7389*552f7358SJed Brown 7390*552f7358SJed Brown #undef __FUNCT__ 7391*552f7358SJed Brown #define __FUNCT__ "DMLocatePoints_Plex" 7392*552f7358SJed Brown /* 7393*552f7358SJed Brown Need to implement using the guess 7394*552f7358SJed Brown */ 7395*552f7358SJed Brown PetscErrorCode DMLocatePoints_Plex(DM dm, Vec v, IS *cellIS) 7396*552f7358SJed Brown { 7397*552f7358SJed Brown PetscInt cell = -1/*, guess = -1*/; 7398*552f7358SJed Brown PetscInt bs, numPoints, p; 7399*552f7358SJed Brown PetscInt dim, cStart, cEnd, cMax, c, coneSize; 7400*552f7358SJed Brown PetscInt *cells; 7401*552f7358SJed Brown PetscScalar *a; 7402*552f7358SJed Brown PetscErrorCode ierr; 7403*552f7358SJed Brown 7404*552f7358SJed Brown PetscFunctionBegin; 7405*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 7406*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 7407*552f7358SJed Brown ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr); 7408*552f7358SJed Brown ierr = VecGetLocalSize(v, &numPoints);CHKERRQ(ierr); 7409*552f7358SJed Brown ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr); 7410*552f7358SJed Brown ierr = VecGetArray(v, &a);CHKERRQ(ierr); 7411*552f7358SJed Brown if (bs != dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Block size for point vector %d must be the mesh coordinate dimension %d", bs, dim); 7412*552f7358SJed Brown numPoints /= bs; 7413*552f7358SJed Brown ierr = PetscMalloc(numPoints * sizeof(PetscInt), &cells);CHKERRQ(ierr); 7414*552f7358SJed Brown for(p = 0; p < numPoints; ++p) { 7415*552f7358SJed Brown const PetscScalar *point = &a[p*bs]; 7416*552f7358SJed Brown 7417*552f7358SJed Brown switch(dim) { 7418*552f7358SJed Brown case 2: 7419*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 7420*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7421*552f7358SJed Brown switch(coneSize) { 7422*552f7358SJed Brown case 3: 7423*552f7358SJed Brown ierr = DMPlexLocatePoint_Simplex_2D(dm, point, c, &cell);CHKERRQ(ierr); 7424*552f7358SJed Brown break; 7425*552f7358SJed Brown case 4: 7426*552f7358SJed Brown ierr = DMPlexLocatePoint_General_2D(dm, point, c, &cell);CHKERRQ(ierr); 7427*552f7358SJed Brown break; 7428*552f7358SJed Brown default: 7429*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7430*552f7358SJed Brown } 7431*552f7358SJed Brown if (cell >= 0) break; 7432*552f7358SJed Brown } 7433*552f7358SJed Brown break; 7434*552f7358SJed Brown case 3: 7435*552f7358SJed Brown for(c = cStart; c < cEnd; ++c) { 7436*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 7437*552f7358SJed Brown switch(coneSize) { 7438*552f7358SJed Brown case 4: 7439*552f7358SJed Brown ierr = DMPlexLocatePoint_Simplex_3D(dm, point, c, &cell);CHKERRQ(ierr); 7440*552f7358SJed Brown break; 7441*552f7358SJed Brown case 8: 7442*552f7358SJed Brown ierr = DMPlexLocatePoint_General_3D(dm, point, c, &cell);CHKERRQ(ierr); 7443*552f7358SJed Brown break; 7444*552f7358SJed Brown default: 7445*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for cell with cone size %d", coneSize); 7446*552f7358SJed Brown } 7447*552f7358SJed Brown if (cell >= 0) break; 7448*552f7358SJed Brown } 7449*552f7358SJed Brown break; 7450*552f7358SJed Brown default: 7451*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "No point location for mesh dimension %d", dim); 7452*552f7358SJed Brown } 7453*552f7358SJed Brown cells[p] = cell; 7454*552f7358SJed Brown } 7455*552f7358SJed Brown ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 7456*552f7358SJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF, numPoints, cells, PETSC_OWN_POINTER, cellIS);CHKERRQ(ierr); 7457*552f7358SJed Brown PetscFunctionReturn(0); 7458*552f7358SJed Brown } 7459*552f7358SJed Brown 7460*552f7358SJed Brown /******************************** FEM Support **********************************/ 7461*552f7358SJed Brown 7462*552f7358SJed Brown #undef __FUNCT__ 7463*552f7358SJed Brown #define __FUNCT__ "DMPlexVecGetClosure" 7464*552f7358SJed Brown /*@C 7465*552f7358SJed Brown DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 7466*552f7358SJed Brown 7467*552f7358SJed Brown Not collective 7468*552f7358SJed Brown 7469*552f7358SJed Brown Input Parameters: 7470*552f7358SJed Brown + dm - The DM 7471*552f7358SJed Brown . section - The section describing the layout in v, or PETSC_NULL to use the default section 7472*552f7358SJed Brown . v - The local vector 7473*552f7358SJed Brown - point - The sieve point in the DM 7474*552f7358SJed Brown 7475*552f7358SJed Brown Output Parameters: 7476*552f7358SJed Brown + csize - The number of values in the closure, or PETSC_NULL 7477*552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 7478*552f7358SJed Brown 7479*552f7358SJed Brown Level: intermediate 7480*552f7358SJed Brown 7481*552f7358SJed Brown .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7482*552f7358SJed Brown @*/ 7483*552f7358SJed Brown PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 7484*552f7358SJed Brown PetscScalar *array, *vArray; 7485*552f7358SJed Brown PetscInt *points = PETSC_NULL; 7486*552f7358SJed Brown PetscInt offsets[32]; 7487*552f7358SJed Brown PetscInt numFields, size, numPoints, pStart, pEnd, p, q, f; 7488*552f7358SJed Brown PetscErrorCode ierr; 7489*552f7358SJed Brown 7490*552f7358SJed Brown PetscFunctionBegin; 7491*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7492*552f7358SJed Brown PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7493*552f7358SJed Brown if (!section) { 7494*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7495*552f7358SJed Brown } 7496*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7497*552f7358SJed Brown if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7498*552f7358SJed Brown ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7499*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7500*552f7358SJed Brown /* Compress out points not in the section */ 7501*552f7358SJed Brown ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7502*552f7358SJed Brown for (p = 0, q = 0; p < numPoints*2; p += 2) { 7503*552f7358SJed Brown if ((points[p] >= pStart) && (points[p] < pEnd)) { 7504*552f7358SJed Brown points[q*2] = points[p]; 7505*552f7358SJed Brown points[q*2+1] = points[p+1]; 7506*552f7358SJed Brown ++q; 7507*552f7358SJed Brown } 7508*552f7358SJed Brown } 7509*552f7358SJed Brown numPoints = q; 7510*552f7358SJed Brown for (p = 0, size = 0; p < numPoints*2; p += 2) { 7511*552f7358SJed Brown PetscInt dof, fdof; 7512*552f7358SJed Brown 7513*552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7514*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 7515*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7516*552f7358SJed Brown offsets[f+1] += fdof; 7517*552f7358SJed Brown } 7518*552f7358SJed Brown size += dof; 7519*552f7358SJed Brown } 7520*552f7358SJed Brown for (f = 1; f < numFields; ++f) { 7521*552f7358SJed Brown offsets[f+1] += offsets[f]; 7522*552f7358SJed Brown } 7523*552f7358SJed Brown if (numFields && offsets[numFields] != size) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], size); 7524*552f7358SJed Brown ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 7525*552f7358SJed Brown ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 7526*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 7527*552f7358SJed Brown PetscInt o = points[p+1]; 7528*552f7358SJed Brown PetscInt dof, off, d; 7529*552f7358SJed Brown PetscScalar *varr; 7530*552f7358SJed Brown 7531*552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7532*552f7358SJed Brown ierr = PetscSectionGetOffset(section, points[p], &off);CHKERRQ(ierr); 7533*552f7358SJed Brown varr = &vArray[off]; 7534*552f7358SJed Brown if (numFields) { 7535*552f7358SJed Brown PetscInt fdof, foff, fcomp, f, c; 7536*552f7358SJed Brown 7537*552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 7538*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7539*552f7358SJed Brown if (o >= 0) { 7540*552f7358SJed Brown for (d = 0; d < fdof; ++d, ++offsets[f]) { 7541*552f7358SJed Brown array[offsets[f]] = varr[foff+d]; 7542*552f7358SJed Brown } 7543*552f7358SJed Brown } else { 7544*552f7358SJed Brown ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7545*552f7358SJed Brown for (d = fdof/fcomp-1; d >= 0; --d) { 7546*552f7358SJed Brown for (c = 0; c < fcomp; ++c, ++offsets[f]) { 7547*552f7358SJed Brown array[offsets[f]] = varr[foff+d*fcomp+c]; 7548*552f7358SJed Brown } 7549*552f7358SJed Brown } 7550*552f7358SJed Brown } 7551*552f7358SJed Brown foff += fdof; 7552*552f7358SJed Brown } 7553*552f7358SJed Brown } else { 7554*552f7358SJed Brown if (o >= 0) { 7555*552f7358SJed Brown for (d = 0; d < dof; ++d, ++offsets[0]) { 7556*552f7358SJed Brown array[offsets[0]] = varr[d]; 7557*552f7358SJed Brown } 7558*552f7358SJed Brown } else { 7559*552f7358SJed Brown for (d = dof-1; d >= 0; --d, ++offsets[0]) { 7560*552f7358SJed Brown array[offsets[0]] = varr[d]; 7561*552f7358SJed Brown } 7562*552f7358SJed Brown } 7563*552f7358SJed Brown } 7564*552f7358SJed Brown } 7565*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7566*552f7358SJed Brown ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 7567*552f7358SJed Brown if (csize) *csize = size; 7568*552f7358SJed Brown *values = array; 7569*552f7358SJed Brown PetscFunctionReturn(0); 7570*552f7358SJed Brown } 7571*552f7358SJed Brown 7572*552f7358SJed Brown #undef __FUNCT__ 7573*552f7358SJed Brown #define __FUNCT__ "DMPlexVecRestoreClosure" 7574*552f7358SJed Brown /*@C 7575*552f7358SJed Brown DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 7576*552f7358SJed Brown 7577*552f7358SJed Brown Not collective 7578*552f7358SJed Brown 7579*552f7358SJed Brown Input Parameters: 7580*552f7358SJed Brown + dm - The DM 7581*552f7358SJed Brown . section - The section describing the layout in v, or PETSC_NULL to use the default section 7582*552f7358SJed Brown . v - The local vector 7583*552f7358SJed Brown . point - The sieve point in the DM 7584*552f7358SJed Brown . csize - The number of values in the closure, or PETSC_NULL 7585*552f7358SJed Brown - values - The array of values, which is a borrowed array and should not be freed 7586*552f7358SJed Brown 7587*552f7358SJed Brown Level: intermediate 7588*552f7358SJed Brown 7589*552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 7590*552f7358SJed Brown @*/ 7591*552f7358SJed Brown PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, const PetscScalar *values[]) { 7592*552f7358SJed Brown PetscInt size = 0; 7593*552f7358SJed Brown PetscErrorCode ierr; 7594*552f7358SJed Brown 7595*552f7358SJed Brown PetscFunctionBegin; 7596*552f7358SJed Brown /* Should work without recalculating size */ 7597*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void *) values);CHKERRQ(ierr); 7598*552f7358SJed Brown PetscFunctionReturn(0); 7599*552f7358SJed Brown } 7600*552f7358SJed Brown 7601*552f7358SJed Brown PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 7602*552f7358SJed Brown PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 7603*552f7358SJed Brown 7604*552f7358SJed Brown #undef __FUNCT__ 7605*552f7358SJed Brown #define __FUNCT__ "updatePoint_private" 7606*552f7358SJed Brown PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 7607*552f7358SJed Brown { 7608*552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7609*552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7610*552f7358SJed Brown PetscScalar *a; 7611*552f7358SJed Brown PetscInt off, cind = 0, k; 7612*552f7358SJed Brown PetscErrorCode ierr; 7613*552f7358SJed Brown 7614*552f7358SJed Brown PetscFunctionBegin; 7615*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7616*552f7358SJed Brown ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 7617*552f7358SJed Brown a = &array[off]; 7618*552f7358SJed Brown if (!cdof || setBC) { 7619*552f7358SJed Brown if (orientation >= 0) { 7620*552f7358SJed Brown for (k = 0; k < dof; ++k) { 7621*552f7358SJed Brown fuse(&a[k], values[k]); 7622*552f7358SJed Brown } 7623*552f7358SJed Brown } else { 7624*552f7358SJed Brown for (k = 0; k < dof; ++k) { 7625*552f7358SJed Brown fuse(&a[k], values[dof-k-1]); 7626*552f7358SJed Brown } 7627*552f7358SJed Brown } 7628*552f7358SJed Brown } else { 7629*552f7358SJed Brown ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7630*552f7358SJed Brown if (orientation >= 0) { 7631*552f7358SJed Brown for (k = 0; k < dof; ++k) { 7632*552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7633*552f7358SJed Brown fuse(&a[k], values[k]); 7634*552f7358SJed Brown } 7635*552f7358SJed Brown } else { 7636*552f7358SJed Brown for (k = 0; k < dof; ++k) { 7637*552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 7638*552f7358SJed Brown fuse(&a[k], values[dof-k-1]); 7639*552f7358SJed Brown } 7640*552f7358SJed Brown } 7641*552f7358SJed Brown } 7642*552f7358SJed Brown PetscFunctionReturn(0); 7643*552f7358SJed Brown } 7644*552f7358SJed Brown 7645*552f7358SJed Brown #undef __FUNCT__ 7646*552f7358SJed Brown #define __FUNCT__ "updatePointFields_private" 7647*552f7358SJed Brown PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt foffs[], void (*fuse)(PetscScalar *, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) { 7648*552f7358SJed Brown PetscScalar *a; 7649*552f7358SJed Brown PetscInt numFields, off, foff, f; 7650*552f7358SJed Brown PetscErrorCode ierr; 7651*552f7358SJed Brown 7652*552f7358SJed Brown PetscFunctionBegin; 7653*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7654*552f7358SJed Brown ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 7655*552f7358SJed Brown a = &array[off]; 7656*552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 7657*552f7358SJed Brown PetscInt fdof, fcomp, fcdof; 7658*552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7659*552f7358SJed Brown PetscInt cind = 0, k, c; 7660*552f7358SJed Brown 7661*552f7358SJed Brown ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7662*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7663*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 7664*552f7358SJed Brown if (!fcdof || setBC) { 7665*552f7358SJed Brown if (orientation >= 0) { 7666*552f7358SJed Brown for (k = 0; k < fdof; ++k) { 7667*552f7358SJed Brown fuse(&a[foff+k], values[foffs[f]+k]); 7668*552f7358SJed Brown } 7669*552f7358SJed Brown } else { 7670*552f7358SJed Brown for (k = fdof/fcomp-1; k >= 0; --k) { 7671*552f7358SJed Brown for (c = 0; c < fcomp; ++c) { 7672*552f7358SJed Brown fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7673*552f7358SJed Brown } 7674*552f7358SJed Brown } 7675*552f7358SJed Brown } 7676*552f7358SJed Brown } else { 7677*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7678*552f7358SJed Brown if (orientation >= 0) { 7679*552f7358SJed Brown for (k = 0; k < fdof; ++k) { 7680*552f7358SJed Brown if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 7681*552f7358SJed Brown fuse(&a[foff+k], values[foffs[f]+k]); 7682*552f7358SJed Brown } 7683*552f7358SJed Brown } else { 7684*552f7358SJed Brown for (k = fdof/fcomp-1; k >= 0; --k) { 7685*552f7358SJed Brown for (c = 0; c < fcomp; ++c) { 7686*552f7358SJed Brown if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 7687*552f7358SJed Brown fuse(&a[foff+(fdof/fcomp-1-k)*fcomp+c], values[foffs[f]+k*fcomp+c]); 7688*552f7358SJed Brown } 7689*552f7358SJed Brown } 7690*552f7358SJed Brown } 7691*552f7358SJed Brown } 7692*552f7358SJed Brown foff += fdof; 7693*552f7358SJed Brown foffs[f] += fdof; 7694*552f7358SJed Brown } 7695*552f7358SJed Brown PetscFunctionReturn(0); 7696*552f7358SJed Brown } 7697*552f7358SJed Brown 7698*552f7358SJed Brown #undef __FUNCT__ 7699*552f7358SJed Brown #define __FUNCT__ "DMPlexVecSetClosure" 7700*552f7358SJed Brown /*@C 7701*552f7358SJed Brown DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 7702*552f7358SJed Brown 7703*552f7358SJed Brown Not collective 7704*552f7358SJed Brown 7705*552f7358SJed Brown Input Parameters: 7706*552f7358SJed Brown + dm - The DM 7707*552f7358SJed Brown . section - The section describing the layout in v, or PETSC_NULL to use the default sectionw 7708*552f7358SJed Brown . v - The local vector 7709*552f7358SJed Brown . point - The sieve point in the DM 7710*552f7358SJed Brown . values - The array of values, which is a borrowed array and should not be freed 7711*552f7358SJed Brown - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 7712*552f7358SJed Brown 7713*552f7358SJed Brown Level: intermediate 7714*552f7358SJed Brown 7715*552f7358SJed Brown .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 7716*552f7358SJed Brown @*/ 7717*552f7358SJed Brown PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) { 7718*552f7358SJed Brown PetscScalar *array; 7719*552f7358SJed Brown PetscInt *points = PETSC_NULL; 7720*552f7358SJed Brown PetscInt offsets[32]; 7721*552f7358SJed Brown PetscInt numFields, numPoints, off, dof, pStart, pEnd, p, q, f; 7722*552f7358SJed Brown PetscErrorCode ierr; 7723*552f7358SJed Brown 7724*552f7358SJed Brown PetscFunctionBegin; 7725*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7726*552f7358SJed Brown PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 7727*552f7358SJed Brown if (!section) { 7728*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7729*552f7358SJed Brown } 7730*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7731*552f7358SJed Brown if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7732*552f7358SJed Brown ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7733*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7734*552f7358SJed Brown /* Compress out points not in the section */ 7735*552f7358SJed Brown ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7736*552f7358SJed Brown for (p = 0, q = 0; p < numPoints*2; p += 2) { 7737*552f7358SJed Brown if ((points[p] >= pStart) && (points[p] < pEnd)) { 7738*552f7358SJed Brown points[q*2] = points[p]; 7739*552f7358SJed Brown points[q*2+1] = points[p+1]; 7740*552f7358SJed Brown ++q; 7741*552f7358SJed Brown } 7742*552f7358SJed Brown } 7743*552f7358SJed Brown numPoints = q; 7744*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 7745*552f7358SJed Brown PetscInt fdof; 7746*552f7358SJed Brown 7747*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 7748*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7749*552f7358SJed Brown offsets[f+1] += fdof; 7750*552f7358SJed Brown } 7751*552f7358SJed Brown } 7752*552f7358SJed Brown for (f = 1; f < numFields; ++f) { 7753*552f7358SJed Brown offsets[f+1] += offsets[f]; 7754*552f7358SJed Brown } 7755*552f7358SJed Brown ierr = VecGetArray(v, &array);CHKERRQ(ierr); 7756*552f7358SJed Brown if (numFields) { 7757*552f7358SJed Brown switch(mode) { 7758*552f7358SJed Brown case INSERT_VALUES: 7759*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 7760*552f7358SJed Brown PetscInt o = points[p+1]; 7761*552f7358SJed Brown updatePointFields_private(section, points[p], offsets, insert, PETSC_FALSE, o, values, array); 7762*552f7358SJed Brown } break; 7763*552f7358SJed Brown case INSERT_ALL_VALUES: 7764*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 7765*552f7358SJed Brown PetscInt o = points[p+1]; 7766*552f7358SJed Brown updatePointFields_private(section, points[p], offsets, insert, PETSC_TRUE, o, values, array); 7767*552f7358SJed Brown } break; 7768*552f7358SJed Brown case ADD_VALUES: 7769*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 7770*552f7358SJed Brown PetscInt o = points[p+1]; 7771*552f7358SJed Brown updatePointFields_private(section, points[p], offsets, add, PETSC_FALSE, o, values, array); 7772*552f7358SJed Brown } break; 7773*552f7358SJed Brown case ADD_ALL_VALUES: 7774*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 7775*552f7358SJed Brown PetscInt o = points[p+1]; 7776*552f7358SJed Brown updatePointFields_private(section, points[p], offsets, add, PETSC_TRUE, o, values, array); 7777*552f7358SJed Brown } break; 7778*552f7358SJed Brown default: 7779*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7780*552f7358SJed Brown } 7781*552f7358SJed Brown } else { 7782*552f7358SJed Brown switch(mode) { 7783*552f7358SJed Brown case INSERT_VALUES: 7784*552f7358SJed Brown for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7785*552f7358SJed Brown PetscInt o = points[p+1]; 7786*552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7787*552f7358SJed Brown updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 7788*552f7358SJed Brown } break; 7789*552f7358SJed Brown case INSERT_ALL_VALUES: 7790*552f7358SJed Brown for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7791*552f7358SJed Brown PetscInt o = points[p+1]; 7792*552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7793*552f7358SJed Brown updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 7794*552f7358SJed Brown } break; 7795*552f7358SJed Brown case ADD_VALUES: 7796*552f7358SJed Brown for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7797*552f7358SJed Brown PetscInt o = points[p+1]; 7798*552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7799*552f7358SJed Brown updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 7800*552f7358SJed Brown } break; 7801*552f7358SJed Brown case ADD_ALL_VALUES: 7802*552f7358SJed Brown for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 7803*552f7358SJed Brown PetscInt o = points[p+1]; 7804*552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7805*552f7358SJed Brown updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 7806*552f7358SJed Brown } break; 7807*552f7358SJed Brown default: 7808*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 7809*552f7358SJed Brown } 7810*552f7358SJed Brown } 7811*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7812*552f7358SJed Brown ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 7813*552f7358SJed Brown PetscFunctionReturn(0); 7814*552f7358SJed Brown } 7815*552f7358SJed Brown 7816*552f7358SJed Brown #undef __FUNCT__ 7817*552f7358SJed Brown #define __FUNCT__ "DMPlexPrintMatSetValues" 7818*552f7358SJed Brown PetscErrorCode DMPlexPrintMatSetValues(Mat A, PetscInt point, PetscInt numIndices, const PetscInt indices[], PetscScalar values[]) 7819*552f7358SJed Brown { 7820*552f7358SJed Brown PetscMPIInt rank; 7821*552f7358SJed Brown PetscInt i, j; 7822*552f7358SJed Brown PetscErrorCode ierr; 7823*552f7358SJed Brown 7824*552f7358SJed Brown PetscFunctionBegin; 7825*552f7358SJed Brown ierr = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr); 7826*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 7827*552f7358SJed Brown for (i = 0; i < numIndices; i++) { 7828*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]mat indices[%D] = %D\n", rank, i, indices[i]);CHKERRQ(ierr); 7829*552f7358SJed Brown } 7830*552f7358SJed Brown for (i = 0; i < numIndices; i++) { 7831*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_SELF, "[%D]", rank);CHKERRQ(ierr); 7832*552f7358SJed Brown for (j = 0; j < numIndices; j++) { 7833*552f7358SJed Brown #ifdef PETSC_USE_COMPLEX 7834*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_SELF, " (%G,%G)", PetscRealPart(values[i*numIndices+j]), PetscImaginaryPart(values[i*numIndices+j]));CHKERRQ(ierr); 7835*552f7358SJed Brown #else 7836*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_SELF, " %G", values[i*numIndices+j]);CHKERRQ(ierr); 7837*552f7358SJed Brown #endif 7838*552f7358SJed Brown } 7839*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 7840*552f7358SJed Brown } 7841*552f7358SJed Brown PetscFunctionReturn(0); 7842*552f7358SJed Brown } 7843*552f7358SJed Brown 7844*552f7358SJed Brown #undef __FUNCT__ 7845*552f7358SJed Brown #define __FUNCT__ "indicesPoint_private" 7846*552f7358SJed Brown /* . off - The global offset of this point */ 7847*552f7358SJed Brown PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt dof, PetscInt off, PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 7848*552f7358SJed Brown PetscInt cdof; /* The number of constraints on this point */ 7849*552f7358SJed Brown const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 7850*552f7358SJed Brown PetscInt cind = 0, k; 7851*552f7358SJed Brown PetscErrorCode ierr; 7852*552f7358SJed Brown 7853*552f7358SJed Brown PetscFunctionBegin; 7854*552f7358SJed Brown ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 7855*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 7856*552f7358SJed Brown if (!cdof || setBC) { 7857*552f7358SJed Brown if (orientation >= 0) { 7858*552f7358SJed Brown for (k = 0; k < dof; ++k) { 7859*552f7358SJed Brown indices[k] = off+k; 7860*552f7358SJed Brown } 7861*552f7358SJed Brown } else { 7862*552f7358SJed Brown for (k = 0; k < dof; ++k) { 7863*552f7358SJed Brown indices[dof-k-1] = off+k; 7864*552f7358SJed Brown } 7865*552f7358SJed Brown } 7866*552f7358SJed Brown } else { 7867*552f7358SJed Brown ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 7868*552f7358SJed Brown if (orientation >= 0) { 7869*552f7358SJed Brown for (k = 0; k < dof; ++k) { 7870*552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) { 7871*552f7358SJed Brown /* Insert check for returning constrained indices */ 7872*552f7358SJed Brown indices[k] = -(off+k+1); 7873*552f7358SJed Brown ++cind; 7874*552f7358SJed Brown } else { 7875*552f7358SJed Brown indices[k] = off+k-cind; 7876*552f7358SJed Brown } 7877*552f7358SJed Brown } 7878*552f7358SJed Brown } else { 7879*552f7358SJed Brown for (k = 0; k < dof; ++k) { 7880*552f7358SJed Brown if ((cind < cdof) && (k == cdofs[cind])) { 7881*552f7358SJed Brown /* Insert check for returning constrained indices */ 7882*552f7358SJed Brown indices[dof-k-1] = -(off+k+1); 7883*552f7358SJed Brown ++cind; 7884*552f7358SJed Brown } else { 7885*552f7358SJed Brown indices[dof-k-1] = off+k-cind; 7886*552f7358SJed Brown } 7887*552f7358SJed Brown } 7888*552f7358SJed Brown } 7889*552f7358SJed Brown } 7890*552f7358SJed Brown PetscFunctionReturn(0); 7891*552f7358SJed Brown } 7892*552f7358SJed Brown 7893*552f7358SJed Brown #undef __FUNCT__ 7894*552f7358SJed Brown #define __FUNCT__ "indicesPointFields_private" 7895*552f7358SJed Brown /* . off - The global offset of this point */ 7896*552f7358SJed Brown PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) { 7897*552f7358SJed Brown PetscInt numFields, foff, f; 7898*552f7358SJed Brown PetscErrorCode ierr; 7899*552f7358SJed Brown 7900*552f7358SJed Brown PetscFunctionBegin; 7901*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7902*552f7358SJed Brown for (f = 0, foff = 0; f < numFields; ++f) { 7903*552f7358SJed Brown PetscInt fdof, fcomp, cfdof; 7904*552f7358SJed Brown const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 7905*552f7358SJed Brown PetscInt cind = 0, k, c; 7906*552f7358SJed Brown 7907*552f7358SJed Brown ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 7908*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 7909*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 7910*552f7358SJed Brown if (!cfdof || setBC) { 7911*552f7358SJed Brown if (orientation >= 0) { 7912*552f7358SJed Brown for (k = 0; k < fdof; ++k) { 7913*552f7358SJed Brown indices[foffs[f]+k] = off+foff+k; 7914*552f7358SJed Brown } 7915*552f7358SJed Brown } else { 7916*552f7358SJed Brown for (k = fdof/fcomp-1; k >= 0; --k) { 7917*552f7358SJed Brown for (c = 0; c < fcomp; ++c) { 7918*552f7358SJed Brown indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 7919*552f7358SJed Brown } 7920*552f7358SJed Brown } 7921*552f7358SJed Brown } 7922*552f7358SJed Brown } else { 7923*552f7358SJed Brown ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 7924*552f7358SJed Brown if (orientation >= 0) { 7925*552f7358SJed Brown for (k = 0; k < fdof; ++k) { 7926*552f7358SJed Brown if ((cind < cfdof) && (k == fcdofs[cind])) { 7927*552f7358SJed Brown indices[foffs[f]+k] = -(off+foff+k+1); 7928*552f7358SJed Brown ++cind; 7929*552f7358SJed Brown } else { 7930*552f7358SJed Brown indices[foffs[f]+k] = off+foff+k-cind; 7931*552f7358SJed Brown } 7932*552f7358SJed Brown } 7933*552f7358SJed Brown } else { 7934*552f7358SJed Brown for (k = fdof/fcomp-1; k >= 0; --k) { 7935*552f7358SJed Brown for (c = 0; c < fcomp; ++c) { 7936*552f7358SJed Brown if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 7937*552f7358SJed Brown indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 7938*552f7358SJed Brown ++cind; 7939*552f7358SJed Brown } else { 7940*552f7358SJed Brown indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 7941*552f7358SJed Brown } 7942*552f7358SJed Brown } 7943*552f7358SJed Brown } 7944*552f7358SJed Brown } 7945*552f7358SJed Brown } 7946*552f7358SJed Brown foff += fdof - cfdof; 7947*552f7358SJed Brown foffs[f] += fdof; 7948*552f7358SJed Brown } 7949*552f7358SJed Brown PetscFunctionReturn(0); 7950*552f7358SJed Brown } 7951*552f7358SJed Brown 7952*552f7358SJed Brown #undef __FUNCT__ 7953*552f7358SJed Brown #define __FUNCT__ "DMPlexMatSetClosure" 7954*552f7358SJed Brown PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, PetscScalar values[], InsertMode mode) 7955*552f7358SJed Brown { 7956*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 7957*552f7358SJed Brown PetscInt *points = PETSC_NULL; 7958*552f7358SJed Brown PetscInt *indices; 7959*552f7358SJed Brown PetscInt offsets[32]; 7960*552f7358SJed Brown PetscInt numFields, numPoints, numIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 7961*552f7358SJed Brown PetscBool useDefault = !section ? PETSC_TRUE : PETSC_FALSE; 7962*552f7358SJed Brown PetscBool useGlobalDefault = !globalSection ? PETSC_TRUE : PETSC_FALSE; 7963*552f7358SJed Brown PetscErrorCode ierr; 7964*552f7358SJed Brown 7965*552f7358SJed Brown PetscFunctionBegin; 7966*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 7967*552f7358SJed Brown PetscValidHeaderSpecific(A, MAT_CLASSID, 3); 7968*552f7358SJed Brown if (useDefault) { 7969*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 7970*552f7358SJed Brown } 7971*552f7358SJed Brown if (useGlobalDefault) { 7972*552f7358SJed Brown if (useDefault) { 7973*552f7358SJed Brown ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 7974*552f7358SJed Brown } else { 7975*552f7358SJed Brown ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 7976*552f7358SJed Brown } 7977*552f7358SJed Brown } 7978*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 7979*552f7358SJed Brown if (numFields > 31) SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 7980*552f7358SJed Brown ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 7981*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 7982*552f7358SJed Brown /* Compress out points not in the section */ 7983*552f7358SJed Brown ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 7984*552f7358SJed Brown for (p = 0, q = 0; p < numPoints*2; p += 2) { 7985*552f7358SJed Brown if ((points[p] >= pStart) && (points[p] < pEnd)) { 7986*552f7358SJed Brown points[q*2] = points[p]; 7987*552f7358SJed Brown points[q*2+1] = points[p+1]; 7988*552f7358SJed Brown ++q; 7989*552f7358SJed Brown } 7990*552f7358SJed Brown } 7991*552f7358SJed Brown numPoints = q; 7992*552f7358SJed Brown for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 7993*552f7358SJed Brown PetscInt fdof; 7994*552f7358SJed Brown 7995*552f7358SJed Brown ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 7996*552f7358SJed Brown for (f = 0; f < numFields; ++f) { 7997*552f7358SJed Brown ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 7998*552f7358SJed Brown offsets[f+1] += fdof; 7999*552f7358SJed Brown } 8000*552f7358SJed Brown numIndices += dof; 8001*552f7358SJed Brown } 8002*552f7358SJed Brown for (f = 1; f < numFields; ++f) { 8003*552f7358SJed Brown offsets[f+1] += offsets[f]; 8004*552f7358SJed Brown } 8005*552f7358SJed Brown if (numFields && offsets[numFields] != numIndices) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 8006*552f7358SJed Brown ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8007*552f7358SJed Brown if (numFields) { 8008*552f7358SJed Brown for (p = 0; p < numPoints*2; p += 2) { 8009*552f7358SJed Brown PetscInt o = points[p+1]; 8010*552f7358SJed Brown ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8011*552f7358SJed Brown indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 8012*552f7358SJed Brown } 8013*552f7358SJed Brown } else { 8014*552f7358SJed Brown for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 8015*552f7358SJed Brown PetscInt o = points[p+1]; 8016*552f7358SJed Brown ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 8017*552f7358SJed Brown indicesPoint_private(section, points[p], dof, globalOff < 0 ? -(globalOff+1) : globalOff, PETSC_FALSE, o, &indices[off]); 8018*552f7358SJed Brown } 8019*552f7358SJed Brown } 8020*552f7358SJed Brown if (useGlobalDefault && !useDefault) { 8021*552f7358SJed Brown ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 8022*552f7358SJed Brown } 8023*552f7358SJed Brown if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(A, point, numIndices, indices, values);CHKERRQ(ierr);} 8024*552f7358SJed Brown ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 8025*552f7358SJed Brown if (ierr) { 8026*552f7358SJed Brown PetscMPIInt rank; 8027*552f7358SJed Brown PetscErrorCode ierr2; 8028*552f7358SJed Brown 8029*552f7358SJed Brown ierr2 = MPI_Comm_rank(((PetscObject) A)->comm, &rank);CHKERRQ(ierr2); 8030*552f7358SJed Brown ierr2 = PetscPrintf(PETSC_COMM_SELF, "[%D]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 8031*552f7358SJed Brown ierr2 = DMPlexPrintMatSetValues(A, point, numIndices, indices, values);CHKERRQ(ierr2); 8032*552f7358SJed Brown ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8033*552f7358SJed Brown CHKERRQ(ierr); 8034*552f7358SJed Brown } 8035*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 8036*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 8037*552f7358SJed Brown PetscFunctionReturn(0); 8038*552f7358SJed Brown } 8039*552f7358SJed Brown 8040*552f7358SJed Brown #undef __FUNCT__ 8041*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeTriangleGeometry_private" 8042*552f7358SJed Brown PetscErrorCode DMPlexComputeTriangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8043*552f7358SJed Brown { 8044*552f7358SJed Brown PetscSection coordSection; 8045*552f7358SJed Brown Vec coordinates; 8046*552f7358SJed Brown const PetscScalar *coords; 8047*552f7358SJed Brown const PetscInt dim = 2; 8048*552f7358SJed Brown PetscInt d, f; 8049*552f7358SJed Brown PetscErrorCode ierr; 8050*552f7358SJed Brown 8051*552f7358SJed Brown PetscFunctionBegin; 8052*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8053*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8054*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8055*552f7358SJed Brown if (v0) { 8056*552f7358SJed Brown for (d = 0; d < dim; d++) { 8057*552f7358SJed Brown v0[d] = PetscRealPart(coords[d]); 8058*552f7358SJed Brown } 8059*552f7358SJed Brown } 8060*552f7358SJed Brown if (J) { 8061*552f7358SJed Brown for (d = 0; d < dim; d++) { 8062*552f7358SJed Brown for (f = 0; f < dim; f++) { 8063*552f7358SJed Brown J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8064*552f7358SJed Brown } 8065*552f7358SJed Brown } 8066*552f7358SJed Brown *detJ = J[0]*J[3] - J[1]*J[2]; 8067*552f7358SJed Brown #if 0 8068*552f7358SJed Brown if (detJ < 0.0) { 8069*552f7358SJed Brown const PetscReal xLength = mesh->periodicity[0]; 8070*552f7358SJed Brown 8071*552f7358SJed Brown if (xLength != 0.0) { 8072*552f7358SJed Brown PetscReal v0x = coords[0*dim+0]; 8073*552f7358SJed Brown 8074*552f7358SJed Brown if (v0x == 0.0) { 8075*552f7358SJed Brown v0x = v0[0] = xLength; 8076*552f7358SJed Brown } 8077*552f7358SJed Brown for (f = 0; f < dim; f++) { 8078*552f7358SJed Brown const PetscReal px = coords[(f+1)*dim+0] == 0.0 ? xLength : coords[(f+1)*dim+0]; 8079*552f7358SJed Brown 8080*552f7358SJed Brown J[0*dim+f] = 0.5*(px - v0x); 8081*552f7358SJed Brown } 8082*552f7358SJed Brown } 8083*552f7358SJed Brown detJ = J[0]*J[3] - J[1]*J[2]; 8084*552f7358SJed Brown } 8085*552f7358SJed Brown #endif 8086*552f7358SJed Brown PetscLogFlops(8.0 + 3.0); 8087*552f7358SJed Brown } 8088*552f7358SJed Brown if (invJ) { 8089*552f7358SJed Brown const PetscReal invDet = 1.0/(*detJ); 8090*552f7358SJed Brown 8091*552f7358SJed Brown invJ[0] = invDet*J[3]; 8092*552f7358SJed Brown invJ[1] = -invDet*J[1]; 8093*552f7358SJed Brown invJ[2] = -invDet*J[2]; 8094*552f7358SJed Brown invJ[3] = invDet*J[0]; 8095*552f7358SJed Brown PetscLogFlops(5.0); 8096*552f7358SJed Brown } 8097*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8098*552f7358SJed Brown PetscFunctionReturn(0); 8099*552f7358SJed Brown } 8100*552f7358SJed Brown 8101*552f7358SJed Brown #undef __FUNCT__ 8102*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeRectangleGeometry_private" 8103*552f7358SJed Brown PetscErrorCode DMPlexComputeRectangleGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8104*552f7358SJed Brown { 8105*552f7358SJed Brown PetscSection coordSection; 8106*552f7358SJed Brown Vec coordinates; 8107*552f7358SJed Brown const PetscScalar *coords; 8108*552f7358SJed Brown const PetscInt dim = 2; 8109*552f7358SJed Brown PetscInt d, f; 8110*552f7358SJed Brown PetscErrorCode ierr; 8111*552f7358SJed Brown 8112*552f7358SJed Brown PetscFunctionBegin; 8113*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8114*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8115*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8116*552f7358SJed Brown if (v0) { 8117*552f7358SJed Brown for (d = 0; d < dim; d++) { 8118*552f7358SJed Brown v0[d] = PetscRealPart(coords[d]); 8119*552f7358SJed Brown } 8120*552f7358SJed Brown } 8121*552f7358SJed Brown if (J) { 8122*552f7358SJed Brown for (d = 0; d < dim; d++) { 8123*552f7358SJed Brown for (f = 0; f < dim; f++) { 8124*552f7358SJed Brown J[d*dim+f] = 0.5*(PetscRealPart(coords[(f*2+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8125*552f7358SJed Brown } 8126*552f7358SJed Brown } 8127*552f7358SJed Brown *detJ = J[0]*J[3] - J[1]*J[2]; 8128*552f7358SJed Brown PetscLogFlops(8.0 + 3.0); 8129*552f7358SJed Brown } 8130*552f7358SJed Brown if (invJ) { 8131*552f7358SJed Brown const PetscReal invDet = 1.0/(*detJ); 8132*552f7358SJed Brown 8133*552f7358SJed Brown invJ[0] = invDet*J[3]; 8134*552f7358SJed Brown invJ[1] = -invDet*J[1]; 8135*552f7358SJed Brown invJ[2] = -invDet*J[2]; 8136*552f7358SJed Brown invJ[3] = invDet*J[0]; 8137*552f7358SJed Brown PetscLogFlops(5.0); 8138*552f7358SJed Brown } 8139*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8140*552f7358SJed Brown PetscFunctionReturn(0); 8141*552f7358SJed Brown } 8142*552f7358SJed Brown 8143*552f7358SJed Brown #undef __FUNCT__ 8144*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeTetrahedronGeometry_private" 8145*552f7358SJed Brown PetscErrorCode DMPlexComputeTetrahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8146*552f7358SJed Brown { 8147*552f7358SJed Brown PetscSection coordSection; 8148*552f7358SJed Brown Vec coordinates; 8149*552f7358SJed Brown const PetscScalar *coords; 8150*552f7358SJed Brown const PetscInt dim = 3; 8151*552f7358SJed Brown PetscInt d, f; 8152*552f7358SJed Brown PetscErrorCode ierr; 8153*552f7358SJed Brown 8154*552f7358SJed Brown PetscFunctionBegin; 8155*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8156*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8157*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8158*552f7358SJed Brown if (v0) { 8159*552f7358SJed Brown for (d = 0; d < dim; d++) { 8160*552f7358SJed Brown v0[d] = PetscRealPart(coords[d]); 8161*552f7358SJed Brown } 8162*552f7358SJed Brown } 8163*552f7358SJed Brown if (J) { 8164*552f7358SJed Brown for (d = 0; d < dim; d++) { 8165*552f7358SJed Brown for (f = 0; f < dim; f++) { 8166*552f7358SJed Brown J[d*dim+f] = 0.5*(PetscRealPart(coords[(f+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8167*552f7358SJed Brown } 8168*552f7358SJed Brown } 8169*552f7358SJed Brown /* ??? This does not work with CTetGen: The minus sign is here since I orient the first face to get the outward normal */ 8170*552f7358SJed Brown *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8171*552f7358SJed Brown J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8172*552f7358SJed Brown J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8173*552f7358SJed Brown PetscLogFlops(18.0 + 12.0); 8174*552f7358SJed Brown } 8175*552f7358SJed Brown if (invJ) { 8176*552f7358SJed Brown const PetscReal invDet = -1.0/(*detJ); 8177*552f7358SJed Brown 8178*552f7358SJed Brown invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8179*552f7358SJed Brown invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8180*552f7358SJed Brown invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8181*552f7358SJed Brown invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8182*552f7358SJed Brown invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8183*552f7358SJed Brown invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8184*552f7358SJed Brown invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8185*552f7358SJed Brown invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8186*552f7358SJed Brown invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8187*552f7358SJed Brown PetscLogFlops(37.0); 8188*552f7358SJed Brown } 8189*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8190*552f7358SJed Brown PetscFunctionReturn(0); 8191*552f7358SJed Brown } 8192*552f7358SJed Brown 8193*552f7358SJed Brown #undef __FUNCT__ 8194*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeHexahedronGeometry_private" 8195*552f7358SJed Brown PetscErrorCode DMPlexComputeHexahedronGeometry_private(DM dm, PetscInt e, PetscReal v0[], PetscReal J[], PetscReal invJ[], PetscReal *detJ) 8196*552f7358SJed Brown { 8197*552f7358SJed Brown PetscSection coordSection; 8198*552f7358SJed Brown Vec coordinates; 8199*552f7358SJed Brown const PetscScalar *coords; 8200*552f7358SJed Brown const PetscInt dim = 3; 8201*552f7358SJed Brown PetscInt d; 8202*552f7358SJed Brown PetscErrorCode ierr; 8203*552f7358SJed Brown 8204*552f7358SJed Brown PetscFunctionBegin; 8205*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8206*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8207*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8208*552f7358SJed Brown if (v0) { 8209*552f7358SJed Brown for (d = 0; d < dim; d++) { 8210*552f7358SJed Brown v0[d] = PetscRealPart(coords[d]); 8211*552f7358SJed Brown } 8212*552f7358SJed Brown } 8213*552f7358SJed Brown if (J) { 8214*552f7358SJed Brown for (d = 0; d < dim; d++) { 8215*552f7358SJed Brown J[d*dim+0] = 0.5*(PetscRealPart(coords[(0+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8216*552f7358SJed Brown J[d*dim+1] = 0.5*(PetscRealPart(coords[(1+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8217*552f7358SJed Brown J[d*dim+2] = 0.5*(PetscRealPart(coords[(3+1)*dim+d]) - PetscRealPart(coords[0*dim+d])); 8218*552f7358SJed Brown } 8219*552f7358SJed Brown *detJ = (J[0*3+0]*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]) + 8220*552f7358SJed Brown J[0*3+1]*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]) + 8221*552f7358SJed Brown J[0*3+2]*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0])); 8222*552f7358SJed Brown PetscLogFlops(18.0 + 12.0); 8223*552f7358SJed Brown } 8224*552f7358SJed Brown if (invJ) { 8225*552f7358SJed Brown const PetscReal invDet = -1.0/(*detJ); 8226*552f7358SJed Brown 8227*552f7358SJed Brown invJ[0*3+0] = invDet*(J[1*3+1]*J[2*3+2] - J[1*3+2]*J[2*3+1]); 8228*552f7358SJed Brown invJ[0*3+1] = invDet*(J[0*3+2]*J[2*3+1] - J[0*3+1]*J[2*3+2]); 8229*552f7358SJed Brown invJ[0*3+2] = invDet*(J[0*3+1]*J[1*3+2] - J[0*3+2]*J[1*3+1]); 8230*552f7358SJed Brown invJ[1*3+0] = invDet*(J[1*3+2]*J[2*3+0] - J[1*3+0]*J[2*3+2]); 8231*552f7358SJed Brown invJ[1*3+1] = invDet*(J[0*3+0]*J[2*3+2] - J[0*3+2]*J[2*3+0]); 8232*552f7358SJed Brown invJ[1*3+2] = invDet*(J[0*3+2]*J[1*3+0] - J[0*3+0]*J[1*3+2]); 8233*552f7358SJed Brown invJ[2*3+0] = invDet*(J[1*3+0]*J[2*3+1] - J[1*3+1]*J[2*3+0]); 8234*552f7358SJed Brown invJ[2*3+1] = invDet*(J[0*3+1]*J[2*3+0] - J[0*3+0]*J[2*3+1]); 8235*552f7358SJed Brown invJ[2*3+2] = invDet*(J[0*3+0]*J[1*3+1] - J[0*3+1]*J[1*3+0]); 8236*552f7358SJed Brown PetscLogFlops(37.0); 8237*552f7358SJed Brown } 8238*552f7358SJed Brown *detJ *= 8.0; 8239*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, e, PETSC_NULL, &coords);CHKERRQ(ierr); 8240*552f7358SJed Brown PetscFunctionReturn(0); 8241*552f7358SJed Brown } 8242*552f7358SJed Brown 8243*552f7358SJed Brown #undef __FUNCT__ 8244*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeCellGeometry" 8245*552f7358SJed Brown /*@C 8246*552f7358SJed Brown DMPlexComputeCellGeometry - Compute the Jacobian, inverse Jacobian, and Jacobian determinant for a given cell 8247*552f7358SJed Brown 8248*552f7358SJed Brown Collective on DM 8249*552f7358SJed Brown 8250*552f7358SJed Brown Input Arguments: 8251*552f7358SJed Brown + dm - the DM 8252*552f7358SJed Brown - cell - the cell 8253*552f7358SJed Brown 8254*552f7358SJed Brown Output Arguments: 8255*552f7358SJed Brown + v0 - the translation part of this affine transform 8256*552f7358SJed Brown . J - the Jacobian of the transform to the reference element 8257*552f7358SJed Brown . invJ - the inverse of the Jacobian 8258*552f7358SJed Brown - detJ - the Jacobian determinant 8259*552f7358SJed Brown 8260*552f7358SJed Brown Level: advanced 8261*552f7358SJed Brown 8262*552f7358SJed Brown .seealso: DMPlexGetCoordinateSection(), DMPlexGetCoordinateVec() 8263*552f7358SJed Brown @*/ 8264*552f7358SJed Brown PetscErrorCode DMPlexComputeCellGeometry(DM dm, PetscInt cell, PetscReal *v0, PetscReal *J, PetscReal *invJ, PetscReal *detJ) { 8265*552f7358SJed Brown PetscInt dim, maxConeSize; 8266*552f7358SJed Brown PetscErrorCode ierr; 8267*552f7358SJed Brown 8268*552f7358SJed Brown PetscFunctionBegin; 8269*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8270*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 8271*552f7358SJed Brown switch(dim) { 8272*552f7358SJed Brown case 2: 8273*552f7358SJed Brown switch(maxConeSize) { 8274*552f7358SJed Brown case 3: 8275*552f7358SJed Brown ierr = DMPlexComputeTriangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8276*552f7358SJed Brown break; 8277*552f7358SJed Brown case 4: 8278*552f7358SJed Brown ierr = DMPlexComputeRectangleGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8279*552f7358SJed Brown break; 8280*552f7358SJed Brown default: 8281*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize); 8282*552f7358SJed Brown } 8283*552f7358SJed Brown break; 8284*552f7358SJed Brown case 3: 8285*552f7358SJed Brown switch(maxConeSize) { 8286*552f7358SJed Brown case 4: 8287*552f7358SJed Brown ierr = DMPlexComputeTetrahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8288*552f7358SJed Brown break; 8289*552f7358SJed Brown case 8: 8290*552f7358SJed Brown ierr = DMPlexComputeHexahedronGeometry_private(dm, cell, v0, J, invJ, detJ);CHKERRQ(ierr); 8291*552f7358SJed Brown break; 8292*552f7358SJed Brown default: 8293*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported number of cell vertices %D for element geometry computation", maxConeSize); 8294*552f7358SJed Brown } 8295*552f7358SJed Brown break; 8296*552f7358SJed Brown default: 8297*552f7358SJed Brown SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Unsupported dimension %D for element geometry computation", dim); 8298*552f7358SJed Brown } 8299*552f7358SJed Brown PetscFunctionReturn(0); 8300*552f7358SJed Brown } 8301*552f7358SJed Brown 8302*552f7358SJed Brown #undef __FUNCT__ 8303*552f7358SJed Brown #define __FUNCT__ "DMPlexGetFaceOrientation" 8304*552f7358SJed Brown PetscErrorCode DMPlexGetFaceOrientation(DM dm, PetscInt cell, PetscInt numCorners, PetscInt indices[], PetscInt oppositeVertex, PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) { 8305*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 8306*552f7358SJed Brown PetscBool posOrient = PETSC_FALSE; 8307*552f7358SJed Brown const PetscInt debug = 0; 8308*552f7358SJed Brown PetscInt cellDim, faceSize, f; 8309*552f7358SJed Brown PetscErrorCode ierr; 8310*552f7358SJed Brown 8311*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &cellDim);CHKERRQ(ierr); 8312*552f7358SJed Brown if (debug) {PetscPrintf(comm, "cellDim: %d numCorners: %d\n", cellDim, numCorners);CHKERRQ(ierr);} 8313*552f7358SJed Brown 8314*552f7358SJed Brown if (cellDim == numCorners-1) { 8315*552f7358SJed Brown /* Simplices */ 8316*552f7358SJed Brown faceSize = numCorners-1; 8317*552f7358SJed Brown posOrient = !(oppositeVertex%2) ? PETSC_TRUE : PETSC_FALSE; 8318*552f7358SJed Brown } else if (cellDim == 1 && numCorners == 3) { 8319*552f7358SJed Brown /* Quadratic line */ 8320*552f7358SJed Brown faceSize = 1; 8321*552f7358SJed Brown posOrient = PETSC_TRUE; 8322*552f7358SJed Brown } else if (cellDim == 2 && numCorners == 4) { 8323*552f7358SJed Brown /* Quads */ 8324*552f7358SJed Brown faceSize = 2; 8325*552f7358SJed Brown if ((indices[1] > indices[0]) && (indices[1] - indices[0] == 1)) { 8326*552f7358SJed Brown posOrient = PETSC_TRUE; 8327*552f7358SJed Brown } else if ((indices[0] == 3) && (indices[1] == 0)) { 8328*552f7358SJed Brown posOrient = PETSC_TRUE; 8329*552f7358SJed Brown } else { 8330*552f7358SJed Brown if (((indices[0] > indices[1]) && (indices[0] - indices[1] == 1)) || ((indices[0] == 0) && (indices[1] == 3))) { 8331*552f7358SJed Brown posOrient = PETSC_FALSE; 8332*552f7358SJed Brown } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossedge"); 8333*552f7358SJed Brown } 8334*552f7358SJed Brown } else if (cellDim == 2 && numCorners == 6) { 8335*552f7358SJed Brown /* Quadratic triangle (I hate this) */ 8336*552f7358SJed Brown /* Edges are determined by the first 2 vertices (corners of edges) */ 8337*552f7358SJed Brown const PetscInt faceSizeTri = 3; 8338*552f7358SJed Brown PetscInt sortedIndices[3], i, iFace; 8339*552f7358SJed Brown PetscBool found = PETSC_FALSE; 8340*552f7358SJed Brown PetscInt faceVerticesTriSorted[9] = { 8341*552f7358SJed Brown 0, 3, 4, /* bottom */ 8342*552f7358SJed Brown 1, 4, 5, /* right */ 8343*552f7358SJed Brown 2, 3, 5, /* left */ 8344*552f7358SJed Brown }; 8345*552f7358SJed Brown PetscInt faceVerticesTri[9] = { 8346*552f7358SJed Brown 0, 3, 4, /* bottom */ 8347*552f7358SJed Brown 1, 4, 5, /* right */ 8348*552f7358SJed Brown 2, 5, 3, /* left */ 8349*552f7358SJed Brown }; 8350*552f7358SJed Brown 8351*552f7358SJed Brown faceSize = faceSizeTri; 8352*552f7358SJed Brown for (i = 0; i < faceSizeTri; ++i) sortedIndices[i] = indices[i]; 8353*552f7358SJed Brown ierr = PetscSortInt(faceSizeTri, sortedIndices);CHKERRQ(ierr); 8354*552f7358SJed Brown for (iFace = 0; iFace < 3; ++iFace) { 8355*552f7358SJed Brown const PetscInt ii = iFace*faceSizeTri; 8356*552f7358SJed Brown PetscInt fVertex, cVertex; 8357*552f7358SJed Brown 8358*552f7358SJed Brown if ((sortedIndices[0] == faceVerticesTriSorted[ii+0]) && 8359*552f7358SJed Brown (sortedIndices[1] == faceVerticesTriSorted[ii+1])) { 8360*552f7358SJed Brown for (fVertex = 0; fVertex < faceSizeTri; ++fVertex) { 8361*552f7358SJed Brown for (cVertex = 0; cVertex < faceSizeTri; ++cVertex) { 8362*552f7358SJed Brown if (indices[cVertex] == faceVerticesTri[ii+fVertex]) { 8363*552f7358SJed Brown faceVertices[fVertex] = origVertices[cVertex]; 8364*552f7358SJed Brown break; 8365*552f7358SJed Brown } 8366*552f7358SJed Brown } 8367*552f7358SJed Brown } 8368*552f7358SJed Brown found = PETSC_TRUE; 8369*552f7358SJed Brown break; 8370*552f7358SJed Brown } 8371*552f7358SJed Brown } 8372*552f7358SJed Brown if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tri crossface"); 8373*552f7358SJed Brown if (posOriented) {*posOriented = PETSC_TRUE;} 8374*552f7358SJed Brown PetscFunctionReturn(0); 8375*552f7358SJed Brown } else if (cellDim == 2 && numCorners == 9) { 8376*552f7358SJed Brown /* Quadratic quad (I hate this) */ 8377*552f7358SJed Brown /* Edges are determined by the first 2 vertices (corners of edges) */ 8378*552f7358SJed Brown const PetscInt faceSizeQuad = 3; 8379*552f7358SJed Brown PetscInt sortedIndices[3], i, iFace; 8380*552f7358SJed Brown PetscBool found = PETSC_FALSE; 8381*552f7358SJed Brown PetscInt faceVerticesQuadSorted[12] = { 8382*552f7358SJed Brown 0, 1, 4, /* bottom */ 8383*552f7358SJed Brown 1, 2, 5, /* right */ 8384*552f7358SJed Brown 2, 3, 6, /* top */ 8385*552f7358SJed Brown 0, 3, 7, /* left */ 8386*552f7358SJed Brown }; 8387*552f7358SJed Brown PetscInt faceVerticesQuad[12] = { 8388*552f7358SJed Brown 0, 1, 4, /* bottom */ 8389*552f7358SJed Brown 1, 2, 5, /* right */ 8390*552f7358SJed Brown 2, 3, 6, /* top */ 8391*552f7358SJed Brown 3, 0, 7, /* left */ 8392*552f7358SJed Brown }; 8393*552f7358SJed Brown 8394*552f7358SJed Brown faceSize = faceSizeQuad; 8395*552f7358SJed Brown for (i = 0; i < faceSizeQuad; ++i) sortedIndices[i] = indices[i]; 8396*552f7358SJed Brown ierr = PetscSortInt(faceSizeQuad, sortedIndices);CHKERRQ(ierr); 8397*552f7358SJed Brown for (iFace = 0; iFace < 4; ++iFace) { 8398*552f7358SJed Brown const PetscInt ii = iFace*faceSizeQuad; 8399*552f7358SJed Brown PetscInt fVertex, cVertex; 8400*552f7358SJed Brown 8401*552f7358SJed Brown if ((sortedIndices[0] == faceVerticesQuadSorted[ii+0]) && 8402*552f7358SJed Brown (sortedIndices[1] == faceVerticesQuadSorted[ii+1])) { 8403*552f7358SJed Brown for (fVertex = 0; fVertex < faceSizeQuad; ++fVertex) { 8404*552f7358SJed Brown for (cVertex = 0; cVertex < faceSizeQuad; ++cVertex) { 8405*552f7358SJed Brown if (indices[cVertex] == faceVerticesQuad[ii+fVertex]) { 8406*552f7358SJed Brown faceVertices[fVertex] = origVertices[cVertex]; 8407*552f7358SJed Brown break; 8408*552f7358SJed Brown } 8409*552f7358SJed Brown } 8410*552f7358SJed Brown } 8411*552f7358SJed Brown found = PETSC_TRUE; 8412*552f7358SJed Brown break; 8413*552f7358SJed Brown } 8414*552f7358SJed Brown } 8415*552f7358SJed Brown if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid quad crossface"); 8416*552f7358SJed Brown if (posOriented) {*posOriented = PETSC_TRUE;} 8417*552f7358SJed Brown PetscFunctionReturn(0); 8418*552f7358SJed Brown } else if (cellDim == 3 && numCorners == 8) { 8419*552f7358SJed Brown /* Hexes 8420*552f7358SJed Brown A hex is two oriented quads with the normal of the first 8421*552f7358SJed Brown pointing up at the second. 8422*552f7358SJed Brown 8423*552f7358SJed Brown 7---6 8424*552f7358SJed Brown /| /| 8425*552f7358SJed Brown 4---5 | 8426*552f7358SJed Brown | 3-|-2 8427*552f7358SJed Brown |/ |/ 8428*552f7358SJed Brown 0---1 8429*552f7358SJed Brown 8430*552f7358SJed Brown Faces are determined by the first 4 vertices (corners of faces) */ 8431*552f7358SJed Brown const PetscInt faceSizeHex = 4; 8432*552f7358SJed Brown PetscInt sortedIndices[4], i, iFace; 8433*552f7358SJed Brown PetscBool found = PETSC_FALSE; 8434*552f7358SJed Brown PetscInt faceVerticesHexSorted[24] = { 8435*552f7358SJed Brown 0, 1, 2, 3, /* bottom */ 8436*552f7358SJed Brown 4, 5, 6, 7, /* top */ 8437*552f7358SJed Brown 0, 1, 4, 5, /* front */ 8438*552f7358SJed Brown 1, 2, 5, 6, /* right */ 8439*552f7358SJed Brown 2, 3, 6, 7, /* back */ 8440*552f7358SJed Brown 0, 3, 4, 7, /* left */ 8441*552f7358SJed Brown }; 8442*552f7358SJed Brown PetscInt faceVerticesHex[24] = { 8443*552f7358SJed Brown 3, 2, 1, 0, /* bottom */ 8444*552f7358SJed Brown 4, 5, 6, 7, /* top */ 8445*552f7358SJed Brown 0, 1, 5, 4, /* front */ 8446*552f7358SJed Brown 1, 2, 6, 5, /* right */ 8447*552f7358SJed Brown 2, 3, 7, 6, /* back */ 8448*552f7358SJed Brown 3, 0, 4, 7, /* left */ 8449*552f7358SJed Brown }; 8450*552f7358SJed Brown 8451*552f7358SJed Brown faceSize = faceSizeHex; 8452*552f7358SJed Brown for (i = 0; i < faceSizeHex; ++i) sortedIndices[i] = indices[i]; 8453*552f7358SJed Brown ierr = PetscSortInt(faceSizeHex, sortedIndices);CHKERRQ(ierr); 8454*552f7358SJed Brown for (iFace = 0; iFace < 6; ++iFace) { 8455*552f7358SJed Brown const PetscInt ii = iFace*faceSizeHex; 8456*552f7358SJed Brown PetscInt fVertex, cVertex; 8457*552f7358SJed Brown 8458*552f7358SJed Brown if ((sortedIndices[0] == faceVerticesHexSorted[ii+0]) && 8459*552f7358SJed Brown (sortedIndices[1] == faceVerticesHexSorted[ii+1]) && 8460*552f7358SJed Brown (sortedIndices[2] == faceVerticesHexSorted[ii+2]) && 8461*552f7358SJed Brown (sortedIndices[3] == faceVerticesHexSorted[ii+3])) { 8462*552f7358SJed Brown for (fVertex = 0; fVertex < faceSizeHex; ++fVertex) { 8463*552f7358SJed Brown for (cVertex = 0; cVertex < faceSizeHex; ++cVertex) { 8464*552f7358SJed Brown if (indices[cVertex] == faceVerticesHex[ii+fVertex]) { 8465*552f7358SJed Brown faceVertices[fVertex] = origVertices[cVertex]; 8466*552f7358SJed Brown break; 8467*552f7358SJed Brown } 8468*552f7358SJed Brown } 8469*552f7358SJed Brown } 8470*552f7358SJed Brown found = PETSC_TRUE; 8471*552f7358SJed Brown break; 8472*552f7358SJed Brown } 8473*552f7358SJed Brown } 8474*552f7358SJed Brown if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 8475*552f7358SJed Brown if (posOriented) {*posOriented = PETSC_TRUE;} 8476*552f7358SJed Brown PetscFunctionReturn(0); 8477*552f7358SJed Brown } else if (cellDim == 3 && numCorners == 10) { 8478*552f7358SJed Brown /* Quadratic tet */ 8479*552f7358SJed Brown /* Faces are determined by the first 3 vertices (corners of faces) */ 8480*552f7358SJed Brown const PetscInt faceSizeTet = 6; 8481*552f7358SJed Brown PetscInt sortedIndices[6], i, iFace; 8482*552f7358SJed Brown PetscBool found = PETSC_FALSE; 8483*552f7358SJed Brown PetscInt faceVerticesTetSorted[24] = { 8484*552f7358SJed Brown 0, 1, 2, 6, 7, 8, /* bottom */ 8485*552f7358SJed Brown 0, 3, 4, 6, 7, 9, /* front */ 8486*552f7358SJed Brown 1, 4, 5, 7, 8, 9, /* right */ 8487*552f7358SJed Brown 2, 3, 5, 6, 8, 9, /* left */ 8488*552f7358SJed Brown }; 8489*552f7358SJed Brown PetscInt faceVerticesTet[24] = { 8490*552f7358SJed Brown 0, 1, 2, 6, 7, 8, /* bottom */ 8491*552f7358SJed Brown 0, 4, 3, 6, 7, 9, /* front */ 8492*552f7358SJed Brown 1, 5, 4, 7, 8, 9, /* right */ 8493*552f7358SJed Brown 2, 3, 5, 8, 6, 9, /* left */ 8494*552f7358SJed Brown }; 8495*552f7358SJed Brown 8496*552f7358SJed Brown faceSize = faceSizeTet; 8497*552f7358SJed Brown for (i = 0; i < faceSizeTet; ++i) sortedIndices[i] = indices[i]; 8498*552f7358SJed Brown ierr = PetscSortInt(faceSizeTet, sortedIndices);CHKERRQ(ierr); 8499*552f7358SJed Brown for (iFace=0; iFace < 4; ++iFace) { 8500*552f7358SJed Brown const PetscInt ii = iFace*faceSizeTet; 8501*552f7358SJed Brown PetscInt fVertex, cVertex; 8502*552f7358SJed Brown 8503*552f7358SJed Brown if ((sortedIndices[0] == faceVerticesTetSorted[ii+0]) && 8504*552f7358SJed Brown (sortedIndices[1] == faceVerticesTetSorted[ii+1]) && 8505*552f7358SJed Brown (sortedIndices[2] == faceVerticesTetSorted[ii+2]) && 8506*552f7358SJed Brown (sortedIndices[3] == faceVerticesTetSorted[ii+3])) { 8507*552f7358SJed Brown for (fVertex = 0; fVertex < faceSizeTet; ++fVertex) { 8508*552f7358SJed Brown for (cVertex = 0; cVertex < faceSizeTet; ++cVertex) { 8509*552f7358SJed Brown if (indices[cVertex] == faceVerticesTet[ii+fVertex]) { 8510*552f7358SJed Brown faceVertices[fVertex] = origVertices[cVertex]; 8511*552f7358SJed Brown break; 8512*552f7358SJed Brown } 8513*552f7358SJed Brown } 8514*552f7358SJed Brown } 8515*552f7358SJed Brown found = PETSC_TRUE; 8516*552f7358SJed Brown break; 8517*552f7358SJed Brown } 8518*552f7358SJed Brown } 8519*552f7358SJed Brown if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid tet crossface"); 8520*552f7358SJed Brown if (posOriented) {*posOriented = PETSC_TRUE;} 8521*552f7358SJed Brown PetscFunctionReturn(0); 8522*552f7358SJed Brown } else if (cellDim == 3 && numCorners == 27) { 8523*552f7358SJed Brown /* Quadratic hexes (I hate this) 8524*552f7358SJed Brown A hex is two oriented quads with the normal of the first 8525*552f7358SJed Brown pointing up at the second. 8526*552f7358SJed Brown 8527*552f7358SJed Brown 7---6 8528*552f7358SJed Brown /| /| 8529*552f7358SJed Brown 4---5 | 8530*552f7358SJed Brown | 3-|-2 8531*552f7358SJed Brown |/ |/ 8532*552f7358SJed Brown 0---1 8533*552f7358SJed Brown 8534*552f7358SJed Brown Faces are determined by the first 4 vertices (corners of faces) */ 8535*552f7358SJed Brown const PetscInt faceSizeQuadHex = 9; 8536*552f7358SJed Brown PetscInt sortedIndices[9], i, iFace; 8537*552f7358SJed Brown PetscBool found = PETSC_FALSE; 8538*552f7358SJed Brown PetscInt faceVerticesQuadHexSorted[54] = { 8539*552f7358SJed Brown 0, 1, 2, 3, 8, 9, 10, 11, 24, /* bottom */ 8540*552f7358SJed Brown 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 8541*552f7358SJed Brown 0, 1, 4, 5, 8, 12, 16, 17, 22, /* front */ 8542*552f7358SJed Brown 1, 2, 5, 6, 9, 13, 17, 18, 21, /* right */ 8543*552f7358SJed Brown 2, 3, 6, 7, 10, 14, 18, 19, 23, /* back */ 8544*552f7358SJed Brown 0, 3, 4, 7, 11, 15, 16, 19, 20, /* left */ 8545*552f7358SJed Brown }; 8546*552f7358SJed Brown PetscInt faceVerticesQuadHex[54] = { 8547*552f7358SJed Brown 3, 2, 1, 0, 10, 9, 8, 11, 24, /* bottom */ 8548*552f7358SJed Brown 4, 5, 6, 7, 12, 13, 14, 15, 25, /* top */ 8549*552f7358SJed Brown 0, 1, 5, 4, 8, 17, 12, 16, 22, /* front */ 8550*552f7358SJed Brown 1, 2, 6, 5, 9, 18, 13, 17, 21, /* right */ 8551*552f7358SJed Brown 2, 3, 7, 6, 10, 19, 14, 18, 23, /* back */ 8552*552f7358SJed Brown 3, 0, 4, 7, 11, 16, 15, 19, 20 /* left */ 8553*552f7358SJed Brown }; 8554*552f7358SJed Brown 8555*552f7358SJed Brown faceSize = faceSizeQuadHex; 8556*552f7358SJed Brown for (i = 0; i < faceSizeQuadHex; ++i) sortedIndices[i] = indices[i]; 8557*552f7358SJed Brown ierr = PetscSortInt(faceSizeQuadHex, sortedIndices);CHKERRQ(ierr); 8558*552f7358SJed Brown for (iFace = 0; iFace < 6; ++iFace) { 8559*552f7358SJed Brown const PetscInt ii = iFace*faceSizeQuadHex; 8560*552f7358SJed Brown PetscInt fVertex, cVertex; 8561*552f7358SJed Brown 8562*552f7358SJed Brown if ((sortedIndices[0] == faceVerticesQuadHexSorted[ii+0]) && 8563*552f7358SJed Brown (sortedIndices[1] == faceVerticesQuadHexSorted[ii+1]) && 8564*552f7358SJed Brown (sortedIndices[2] == faceVerticesQuadHexSorted[ii+2]) && 8565*552f7358SJed Brown (sortedIndices[3] == faceVerticesQuadHexSorted[ii+3])) { 8566*552f7358SJed Brown for (fVertex = 0; fVertex < faceSizeQuadHex; ++fVertex) { 8567*552f7358SJed Brown for (cVertex = 0; cVertex < faceSizeQuadHex; ++cVertex) { 8568*552f7358SJed Brown if (indices[cVertex] == faceVerticesQuadHex[ii+fVertex]) { 8569*552f7358SJed Brown faceVertices[fVertex] = origVertices[cVertex]; 8570*552f7358SJed Brown break; 8571*552f7358SJed Brown } 8572*552f7358SJed Brown } 8573*552f7358SJed Brown } 8574*552f7358SJed Brown found = PETSC_TRUE; 8575*552f7358SJed Brown break; 8576*552f7358SJed Brown } 8577*552f7358SJed Brown } 8578*552f7358SJed Brown if (!found) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Invalid hex crossface"); 8579*552f7358SJed Brown if (posOriented) {*posOriented = PETSC_TRUE;} 8580*552f7358SJed Brown PetscFunctionReturn(0); 8581*552f7358SJed Brown } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Unknown cell type for faceOrientation()."); 8582*552f7358SJed Brown if (!posOrient) { 8583*552f7358SJed Brown if (debug) {ierr = PetscPrintf(comm, " Reversing initial face orientation\n");CHKERRQ(ierr);} 8584*552f7358SJed Brown for (f = 0; f < faceSize; ++f) { 8585*552f7358SJed Brown faceVertices[f] = origVertices[faceSize-1 - f]; 8586*552f7358SJed Brown } 8587*552f7358SJed Brown } else { 8588*552f7358SJed Brown if (debug) {ierr = PetscPrintf(comm, " Keeping initial face orientation\n");CHKERRQ(ierr);} 8589*552f7358SJed Brown for (f = 0; f < faceSize; ++f) { 8590*552f7358SJed Brown faceVertices[f] = origVertices[f]; 8591*552f7358SJed Brown } 8592*552f7358SJed Brown } 8593*552f7358SJed Brown if (posOriented) {*posOriented = posOrient;} 8594*552f7358SJed Brown PetscFunctionReturn(0); 8595*552f7358SJed Brown } 8596*552f7358SJed Brown 8597*552f7358SJed Brown #undef __FUNCT__ 8598*552f7358SJed Brown #define __FUNCT__ "DMPlexGetOrientedFace" 8599*552f7358SJed Brown /* 8600*552f7358SJed Brown Given a cell and a face, as a set of vertices, 8601*552f7358SJed Brown return the oriented face, as a set of vertices, in faceVertices 8602*552f7358SJed Brown The orientation is such that the face normal points out of the cell 8603*552f7358SJed Brown */ 8604*552f7358SJed Brown PetscErrorCode DMPlexGetOrientedFace(DM dm, PetscInt cell, PetscInt faceSize, const PetscInt face[], PetscInt numCorners, PetscInt indices[], PetscInt origVertices[], PetscInt faceVertices[], PetscBool *posOriented) 8605*552f7358SJed Brown { 8606*552f7358SJed Brown const PetscInt *cone = PETSC_NULL; 8607*552f7358SJed Brown PetscInt coneSize, v, f, v2; 8608*552f7358SJed Brown PetscInt oppositeVertex = -1; 8609*552f7358SJed Brown PetscErrorCode ierr; 8610*552f7358SJed Brown 8611*552f7358SJed Brown PetscFunctionBegin; 8612*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, cell, &coneSize);CHKERRQ(ierr); 8613*552f7358SJed Brown ierr = DMPlexGetCone(dm, cell, &cone);CHKERRQ(ierr); 8614*552f7358SJed Brown for (v = 0, v2 = 0; v < coneSize; ++v) { 8615*552f7358SJed Brown PetscBool found = PETSC_FALSE; 8616*552f7358SJed Brown 8617*552f7358SJed Brown for (f = 0; f < faceSize; ++f) { 8618*552f7358SJed Brown if (face[f] == cone[v]) {found = PETSC_TRUE; break;} 8619*552f7358SJed Brown } 8620*552f7358SJed Brown if (found) { 8621*552f7358SJed Brown indices[v2] = v; 8622*552f7358SJed Brown origVertices[v2] = cone[v]; 8623*552f7358SJed Brown ++v2; 8624*552f7358SJed Brown } else { 8625*552f7358SJed Brown oppositeVertex = v; 8626*552f7358SJed Brown } 8627*552f7358SJed Brown } 8628*552f7358SJed Brown ierr = DMPlexGetFaceOrientation(dm, cell, numCorners, indices, oppositeVertex, origVertices, faceVertices, posOriented);CHKERRQ(ierr); 8629*552f7358SJed Brown PetscFunctionReturn(0); 8630*552f7358SJed Brown } 8631*552f7358SJed Brown 8632*552f7358SJed Brown PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 8633*552f7358SJed Brown { 8634*552f7358SJed Brown switch(i) { 8635*552f7358SJed Brown case 0: 8636*552f7358SJed Brown switch(j) { 8637*552f7358SJed Brown case 0: return 0; 8638*552f7358SJed Brown case 1: 8639*552f7358SJed Brown switch(k) { 8640*552f7358SJed Brown case 0: return 0; 8641*552f7358SJed Brown case 1: return 0; 8642*552f7358SJed Brown case 2: return 1; 8643*552f7358SJed Brown } 8644*552f7358SJed Brown case 2: 8645*552f7358SJed Brown switch(k) { 8646*552f7358SJed Brown case 0: return 0; 8647*552f7358SJed Brown case 1: return -1; 8648*552f7358SJed Brown case 2: return 0; 8649*552f7358SJed Brown } 8650*552f7358SJed Brown } 8651*552f7358SJed Brown case 1: 8652*552f7358SJed Brown switch(j) { 8653*552f7358SJed Brown case 0: 8654*552f7358SJed Brown switch(k) { 8655*552f7358SJed Brown case 0: return 0; 8656*552f7358SJed Brown case 1: return 0; 8657*552f7358SJed Brown case 2: return -1; 8658*552f7358SJed Brown } 8659*552f7358SJed Brown case 1: return 0; 8660*552f7358SJed Brown case 2: 8661*552f7358SJed Brown switch(k) { 8662*552f7358SJed Brown case 0: return 1; 8663*552f7358SJed Brown case 1: return 0; 8664*552f7358SJed Brown case 2: return 0; 8665*552f7358SJed Brown } 8666*552f7358SJed Brown } 8667*552f7358SJed Brown case 2: 8668*552f7358SJed Brown switch(j) { 8669*552f7358SJed Brown case 0: 8670*552f7358SJed Brown switch(k) { 8671*552f7358SJed Brown case 0: return 0; 8672*552f7358SJed Brown case 1: return 1; 8673*552f7358SJed Brown case 2: return 0; 8674*552f7358SJed Brown } 8675*552f7358SJed Brown case 1: 8676*552f7358SJed Brown switch(k) { 8677*552f7358SJed Brown case 0: return -1; 8678*552f7358SJed Brown case 1: return 0; 8679*552f7358SJed Brown case 2: return 0; 8680*552f7358SJed Brown } 8681*552f7358SJed Brown case 2: return 0; 8682*552f7358SJed Brown } 8683*552f7358SJed Brown } 8684*552f7358SJed Brown return 0; 8685*552f7358SJed Brown } 8686*552f7358SJed Brown 8687*552f7358SJed Brown #undef __FUNCT__ 8688*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateRigidBody" 8689*552f7358SJed Brown /*@C 8690*552f7358SJed Brown DMPlexCreateRigidBody - create rigid body modes from coordinates 8691*552f7358SJed Brown 8692*552f7358SJed Brown Collective on DM 8693*552f7358SJed Brown 8694*552f7358SJed Brown Input Arguments: 8695*552f7358SJed Brown + dm - the DM 8696*552f7358SJed Brown . section - the local section associated with the rigid field, or PETSC_NULL for the default section 8697*552f7358SJed Brown - globalSection - the global section associated with the rigid field, or PETSC_NULL for the default section 8698*552f7358SJed Brown 8699*552f7358SJed Brown Output Argument: 8700*552f7358SJed Brown . sp - the null space 8701*552f7358SJed Brown 8702*552f7358SJed Brown Note: This is necessary to take account of Dirichlet conditions on the displacements 8703*552f7358SJed Brown 8704*552f7358SJed Brown Level: advanced 8705*552f7358SJed Brown 8706*552f7358SJed Brown .seealso: MatNullSpaceCreate() 8707*552f7358SJed Brown @*/ 8708*552f7358SJed Brown PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 8709*552f7358SJed Brown { 8710*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 8711*552f7358SJed Brown Vec coordinates, localMode, mode[6]; 8712*552f7358SJed Brown PetscSection coordSection; 8713*552f7358SJed Brown PetscScalar *coords; 8714*552f7358SJed Brown PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 8715*552f7358SJed Brown PetscErrorCode ierr; 8716*552f7358SJed Brown 8717*552f7358SJed Brown PetscFunctionBegin; 8718*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8719*552f7358SJed Brown if (dim == 1) { 8720*552f7358SJed Brown ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, PETSC_NULL, sp);CHKERRQ(ierr); 8721*552f7358SJed Brown PetscFunctionReturn(0); 8722*552f7358SJed Brown } 8723*552f7358SJed Brown if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 8724*552f7358SJed Brown if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 8725*552f7358SJed Brown ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 8726*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8727*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 8728*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 8729*552f7358SJed Brown m = (dim*(dim+1))/2; 8730*552f7358SJed Brown ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 8731*552f7358SJed Brown ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 8732*552f7358SJed Brown ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 8733*552f7358SJed Brown for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 8734*552f7358SJed Brown /* Assume P1 */ 8735*552f7358SJed Brown ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 8736*552f7358SJed Brown for (d = 0; d < dim; ++d) { 8737*552f7358SJed Brown PetscScalar values[3] = {0.0, 0.0, 0.0}; 8738*552f7358SJed Brown 8739*552f7358SJed Brown values[d] = 1.0; 8740*552f7358SJed Brown ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8741*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 8742*552f7358SJed Brown ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8743*552f7358SJed Brown } 8744*552f7358SJed Brown ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8745*552f7358SJed Brown ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8746*552f7358SJed Brown } 8747*552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 8748*552f7358SJed Brown for (d = dim; d < dim*(dim+1)/2; ++d) { 8749*552f7358SJed Brown PetscInt i, j, k = dim > 2 ? d - dim : d; 8750*552f7358SJed Brown 8751*552f7358SJed Brown ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 8752*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 8753*552f7358SJed Brown PetscScalar values[3] = {0.0, 0.0, 0.0}; 8754*552f7358SJed Brown PetscInt off; 8755*552f7358SJed Brown 8756*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 8757*552f7358SJed Brown for (i = 0; i < dim; ++i) { 8758*552f7358SJed Brown for (j = 0; j < dim; ++j) { 8759*552f7358SJed Brown values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 8760*552f7358SJed Brown } 8761*552f7358SJed Brown } 8762*552f7358SJed Brown ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 8763*552f7358SJed Brown } 8764*552f7358SJed Brown ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8765*552f7358SJed Brown ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 8766*552f7358SJed Brown } 8767*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 8768*552f7358SJed Brown ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 8769*552f7358SJed Brown for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr);} 8770*552f7358SJed Brown /* Orthonormalize system */ 8771*552f7358SJed Brown for (i = dim; i < m; ++i) { 8772*552f7358SJed Brown PetscScalar dots[6]; 8773*552f7358SJed Brown 8774*552f7358SJed Brown ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 8775*552f7358SJed Brown for (j = 0; j < i; ++j) dots[j] *= -1.0; 8776*552f7358SJed Brown ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 8777*552f7358SJed Brown ierr = VecNormalize(mode[i], PETSC_NULL);CHKERRQ(ierr); 8778*552f7358SJed Brown } 8779*552f7358SJed Brown ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 8780*552f7358SJed Brown for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 8781*552f7358SJed Brown PetscFunctionReturn(0); 8782*552f7358SJed Brown } 8783*552f7358SJed Brown 8784*552f7358SJed Brown #undef __FUNCT__ 8785*552f7358SJed Brown #define __FUNCT__ "DMPlexGetVTKBounds" 8786*552f7358SJed Brown PetscErrorCode DMPlexGetVTKBounds(DM dm, PetscInt *cMax, PetscInt *vMax) 8787*552f7358SJed Brown { 8788*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 8789*552f7358SJed Brown 8790*552f7358SJed Brown PetscFunctionBegin; 8791*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8792*552f7358SJed Brown if (cMax) *cMax = mesh->vtkCellMax; 8793*552f7358SJed Brown if (vMax) *vMax = mesh->vtkVertexMax; 8794*552f7358SJed Brown PetscFunctionReturn(0); 8795*552f7358SJed Brown } 8796*552f7358SJed Brown 8797*552f7358SJed Brown #undef __FUNCT__ 8798*552f7358SJed Brown #define __FUNCT__ "DMPlexSetVTKBounds" 8799*552f7358SJed Brown PetscErrorCode DMPlexSetVTKBounds(DM dm, PetscInt cMax, PetscInt vMax) 8800*552f7358SJed Brown { 8801*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 8802*552f7358SJed Brown 8803*552f7358SJed Brown PetscFunctionBegin; 8804*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8805*552f7358SJed Brown if (cMax >= 0) mesh->vtkCellMax = cMax; 8806*552f7358SJed Brown if (vMax >= 0) mesh->vtkVertexMax = vMax; 8807*552f7358SJed Brown PetscFunctionReturn(0); 8808*552f7358SJed Brown } 8809*552f7358SJed Brown 8810*552f7358SJed Brown #undef __FUNCT__ 8811*552f7358SJed Brown #define __FUNCT__ "DMPlexGetVTKCellHeight" 8812*552f7358SJed Brown PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 8813*552f7358SJed Brown { 8814*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 8815*552f7358SJed Brown 8816*552f7358SJed Brown PetscFunctionBegin; 8817*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8818*552f7358SJed Brown PetscValidPointer(cellHeight, 2); 8819*552f7358SJed Brown *cellHeight = mesh->vtkCellHeight; 8820*552f7358SJed Brown PetscFunctionReturn(0); 8821*552f7358SJed Brown } 8822*552f7358SJed Brown 8823*552f7358SJed Brown #undef __FUNCT__ 8824*552f7358SJed Brown #define __FUNCT__ "DMPlexSetVTKCellHeight" 8825*552f7358SJed Brown PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 8826*552f7358SJed Brown { 8827*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 8828*552f7358SJed Brown 8829*552f7358SJed Brown PetscFunctionBegin; 8830*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 8831*552f7358SJed Brown mesh->vtkCellHeight = cellHeight; 8832*552f7358SJed Brown PetscFunctionReturn(0); 8833*552f7358SJed Brown } 8834*552f7358SJed Brown 8835*552f7358SJed Brown #undef __FUNCT__ 8836*552f7358SJed Brown #define __FUNCT__ "DMPlexInsertFace_Private" 8837*552f7358SJed Brown /* 8838*552f7358SJed Brown DMPlexInsertFace_Private - Puts a face into the mesh 8839*552f7358SJed Brown 8840*552f7358SJed Brown Not collective 8841*552f7358SJed Brown 8842*552f7358SJed Brown Input Parameters: 8843*552f7358SJed Brown + dm - The DMPlex 8844*552f7358SJed Brown . numFaceVertex - The number of vertices in the face 8845*552f7358SJed Brown . faceVertices - The vertices in the face for dm 8846*552f7358SJed Brown . subfaceVertices - The vertices in the face for subdm 8847*552f7358SJed Brown . numCorners - The number of vertices in the cell 8848*552f7358SJed Brown . cell - A cell in dm containing the face 8849*552f7358SJed Brown . subcell - A cell in subdm containing the face 8850*552f7358SJed Brown . firstFace - First face in the mesh 8851*552f7358SJed Brown - newFacePoint - Next face in the mesh 8852*552f7358SJed Brown 8853*552f7358SJed Brown Output Parameters: 8854*552f7358SJed Brown . newFacePoint - Contains next face point number on input, updated on output 8855*552f7358SJed Brown 8856*552f7358SJed Brown Level: developer 8857*552f7358SJed Brown */ 8858*552f7358SJed Brown PetscErrorCode DMPlexInsertFace_Private(DM dm, DM subdm, PetscInt numFaceVertices, const PetscInt faceVertices[], const PetscInt subfaceVertices[], PetscInt numCorners, PetscInt cell, PetscInt subcell, PetscInt firstFace, PetscInt *newFacePoint) 8859*552f7358SJed Brown { 8860*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 8861*552f7358SJed Brown DM_Plex *submesh = (DM_Plex *) subdm->data; 8862*552f7358SJed Brown const PetscInt *faces; 8863*552f7358SJed Brown PetscInt numFaces, coneSize; 8864*552f7358SJed Brown PetscErrorCode ierr; 8865*552f7358SJed Brown 8866*552f7358SJed Brown PetscFunctionBegin; 8867*552f7358SJed Brown ierr = DMPlexGetConeSize(subdm, subcell, &coneSize);CHKERRQ(ierr); 8868*552f7358SJed Brown if (coneSize != 1) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cone size of cell %d is %d != 1", cell, coneSize); 8869*552f7358SJed Brown #if 0 8870*552f7358SJed Brown /* Cannot use this because support() has not been constructed yet */ 8871*552f7358SJed Brown ierr = DMPlexGetJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 8872*552f7358SJed Brown #else 8873*552f7358SJed Brown { 8874*552f7358SJed Brown PetscInt f; 8875*552f7358SJed Brown 8876*552f7358SJed Brown numFaces = 0; 8877*552f7358SJed Brown ierr = DMGetWorkArray(subdm, 1, PETSC_INT, (void **) &faces);CHKERRQ(ierr); 8878*552f7358SJed Brown for(f = firstFace; f < *newFacePoint; ++f) { 8879*552f7358SJed Brown PetscInt dof, off, d; 8880*552f7358SJed Brown 8881*552f7358SJed Brown ierr = PetscSectionGetDof(submesh->coneSection, f, &dof);CHKERRQ(ierr); 8882*552f7358SJed Brown ierr = PetscSectionGetOffset(submesh->coneSection, f, &off);CHKERRQ(ierr); 8883*552f7358SJed Brown /* Yes, I know this is quadratic, but I expect the sizes to be <5 */ 8884*552f7358SJed Brown for(d = 0; d < dof; ++d) { 8885*552f7358SJed Brown const PetscInt p = submesh->cones[off+d]; 8886*552f7358SJed Brown PetscInt v; 8887*552f7358SJed Brown 8888*552f7358SJed Brown for(v = 0; v < numFaceVertices; ++v) { 8889*552f7358SJed Brown if (subfaceVertices[v] == p) break; 8890*552f7358SJed Brown } 8891*552f7358SJed Brown if (v == numFaceVertices) break; 8892*552f7358SJed Brown } 8893*552f7358SJed Brown if (d == dof) { 8894*552f7358SJed Brown numFaces = 1; 8895*552f7358SJed Brown ((PetscInt *) faces)[0] = f; 8896*552f7358SJed Brown } 8897*552f7358SJed Brown } 8898*552f7358SJed Brown } 8899*552f7358SJed Brown #endif 8900*552f7358SJed Brown if (numFaces > 1) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Vertex set had %d faces, not one", numFaces); 8901*552f7358SJed Brown else if (numFaces == 1) { 8902*552f7358SJed Brown /* Add the other cell neighbor for this face */ 8903*552f7358SJed Brown ierr = DMPlexSetCone(subdm, cell, faces);CHKERRQ(ierr); 8904*552f7358SJed Brown } else { 8905*552f7358SJed Brown PetscInt *indices, *origVertices, *orientedVertices, *orientedSubVertices, v, ov; 8906*552f7358SJed Brown PetscBool posOriented; 8907*552f7358SJed Brown 8908*552f7358SJed Brown ierr = DMGetWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 8909*552f7358SJed Brown origVertices = &orientedVertices[numFaceVertices]; 8910*552f7358SJed Brown indices = &orientedVertices[numFaceVertices*2]; 8911*552f7358SJed Brown orientedSubVertices = &orientedVertices[numFaceVertices*3]; 8912*552f7358SJed Brown ierr = DMPlexGetOrientedFace(dm, cell, numFaceVertices, faceVertices, numCorners, indices, origVertices, orientedVertices, &posOriented);CHKERRQ(ierr); 8913*552f7358SJed Brown /* TODO: I know that routine should return a permutation, not the indices */ 8914*552f7358SJed Brown for(v = 0; v < numFaceVertices; ++v) { 8915*552f7358SJed Brown const PetscInt vertex = faceVertices[v], subvertex = subfaceVertices[v]; 8916*552f7358SJed Brown for(ov = 0; ov < numFaceVertices; ++ov) { 8917*552f7358SJed Brown if (orientedVertices[ov] == vertex) { 8918*552f7358SJed Brown orientedSubVertices[ov] = subvertex; 8919*552f7358SJed Brown break; 8920*552f7358SJed Brown } 8921*552f7358SJed Brown } 8922*552f7358SJed Brown if (ov == numFaceVertices) SETERRQ1(comm, PETSC_ERR_PLIB, "Could not find face vertex %d in orientated set", vertex); 8923*552f7358SJed Brown } 8924*552f7358SJed Brown ierr = DMPlexSetCone(subdm, *newFacePoint, orientedSubVertices);CHKERRQ(ierr); 8925*552f7358SJed Brown ierr = DMPlexSetCone(subdm, subcell, newFacePoint);CHKERRQ(ierr); 8926*552f7358SJed Brown ierr = DMRestoreWorkArray(subdm, 4*numFaceVertices * sizeof(PetscInt), PETSC_INT, &orientedVertices);CHKERRQ(ierr); 8927*552f7358SJed Brown ++(*newFacePoint); 8928*552f7358SJed Brown } 8929*552f7358SJed Brown ierr = DMPlexRestoreJoin(subdm, numFaceVertices, subfaceVertices, &numFaces, &faces);CHKERRQ(ierr); 8930*552f7358SJed Brown PetscFunctionReturn(0); 8931*552f7358SJed Brown } 8932*552f7358SJed Brown 8933*552f7358SJed Brown #undef __FUNCT__ 8934*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateSubmesh" 8935*552f7358SJed Brown PetscErrorCode DMPlexCreateSubmesh(DM dm, const char label[], DM *subdm) 8936*552f7358SJed Brown { 8937*552f7358SJed Brown MPI_Comm comm = ((PetscObject) dm)->comm; 8938*552f7358SJed Brown DM_Plex *submesh; 8939*552f7358SJed Brown PetscBool boundaryFaces = PETSC_FALSE; 8940*552f7358SJed Brown PetscSection coordSection, subCoordSection; 8941*552f7358SJed Brown Vec coordinates, subCoordinates; 8942*552f7358SJed Brown PetscScalar *coords, *subCoords; 8943*552f7358SJed Brown IS labelIS; 8944*552f7358SJed Brown const PetscInt *subVertices; 8945*552f7358SJed Brown PetscInt *subVerticesActive, *tmpPoints; 8946*552f7358SJed Brown PetscInt *subCells = PETSC_NULL; 8947*552f7358SJed Brown PetscInt numSubVertices, numSubVerticesActive, firstSubVertex, numSubCells = 0, maxSubCells = 0, numOldSubCells; 8948*552f7358SJed Brown PetscInt *face, *subface, maxConeSize, numSubFaces = 0, firstSubFace, newFacePoint, nFV = 0, coordSize; 8949*552f7358SJed Brown PetscInt dim; /* Right now, do not specify dimension */ 8950*552f7358SJed Brown PetscInt cStart, cEnd, cMax, c, vStart, vEnd, vMax, v, p, corner, i, d, f; 8951*552f7358SJed Brown PetscErrorCode ierr; 8952*552f7358SJed Brown 8953*552f7358SJed Brown PetscFunctionBegin; 8954*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 8955*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 8956*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 8957*552f7358SJed Brown ierr = DMPlexGetMaxSizes(dm, &maxConeSize, PETSC_NULL);CHKERRQ(ierr); 8958*552f7358SJed Brown ierr = DMPlexGetVTKBounds(dm, &cMax, &vMax);CHKERRQ(ierr); 8959*552f7358SJed Brown if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 8960*552f7358SJed Brown if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 8961*552f7358SJed Brown ierr = DMGetWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 8962*552f7358SJed Brown subface = &face[maxConeSize]; 8963*552f7358SJed Brown ierr = DMCreate(comm, subdm);CHKERRQ(ierr); 8964*552f7358SJed Brown ierr = DMSetType(*subdm, DMPLEX);CHKERRQ(ierr); 8965*552f7358SJed Brown ierr = DMPlexSetDimension(*subdm, dim-1);CHKERRQ(ierr); 8966*552f7358SJed Brown ierr = DMPlexGetStratumIS(dm, label, 1, &labelIS);CHKERRQ(ierr); 8967*552f7358SJed Brown ierr = ISGetSize(labelIS, &numSubVertices);CHKERRQ(ierr); 8968*552f7358SJed Brown ierr = ISGetIndices(labelIS, &subVertices);CHKERRQ(ierr); 8969*552f7358SJed Brown maxSubCells = numSubVertices; 8970*552f7358SJed Brown ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &subCells);CHKERRQ(ierr); 8971*552f7358SJed Brown ierr = PetscMalloc(numSubVertices * sizeof(PetscInt), &subVerticesActive);CHKERRQ(ierr); 8972*552f7358SJed Brown ierr = PetscMemzero(subVerticesActive, numSubVertices * sizeof(PetscInt));CHKERRQ(ierr); 8973*552f7358SJed Brown for(v = 0; v < numSubVertices; ++v) { 8974*552f7358SJed Brown const PetscInt vertex = subVertices[v]; 8975*552f7358SJed Brown PetscInt *star = PETSC_NULL; 8976*552f7358SJed Brown PetscInt starSize, numCells = 0; 8977*552f7358SJed Brown 8978*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 8979*552f7358SJed Brown for(p = 0; p < starSize*2; p += 2) { 8980*552f7358SJed Brown const PetscInt point = star[p]; 8981*552f7358SJed Brown if ((point >= cStart) && (point < cEnd)) { 8982*552f7358SJed Brown star[numCells++] = point; 8983*552f7358SJed Brown } 8984*552f7358SJed Brown } 8985*552f7358SJed Brown numOldSubCells = numSubCells; 8986*552f7358SJed Brown for(c = 0; c < numCells; ++c) { 8987*552f7358SJed Brown const PetscInt cell = star[c]; 8988*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 8989*552f7358SJed Brown PetscInt closureSize, numCorners = 0, faceSize = 0; 8990*552f7358SJed Brown PetscInt cellLoc; 8991*552f7358SJed Brown 8992*552f7358SJed Brown ierr = PetscFindInt(cell, numOldSubCells, subCells, &cellLoc);CHKERRQ(ierr); 8993*552f7358SJed Brown if (cellLoc >= 0) continue; 8994*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 8995*552f7358SJed Brown for(p = 0; p < closureSize*2; p += 2) { 8996*552f7358SJed Brown const PetscInt point = closure[p]; 8997*552f7358SJed Brown if ((point >= vStart) && (point < vEnd)) { 8998*552f7358SJed Brown closure[numCorners++] = point; 8999*552f7358SJed Brown } 9000*552f7358SJed Brown } 9001*552f7358SJed Brown if (!nFV) {ierr = DMPlexGetNumFaceVertices(dm, numCorners, &nFV);CHKERRQ(ierr);} 9002*552f7358SJed Brown for(corner = 0; corner < numCorners; ++corner) { 9003*552f7358SJed Brown const PetscInt cellVertex = closure[corner]; 9004*552f7358SJed Brown PetscInt subVertex; 9005*552f7358SJed Brown 9006*552f7358SJed Brown ierr = PetscFindInt(cellVertex, numSubVertices, subVertices, &subVertex);CHKERRQ(ierr); 9007*552f7358SJed Brown if (subVertex >= 0) { /* contains submesh vertex */ 9008*552f7358SJed Brown for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9009*552f7358SJed Brown if (i == faceSize) { 9010*552f7358SJed Brown if (faceSize >= maxConeSize) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices in face %d should not exceed %d", faceSize+1, maxConeSize); 9011*552f7358SJed Brown face[faceSize] = cellVertex; 9012*552f7358SJed Brown subface[faceSize] = subVertex; 9013*552f7358SJed Brown ++faceSize; 9014*552f7358SJed Brown } 9015*552f7358SJed Brown } 9016*552f7358SJed Brown } 9017*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9018*552f7358SJed Brown if (faceSize >= nFV) { 9019*552f7358SJed Brown if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9020*552f7358SJed Brown if (numSubCells >= maxSubCells) { 9021*552f7358SJed Brown PetscInt *tmpCells; 9022*552f7358SJed Brown maxSubCells *= 2; 9023*552f7358SJed Brown ierr = PetscMalloc(maxSubCells * sizeof(PetscInt), &tmpCells);CHKERRQ(ierr); 9024*552f7358SJed Brown ierr = PetscMemcpy(tmpCells, subCells, numSubCells * sizeof(PetscInt));CHKERRQ(ierr); 9025*552f7358SJed Brown ierr = PetscFree(subCells);CHKERRQ(ierr); 9026*552f7358SJed Brown subCells = tmpCells; 9027*552f7358SJed Brown } 9028*552f7358SJed Brown /* TOOD: Maybe overestimate then squeeze out empty faces */ 9029*552f7358SJed Brown if (faceSize > nFV) { 9030*552f7358SJed Brown /* TODO: This is tricky. Maybe just add all faces */ 9031*552f7358SJed Brown numSubFaces++; 9032*552f7358SJed Brown } else { 9033*552f7358SJed Brown numSubFaces++; 9034*552f7358SJed Brown } 9035*552f7358SJed Brown for(f = 0; f < faceSize; ++f) { 9036*552f7358SJed Brown subVerticesActive[subface[f]] = 1; 9037*552f7358SJed Brown } 9038*552f7358SJed Brown subCells[numSubCells++] = cell; 9039*552f7358SJed Brown } 9040*552f7358SJed Brown } 9041*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, vertex, PETSC_FALSE, &starSize, &star);CHKERRQ(ierr); 9042*552f7358SJed Brown ierr = PetscSortRemoveDupsInt(&numSubCells, subCells);CHKERRQ(ierr); 9043*552f7358SJed Brown } 9044*552f7358SJed Brown /* Pick out active subvertices */ 9045*552f7358SJed Brown for(v = 0, numSubVerticesActive = 0; v < numSubVertices; ++v) { 9046*552f7358SJed Brown if (subVerticesActive[v]) { 9047*552f7358SJed Brown subVerticesActive[numSubVerticesActive++] = subVertices[v]; 9048*552f7358SJed Brown } 9049*552f7358SJed Brown } 9050*552f7358SJed Brown ierr = DMPlexSetChart(*subdm, 0, numSubCells+numSubFaces+numSubVerticesActive);CHKERRQ(ierr); 9051*552f7358SJed Brown /* Set cone sizes */ 9052*552f7358SJed Brown firstSubVertex = numSubCells; 9053*552f7358SJed Brown firstSubFace = numSubCells+numSubVerticesActive; 9054*552f7358SJed Brown newFacePoint = firstSubFace; 9055*552f7358SJed Brown for(c = 0; c < numSubCells; ++c) { 9056*552f7358SJed Brown ierr = DMPlexSetConeSize(*subdm, c, 1);CHKERRQ(ierr); 9057*552f7358SJed Brown } 9058*552f7358SJed Brown for(f = firstSubFace; f < firstSubFace+numSubFaces; ++f) { 9059*552f7358SJed Brown ierr = DMPlexSetConeSize(*subdm, f, nFV);CHKERRQ(ierr); 9060*552f7358SJed Brown } 9061*552f7358SJed Brown ierr = DMSetUp(*subdm);CHKERRQ(ierr); 9062*552f7358SJed Brown /* Create face cones */ 9063*552f7358SJed Brown for(c = 0; c < numSubCells; ++c) { 9064*552f7358SJed Brown const PetscInt cell = subCells[c]; 9065*552f7358SJed Brown PetscInt *closure = PETSC_NULL; 9066*552f7358SJed Brown PetscInt closureSize, numCorners = 0, faceSize = 0; 9067*552f7358SJed Brown 9068*552f7358SJed Brown ierr = DMPlexGetTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9069*552f7358SJed Brown for(p = 0; p < closureSize*2; p += 2) { 9070*552f7358SJed Brown const PetscInt point = closure[p]; 9071*552f7358SJed Brown if ((point >= vStart) && (point < vEnd)) { 9072*552f7358SJed Brown closure[numCorners++] = point; 9073*552f7358SJed Brown } 9074*552f7358SJed Brown } 9075*552f7358SJed Brown for(corner = 0; corner < numCorners; ++corner) { 9076*552f7358SJed Brown const PetscInt cellVertex = closure[corner]; 9077*552f7358SJed Brown PetscInt subVertex; 9078*552f7358SJed Brown 9079*552f7358SJed Brown ierr = PetscFindInt(cellVertex, numSubVerticesActive, subVerticesActive, &subVertex);CHKERRQ(ierr); 9080*552f7358SJed Brown if (subVertex >= 0) { /* contains submesh vertex */ 9081*552f7358SJed Brown for(i = 0; i < faceSize; ++i) {if (cellVertex == face[i]) break;} 9082*552f7358SJed Brown if (i == faceSize) { 9083*552f7358SJed Brown face[faceSize] = cellVertex; 9084*552f7358SJed Brown subface[faceSize] = numSubCells+subVertex; 9085*552f7358SJed Brown ++faceSize; 9086*552f7358SJed Brown } 9087*552f7358SJed Brown } 9088*552f7358SJed Brown } 9089*552f7358SJed Brown ierr = DMPlexRestoreTransitiveClosure(dm, cell, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 9090*552f7358SJed Brown if (faceSize >= nFV) { 9091*552f7358SJed Brown if (faceSize > nFV && !boundaryFaces) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "Invalid submesh: Too many vertices %d of an element on the surface", faceSize); 9092*552f7358SJed Brown // Here we allow a set of vertices to lie completely on a boundary cell (like a corner tetrahedron) 9093*552f7358SJed Brown // We have to take all the faces, and discard those in the interior 9094*552f7358SJed Brown // We check the join of the face vertices, which produces 2 cells if in the interior 9095*552f7358SJed Brown #if 0 9096*552f7358SJed Brown // This object just calls insert on each face that comes from subsets() 9097*552f7358SJed Brown // In fact, we can just always acll subsets(), since when we pass a single face it is a single call 9098*552f7358SJed Brown FaceInserterV<FlexMesh::sieve_type> inserter(mesh, sieve, subSieve, f, *c_iter, numCorners, indices, &origVertices, &faceVertices, &submeshCells); 9099*552f7358SJed Brown PointArray faceVec(face->begin(), face->end()); 9100*552f7358SJed Brown 9101*552f7358SJed Brown subsets(faceVec, nFV, inserter); 9102*552f7358SJed Brown #endif 9103*552f7358SJed Brown ierr = DMPlexInsertFace_Private(dm, *subdm, faceSize, face, subface, numCorners, cell, c, firstSubFace, &newFacePoint);CHKERRQ(ierr); 9104*552f7358SJed Brown } 9105*552f7358SJed Brown } 9106*552f7358SJed Brown ierr = DMPlexSymmetrize(*subdm);CHKERRQ(ierr); 9107*552f7358SJed Brown ierr = DMPlexStratify(*subdm);CHKERRQ(ierr); 9108*552f7358SJed Brown /* Build coordinates */ 9109*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 9110*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9111*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(*subdm, &subCoordSection);CHKERRQ(ierr); 9112*552f7358SJed Brown ierr = PetscSectionSetChart(subCoordSection, firstSubVertex, firstSubVertex+numSubVerticesActive);CHKERRQ(ierr); 9113*552f7358SJed Brown for (v = firstSubVertex; v < firstSubVertex+numSubVerticesActive; ++v) { 9114*552f7358SJed Brown ierr = PetscSectionSetDof(subCoordSection, v, dim);CHKERRQ(ierr); 9115*552f7358SJed Brown } 9116*552f7358SJed Brown ierr = PetscSectionSetUp(subCoordSection);CHKERRQ(ierr); 9117*552f7358SJed Brown ierr = PetscSectionGetStorageSize(subCoordSection, &coordSize);CHKERRQ(ierr); 9118*552f7358SJed Brown ierr = VecCreate(((PetscObject) dm)->comm, &subCoordinates);CHKERRQ(ierr); 9119*552f7358SJed Brown ierr = VecSetSizes(subCoordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 9120*552f7358SJed Brown ierr = VecSetFromOptions(subCoordinates);CHKERRQ(ierr); 9121*552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9122*552f7358SJed Brown ierr = VecGetArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9123*552f7358SJed Brown for(v = 0; v < numSubVerticesActive; ++v) { 9124*552f7358SJed Brown const PetscInt vertex = subVerticesActive[v]; 9125*552f7358SJed Brown const PetscInt subVertex = firstSubVertex+v; 9126*552f7358SJed Brown PetscInt dof, off, sdof, soff; 9127*552f7358SJed Brown 9128*552f7358SJed Brown ierr = PetscSectionGetDof(coordSection, vertex, &dof);CHKERRQ(ierr); 9129*552f7358SJed Brown ierr = PetscSectionGetOffset(coordSection, vertex, &off);CHKERRQ(ierr); 9130*552f7358SJed Brown ierr = PetscSectionGetDof(subCoordSection, subVertex, &sdof);CHKERRQ(ierr); 9131*552f7358SJed Brown ierr = PetscSectionGetOffset(subCoordSection, subVertex, &soff);CHKERRQ(ierr); 9132*552f7358SJed Brown if (dof != sdof) SETERRQ4(comm, PETSC_ERR_PLIB, "Coordinate dimension %d on subvertex %d, vertex %d should be %d", sdof, subVertex, vertex, dof); 9133*552f7358SJed Brown for(d = 0; d < dof; ++d) { 9134*552f7358SJed Brown subCoords[soff+d] = coords[off+d]; 9135*552f7358SJed Brown } 9136*552f7358SJed Brown } 9137*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 9138*552f7358SJed Brown ierr = VecRestoreArray(subCoordinates, &subCoords);CHKERRQ(ierr); 9139*552f7358SJed Brown ierr = DMSetCoordinatesLocal(*subdm, subCoordinates);CHKERRQ(ierr); 9140*552f7358SJed Brown ierr = VecDestroy(&subCoordinates);CHKERRQ(ierr); 9141*552f7358SJed Brown 9142*552f7358SJed Brown ierr = DMPlexSetVTKCellHeight(*subdm, 1);CHKERRQ(ierr); 9143*552f7358SJed Brown /* Create map from submesh points to original mesh points */ 9144*552f7358SJed Brown submesh = (DM_Plex *) (*subdm)->data; 9145*552f7358SJed Brown ierr = PetscMalloc((numSubCells+numSubVerticesActive) * sizeof(PetscInt), &tmpPoints);CHKERRQ(ierr); 9146*552f7358SJed Brown for(c = 0; c < numSubCells; ++c) { 9147*552f7358SJed Brown tmpPoints[c] = subCells[c]; 9148*552f7358SJed Brown } 9149*552f7358SJed Brown for(v = numSubCells; v < numSubCells+numSubVerticesActive; ++v) { 9150*552f7358SJed Brown tmpPoints[v] = subVerticesActive[v-numSubCells]; 9151*552f7358SJed Brown } 9152*552f7358SJed Brown ierr = ISCreateGeneral(comm, numSubCells+numSubVerticesActive, tmpPoints, PETSC_OWN_POINTER, &submesh->subpointMap);CHKERRQ(ierr); 9153*552f7358SJed Brown 9154*552f7358SJed Brown ierr = PetscFree(subCells);CHKERRQ(ierr); 9155*552f7358SJed Brown ierr = PetscFree(subVerticesActive);CHKERRQ(ierr); 9156*552f7358SJed Brown ierr = ISRestoreIndices(labelIS, &subVertices);CHKERRQ(ierr); 9157*552f7358SJed Brown ierr = ISDestroy(&labelIS);CHKERRQ(ierr); 9158*552f7358SJed Brown ierr = DMRestoreWorkArray(dm, 2*maxConeSize, PETSC_INT, &face);CHKERRQ(ierr); 9159*552f7358SJed Brown PetscFunctionReturn(0); 9160*552f7358SJed Brown } 9161*552f7358SJed Brown 9162*552f7358SJed Brown #undef __FUNCT__ 9163*552f7358SJed Brown #define __FUNCT__ "DMPlexCreateNumbering_Private" 9164*552f7358SJed Brown /* We can easily have a form that takes an IS instead */ 9165*552f7358SJed Brown PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscSF sf, IS *numbering) 9166*552f7358SJed Brown { 9167*552f7358SJed Brown PetscSection section, globalSection; 9168*552f7358SJed Brown PetscInt *numbers, p; 9169*552f7358SJed Brown PetscErrorCode ierr; 9170*552f7358SJed Brown 9171*552f7358SJed Brown PetscFunctionBegin; 9172*552f7358SJed Brown ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); 9173*552f7358SJed Brown ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 9174*552f7358SJed Brown for(p = pStart; p < pEnd; ++p) { 9175*552f7358SJed Brown ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 9176*552f7358SJed Brown } 9177*552f7358SJed Brown ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 9178*552f7358SJed Brown ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 9179*552f7358SJed Brown ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &numbers);CHKERRQ(ierr); 9180*552f7358SJed Brown for(p = pStart; p < pEnd; ++p) { 9181*552f7358SJed Brown ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 9182*552f7358SJed Brown } 9183*552f7358SJed Brown ierr = ISCreateGeneral(((PetscObject) dm)->comm, pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 9184*552f7358SJed Brown ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 9185*552f7358SJed Brown ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 9186*552f7358SJed Brown PetscFunctionReturn(0); 9187*552f7358SJed Brown } 9188*552f7358SJed Brown 9189*552f7358SJed Brown #undef __FUNCT__ 9190*552f7358SJed Brown #define __FUNCT__ "DMPlexGetCellNumbering" 9191*552f7358SJed Brown PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 9192*552f7358SJed Brown { 9193*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9194*552f7358SJed Brown PetscInt cellHeight, cStart, cEnd, cMax; 9195*552f7358SJed Brown PetscErrorCode ierr; 9196*552f7358SJed Brown 9197*552f7358SJed Brown PetscFunctionBegin; 9198*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9199*552f7358SJed Brown if (!mesh->globalCellNumbers) { 9200*552f7358SJed Brown ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 9201*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 9202*552f7358SJed Brown ierr = DMPlexGetVTKBounds(dm, &cMax, PETSC_NULL);CHKERRQ(ierr); 9203*552f7358SJed Brown if (cMax >= 0) {cEnd = PetscMin(cEnd, cMax);} 9204*552f7358SJed Brown ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 9205*552f7358SJed Brown } 9206*552f7358SJed Brown *globalCellNumbers = mesh->globalCellNumbers; 9207*552f7358SJed Brown PetscFunctionReturn(0); 9208*552f7358SJed Brown } 9209*552f7358SJed Brown 9210*552f7358SJed Brown #undef __FUNCT__ 9211*552f7358SJed Brown #define __FUNCT__ "DMPlexGetVertexNumbering" 9212*552f7358SJed Brown PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 9213*552f7358SJed Brown { 9214*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9215*552f7358SJed Brown PetscInt vStart, vEnd, vMax; 9216*552f7358SJed Brown PetscErrorCode ierr; 9217*552f7358SJed Brown 9218*552f7358SJed Brown PetscFunctionBegin; 9219*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9220*552f7358SJed Brown if (!mesh->globalVertexNumbers) { 9221*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9222*552f7358SJed Brown ierr = DMPlexGetVTKBounds(dm, PETSC_NULL, &vMax);CHKERRQ(ierr); 9223*552f7358SJed Brown if (vMax >= 0) {vEnd = PetscMin(vEnd, vMax);} 9224*552f7358SJed Brown ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 9225*552f7358SJed Brown } 9226*552f7358SJed Brown *globalVertexNumbers = mesh->globalVertexNumbers; 9227*552f7358SJed Brown PetscFunctionReturn(0); 9228*552f7358SJed Brown } 9229*552f7358SJed Brown 9230*552f7358SJed Brown #undef __FUNCT__ 9231*552f7358SJed Brown #define __FUNCT__ "DMPlexGetSubpointMap" 9232*552f7358SJed Brown PetscErrorCode DMPlexGetSubpointMap(DM dm, IS *subpointMap) 9233*552f7358SJed Brown { 9234*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9235*552f7358SJed Brown 9236*552f7358SJed Brown PetscFunctionBegin; 9237*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9238*552f7358SJed Brown PetscValidPointer(subpointMap, 2); 9239*552f7358SJed Brown *subpointMap = mesh->subpointMap; 9240*552f7358SJed Brown PetscFunctionReturn(0); 9241*552f7358SJed Brown } 9242*552f7358SJed Brown 9243*552f7358SJed Brown #undef __FUNCT__ 9244*552f7358SJed Brown #define __FUNCT__ "DMPlexSetSubpointMap" 9245*552f7358SJed Brown /* Note: Should normally not be called by the user, since it is set in DMPlexCreateSubmesh() */ 9246*552f7358SJed Brown PetscErrorCode DMPlexSetSubpointMap(DM dm, IS subpointMap) 9247*552f7358SJed Brown { 9248*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9249*552f7358SJed Brown 9250*552f7358SJed Brown PetscFunctionBegin; 9251*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9252*552f7358SJed Brown PetscValidHeaderSpecific(subpointMap, IS_CLASSID, 2); 9253*552f7358SJed Brown mesh->subpointMap = subpointMap; 9254*552f7358SJed Brown PetscFunctionReturn(0); 9255*552f7358SJed Brown } 9256*552f7358SJed Brown 9257*552f7358SJed Brown #undef __FUNCT__ 9258*552f7358SJed Brown #define __FUNCT__ "DMPlexGetScale" 9259*552f7358SJed Brown PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 9260*552f7358SJed Brown { 9261*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9262*552f7358SJed Brown 9263*552f7358SJed Brown PetscFunctionBegin; 9264*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9265*552f7358SJed Brown PetscValidPointer(scale, 3); 9266*552f7358SJed Brown *scale = mesh->scale[unit]; 9267*552f7358SJed Brown PetscFunctionReturn(0); 9268*552f7358SJed Brown } 9269*552f7358SJed Brown 9270*552f7358SJed Brown #undef __FUNCT__ 9271*552f7358SJed Brown #define __FUNCT__ "DMPlexSetScale" 9272*552f7358SJed Brown PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 9273*552f7358SJed Brown { 9274*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9275*552f7358SJed Brown 9276*552f7358SJed Brown PetscFunctionBegin; 9277*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9278*552f7358SJed Brown mesh->scale[unit] = scale; 9279*552f7358SJed Brown PetscFunctionReturn(0); 9280*552f7358SJed Brown } 9281*552f7358SJed Brown 9282*552f7358SJed Brown 9283*552f7358SJed Brown /******************************************************************************* 9284*552f7358SJed Brown This should be in a separate Discretization object, but I am not sure how to lay 9285*552f7358SJed Brown it out yet, so I am stuffing things here while I experiment. 9286*552f7358SJed Brown *******************************************************************************/ 9287*552f7358SJed Brown #undef __FUNCT__ 9288*552f7358SJed Brown #define __FUNCT__ "DMPlexSetFEMIntegration" 9289*552f7358SJed Brown PetscErrorCode DMPlexSetFEMIntegration(DM dm, 9290*552f7358SJed Brown PetscErrorCode (*integrateResidualFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9291*552f7358SJed Brown const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9292*552f7358SJed Brown void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9293*552f7358SJed Brown void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9294*552f7358SJed Brown PetscErrorCode (*integrateJacobianActionFEM)(PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], const PetscScalar[], 9295*552f7358SJed Brown const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9296*552f7358SJed Brown void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9297*552f7358SJed Brown void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9298*552f7358SJed Brown void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9299*552f7358SJed Brown void (**)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[]), 9300*552f7358SJed Brown PetscErrorCode (*integrateJacobianFEM)(PetscInt, PetscInt, PetscInt, PetscInt, PetscQuadrature[], const PetscScalar[], 9301*552f7358SJed Brown const PetscReal[], const PetscReal[], const PetscReal[], const PetscReal[], 9302*552f7358SJed Brown void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9303*552f7358SJed Brown void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9304*552f7358SJed Brown void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), 9305*552f7358SJed Brown void (*)(const PetscScalar[], const PetscScalar[], const PetscReal[], PetscScalar[]), PetscScalar[])) 9306*552f7358SJed Brown { 9307*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9308*552f7358SJed Brown 9309*552f7358SJed Brown PetscFunctionBegin; 9310*552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 9311*552f7358SJed Brown mesh->integrateResidualFEM = integrateResidualFEM; 9312*552f7358SJed Brown mesh->integrateJacobianActionFEM = integrateJacobianActionFEM; 9313*552f7358SJed Brown mesh->integrateJacobianFEM = integrateJacobianFEM; 9314*552f7358SJed Brown PetscFunctionReturn(0); 9315*552f7358SJed Brown } 9316*552f7358SJed Brown 9317*552f7358SJed Brown #undef __FUNCT__ 9318*552f7358SJed Brown #define __FUNCT__ "DMPlexProjectFunctionLocal" 9319*552f7358SJed Brown PetscErrorCode DMPlexProjectFunctionLocal(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec localX) 9320*552f7358SJed Brown { 9321*552f7358SJed Brown Vec coordinates; 9322*552f7358SJed Brown PetscSection section, cSection; 9323*552f7358SJed Brown PetscInt dim, vStart, vEnd, v, c, d; 9324*552f7358SJed Brown PetscScalar *values, *cArray; 9325*552f7358SJed Brown PetscReal *coords; 9326*552f7358SJed Brown PetscErrorCode ierr; 9327*552f7358SJed Brown 9328*552f7358SJed Brown PetscFunctionBegin; 9329*552f7358SJed Brown ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 9330*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9331*552f7358SJed Brown ierr = DMPlexGetCoordinateSection(dm, &cSection);CHKERRQ(ierr); 9332*552f7358SJed Brown ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 9333*552f7358SJed Brown ierr = PetscMalloc(numComp * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9334*552f7358SJed Brown ierr = VecGetArray(coordinates, &cArray);CHKERRQ(ierr); 9335*552f7358SJed Brown ierr = PetscSectionGetDof(cSection, vStart, &dim);CHKERRQ(ierr); 9336*552f7358SJed Brown ierr = PetscMalloc(dim * sizeof(PetscReal),&coords);CHKERRQ(ierr); 9337*552f7358SJed Brown for (v = vStart; v < vEnd; ++v) { 9338*552f7358SJed Brown PetscInt dof, off; 9339*552f7358SJed Brown 9340*552f7358SJed Brown ierr = PetscSectionGetDof(cSection, v, &dof);CHKERRQ(ierr); 9341*552f7358SJed Brown ierr = PetscSectionGetOffset(cSection, v, &off);CHKERRQ(ierr); 9342*552f7358SJed Brown if (dof > dim) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_WRONG, "Cannot have more coordinates %d then dimensions %d", dof, dim); 9343*552f7358SJed Brown for(d = 0; d < dof; ++d) { 9344*552f7358SJed Brown coords[d] = PetscRealPart(cArray[off+d]); 9345*552f7358SJed Brown } 9346*552f7358SJed Brown for(c = 0; c < numComp; ++c) { 9347*552f7358SJed Brown values[c] = (*funcs[c])(coords); 9348*552f7358SJed Brown } 9349*552f7358SJed Brown ierr = VecSetValuesSection(localX, section, v, values, mode);CHKERRQ(ierr); 9350*552f7358SJed Brown } 9351*552f7358SJed Brown ierr = VecRestoreArray(coordinates, &cArray);CHKERRQ(ierr); 9352*552f7358SJed Brown /* Temporary, must be replaced by a projection on the finite element basis */ 9353*552f7358SJed Brown { 9354*552f7358SJed Brown PetscInt eStart = 0, eEnd = 0, e, depth; 9355*552f7358SJed Brown 9356*552f7358SJed Brown ierr = DMPlexGetLabelSize(dm, "depth", &depth);CHKERRQ(ierr); 9357*552f7358SJed Brown --depth; 9358*552f7358SJed Brown if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 9359*552f7358SJed Brown for (e = eStart; e < eEnd; ++e) { 9360*552f7358SJed Brown const PetscInt *cone = PETSC_NULL; 9361*552f7358SJed Brown PetscInt coneSize, d; 9362*552f7358SJed Brown PetscScalar *coordsA, *coordsB; 9363*552f7358SJed Brown 9364*552f7358SJed Brown ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 9365*552f7358SJed Brown ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 9366*552f7358SJed Brown if (coneSize != 2) SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_ARG_SIZ, "Cone size %d for point %d should be 2", coneSize, e); 9367*552f7358SJed Brown ierr = VecGetValuesSection(coordinates, cSection, cone[0], &coordsA);CHKERRQ(ierr); 9368*552f7358SJed Brown ierr = VecGetValuesSection(coordinates, cSection, cone[1], &coordsB);CHKERRQ(ierr); 9369*552f7358SJed Brown for (d = 0; d < dim; ++d) { 9370*552f7358SJed Brown coords[d] = 0.5*(PetscRealPart(coordsA[d]) + PetscRealPart(coordsB[d])); 9371*552f7358SJed Brown } 9372*552f7358SJed Brown for (c = 0; c < numComp; ++c) { 9373*552f7358SJed Brown values[c] = (*funcs[c])(coords); 9374*552f7358SJed Brown } 9375*552f7358SJed Brown ierr = VecSetValuesSection(localX, section, e, values, mode);CHKERRQ(ierr); 9376*552f7358SJed Brown } 9377*552f7358SJed Brown } 9378*552f7358SJed Brown 9379*552f7358SJed Brown ierr = PetscFree(coords);CHKERRQ(ierr); 9380*552f7358SJed Brown ierr = PetscFree(values);CHKERRQ(ierr); 9381*552f7358SJed Brown #if 0 9382*552f7358SJed Brown const PetscInt localDof = this->_mesh->sizeWithBC(s, *cells->begin()); 9383*552f7358SJed Brown PetscReal detJ; 9384*552f7358SJed Brown 9385*552f7358SJed Brown ierr = PetscMalloc(localDof * sizeof(PetscScalar), &values);CHKERRQ(ierr); 9386*552f7358SJed Brown ierr = PetscMalloc2(dim,PetscReal,&v0,dim*dim,PetscReal,&J);CHKERRQ(ierr); 9387*552f7358SJed Brown ALE::ISieveVisitor::PointRetriever<PETSC_MESH_TYPE::sieve_type> pV((int) pow(this->_mesh->getSieve()->getMaxConeSize(), dim+1)+1, true); 9388*552f7358SJed Brown 9389*552f7358SJed Brown for (PetscInt c = cStart; c < cEnd; ++c) { 9390*552f7358SJed Brown ALE::ISieveTraversal<PETSC_MESH_TYPE::sieve_type>::orientedClosure(*this->_mesh->getSieve(), c, pV); 9391*552f7358SJed Brown const PETSC_MESH_TYPE::point_type *oPoints = pV.getPoints(); 9392*552f7358SJed Brown const int oSize = pV.getSize(); 9393*552f7358SJed Brown int v = 0; 9394*552f7358SJed Brown 9395*552f7358SJed Brown ierr = DMPlexComputeCellGeometry(dm, c, v0, J, PETSC_NULL, &detJ);CHKERRQ(ierr); 9396*552f7358SJed Brown for (PetscInt cl = 0; cl < oSize; ++cl) { 9397*552f7358SJed Brown const PetscInt fDim; 9398*552f7358SJed Brown 9399*552f7358SJed Brown ierr = PetscSectionGetDof(oPoints[cl], &fDim);CHKERRQ(ierr); 9400*552f7358SJed Brown if (pointDim) { 9401*552f7358SJed Brown for (PetscInt d = 0; d < fDim; ++d, ++v) { 9402*552f7358SJed Brown values[v] = (*this->_options.integrate)(v0, J, v, initFunc); 9403*552f7358SJed Brown } 9404*552f7358SJed Brown } 9405*552f7358SJed Brown } 9406*552f7358SJed Brown ierr = DMPlexVecSetClosure(dm, PETSC_NULL, localX, c, values);CHKERRQ(ierr); 9407*552f7358SJed Brown pV.clear(); 9408*552f7358SJed Brown } 9409*552f7358SJed Brown ierr = PetscFree2(v0,J);CHKERRQ(ierr); 9410*552f7358SJed Brown ierr = PetscFree(values);CHKERRQ(ierr); 9411*552f7358SJed Brown #endif 9412*552f7358SJed Brown PetscFunctionReturn(0); 9413*552f7358SJed Brown } 9414*552f7358SJed Brown 9415*552f7358SJed Brown #undef __FUNCT__ 9416*552f7358SJed Brown #define __FUNCT__ "DMPlexProjectFunction" 9417*552f7358SJed Brown /*@C 9418*552f7358SJed Brown DMPlexProjectFunction - This projects the given function into the function space provided. 9419*552f7358SJed Brown 9420*552f7358SJed Brown Input Parameters: 9421*552f7358SJed Brown + dm - The DM 9422*552f7358SJed Brown . numComp - The number of components (functions) 9423*552f7358SJed Brown . funcs - The coordinate functions to evaluate 9424*552f7358SJed Brown - mode - The insertion mode for values 9425*552f7358SJed Brown 9426*552f7358SJed Brown Output Parameter: 9427*552f7358SJed Brown . X - vector 9428*552f7358SJed Brown 9429*552f7358SJed Brown Level: developer 9430*552f7358SJed Brown 9431*552f7358SJed Brown Note: 9432*552f7358SJed Brown This currently just calls the function with the coordinates of each vertex and edge midpoint, and stores the result in a vector. 9433*552f7358SJed Brown We will eventually fix it. 9434*552f7358SJed Brown 9435*552f7358SJed Brown ,seealso: DMPlexComputeL2Diff() 9436*552f7358SJed Brown */ 9437*552f7358SJed Brown PetscErrorCode DMPlexProjectFunction(DM dm, PetscInt numComp, PetscScalar (**funcs)(const PetscReal []), InsertMode mode, Vec X) 9438*552f7358SJed Brown { 9439*552f7358SJed Brown Vec localX; 9440*552f7358SJed Brown PetscErrorCode ierr; 9441*552f7358SJed Brown 9442*552f7358SJed Brown PetscFunctionBegin; 9443*552f7358SJed Brown ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9444*552f7358SJed Brown ierr = DMPlexProjectFunctionLocal(dm, numComp, funcs, mode, localX);CHKERRQ(ierr); 9445*552f7358SJed Brown ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 9446*552f7358SJed Brown ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 9447*552f7358SJed Brown ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9448*552f7358SJed Brown PetscFunctionReturn(0); 9449*552f7358SJed Brown } 9450*552f7358SJed Brown 9451*552f7358SJed Brown #undef __FUNCT__ 9452*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeL2Diff" 9453*552f7358SJed Brown /*@C 9454*552f7358SJed Brown DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 9455*552f7358SJed Brown 9456*552f7358SJed Brown Input Parameters: 9457*552f7358SJed Brown + dm - The DM 9458*552f7358SJed Brown . quad - The PetscQuadrature object for each field 9459*552f7358SJed Brown . funcs - The functions to evaluate for each field component 9460*552f7358SJed Brown - X - The coefficient vector u_h 9461*552f7358SJed Brown 9462*552f7358SJed Brown Output Parameter: 9463*552f7358SJed Brown . diff - The diff ||u - u_h||_2 9464*552f7358SJed Brown 9465*552f7358SJed Brown Level: developer 9466*552f7358SJed Brown 9467*552f7358SJed Brown .seealso: DMPlexProjectFunction() 9468*552f7358SJed Brown */ 9469*552f7358SJed Brown PetscErrorCode DMPlexComputeL2Diff(DM dm, PetscQuadrature quad[], PetscScalar (**funcs)(const PetscReal []), Vec X, PetscReal *diff) { 9470*552f7358SJed Brown const PetscInt debug = 0; 9471*552f7358SJed Brown PetscSection section; 9472*552f7358SJed Brown Vec localX; 9473*552f7358SJed Brown PetscReal *coords, *v0, *J, *invJ, detJ; 9474*552f7358SJed Brown PetscReal localDiff = 0.0; 9475*552f7358SJed Brown PetscInt dim, numFields, numComponents = 0, cStart, cEnd, c, field, fieldOffset, comp; 9476*552f7358SJed Brown PetscErrorCode ierr; 9477*552f7358SJed Brown 9478*552f7358SJed Brown PetscFunctionBegin; 9479*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9480*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9481*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9482*552f7358SJed Brown ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 9483*552f7358SJed Brown ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9484*552f7358SJed Brown ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 9485*552f7358SJed Brown for (field = 0; field < numFields; ++field) { 9486*552f7358SJed Brown numComponents += quad[field].numComponents; 9487*552f7358SJed Brown } 9488*552f7358SJed Brown ierr = DMPlexProjectFunctionLocal(dm, numComponents, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 9489*552f7358SJed Brown ierr = PetscMalloc4(dim,PetscReal,&coords,dim,PetscReal,&v0,dim*dim,PetscReal,&J,dim*dim,PetscReal,&invJ);CHKERRQ(ierr); 9490*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9491*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 9492*552f7358SJed Brown const PetscScalar *x; 9493*552f7358SJed Brown PetscReal elemDiff = 0.0; 9494*552f7358SJed Brown 9495*552f7358SJed Brown ierr = DMPlexComputeCellGeometry(dm, c, v0, J, invJ, &detJ);CHKERRQ(ierr); 9496*552f7358SJed Brown if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 9497*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9498*552f7358SJed Brown 9499*552f7358SJed Brown for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 9500*552f7358SJed Brown const PetscInt numQuadPoints = quad[field].numQuadPoints; 9501*552f7358SJed Brown const PetscReal *quadPoints = quad[field].quadPoints; 9502*552f7358SJed Brown const PetscReal *quadWeights = quad[field].quadWeights; 9503*552f7358SJed Brown const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9504*552f7358SJed Brown const PetscInt numBasisComps = quad[field].numComponents; 9505*552f7358SJed Brown const PetscReal *basis = quad[field].basis; 9506*552f7358SJed Brown PetscInt q, d, e, fc, f; 9507*552f7358SJed Brown 9508*552f7358SJed Brown if (debug) { 9509*552f7358SJed Brown char title[1024]; 9510*552f7358SJed Brown ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 9511*552f7358SJed Brown ierr = DMPrintCellVector(c, title, numBasisFuncs*numBasisComps, &x[fieldOffset]);CHKERRQ(ierr); 9512*552f7358SJed Brown } 9513*552f7358SJed Brown for (q = 0; q < numQuadPoints; ++q) { 9514*552f7358SJed Brown for (d = 0; d < dim; d++) { 9515*552f7358SJed Brown coords[d] = v0[d]; 9516*552f7358SJed Brown for (e = 0; e < dim; e++) { 9517*552f7358SJed Brown coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 9518*552f7358SJed Brown } 9519*552f7358SJed Brown } 9520*552f7358SJed Brown for (fc = 0; fc < numBasisComps; ++fc) { 9521*552f7358SJed Brown const PetscReal funcVal = PetscRealPart((*funcs[comp+fc])(coords)); 9522*552f7358SJed Brown PetscReal interpolant = 0.0; 9523*552f7358SJed Brown for (f = 0; f < numBasisFuncs; ++f) { 9524*552f7358SJed Brown const PetscInt fidx = f*numBasisComps+fc; 9525*552f7358SJed Brown interpolant += PetscRealPart(x[fieldOffset+fidx])*basis[q*numBasisFuncs*numBasisComps+fidx]; 9526*552f7358SJed Brown } 9527*552f7358SJed Brown if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ);CHKERRQ(ierr);} 9528*552f7358SJed Brown elemDiff += PetscSqr(interpolant - funcVal)*quadWeights[q]*detJ; 9529*552f7358SJed Brown } 9530*552f7358SJed Brown } 9531*552f7358SJed Brown comp += numBasisComps; 9532*552f7358SJed Brown fieldOffset += numBasisFuncs*numBasisComps; 9533*552f7358SJed Brown } 9534*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, localX, c, PETSC_NULL, &x);CHKERRQ(ierr); 9535*552f7358SJed Brown if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 9536*552f7358SJed Brown localDiff += elemDiff; 9537*552f7358SJed Brown } 9538*552f7358SJed Brown ierr = PetscFree4(coords,v0,J,invJ);CHKERRQ(ierr); 9539*552f7358SJed Brown ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 9540*552f7358SJed Brown ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD);CHKERRQ(ierr); 9541*552f7358SJed Brown *diff = PetscSqrtReal(*diff); 9542*552f7358SJed Brown PetscFunctionReturn(0); 9543*552f7358SJed Brown } 9544*552f7358SJed Brown 9545*552f7358SJed Brown #undef __FUNCT__ 9546*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeResidualFEM" 9547*552f7358SJed Brown /*@ 9548*552f7358SJed Brown DMPlexComputeResidualFEM - Form the local residual F from the local input X using pointwise functions specified by the user 9549*552f7358SJed Brown 9550*552f7358SJed Brown Input Parameters: 9551*552f7358SJed Brown + dm - The mesh 9552*552f7358SJed Brown . X - Local input vector 9553*552f7358SJed Brown - user - The user context 9554*552f7358SJed Brown 9555*552f7358SJed Brown Output Parameter: 9556*552f7358SJed Brown . F - Local output vector 9557*552f7358SJed Brown 9558*552f7358SJed Brown Note: 9559*552f7358SJed Brown The second member of the user context must be an FEMContext. 9560*552f7358SJed Brown 9561*552f7358SJed Brown We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9562*552f7358SJed Brown like a GPU, or vectorize on a multicore machine. 9563*552f7358SJed Brown 9564*552f7358SJed Brown .seealso: DMPlexComputeJacobianActionFEM() 9565*552f7358SJed Brown */ 9566*552f7358SJed Brown PetscErrorCode DMPlexComputeResidualFEM(DM dm, Vec X, Vec F, void *user) 9567*552f7358SJed Brown { 9568*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9569*552f7358SJed Brown PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9570*552f7358SJed Brown PetscQuadrature *quad = fem->quad; 9571*552f7358SJed Brown PetscSection section; 9572*552f7358SJed Brown PetscReal *v0, *J, *invJ, *detJ; 9573*552f7358SJed Brown PetscScalar *elemVec, *u; 9574*552f7358SJed Brown PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9575*552f7358SJed Brown PetscInt cellDof = 0, numComponents = 0; 9576*552f7358SJed Brown PetscErrorCode ierr; 9577*552f7358SJed Brown 9578*552f7358SJed Brown PetscFunctionBegin; 9579*552f7358SJed Brown /* ierr = PetscLogEventBegin(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9580*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9581*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9582*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9583*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9584*552f7358SJed Brown numCells = cEnd - cStart; 9585*552f7358SJed Brown for (field = 0; field < numFields; ++field) { 9586*552f7358SJed Brown cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9587*552f7358SJed Brown numComponents += quad[field].numComponents; 9588*552f7358SJed Brown } 9589*552f7358SJed Brown ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9590*552f7358SJed Brown ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9591*552f7358SJed Brown ierr = PetscMalloc6(numCells*cellDof,PetscScalar,&u,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr); 9592*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 9593*552f7358SJed Brown const PetscScalar *x; 9594*552f7358SJed Brown PetscInt i; 9595*552f7358SJed Brown 9596*552f7358SJed Brown ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9597*552f7358SJed Brown if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9598*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9599*552f7358SJed Brown 9600*552f7358SJed Brown for (i = 0; i < cellDof; ++i) { 9601*552f7358SJed Brown u[c*cellDof+i] = x[i]; 9602*552f7358SJed Brown } 9603*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9604*552f7358SJed Brown } 9605*552f7358SJed Brown for (field = 0; field < numFields; ++field) { 9606*552f7358SJed Brown const PetscInt numQuadPoints = quad[field].numQuadPoints; 9607*552f7358SJed Brown const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9608*552f7358SJed Brown void (*f0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f0[]) = fem->f0Funcs[field]; 9609*552f7358SJed Brown void (*f1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar f1[]) = fem->f1Funcs[field]; 9610*552f7358SJed Brown /* Conforming batches */ 9611*552f7358SJed Brown PetscInt blockSize = numBasisFuncs*numQuadPoints; 9612*552f7358SJed Brown PetscInt numBlocks = 1; 9613*552f7358SJed Brown PetscInt batchSize = numBlocks * blockSize; 9614*552f7358SJed Brown PetscInt numBatches = numBatchesTmp; 9615*552f7358SJed Brown PetscInt numChunks = numCells / (numBatches*batchSize); 9616*552f7358SJed Brown /* Remainder */ 9617*552f7358SJed Brown PetscInt numRemainder = numCells % (numBatches * batchSize); 9618*552f7358SJed Brown PetscInt offset = numCells - numRemainder; 9619*552f7358SJed Brown 9620*552f7358SJed Brown ierr = (*mesh->integrateResidualFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, v0, J, invJ, detJ, f0, f1, elemVec);CHKERRQ(ierr); 9621*552f7358SJed Brown ierr = (*mesh->integrateResidualFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9622*552f7358SJed Brown f0, f1, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9623*552f7358SJed Brown } 9624*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 9625*552f7358SJed Brown if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9626*552f7358SJed Brown ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9627*552f7358SJed Brown } 9628*552f7358SJed Brown ierr = PetscFree6(u,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9629*552f7358SJed Brown if (mesh->printFEM) { 9630*552f7358SJed Brown PetscMPIInt rank, numProcs; 9631*552f7358SJed Brown PetscInt p; 9632*552f7358SJed Brown 9633*552f7358SJed Brown ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9634*552f7358SJed Brown ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9635*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); 9636*552f7358SJed Brown for (p = 0; p < numProcs; ++p) { 9637*552f7358SJed Brown if (p == rank) { 9638*552f7358SJed Brown Vec f; 9639*552f7358SJed Brown 9640*552f7358SJed Brown ierr = VecDuplicate(F, &f);CHKERRQ(ierr); 9641*552f7358SJed Brown ierr = VecCopy(F, f);CHKERRQ(ierr); 9642*552f7358SJed Brown ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); 9643*552f7358SJed Brown ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9644*552f7358SJed Brown ierr = VecDestroy(&f);CHKERRQ(ierr); 9645*552f7358SJed Brown ierr = PetscViewerFlush(PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); 9646*552f7358SJed Brown } 9647*552f7358SJed Brown ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9648*552f7358SJed Brown } 9649*552f7358SJed Brown } 9650*552f7358SJed Brown /* ierr = PetscLogEventEnd(ResidualFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9651*552f7358SJed Brown PetscFunctionReturn(0); 9652*552f7358SJed Brown } 9653*552f7358SJed Brown 9654*552f7358SJed Brown #undef __FUNCT__ 9655*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeJacobianActionFEM" 9656*552f7358SJed Brown /*@C 9657*552f7358SJed Brown DMPlexComputeJacobianActionFEM - Form the local action of Jacobian J(u) on the local input X using pointwise functions specified by the user 9658*552f7358SJed Brown 9659*552f7358SJed Brown Input Parameters: 9660*552f7358SJed Brown + dm - The mesh 9661*552f7358SJed Brown . J - The Jacobian shell matrix 9662*552f7358SJed Brown . X - Local input vector 9663*552f7358SJed Brown - user - The user context 9664*552f7358SJed Brown 9665*552f7358SJed Brown Output Parameter: 9666*552f7358SJed Brown . F - Local output vector 9667*552f7358SJed Brown 9668*552f7358SJed Brown Note: 9669*552f7358SJed Brown The second member of the user context must be an FEMContext. 9670*552f7358SJed Brown 9671*552f7358SJed Brown We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9672*552f7358SJed Brown like a GPU, or vectorize on a multicore machine. 9673*552f7358SJed Brown 9674*552f7358SJed Brown .seealso: DMPlexComputeResidualFEM() 9675*552f7358SJed Brown */ 9676*552f7358SJed Brown PetscErrorCode DMPlexComputeJacobianActionFEM(DM dm, Mat Jac, Vec X, Vec F, void *user) 9677*552f7358SJed Brown { 9678*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9679*552f7358SJed Brown PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9680*552f7358SJed Brown PetscQuadrature *quad = fem->quad; 9681*552f7358SJed Brown PetscSection section; 9682*552f7358SJed Brown JacActionCtx *jctx; 9683*552f7358SJed Brown PetscReal *v0, *J, *invJ, *detJ; 9684*552f7358SJed Brown PetscScalar *elemVec, *u, *a; 9685*552f7358SJed Brown PetscInt dim, numFields, field, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9686*552f7358SJed Brown PetscInt cellDof = 0; 9687*552f7358SJed Brown PetscErrorCode ierr; 9688*552f7358SJed Brown 9689*552f7358SJed Brown PetscFunctionBegin; 9690*552f7358SJed Brown /* ierr = PetscLogEventBegin(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9691*552f7358SJed Brown ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9692*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9693*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9694*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9695*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9696*552f7358SJed Brown numCells = cEnd - cStart; 9697*552f7358SJed Brown for (field = 0; field < numFields; ++field) { 9698*552f7358SJed Brown cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9699*552f7358SJed Brown } 9700*552f7358SJed Brown ierr = VecSet(F, 0.0);CHKERRQ(ierr); 9701*552f7358SJed Brown ierr = PetscMalloc7(numCells*cellDof,PetscScalar,&u,numCells*cellDof,PetscScalar,&a,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr); 9702*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 9703*552f7358SJed Brown const PetscScalar *x; 9704*552f7358SJed Brown PetscInt i; 9705*552f7358SJed Brown 9706*552f7358SJed Brown ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9707*552f7358SJed Brown if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9708*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9709*552f7358SJed Brown for (i = 0; i < cellDof; ++i) { 9710*552f7358SJed Brown u[c*cellDof+i] = x[i]; 9711*552f7358SJed Brown } 9712*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, jctx->u, c, PETSC_NULL, &x);CHKERRQ(ierr); 9713*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9714*552f7358SJed Brown for (i = 0; i < cellDof; ++i) { 9715*552f7358SJed Brown a[c*cellDof+i] = x[i]; 9716*552f7358SJed Brown } 9717*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9718*552f7358SJed Brown } 9719*552f7358SJed Brown for (field = 0; field < numFields; ++field) { 9720*552f7358SJed Brown const PetscInt numQuadPoints = quad[field].numQuadPoints; 9721*552f7358SJed Brown const PetscInt numBasisFuncs = quad[field].numBasisFuncs; 9722*552f7358SJed Brown /* Conforming batches */ 9723*552f7358SJed Brown PetscInt blockSize = numBasisFuncs*numQuadPoints; 9724*552f7358SJed Brown PetscInt numBlocks = 1; 9725*552f7358SJed Brown PetscInt batchSize = numBlocks * blockSize; 9726*552f7358SJed Brown PetscInt numBatches = numBatchesTmp; 9727*552f7358SJed Brown PetscInt numChunks = numCells / (numBatches*batchSize); 9728*552f7358SJed Brown /* Remainder */ 9729*552f7358SJed Brown PetscInt numRemainder = numCells % (numBatches * batchSize); 9730*552f7358SJed Brown PetscInt offset = numCells - numRemainder; 9731*552f7358SJed Brown 9732*552f7358SJed Brown ierr = (*mesh->integrateJacobianActionFEM)(numChunks*numBatches*batchSize, numFields, field, quad, u, a, v0, J, invJ, detJ, fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, elemVec);CHKERRQ(ierr); 9733*552f7358SJed Brown ierr = (*mesh->integrateJacobianActionFEM)(numRemainder, numFields, field, quad, &u[offset*cellDof], &a[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9734*552f7358SJed Brown fem->g0Funcs, fem->g1Funcs, fem->g2Funcs, fem->g3Funcs, &elemVec[offset*cellDof]);CHKERRQ(ierr); 9735*552f7358SJed Brown } 9736*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 9737*552f7358SJed Brown if (mesh->printFEM > 1) {ierr = DMPrintCellVector(c, "Jacobian Action", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} 9738*552f7358SJed Brown ierr = DMPlexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); 9739*552f7358SJed Brown } 9740*552f7358SJed Brown ierr = PetscFree7(u,a,v0,J,invJ,detJ,elemVec);CHKERRQ(ierr); 9741*552f7358SJed Brown if (mesh->printFEM) { 9742*552f7358SJed Brown PetscMPIInt rank, numProcs; 9743*552f7358SJed Brown PetscInt p; 9744*552f7358SJed Brown 9745*552f7358SJed Brown ierr = MPI_Comm_rank(((PetscObject) dm)->comm, &rank);CHKERRQ(ierr); 9746*552f7358SJed Brown ierr = MPI_Comm_size(((PetscObject) dm)->comm, &numProcs);CHKERRQ(ierr); 9747*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian Action:\n");CHKERRQ(ierr); 9748*552f7358SJed Brown for (p = 0; p < numProcs; ++p) { 9749*552f7358SJed Brown if (p == rank) {ierr = VecView(F, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr);} 9750*552f7358SJed Brown ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); 9751*552f7358SJed Brown } 9752*552f7358SJed Brown } 9753*552f7358SJed Brown /* ierr = PetscLogEventEnd(JacobianActionFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9754*552f7358SJed Brown PetscFunctionReturn(0); 9755*552f7358SJed Brown } 9756*552f7358SJed Brown 9757*552f7358SJed Brown #undef __FUNCT__ 9758*552f7358SJed Brown #define __FUNCT__ "DMPlexComputeJacobianFEM" 9759*552f7358SJed Brown /*@ 9760*552f7358SJed Brown DMPlexComputeJacobianFEM - Form the local portion of the Jacobian matrix J at the local solution X using pointwise functions specified by the user. 9761*552f7358SJed Brown 9762*552f7358SJed Brown Input Parameters: 9763*552f7358SJed Brown + dm - The mesh 9764*552f7358SJed Brown . X - Local input vector 9765*552f7358SJed Brown - user - The user context 9766*552f7358SJed Brown 9767*552f7358SJed Brown Output Parameter: 9768*552f7358SJed Brown . Jac - Jacobian matrix 9769*552f7358SJed Brown 9770*552f7358SJed Brown Note: 9771*552f7358SJed Brown The second member of the user context must be an FEMContext. 9772*552f7358SJed Brown 9773*552f7358SJed Brown We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 9774*552f7358SJed Brown like a GPU, or vectorize on a multicore machine. 9775*552f7358SJed Brown 9776*552f7358SJed Brown .seealso: FormFunctionLocal() 9777*552f7358SJed Brown */ 9778*552f7358SJed Brown PetscErrorCode DMPlexComputeJacobianFEM(DM dm, Vec X, Mat Jac, Mat JacP, MatStructure *str,void *user) 9779*552f7358SJed Brown { 9780*552f7358SJed Brown DM_Plex *mesh = (DM_Plex *) dm->data; 9781*552f7358SJed Brown PetscFEM *fem = (PetscFEM *) &((DM *) user)[1]; 9782*552f7358SJed Brown PetscQuadrature *quad = fem->quad; 9783*552f7358SJed Brown PetscSection section; 9784*552f7358SJed Brown PetscReal *v0, *J, *invJ, *detJ; 9785*552f7358SJed Brown PetscScalar *elemMat, *u; 9786*552f7358SJed Brown PetscInt dim, numFields, field, fieldI, numBatchesTmp = 1, numCells, cStart, cEnd, c; 9787*552f7358SJed Brown PetscInt cellDof = 0, numComponents = 0; 9788*552f7358SJed Brown PetscBool isShell; 9789*552f7358SJed Brown PetscErrorCode ierr; 9790*552f7358SJed Brown 9791*552f7358SJed Brown PetscFunctionBegin; 9792*552f7358SJed Brown /* ierr = PetscLogEventBegin(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9793*552f7358SJed Brown ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 9794*552f7358SJed Brown ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 9795*552f7358SJed Brown ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 9796*552f7358SJed Brown ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 9797*552f7358SJed Brown numCells = cEnd - cStart; 9798*552f7358SJed Brown for (field = 0; field < numFields; ++field) { 9799*552f7358SJed Brown cellDof += quad[field].numBasisFuncs*quad[field].numComponents; 9800*552f7358SJed Brown numComponents += quad[field].numComponents; 9801*552f7358SJed Brown } 9802*552f7358SJed Brown ierr = DMPlexProjectFunctionLocal(dm, numComponents, fem->bcFuncs, INSERT_BC_VALUES, X);CHKERRQ(ierr); 9803*552f7358SJed Brown ierr = MatZeroEntries(JacP);CHKERRQ(ierr); 9804*552f7358SJed Brown ierr = PetscMalloc6(numCells*cellDof,PetscScalar,&u,numCells*dim,PetscReal,&v0,numCells*dim*dim,PetscReal,&J,numCells*dim*dim,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof*cellDof,PetscScalar,&elemMat);CHKERRQ(ierr); 9805*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 9806*552f7358SJed Brown const PetscScalar *x; 9807*552f7358SJed Brown PetscInt i; 9808*552f7358SJed Brown 9809*552f7358SJed Brown ierr = DMPlexComputeCellGeometry(dm, c, &v0[c*dim], &J[c*dim*dim], &invJ[c*dim*dim], &detJ[c]);CHKERRQ(ierr); 9810*552f7358SJed Brown if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); 9811*552f7358SJed Brown ierr = DMPlexVecGetClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9812*552f7358SJed Brown 9813*552f7358SJed Brown for (i = 0; i < cellDof; ++i) { 9814*552f7358SJed Brown u[c*cellDof+i] = x[i]; 9815*552f7358SJed Brown } 9816*552f7358SJed Brown ierr = DMPlexVecRestoreClosure(dm, PETSC_NULL, X, c, PETSC_NULL, &x);CHKERRQ(ierr); 9817*552f7358SJed Brown } 9818*552f7358SJed Brown ierr = PetscMemzero(elemMat, numCells*cellDof*cellDof * sizeof(PetscScalar));CHKERRQ(ierr); 9819*552f7358SJed Brown for (fieldI = 0; fieldI < numFields; ++fieldI) { 9820*552f7358SJed Brown const PetscInt numQuadPoints = quad[fieldI].numQuadPoints; 9821*552f7358SJed Brown const PetscInt numBasisFuncs = quad[fieldI].numBasisFuncs; 9822*552f7358SJed Brown PetscInt fieldJ; 9823*552f7358SJed Brown 9824*552f7358SJed Brown for (fieldJ = 0; fieldJ < numFields; ++fieldJ) { 9825*552f7358SJed Brown void (*g0)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g0[]) = fem->g0Funcs[fieldI*numFields+fieldJ]; 9826*552f7358SJed Brown void (*g1)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g1[]) = fem->g1Funcs[fieldI*numFields+fieldJ]; 9827*552f7358SJed Brown void (*g2)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g2[]) = fem->g2Funcs[fieldI*numFields+fieldJ]; 9828*552f7358SJed Brown void (*g3)(const PetscScalar u[], const PetscScalar gradU[], const PetscReal x[], PetscScalar g3[]) = fem->g3Funcs[fieldI*numFields+fieldJ]; 9829*552f7358SJed Brown /* Conforming batches */ 9830*552f7358SJed Brown PetscInt blockSize = numBasisFuncs*numQuadPoints; 9831*552f7358SJed Brown PetscInt numBlocks = 1; 9832*552f7358SJed Brown PetscInt batchSize = numBlocks * blockSize; 9833*552f7358SJed Brown PetscInt numBatches = numBatchesTmp; 9834*552f7358SJed Brown PetscInt numChunks = numCells / (numBatches*batchSize); 9835*552f7358SJed Brown /* Remainder */ 9836*552f7358SJed Brown PetscInt numRemainder = numCells % (numBatches * batchSize); 9837*552f7358SJed Brown PetscInt offset = numCells - numRemainder; 9838*552f7358SJed Brown 9839*552f7358SJed Brown ierr = (*mesh->integrateJacobianFEM)(numChunks*numBatches*batchSize, numFields, fieldI, fieldJ, quad, u, v0, J, invJ, detJ, g0, g1, g2, g3, elemMat);CHKERRQ(ierr); 9840*552f7358SJed Brown ierr = (*mesh->integrateJacobianFEM)(numRemainder, numFields, fieldI, fieldJ, quad, &u[offset*cellDof], &v0[offset*dim], &J[offset*dim*dim], &invJ[offset*dim*dim], &detJ[offset], 9841*552f7358SJed Brown g0, g1, g2, g3, &elemMat[offset*cellDof*cellDof]);CHKERRQ(ierr); 9842*552f7358SJed Brown } 9843*552f7358SJed Brown } 9844*552f7358SJed Brown for (c = cStart; c < cEnd; ++c) { 9845*552f7358SJed Brown if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(c, "Jacobian", cellDof, cellDof, &elemMat[c*cellDof*cellDof]);CHKERRQ(ierr);} 9846*552f7358SJed Brown ierr = DMPlexMatSetClosure(dm, PETSC_NULL, PETSC_NULL, JacP, c, &elemMat[c*cellDof*cellDof], ADD_VALUES);CHKERRQ(ierr); 9847*552f7358SJed Brown } 9848*552f7358SJed Brown ierr = PetscFree6(u,v0,J,invJ,detJ,elemMat);CHKERRQ(ierr); 9849*552f7358SJed Brown 9850*552f7358SJed Brown /* Assemble matrix, using the 2-step process: 9851*552f7358SJed Brown MatAssemblyBegin(), MatAssemblyEnd(). */ 9852*552f7358SJed Brown ierr = MatAssemblyBegin(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9853*552f7358SJed Brown ierr = MatAssemblyEnd(JacP, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9854*552f7358SJed Brown 9855*552f7358SJed Brown if (mesh->printFEM) { 9856*552f7358SJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD, "Jacobian:\n");CHKERRQ(ierr); 9857*552f7358SJed Brown ierr = MatChop(JacP, 1.0e-10);CHKERRQ(ierr); 9858*552f7358SJed Brown ierr = MatView(JacP, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 9859*552f7358SJed Brown } 9860*552f7358SJed Brown /* ierr = PetscLogEventEnd(JacobianFEMEvent,0,0,0,0);CHKERRQ(ierr); */ 9861*552f7358SJed Brown ierr = PetscObjectTypeCompare((PetscObject)Jac, MATSHELL, &isShell);CHKERRQ(ierr); 9862*552f7358SJed Brown if (isShell) { 9863*552f7358SJed Brown JacActionCtx *jctx; 9864*552f7358SJed Brown 9865*552f7358SJed Brown ierr = MatShellGetContext(Jac, &jctx);CHKERRQ(ierr); 9866*552f7358SJed Brown ierr = VecCopy(X, jctx->u);CHKERRQ(ierr); 9867*552f7358SJed Brown } 9868*552f7358SJed Brown *str = SAME_NONZERO_PATTERN; 9869*552f7358SJed Brown PetscFunctionReturn(0); 9870*552f7358SJed Brown } 9871*552f7358SJed Brown 9872*552f7358SJed Brown 9873*552f7358SJed Brown #undef __FUNCT__ 9874*552f7358SJed Brown #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 9875*552f7358SJed Brown /*@C 9876*552f7358SJed Brown PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 9877*552f7358SJed Brown the local section and an SF describing the section point overlap. 9878*552f7358SJed Brown 9879*552f7358SJed Brown Input Parameters: 9880*552f7358SJed Brown + s - The PetscSection for the local field layout 9881*552f7358SJed Brown . sf - The SF describing parallel layout of the section points 9882*552f7358SJed Brown . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 9883*552f7358SJed Brown . label - The label specifying the points 9884*552f7358SJed Brown - labelValue - The label stratum specifying the points 9885*552f7358SJed Brown 9886*552f7358SJed Brown Output Parameter: 9887*552f7358SJed Brown . gsection - The PetscSection for the global field layout 9888*552f7358SJed Brown 9889*552f7358SJed Brown Note: This gives negative sizes and offsets to points not owned by this process 9890*552f7358SJed Brown 9891*552f7358SJed Brown Level: developer 9892*552f7358SJed Brown 9893*552f7358SJed Brown .seealso: PetscSectionCreate() 9894*552f7358SJed Brown @*/ 9895*552f7358SJed Brown PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 9896*552f7358SJed Brown { 9897*552f7358SJed Brown PetscInt *neg; 9898*552f7358SJed Brown PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 9899*552f7358SJed Brown PetscErrorCode ierr; 9900*552f7358SJed Brown 9901*552f7358SJed Brown PetscFunctionBegin; 9902*552f7358SJed Brown ierr = PetscSectionCreate(s->atlasLayout.comm, gsection);CHKERRQ(ierr); 9903*552f7358SJed Brown ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 9904*552f7358SJed Brown ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 9905*552f7358SJed Brown ierr = PetscMalloc((pEnd - pStart) * sizeof(PetscInt), &neg);CHKERRQ(ierr); 9906*552f7358SJed Brown /* Mark ghost points with negative dof */ 9907*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 9908*552f7358SJed Brown PetscInt value; 9909*552f7358SJed Brown 9910*552f7358SJed Brown ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 9911*552f7358SJed Brown if (value != labelValue) continue; 9912*552f7358SJed Brown ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 9913*552f7358SJed Brown ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 9914*552f7358SJed Brown ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 9915*552f7358SJed Brown if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 9916*552f7358SJed Brown neg[p-pStart] = -(dof+1); 9917*552f7358SJed Brown } 9918*552f7358SJed Brown ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 9919*552f7358SJed Brown ierr = PetscSFGetGraph(sf, &nroots, PETSC_NULL, PETSC_NULL, PETSC_NULL);CHKERRQ(ierr); 9920*552f7358SJed Brown if (nroots >= 0) { 9921*552f7358SJed Brown if (nroots > pEnd - pStart) { 9922*552f7358SJed Brown PetscInt *tmpDof; 9923*552f7358SJed Brown /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9924*552f7358SJed Brown ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpDof);CHKERRQ(ierr); 9925*552f7358SJed Brown ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9926*552f7358SJed Brown ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpDof);CHKERRQ(ierr); 9927*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 9928*552f7358SJed Brown if (tmpDof[p] < 0) {(*gsection)->atlasDof[p-pStart] = tmpDof[p];} 9929*552f7358SJed Brown } 9930*552f7358SJed Brown ierr = PetscFree(tmpDof);CHKERRQ(ierr); 9931*552f7358SJed Brown } else { 9932*552f7358SJed Brown ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9933*552f7358SJed Brown ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasDof[-pStart]);CHKERRQ(ierr); 9934*552f7358SJed Brown } 9935*552f7358SJed Brown } 9936*552f7358SJed Brown /* Calculate new sizes, get proccess offset, and calculate point offsets */ 9937*552f7358SJed Brown for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9938*552f7358SJed Brown cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 9939*552f7358SJed Brown (*gsection)->atlasOff[p] = off; 9940*552f7358SJed Brown off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 9941*552f7358SJed Brown } 9942*552f7358SJed Brown ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, s->atlasLayout.comm);CHKERRQ(ierr); 9943*552f7358SJed Brown globalOff -= off; 9944*552f7358SJed Brown for (p = 0, off = 0; p < pEnd-pStart; ++p) { 9945*552f7358SJed Brown (*gsection)->atlasOff[p] += globalOff; 9946*552f7358SJed Brown neg[p] = -((*gsection)->atlasOff[p]+1); 9947*552f7358SJed Brown } 9948*552f7358SJed Brown /* Put in negative offsets for ghost points */ 9949*552f7358SJed Brown if (nroots >= 0) { 9950*552f7358SJed Brown if (nroots > pEnd - pStart) { 9951*552f7358SJed Brown PetscInt *tmpOff; 9952*552f7358SJed Brown /* Help Jed: HAVE TO MAKE A BUFFER HERE THE SIZE OF THE COMPLETE SPACE AND THEN COPY INTO THE atlasDof FOR THIS SECTION */ 9953*552f7358SJed Brown ierr = PetscMalloc(nroots * sizeof(PetscInt), &tmpOff);CHKERRQ(ierr); 9954*552f7358SJed Brown ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9955*552f7358SJed Brown ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], tmpOff);CHKERRQ(ierr); 9956*552f7358SJed Brown for (p = pStart; p < pEnd; ++p) { 9957*552f7358SJed Brown if (tmpOff[p] < 0) {(*gsection)->atlasOff[p-pStart] = tmpOff[p];} 9958*552f7358SJed Brown } 9959*552f7358SJed Brown ierr = PetscFree(tmpOff);CHKERRQ(ierr); 9960*552f7358SJed Brown } else { 9961*552f7358SJed Brown ierr = PetscSFBcastBegin(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9962*552f7358SJed Brown ierr = PetscSFBcastEnd(sf, MPIU_INT, &neg[-pStart], &(*gsection)->atlasOff[-pStart]);CHKERRQ(ierr); 9963*552f7358SJed Brown } 9964*552f7358SJed Brown } 9965*552f7358SJed Brown ierr = PetscFree(neg);CHKERRQ(ierr); 9966*552f7358SJed Brown PetscFunctionReturn(0); 9967*552f7358SJed Brown } 9968